簡易版--Java飛行機大戦

18584 ワード

目次
 
射撃ゲームのニーズ:
参加したキャラクター:英雄機、弾丸、小敵機、大敵機、小ミツバチ、空
ロール間の関係:
設計規則:
デザインクラスとゲームオブジェクト:
デマンド設計:
コード実装:
射撃ゲームのニーズ:
参加したキャラクター:英雄機、弾丸、小敵機、大敵機、小ミツバチ、空
ロール間の関係:
1)英雄機が弾を発射し、単倍火力と二倍火力に分ける
2)弾丸は敵(小敵機、大敵機、小ミツバチ)を射撃し、もし射撃したら:
2.1)弾丸が直接消え、敵が爆破してから消える
2.2)弾丸が小敵機を撃ち落とす--------プレイヤーは1点を得る
弾丸は大敵機を撃ち落とす――プレイヤーは3点を取る
弾丸はミツバチを撃ち落とす---英雄機は奨励(1命、40火力値)を得る
3)敵(小敵機、大敵機、小蜂)は英雄機と衝突することができ、もし衝突したら:
3.1)敵は先に爆破してから消える
3.2)英雄機は1つの命を減らして、同時に、火力の値---英雄機の命数が0の時、ゲームは終わります
4)英雄機、弾丸、小敵機、大敵機、小蜂が空を飛ぶ
設計規則:
1.すべての派生クラスが共有する属性と行為をスーパークラスに抽出する----------抽出共通性
2.派生クラスの行為はすべて同じで、普通の方法の派生クラスに設計する行為はすべて異なって、抽象的な方法に設計します
3.派生クラスの一部を共有する行為を、インタフェースに抽出するインタフェースは、単一のルート型を継承する拡張----------マルチ継承を実現する
 
