プログラム
//--------------------------------------------
import java.applet.Applet;
import java.awt.*;
/*
<applet code="Bounce"width=400
height=300>
</applet>
*/
//実際に物体を生成しアニメーションを動かすためのクラス
public class Bounce extends Applet implements
Runnable{
Thread animation;//Threadを宣言
Graphics offscreen;//オフスクリーンバッファの宣言
Image image;
static final int NUM_RECT_BOUNCE = 5;//物体の個数
static final int NUM_OVAL_BOUNCE = 9;
static final int NUM_RECT_MOVEMENT = 2;
static final int REFRESH_RATE = 50;//休止する時間[ms]
BouncingRect br[];//物体を生成するためのクラスの配列の宣言
BouncingOval bo[];
MovingRect mr[];
MovingOval mo[];
int width;//アプレットのサイズ
int height;
//アプレットの初期化を行うメソッド
public void init(){
setBackground(Color.black);//アプレットのの背景の色の初期化
width = getBounds().width;//アプレットの境界を取得
height = getBounds().height;
initShapes();//物体の初期化
image = createImage(width,height);//オフスクリーンバッファの
offscreen = image.getGraphics();// 割り当て
}
//物体の初期化を行うメソッド
public void initShapes(){
br = new BouncingRect[NUM_RECT_BOUNCE];//物体の配列の領域の割り当て
bo = new BouncingOval[NUM_OVAL_BOUNCE];
mr = new MovingRect[NUM_RECT_MOVEMENT];
//物体のインスタンス化
br[0] = new BouncingRect(0,0,20,30,Color.cyan,width-1,height-1,0,0,
60,60,10,10,3,4,true);
br[0].setVelocity(5,7);
br[1] = new BouncingRect(0,0,width-1,height-1,Color.white,0,0,0,
0,0,0,0,0,0,0,false);
br[2] = new BouncingRect(20,20,80,100,Color.pink,0,0,0,0,
0,0,0,0,0,0,false);
br[3] = new BouncingRect(60,70,80,100,Color.green,0,0,0,0,
0,0,0,0,0,0,false);
br[4] = new BouncingRect(100,120,80,100,Color.orange,0,0,0,0,
0,0,0,0,0,0,false);
bo[0] = new BouncingOval(200,150,30,20,Color.magenta,width-1,height-1,0,0,
60,60,10,10,4,3,true);
bo[0].setVelocity(8,4);
bo[1] = new BouncingOval(20,20,10,10,Color.green,100,120,20,20,
0,0,0,0,0,0,true);
bo[1].setVelocity(7,7);
bo[2] = new BouncingOval(60,70,10,10,Color.green,100,120,20,20,
0,0,0,0,0,0,true);
bo[2].setVelocity(7,-7);
bo[3] = new BouncingOval(60,70,10,10,Color.pink,140,170,60,70,
0,0,0,0,0,0,true);
bo[3].setVelocity(7,7);
bo[4] = new BouncingOval(100,120,10,10,Color.pink,140,170,60,70,
0,0,0,0,0,0,true);
bo[4].setVelocity(7,-7);
bo[5] = new BouncingOval(100,120,10,10,Color.orange,140,220,100,120,
0,0,0,0,0,0,true);
bo[5].setVelocity(7,7);
bo[6] = new BouncingOval(140,170,10,10,Color.orange,140,220,100,120,
0,0,0,0,0,0,true);
bo[6].setVelocity(7,-7);
bo[7] = new BouncingOval(0,0,width,height,Color.gray,0,0,0,0,
0,0,0,0,0,0,true);
bo[8] = new BouncingOval(50,0,300,300,Color.black,0,0,0,0,
0,0,0,0,0,0,true);
mr[0] = new MovingRect(40,30,100,140,Color.blue,260,0,40,0,
2,0,0);
mr[1] = new MovingRect(120,180,200,80,Color.lightGray,0,310,0,40,
0,1,2);
}
//アプレットを実行するメソッド
public void start(){
animation = new Thread(this);
if(animation != null){
animation.start();
}
}
//それぞれの物体の(位置や大きさの)更新をするメソッド
public void updateShapes(){
mr[0].updatePositionLR();
mr[1].updatePositionUD();
for(int i=0; i<br.length; i++){
br[i].update();
}
for(int i=0; i<bo.length; i++){
bo[i].update();
}
}
//update()メソッドをオーバーライドし
// アプレットウィンドウを消さないようにする
public void update(Graphics g){
paint(g);
}
//物体のオフスクリーンへの描画とウィンドウの更新をするメソッド
public void paint(Graphics g){
offscreen.setColor(Color.black);
offscreen.fillRect(0,0,width,height);
bo[7].paint(offscreen);
bo[8].paint(offscreen);
mr[0].paint(offscreen);
br[0].paint(offscreen);
bo[0].paint(offscreen);
mr[1].paint(offscreen);
for(int i=1; i<br.length; i++){
br[i].paint(offscreen);
}
for(int i=1; i<7; i++){
bo[i].paint(offscreen);
}
g.drawImage(image,0,0,this);//ウィンドウの更新
}
//Threadの本体であるrun()メソッドのオーバーライド
public void run(){
while(true){
repaint();
updateShapes();
try{
Thread.sleep(REFRESH_RATE);
} catch(Exception exc){};
}
}
//アプレットの停止
public void stop(){
if(animation != null){
animation.stop();
animation = null;
}
}
}
//-------------------------------------------
//バウンドする物体を作るためのクラス
class BouncingShape{
protected int max_width; //バウンドする最大値
protected int max_height;
protected int min_width; //バウンドする最小値
protected int min_height;
protected int vx;//物体の速さ
protected int vy;
protected int locx;//物体の位置
protected int locy;
Color color;//物体の色
boolean fill;//物体を塗りつぶすかどうか
protected int width;//物体の幅
protected int height;//物体の高さ
protected int max_move_width;//物体の大きさの変化の最大値
protected int max_move_height;
protected int min_move_width;//物体の大きさの変化の最小値
protected int min_move_height;
protected int move_speed_width;//物体の大きさの変化の速さ
protected int move_speed_height;
//動かない物体のためのコンストラクタ
public BouncingShape(int x,int y,int w,int
h,Color c,boolean f){
locx = x;
locy = y;
width = w;
height = h;
color = c;
fill = f;
}
//動く物体のためのコンストラクタ
public BouncingShape(int x,int y,int w,int
h,Color c,
int max_w,int max_h,int min_w,int min_h,
int max_m_w,int max_m_h,int min_m_w,int min_m_h,
int msw,int msh,boolean f){
locx = x;
locy = y;
width = w;
height = h;
max_width = max_w;
max_height = max_h;
min_width = min_w;
min_height = min_h;
max_move_width = max_m_w;
max_move_height = max_m_h;
min_move_width = min_m_w;
min_move_height = min_m_h;
move_speed_width = msw;
move_speed_height = msh;
color = c;
fill = f;
}
//物体の速さの設定のためのメソッド
public void setVelocity(int x, int y){
vx = x;
vy = y;
}
//物体の位置の更新のためのメソッド
public void updatePosition(){
locx += vx;
locy += vy;
}
//物体の大きさの変化の速さを設定するためのメソッド
public void setMoveSpeed(int w,int h){
move_speed_width = w;
move_speed_height = h;
}
//物体の大きさの更新
public void updateSize(){
width += move_speed_width;
height += move_speed_height;
}
//反射や大きさの最大最小を考慮しながら全体的に更新するメソッド
public void update(){
if((locx+width > max_width) || locx <
min_width){
vx = -vx;
}
if((locy+height > max_height) || locy
< min_height){
vy = -vy;
}
if(width > max_move_width || width <
min_move_width){
move_speed_width = -move_speed_width;
}
if(height > max_move_height || height
< min_move_height){
move_speed_height = -move_speed_height;
}
updatePosition();
updateSize();
}
//ここでは実装しない
public void paint(Graphics g){
}
}
//--------------------------------------------------
//バウンドする長方形を作るためのクラス
class BouncingRect extends BouncingShape{
//BouncingShapeのものをそのまま継承したコンストラクタ
public BouncingRect(int x,int y,int w,int
h,Color c,
int max_w,int max_h,int min_w,int min_h,
int max_m_w,int max_m_h,int min_m_w,int min_m_h,
int msw,int msh,boolean f){
super(x,y,w,h,c,max_w,max_h,min_w,min_h,
max_m_w,max_m_h,min_m_w,min_m_h,msw,msh,f);
}
//BouncingShapeで実装されなかったpaintをオーバーライド
public void paint(Graphics g){
g.setColor(color);
if(fill){
g.fillRect(locx,locy,width,height);
}
else{
g.drawRect(locx,locy,width,height);
}
}
}
//--------------------------------------------------
//バウンドする楕円を作るためのクラス
class BouncingOval extends BouncingShape{
//BouncingShapeのものをそのまま継承したコンストラクタ
public BouncingOval(int x,int y,int w,int
h,Color c,
int max_w,int max_h,int min_w,int min_h,
int max_m_w,int max_m_h,int min_m_w,int min_m_h,
int msw,int msh,boolean f){
super(x,y,w,h,c,max_w,max_h,min_w,min_h,
max_m_w,max_m_h,min_m_w,min_m_h,msw,msh,f);
}
//BouncingShapeで実装されなかったpaintをオーバーライド
public void paint(Graphics g){
g.setColor(color);
if(fill){
g.fillOval(locx,locy,width,height);
}
else{
g.drawOval(locx,locy,width,height);
}
}
}
//--------------------------------------------------
//動く物体を作るためのクラス
class MovingShape{
protected int locx;//物体の位置
protected int locy;
protected int width;//物体の幅
protected int height;
protected int max_x;//物体の動ける最大値
protected int max_y;
protected int min_x;//物体の動ける最小値
protected int min_y;
protected int vx;//物体の動く速さ
protected int vy;
Color color;//物体の色
static final int RIGHT = 0;//物体の動く方向をきめる数字
static final int LEFT = 1;
static final int UP = 2;
static final int DOWN = 3;
static final int UP_RIGHT = 4;
static final int DOWN_LEFT = 5;
static final int UP_LEFT = 6;
static final int DOWN_RIGHT = 7;
protected int state;//物体の現在の方向の状態
//コンストラクタ
public MovingShape(int x,int y,int w,int
h,Color c,
int max_x,int max_y,int min_x,int min_y,
int vx,int vy,int s){
locx = x;
locy = y;
width = w;
height = h;
color = c;
this.max_x = max_x;
this.max_y = max_y;
this.min_x = min_x;
this.min_y = min_y;
this.vx = vx;
this.vy = vy;
state = s;
}
//物体を左右に動かすメソッド
public void updatePositionLR(){
switch(state){
case RIGHT:
locx += vx;
if(locx >= max_x){
state = LEFT;
}
break;
case LEFT:
locx -= vx;
if(locx <= min_x){
state = RIGHT;
}
break;
}
}
//物体を上下に動かすメソッド
public void updatePositionUD(){
switch(state){
case UP:
locy -= vy;
if(locy <= min_y){
state = DOWN;
}
break;
case DOWN:
locy += vy;
if(locy >= max_y){
state =UP;
}
break;
}
}
//物体を右上から左下へ動かすメソッド
public void updatePositionUR_DL(){
switch(state){
case UP_RIGHT:
locx += vx;
locy -= vy;
if(locx >= max_x || locy <= min_x){
state = DOWN_LEFT;
}
break;
case DOWN_LEFT:
locx -= vx;
locy += vy;
if(locx <= min_x || locy >= max_x){
state = UP_RIGHT;
}
break;
}
}
//物体を左上から右下へ動かすメソッド
public void updatePositionUL_DR(){
switch(state){
case UP_LEFT:
locx -= vx;
locy -= vy;
if(locx <= min_x || locy <= min_y){
state = DOWN_RIGHT;
}
break;
case DOWN_RIGHT:
locx += vx;
locy += vy;
if(locx >= max_x || locy >= max_y){
state = UP_LEFT;
}
break;
}
}
//ここでは実装しない
public void paint(){
}
}
//--------------------------------------------
//動く長方形を作るためのクラス
class MovingRect extends MovingShape{
//MovingShapeのものをそのまま継承したコンストラクタ
public MovingRect(int x,int y,int w,int h,Color
c,
int max_x,int max_y,int min_x,int min_y,
int vx,int vy,int s){
super(x,y,w,h,c,max_x,max_y,min_x,min_y,vx,vy,s);
}
//MovingShapeで実装されなかったpaintをオーバーライド
public void paint(Graphics g){
g.setColor(color);
g.fillRect(locx,locy,width,height);
}
}
//--------------------------------------------
//動く楕円を作るためのクラス
class MovingOval extends MovingShape{
//MovingShapeのものをそのまま継承したコンストラクタ
public MovingOval(int x,int y,int w,int h,Color
c,
int max_x,int max_y,int min_x,int min_y,
int vx,int vy,int s){
super(x,y,w,h,c,max_x,max_y,min_x,min_y,vx,vy,s);
}
//MovingShapeで実装されなかったpaintをオーバーライド
public void paint(Graphics g){
g.setColor(color);
g.fillOval(locx,locy,width,height);
}
}
//--------------------------------------------