宿題の内容は以下の通りだった。
が、説明の過程でいくらか変更した部分がある。
/***
*** 落下する図形
***/
import java.awt.*;
import java.awt.event.*;
public class Homework6 extends Frame {
// 生成
public Homework6(){
super("Homework6");
setSize(500,500);
setLocation(100,10);
FigureCanvas can=new FigureCanvas();
add(can);
Panel p=new Panel();
p.setBackground(Color.lightGray);
Choice ch=new Choice();
ch.add("円");
ch.add("正方形");
ch.add("ランダム");
ch.addItemListener(can);
p.add(ch);
ch=new Choice();
ch.add("黒");
ch.add("赤");
ch.add("緑");
ch.add("青");
ch.add("ランダム");
ch.addItemListener(can);
p.add(ch);
add(p,BorderLayout.NORTH);
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent ev){
can.stop();
System.exit(0);
}
});
}
// メイン
public static void main(String[] args){
(new Homework6()).setVisible(true);
}
}
/***
*** 図形描画キャンバス
***/
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class FigureCanvas extends Canvas
implements Runnable,ItemListener,MouseListener,MouseMotionListener {
private ArrayList<Figure> list;
private Thread runner;
private Image off;
private int width,height;
private int fig_type=0;
private Figure grab_figure;
// 生成
public FigureCanvas(){
list=new ArrayList<Figure>();
grab_figure=null;
runner=new Thread(this);
runner.start();
addMouseListener(this);
addMouseMotionListener(this);
}
// 描画
public void update(Graphics g){ paint(g); }
public void paint(Graphics g){
int w=getWidth(),h=getHeight();
if(w!=width || h!=height)
off=createImage(width=w,height=h);
Graphics offg=off.getGraphics();
offg.setColor(getBackground());
offg.fillRect(0,0,width,height);
paint1(offg);
g.drawImage(off,0,0,null);
}
public void paint1(Graphics g){
for(Figure f:list) f.draw(g);
}
// マウスリスナー
public void mousePressed(MouseEvent ev){
int x=ev.getX();
int y=ev.getY();
// 図形上かどうかを判定する
grab_figure=null;
for(int i=list.size()-1;i>=0;i--){
Figure f=list.get(i);
if(f.isOver(x,y)){
grab_figure=f;
grab_figure.pause();
break;
}
}
if(grab_figure==null){
int t=fig_type;
if(t==2) t=(Math.random()<0.5)?0:1;
switch(t){
case 0: list.add(new Circle(x,y,20,Color.black)); break;
case 1: list.add(new Square(x,y,20,Color.red)); break;
}
}
repaint();
}
public void mouseReleased(MouseEvent ev){
if(grab_figure!=null)
grab_figure.resume();
repaint();
}
public void mouseClicked(MouseEvent ev){}
public void mouseEntered(MouseEvent ev){}
public void mouseExited(MouseEvent ev){}
public void mouseMoved(MouseEvent ev){}
public void mouseDragged(MouseEvent ev){
if(grab_figure==null) return;
grab_figure.set(ev.getX(),ev.getY());
repaint();
}
// アイテムリスナー
public void itemStateChanged(ItemEvent ev){
String it=(String)ev.getItem();
if(it.equals("円")) fig_type=0;
if(it.equals("正方形")) fig_type=1;
if(it.equals("ランダム")) fig_type=2;
}
// 実行
public void run(){
while(runner!=null){
int w=getWidth(),h=getHeight();
for(Figure f:list)
f.move(w,h);
repaint();
try{
runner.sleep(100);
}
catch(InterruptedException e){}
}
}
// 停止
public void stop(){
runner=null;
}
}
/***
*** 図形の基底クラス
***/
import java.awt.*;
public class Figure {
protected int px,py; // 位置
protected Color color; // 色
protected boolean is_pausing; // 一時停止中
// 生成
public Figure(int x,int y,Color c){
px=x;
py=y;
color=c;
}
// 位置をセットする
public void set(int x,int y){
px=x;
py=y;
}
// 描画
public void draw(Graphics g){}
// 移動
public void move(int w,int h){}
// 一時停止
public void pause(){ is_pausing=true; }
// 再開
public void resume(){ is_pausing=false; }
// 上に乗っているか?
public boolean isOver(int x,int y){
return false;
}
}
/***
*** 円
***/
import java.awt.*;
public class Circle extends Figure {
private int rad; // 半径
// 生成
public Circle(int x,int y,int r,Color c){
super(x,y,c);
rad=r;
}
// 描画
public void draw(Graphics g){
g.setColor(color);
g.fillOval(px-rad,py-rad,rad*2,rad*2);
}
// 移動
public void move(int w,int h){
if(is_pausing) return;
py+=10;
if(py>h) py=0;
}
// 上に乗っているか?
public boolean isOver(int x,int y){
int dx=px-x,dy=py-y;
double d=Math.sqrt(dx*dx+dy*dy);
return d<=rad;
}
}
/***
*** 正方形
***/
import java.awt.*;
public class Square extends Figure {
private int size; // 一辺の長さ
// 生成
public Square(int x,int y,int s,Color c){
super(x,y,c);
size=s;
}
// 描画
public void draw(Graphics g){
g.setColor(color);
g.fillRect(px-size/2,py-size/2,size,size);
}
// 移動
public void move(int w,int h){
if(is_pausing) return;
px+=10;
if(px>w) px=0;
}
// 上に乗っているか?
public boolean isOver(int x,int y){
return
px-size/2<=x && x<=px+size/2 &&
py-size/2<=y && y<=py+size/2;
}
}