デザインクラスとゲームオブジェクト:
対象:英雄機、弾丸、小敵機、大敵機、小ミツバチ、空
対象類:Hero、Bullet、Airplane、BigAirplane、Bee、Sky
スーパークラス:FlyingObjectスーパークラス、6つのオブジェクトクラスがスーパークラスを継承
画像ツールクラス:Images(画像に関連する操作/方法をカプセル化)
インタフェース:Enemy(得点インタフェース)、Award(奨励インタフェース)
ウィンドウ:Worldクラス
デマンド設計:
1.構築法:FlyingObjectで2つの構築方法を設計し、6つのオブジェクトクラスがそれぞれ呼び出す
2.移動方法:step()移動を6つのオブジェクトクラスで書き換える
3.アクセス制御:クラスのメンバーにアクセス制御修飾子を追加する
4.ウィンドウを描く:Worldクラスで、テストして、呼び出せばいい.
5.描画対象:
1)対象を描くには対象の画像を取得する必要があり、各対象が画像を取得することができ、画像を取得することが対象の共有行為であることを意味する.
したがって、取得ピクチャの動作をスーパークラスに設計すると、オブジェクトごとにピクチャを取得する動作が異なるため、抽象的な方法として設計され、
FlyingObjectで抽象メソッドgetImage()を設計してオブジェクトのピクチャを取得
2)画像を取得する際には、対象の状態を考慮する必要がある.異なる状態で取得する画像は異なるため、
各オブジェクトにはステータスがあり、ステータスがオブジェクトに共通する属性であることを意味するため、スーパークラスに設計され、
状態は一般的に固定されているので、定数として設計され、state変数を設計して現在の状態を表します.
、FlyingObjectでLIFE、DEAD、REMOVEの3つの定数を設計し、state変数で現在の状態を表す
状態があれば、状態を判断する必要があり、対象ごとに判断しなければならない.判断状態が共有行為であることを意味し、
したがって,設計はスーパークラスでは,オブジェクトごとに状態を判断する方式が同じであるため,一般的な方法として設計される.
,FlyingObjectでisLife(),isDead(),isRemove()を設計して対象の状態を判断する.
3)派生クラス書き換えgetImage()取得ピクチャ:
3.1)スカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイスカイ
3.2)弾丸Bullet:
3.2.1)生きていれば、そのままbullet画像に戻ればいい
3.2.2)死んだら、直接削除(画像を返さない)
3.3)英雄機Hero:
3.3.1)生きている場合は,直接heros[0]とheros[1]の往復切替に戻る.
3.4)小敵機Airplane:
3.4.1)生きているなら、airs[0]の画像に戻ればいい.
3.4.2)死んだらairs[1]からairs[4]の爆破図を返し、4後に削除(画像を返さない)
3.5)大敵機BigAirplane:
3.4.1)生きているなら、bairs[0]の画像に戻ればいい.
3.4.2)死んだらbairs[1]からbairs[4]の爆破図に戻り、4後に削除(画像は返さない)
3.4)ミツバチBee:
3.4.1)生きていれば、そのままbees[0]に戻ればいい
3.4.2)死んだらbees[1]からbees[4]の爆破図を返し、4後に削除(画像を返さない)
4)画像があれば絵を描くことができます.ウィンドウに描く必要があるので、ウィンドウWorldクラスでpaint()メソッドを書き換えてオブジェクトを描くことができます.
6.敵の入場:
1)敵オブジェクトはウィンドウから生成されるので,WorldでnextOne()を設計して敵オブジェクトを生成する.
2)敵入場がタイミングで発生するのでrun()でenterAction()を呼び出して敵入場を実現する
EnterActionでは、次の操作を行います.
400ミリ秒ごとに、敵オブジェクトobj,enemies拡張を取得し、objをenemiesの最後の要素に追加します.
忘れないでください:run()でenterAction()を呼び出した下でrepaint()メソッドを呼び出して再描画します.
7.弾丸入場:
1)弾は英雄機から発射されるので、Heroでshoot()を設計して弾の対象を生成する
2)弾丸入場はタイミング的に発生するのでrun()でshootAction()を呼び出して弾丸入場を実現する
shootActionでは、次の操作を行います.
300ミリ秒ごとに弾丸配列オブジェクトbs,bullets拡張を取得し,bsをbulletsの末尾に追加する
8.飛行物体の移動:
1)飛翔物移動は派生クラスが共有する行為であるため,スーパークラスFlyingObjectで抽象メソッドstep()移動を設計し,派生クラスで書き換える.
2)飛行物体移動がタイミングで発生するのでrun()でstepAction()を呼び出して飛行物体移動を実現する
ステップアクション:
空が動いて,敵の敵が動いて,弾丸が動いている.
9.英雄機はマウスに従って移動する:
1)英雄機はマウスに従って英雄機として動くので、HeroでmoveTo()を設計して英雄機がマウスに従って動くことを実現する
2)英雄機はマウスの移動に伴ってイベントがトリガーされるので、リスナーでmouseMoved()マウスの移動イベントを書き換える
mouseMoved()で:
マウスのx座標とy座標を取得し、HeroのmoveTo()メソッドを呼び出す
10.境界を越えた敵と弾丸を削除する:
1)FlyingObjectでoutOfBounds()を設計して敵が境界を越えたかどうかを検出する
BulletでoutofBounds()を書き換え弾丸が境界を越えたかどうかを検出する
2)オフサイドの敵と弾丸を削除するタイミングで発生するのでrunでoutofBoundsAction()を呼び出しオフサイドの敵と弾丸を削除
outOfBoundsAction()で:
非境界敵/弾丸配列を宣言し、enemies/bullets配列を遍歴し、境界を越えなければオブジェクトを非境界配列に装填すると判断する
最後に、非境界配列をenemies/bullets配列にコピーします.
11.インタフェースの設計:
1)Enemy得点インタフェースを設計し、AirplaneとBigAirplaneはEnemyインタフェースを実現し、小敵機/大敵機に当たって1点/3点を得る.
2)Award奨励インタフェースを設計し、BeeはAwardインタフェースを実現し、ミツバチに当たってランダムに奨励する:生命値に1/火力値に40倍の火力を加える
12.敵と弾丸の衝突:
1)FlyingObjectでhit()を設計して敵と弾丸の衝突、goDead()飛行物体の死を検出する
HeroでaddLife()増命、addFire()増火力を設計
2)敵と弾丸の衝突はタイミング的に発生するのでrun()でbulletBangAction()を呼び出して敵と弾丸の衝突を実現する
bulletBangAction()で:
弾丸の弾丸を遍歴し、敵の敵を遍歴し、もしすべて生きていてぶつかったと判断した.
弾丸が死んで敵が死ぬ
Enemy得点と判断するとプレイヤーは得点する
Award奨励なら英雄機が奨励する
13.画分と画命:
1)HeroでgetLife()を設計して英雄機の命数を取得する
2)World類のpaint()で:画分と画命
14.敵と英雄機の衝突:
1)FlyingObjectのhit()衝突検出、goDead()を借りて死ぬ
HeroでsubtractLife()減命、clearFire()クリア火力値を設計
2)敵と英雄機の衝突がタイミングで発生するのでrun()でheroBangAction()を呼び出して敵と英雄機の衝突を実現する
heroBangActionでは、次のようになります.
敵の敵を遍歴して、もしすべて生きていると判断してぶつかった.
敵は死んで、英雄機は命を減らして、英雄機は火力値をクリアします
15.ゲーム終了の検出:
1)HeroのgetLife()で命数を取得する
2)検出ゲーム終了がタイミングで発生するのでrun()でcheckGameOverAction()を呼び出してゲーム終了を検出する
checkGameOverAction()で:
英雄機の命数<=0でゲーム終了を表すと判断すると…
16.描画状態:
1)Worldで4つの状態定数を設計し、同時にstate変数を設計して現在の状態を表し、デフォルトはSTART(起動状態)である.
Imagesでstart、pause、gameoverの3つの状態ピクチャを設計し、staticブロックに値を割り当てる
Worldクラスのpaint()では異なる状態で異なる画像を描くように設計されています
2)run()におけるactionの山を設計し,運転状態時のみ実行する
デザインヒーターはマウスの動きに合わせて、動作状態のみで実行されます.
3)mouseClicked()を書き換えるマウスクリック:起動状態は運転状態になり、ゲーム終了状態は現場を片付けてから起動状態になる
mouseExited()マウスの書き換え:運転状態が一時停止状態になります
mouseEntered()を書き換えるマウスの移動:一時停止状態から実行状態へ
(注:毎回の機能の実現は絶えずテストしてデバッグして、間違いを防ぐ.)
コード実装:
FlyingObject:
package cn.tedu.shoot;
import java.awt.image.BufferedImage;
import java.util.Random;

/**   */
public abstract class FlyingObject {
	public static final int LIFE = 0;  //   
	public static final int DEAD = 1;  //   
	public static final int REMOVE = 2; //   
	protected int state = LIFE;//    (      
	
	protected int width;// 
	protected int height;// 
	protected int x;     //x   
	protected int y;     //y   
	
	/**       ,   ,       */
	public FlyingObject(int width,int height){// 2         width  height    
		this.width=width;
		this.height=height;
		Random rand =new Random();//     
		x =rand.nextInt(World.WIDTH-width);//0 (   -   )    
		y=-height;//       
		
	}
	
	/**       ,    ,    */
	public FlyingObject(int width,int height,int x,int y){//          width,height,x,y    
		this.width=width;
		this.height=height;
		this.x=x;
		this.y=y;
		
	}
	/**     */
	public abstract void step();
	
	/**          */
	public abstract BufferedImage getImage();
	//             
	
	/**        */
	public boolean isLife(){	
		return state ==LIFE;//     LIFE,          true   false
	}
	
	/**         */
	public boolean isDead(){	
		return state ==DEAD;//     DEAD,          true   false
	}
	
	/**         */
	public boolean isRemove(){	
		return state ==REMOVE;//     REMOVE,          true   false
	}
	
	/**        */
	public boolean outOfBounds(){
		return this.y>= World.HEIGHT;//   y               
	}
	
	/**           /      this:    other :  /   */
	public boolean hit(FlyingObject other){
		int x1 = this.x - other.width;//x1:   x-   /     
		int x2 = this.x + this.width; //x2:    x+   width
		int y1 = this.y - other.height;//y1:    y -   /     
		int y2 = this.y + this.height;// y2:     y +     
		int x = other.x;
		int y = other.y;
		// x x1   x2      y y1 y2         
		return x>=x1 && x<=x2 && y>=y1 &&y<=y2;
	}
	
	/**     */
	public void goDead(){
		state = DEAD;//         DEAD 
	}
	
}

Airplane:
package cn.tedu.shoot;

import java.awt.image.BufferedImage;

/**         ,    */
public class Airplane extends FlyingObject implements Enemy{
	
	private int speed;//    
	
	/**    */ //Airplane a=new Airplane
	public Airplane(){
		super(48,50);
		speed=2;
	}
	
	/**   step()   */
	public void step(){
		y+=speed;
	}

	private int index=1;//      
	/**   getImage()       */
	public  BufferedImage getImage(){// 10     
		if(isLife()){//   
			return Images.airs[0];//  airs     
		}else if(isDead()){//   
			BufferedImage img = Images.airs[index++];
			if(index==Images.airs.length){
				state = REMOVE;
			}
			return img;
			/*
			 * index= 1;
			 * 10M airs[1] index=2   airs[1]
			 * 20M airs[2] index=3   airs[2]
			 * 30M airs[3] index=4;  airs[3]
			 * 40M airs[4] index=5(REMOVE)   airs[4]
			 * 50M    REMOVE   ,    isDead()   ,    null 
			 */
		}
		return null;//     ,     
	}
	
	/**  getScore()    */
	public int getScore(){
		return 1;//     ,   1 ;
	}

}

BigAirplane
package cn.tedu.shoot;

import java.awt.image.BufferedImage;

/**         ,    */
public class BigAirplane extends FlyingObject implements Enemy{
	
	private int speed;//     
	
	/**    */
	public BigAirplane(){
		super(66,89);
		speed=2;
	}
	
	/**   step()   */
	public void step(){
		y+=speed;//y+ (    
	}
	
	private int index=1;//      
	/**   getImage()       */
	public  BufferedImage getImage(){// 10     
		if(isLife()){//   
			return Images.bairs[0];//  bairs     
		}else if(isDead()){//   
			BufferedImage img = Images.bairs[index++];
			if(index==Images.bairs.length){
				state = REMOVE;
			}
			return img;
		}
		return null;//     ,     
	}
	
	/**  getScore()    */
	public int getScore(){
		return 3;//     ,   3 ;
	}
	
}

Bee:
package cn.tedu.shoot;

import java.awt.image.BufferedImage;
import java.util.Random;

/**         ,     */
public class Bee extends FlyingObject implements Award{
	
	private int xSpeed;//x      
	private int ySpeed;//y      
	private int awardType;//    
	
	/**    */
	public Bee(){
		super(60,51);
		xSpeed=1;
		ySpeed=2;
		Random rand =new Random();//     
		awardType=rand.nextInt(2);//0-1      
	}

	/**   step()   */
	public void step(){
		x+=xSpeed;//x+(    )
		y+=ySpeed;//y+    
		// x<=0     x>=   -    ,  
		if(x<=0||x>=World.WIDTH-this.width){
			xSpeed*=-1;//    (    ,   )
		}
	}
	
	private int index=1;//      
	/**   getImage()       */
	public  BufferedImage getImage(){// 10     
		if(isLife()){//   
			return Images.bees[0];//  airs     
		}else if(isDead()){//   
			BufferedImage img = Images.bees[index++];
			if(index==Images.bees.length){
				state = REMOVE;
			}
			return img;
		}
		return null;//     ,     
	}
	
	/**  getAwardType()      */
	public int getAwardType(){
		return awardType;//      
	}
	
}

Hero:
package cn.tedu.shoot;

import java.awt.image.BufferedImage;

/**   :    */
public class Hero extends FlyingObject {
	
	private int life;//  
	private int fire;//   
	
	/**    */
	public Hero(){
		super(97,139,140,400);
		life=3;
		fire=0;
	}
	
	/**   step()   */
	public void step(){
		
	}
	
	private int index=0;
	/**  getImage  */
	public BufferedImage getImage(){
		if(isLife()){//   
			return Images.heros[index++%Images.heros.length];//heros[0] heros[1]        
		}                             //       
		return null;////          
	}
	
	
	/**       (      )*/
	public Bullet[] shoot(){	
		int xStep = this.width/4;//1/4     
		int yStep = 20; //  20
		if(fire>0){// 
			Bullet[] bs= new Bullet[2];//2   
			bs[0]= new Bullet(this.x+1*xStep,this.y-yStep);
			bs[1]= new Bullet(this.x+3*xStep,this.y-yStep);
			fire-=2;//              2
			return bs;
		}else{//    
			Bullet[] bs= new Bullet[1];//1   
			// x:    x+2/4       y:    y-  20
			bs[0]= new Bullet(this.x+2*xStep,this.y-yStep);
			return bs;
		}		
	}
	
	/**                   x/y      */
	public void  moveTo(int x,int y){
		this.x = x-this.width/2;//    x =   x- 1/2     
		this.y = y-this.height/2;////    y =   x- 1/2     
	}
	
	/**     */
	public void addLife(){
		life++;//   1
	}
	/**      */
	public int getLife(){
		return life;//   
	}
	/**     */
	public void subtractLife(){
		life--;//   1
	}
	/**       */
	public void addFire(){
		fire+=40;//    40
	}
	/***/
	public void clearFire(){
		fire=0;//    0
	}
	
}


Sky:
package cn.tedu.shoot;
/**        */

import java.awt.Image;
import java.awt.image.BufferedImage;
public class Sky extends FlyingObject{
      //    
	
	private int speed;//    
	private int y1;//      y  
	
	/**    */
	public Sky(){
		super(World.WIDTH,World.HEIGHT,0,0);
		speed=1;
		y1=-World.HEIGHT;
		
	}
	
	/**   step()   */
	public void step(){
		y+=speed;//y+  
		y1+=speed;//y1+  
		if(y>=World.HEIGHT){//y>=   ,      
			y=-World.HEIGHT;//   y       (      )
		}
		if(y1>=World.HEIGHT){//y1>=   ,      
			y1=-World.HEIGHT;//   y1       (      )
		}
	}
	
	/**   getImage()       */
	public  BufferedImage getImage(){
		return Images.sky;
	}
	
	/**    y1  */
	public int getY1(){
		return y1;//  y1  
	}
}

Bullet: 
package cn.tedu.shoot;

import java.awt.image.BufferedImage;

/**        */
public class Bullet extends FlyingObject {
	
	private int speed;//    
	
	/**     */
	public Bullet(int x,int y){//Bullet b=new Bullet(100,200);
		super(8,20,x,y);
		speed=3;
	}

	/**   step()   */
	public void step(){
		y-=speed;//y- (    
	}
	/**   getImage()       */
	public  BufferedImage getImage(){
		if(isLife()){
			return Images.bullet;//  
		}else if(isDead()){
			state=REMOVE;//   
		}
		return null;
	}
	
	/**  outofBounds()--        */
	public boolean outOfBounds(){
		return this.y<= - this.height;//   y               
	}
	
}

Images:
package cn.tedu.shoot;
import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;
/**	     */
public class Images {
   //                       
	public static BufferedImage sky;//    
	public static BufferedImage bullet;//    
	public static BufferedImage[] heros;//    
	public static BufferedImage[] airs;//     
	public static BufferedImage[] bairs;//     
	public static BufferedImage[] bees;//     
	
	public static BufferedImage start;//   
	public static BufferedImage pause;//   
	public static BufferedImage gameover;//     
	
	static{//       
		sky = readImage("background.png");
		bullet = readImage("bullet.png");
		heros =new BufferedImage[2];//    
		heros[0]=readImage("hero0.png");
		heros[1]=readImage("hero1.png");
		
		airs=new BufferedImage[5];
		bairs=new BufferedImage[5];
		bees=new BufferedImage[5];
		
		airs[0]=readImage("airplane1.png");
		bairs[0]=readImage("bigairplane1.png");
		bees[0]=readImage("bee1.png");
		for(int i=1;i

Award:
package cn.tedu.shoot;
/**    */
public interface Award {
	public int FIRE = 0;//       ..  public static final int FIRE
	public int LIFE = 1;//    ..  public static final int LIFE
	
	/**      (0  1)*/
	public int getAwardType();
}

Enemy:
package cn.tedu.shoot;
/**    */
public interface Enemy {
	/**    */
	public int getScore();
}

World:
package cn.tedu.shoot;
import java.awt.event.MouseAdapter;//   
import java.awt.event.MouseEvent;
import javax.swing.JFrame;//  
import javax.swing.JPanel;//  
import java.awt.Graphics;//  
import java.util.Random;
import java.util.Arrays;
import java.util.Timer;//   
import java.util.TimerTask;//    
/**      */
public class World extends JPanel{//       
	/**               */
	public static final int WIDTH=400;//   
	public static final int HEIGHT=700;//   
	
	public static final int START = 0;  //    
	public static final int RUNNING =1; //    
	public static final int PAUSE = 2;  //    
	public static final int GAME_OVER = 3;//      
	private int state = START;//    
	
	/**               */
	private Sky sky=new Sky();//    
	private Hero hero=new Hero();//     
	private FlyingObject[] enemies={};//  (   ,   ,   )  
	private Bullet[] bullets={};//    
	
	/**    (           )  */
	public FlyingObject nextOne(){
		Random rand = new Random();//    
		int type = rand.nextInt(20);//0-19
		if(type<5){//0-4        
			return new Bee();
		}else if(type<12){//5-11     
			return new Airplane();
		}else{//12 19     
			return new BigAirplane();
		}
	}
	//    ,      ,     .
	
	private int enterIndex= 0;
	/**  (           )  */
	public void enterAction(){// 10     
		enterIndex++;// 10   1
		if(enterIndex%40==0){// 400(40*10)     
			FlyingObject obj = nextOne();//      
			enemies = Arrays.copyOf(enemies, enemies.length+1);//  
			enemies[enemies.length-1] = obj;//               
		}
	}
	
	private int shootIndex=0;
	/**    */
	public void shootAction(){// 10     
		shootIndex++;// 10   1
		if(shootIndex%30==0){// 300(30*10)     
			Bullet[] bs=hero.shoot();//              
			bullets = Arrays.copyOf(bullets, bullets.length+bs.length);//  (bs           )
			System.arraycopy(bs,0,bullets,bullets.length-bs.length,bs.length);//     			
		}
	}
	
	/**     */
	public void stepAction(){// 10  
		sky.step();//   
		for(int i=0;i

 
 
 
 
 
 
 
 
: