1. 程式人生 > >java版簡易飛機大戰

java版簡易飛機大戰

Java版飛機大戰

適合初學者的一個簡單的飛機大戰專案用於理解深入理解面向物件,直接開始

1.依次建立好每個類和介面

  • 飛行物類(class FlyingObject)

    package com.loveoyh.shoot;
    
    import java.awt.image.BufferedImage;
    
    /**
     * 飛行物類
     * @author HP
     *
     */
    public class FlyingObject {
    	protected BufferedImage image;//圖片
    	protected int width;  //圖片的寬
    	protected int height; //圖片的高
    protected int x; //圖片左上角的x座標 protected int y; //圖片左上角的y座標 }
  • 敵機得分介面(interface Enemy)

    package com.loveoyh.shoot;
    /**
     * 得分
     * @author HP
     *
     */
    public interface Enemy {
    	/**
    	 * 擊敗敵機獲得分
    	 * @return
    	 */
    	public int getScore();
    }
    
    
  • 獎勵介面(interface Award)

    package com.loveoyh.shoot;
    /**
     * 獎勵
     * @author HP
     *
     */
    public interface Award { public static final int DOUBLE_FIRE = 0;//火力值 public static final int LIFE = 1; //命 /** 獲取獎勵型別(上面的0或1) */ public abstract int getType(); }
  • 敵機:是飛行物,也是敵人所以繼承飛行物類實現得分介面(class Airplane extends FlyingObject implements Enemy)

    package com.loveoyh.shoot;
    import java.util.Random;
    /** * 敵機:是飛行物,也是敵人 */ public class Airplane extends FlyingObject implements Enemy{ public Airplane(){ image = ShootGame.airplane;//圖片 width = image.getWidth(); //寬 height = image.getHeight();//高 Random rand = new Random();//隨機數數的產生 x = rand.nextInt(ShootGame.WIDTH - this.width);//敵機的寬 y = -this.height; } /** 重寫getScore()得分 */ public int getScore(){ return 5;//一個敵機得5分 } }
  • 小蜜蜂: 是飛行物,也是獎勵 繼承飛行物類實現獎勵介面(class Bee extends FlyingObject implements Enemy)

    package com.loveoyh.shoot;
    
    import java.util.Random;
    
    /** 
     * 小蜜蜂: 是飛行物,也是獎勵 
     */
    public class Bee extends FlyingObject implements Award{
    	private int awardType; //獎勵的型別
    	
    	/** 構造方法 */
    	public Bee(){
    		image = ShootGame.bee;//圖片
    		width = image.getWidth();  //寬
    		height = image.getHeight();//高
    		Random rand = new Random();//隨機數數的產生
    		x = rand.nextInt(ShootGame.WIDTH - this.width);//蜜蜂的寬
    		y = -this.height;//y:負的為蜜蜂的高
    		awardType = rand.nextInt(2);//0到1的隨機數
    	}
    	
    	/** 重寫getType()獲取獎勵型別 */
    	public int getType(){
    		return awardType;//返回獎勵型別
    	}
    }
    
  • 子彈:是飛行物 繼承飛行物類(class Bullet extends FlyingObject)

    package com.loveoyh.shoot;
    
    import java.util.Random;
    
    /** 子彈:是飛行物 */
    public class Bullet extends FlyingObject{
    	/** 構造方法 */
    	Bullet(int x,int y){
    		image = ShootGame.bullet;//圖片
    		width = image.getWidth();  //寬
    		height = image.getHeight();//高
    		this.x = x; //隨著英雄機座標而得到的x
    		this.y = y; //隨著英雄機座標而得到的y
    	}
    }
    
  • 英雄機類: 是飛行物 繼承飛行物類(class Hero extends FlyingObject)

    package com.loveoyh.shoot;
    /** 
     * 英雄機:是飛行物 
     */
    import java.awt.image.BufferedImage;
    public class Hero extends FlyingObject{
    	private int doubleFire;//火力值
    	private int life;      //命
    	private BufferedImage[] images = {};//圖片陣列
    	private int index;                  //協助圖片切換
    	
    	/** 構造方法 */
    	Hero(){
    		image = ShootGame.hero0;//圖片
    		width = image.getWidth();  //寬
    		height = image.getHeight();//高
    		x = 150;//固定的x座標
    		y = 400;//固定的y座標
    		doubleFire = 0;//預設為0(單倍火力)
    		life =3;       //預設為3
    		images = new BufferedImage[]{ShootGame.hero0,ShootGame.hero1};//兩張圖片
    		index = 0;//協助切換(預設為0)
    	}
    }
    
  • 主程式類

    ​ 注:這裡主要使用了swing裡面的東西,在註釋裡也寫的很清楚他的作用,這些東西不用記,以後也用的很少,我們這個專案只是更好的對java面向物件的理解

    package com.loveoyh.shoot;
    /** 主程式類 */
    import java.awt.image.BufferedImage;
    import javax.imageio.ImageIO;
    import javax.swing.JFrame;//視窗
    import javax.swing.JPanel;//面板
    import java.awt.Graphics;
    
    public class ShootGame extends JPanel{//當作面板
    	public static final int WIDTH = 400; //視窗的寬
    	public static final int HEIGHT= 645;//視窗的高
    	public static BufferedImage background;  //背景圖
    	public static BufferedImage airplane;   //敵機圖
    	public static BufferedImage bee;        //蜜蜂圖
    	public static BufferedImage bullet;     //子彈圖
    	public static BufferedImage gameover;   //遊戲結束圖
    	public static BufferedImage hero0;      //英雄機0
    	public static BufferedImage hero1;      //英雄機1
    	public static BufferedImage pause;      //暫替圖
    	public static BufferedImage start;      //啟動圖
    	
    	static{//載入初始化靜態圖片
    		try{
    			background = /**read()靜態方法類名點訪問*/ImageIO.read(ShootGame.class.getResource("background.png"));//讀圖片
    			airplane = ImageIO.read(ShootGame.class.getResource("airplane.png"));
    			bee = ImageIO.read(ShootGame.class.getResource("bee.png"));
    			bullet = ImageIO.read(ShootGame.class.getResource("bullet.png"));
    			gameover = ImageIO.read(ShootGame.class.getResource("gameover.png"));
    			hero0 = ImageIO.read(ShootGame.class.getResource("hero0.png"));
    			hero1 = ImageIO.read(ShootGame.class.getResource("hero1.png"));
    			pause = ImageIO.read(ShootGame.class.getResource("pause.png"));
    			start = ImageIO.read(ShootGame.class.getResource("start.png"));
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    	}
    	
    	private Hero hero = new Hero();//一個英雄機物件
    	private FlyingObject[] flyings = {};//飛行物陣列
    	private Bullet[] bullets = {};//子彈陣列
    	
    	
        /** 
         * 重寫paint() g:畫筆 
         */
    	public void paint(Graphics g){
    		g.drawImage(background,0,0,null);//畫背景圖
    		paintHero(g);                    //畫敵機
    		paintFlyingObjects(g);           //敵人物件
    		paintBullets(g);                 //畫子彈物件
    	}
    	/** 
    	 * 畫英雄機物件 
    	 */
    	public void paintHero(Graphics g){
    		g.drawImage(hero.image,hero.x,hero.y,null);
    	}
    	/** 
    	 * 畫敵人(敵機+小蜜蜂)物件
    	 */
    	public void paintFlyingObjects(Graphics g){
    		for(int i=0;i<flyings.length;i++){
    			FlyingObject f = flyings[i];
    			g.drawImage(f.image,f.x,f.y,null);
    		}
    	}
    	/** 
    	 * 畫子彈物件
    	 */
    	public void paintBullets(Graphics g){
    		for(int i=0;i<bullets.length;i++){
    			Bullet b = bullets[i];
    			g.drawImage(b.image,b.x,b.y,null);
    		}
    	}
    	/** 
    	 * 主函式 
    	 */
    	public static void main(String[] args) {
    		JFrame frame = new JFrame("Fly");//
    		ShootGame game = new ShootGame();//
    		frame.add(game);//將面板新增到視窗中
    		
    		frame.setSize(WIDTH,HEIGHT);//設定視窗的大小
    		frame.setAlwaysOnTop(true); //設定一直在最上面
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設定預設關閉操作,視窗關閉時程式結束
    		frame.setLocationRelativeTo(null);//設定視窗居中顯示
    		frame.setVisible(true);//1、設定視窗可見  2、自動儘快調paint()方法
    	}
    }
    

我們基本的框架搭建好了,接下來就是往框架上新增修飾

2.實現具體的方法

  • 實現敵機入場

    • 在main方法的最後裡新增 game.action();

    • 在paint()方法上面新增方法action()如下

      注:此處利用到了定時器java.util.Timer

      	/** 
      	 * 程式啟動執行 
      	 */
      	public void action(){
      		Timer timer = new Timer();//定時器物件
      		int intervel = 10;//時間間隔(以毫秒為單位)
      		timer.schedule(new TimerTask(){//定時計劃日程
      			public void run(){//每10毫秒走一次
      				enterAction();//敵人入場
      				repaint();//重複呼叫paint();
      			}
      		},intervel,intervel);
      	}
      
    • 定義enterAction()方法,就在action()方法上面定義

      	/** 
      	 * 敵人物件
      	 */
      	public FlyingObject nextOne(){
      		Random rand = new Random();
      		int type = rand.nextInt(20);
      		if(type<5){
      			return new Bee();
      		}else{
      			return new Airplane();
      		}
      	}
      	
      	int flyEnteredIndex = 0;
      	/** 
      	 * 敵人入場 
      	 */
      	public void enterAction(){
      		flyEnteredIndex++;
      		if(flyEnteredIndex%40==0){
      			FlyingObject obj = nextOne();
      			flyings = Arrays.copyOf(flyings, flyings.length+1);
      			flyings[flyings.length-1] = obj;
      		}
      	}
      
  • 飛行物走步的實現

    • 在FlyingObject類中新增step()方法並宣告為abstract,並將類宣告為abstract,Airplane,Bee,Bullet,Hero—重寫step().注意的是英雄級的step()方法時切換圖片展現出動態效果

    • 然後在主程式類中呼叫這些step()方法來達到效果,在action()方法上面新增一下程式碼

      	/** 
      	 * 飛行物走一步 
      	 */
      	public void stepAction(){//10毫秒走一次
      		hero.step();
      		for(int i=0;i<flyings.length;i++){//遍歷所有敵人
      			flyings[i].step();//敵人走一步
      		}
      		for(int i=0;i<bullets.length;i++){//遍歷所有子彈
      			bullets[i].step();//子彈走一步
      		}
      	}
      
    • 然後將方法stepAction()新增到action()方法中

  • 子彈入場的實現

    • 在Hero類中新增shoot()方法英雄機發射子彈

      	/** 
      	 * 英雄機發射子彈 生成子彈 
      	 */
      	public Bullet[] shoot(){
      		int xStep = this.width/4;//1/4英雄機的寬
      		int yStep = 20;//固定的y值
      		if(doubleFire>0){//雙倍
      			Bullet[] bs = new Bullet[2];
      			bs[0] = new Bullet(this.x+1*xStep,this.y-yStep);
      			bs[1] = new Bullet(this.x+3*xStep,this.y-yStep);
      			doubleFire -= 2;
      			return bs;
      		}else{//單倍
      			Bullet[] bs = new Bullet[1];
      			bs[0] = new Bullet(this.x+2*xStep,this.y-yStep);
      			return bs;
      		}
      	}
      
    • 在action()方法上面定義shootAction()方法,並新增到action()方法中,和之前一樣的新增

      	int shootIndex = 0;//子彈入場計數
      	/** 
      	 * 子彈入場(英雄機發射子彈) 
      	 */
      	public void shootAction(){//10毫秒走一次
      		shootIndex++;//每10毫秒增加一次
      		if(shootIndex%30==0){//每300(10*30)毫秒走一次
      			Bullet[] bs = hero.shoot();//獲取子彈
      			bullets = Arrays.copyOf(bullets,bullets.length+bs.length);//擴容
      			System.arraycopy(bs, 0, bullets, bullets.length-bs.length, bs.length);//陣列的追加
      		}
      	}
      
  • 英雄機隨著滑鼠移動的實現

    • 在Hero類中新增moveTo方法

      /** 英雄機隨著滑鼠動  x:滑鼠的x座標   Y:滑鼠的y座標 */
      	public void moveTo(int x,int y){
      		this.x = x - this.width/2;//英雄機的x
      		this.y = y - this.height/2;//英雄機的y
      	}
      
    • 在主函式action()中新增如下程式碼

      public void action(){
      		//建立偵聽器物件
      		MouseAdapter l = new MouseAdapter(){
      			/** 處理mouseMoved()滑鼠移動事件 */
      			public void mouseMoved(MouseEvent e){
      				int x = e.getX();//獲取滑鼠的x座標
      				int y = e.getY();//獲取滑鼠的y座標
      				hero.moveTo(x, y);//英雄機隨著滑鼠動
      			}
      		};
      		this.addMouseListener(l);//處理滑鼠的操作事件
      		this.addMouseMotionListener(l);//處理滑鼠滑動事件
          
      		...
      	}
      
  • 刪除越界的敵人和子彈的實現

    • 同樣在FlyingObject類中新增抽象方法 abstract outOfBounds();

    • 子類Airplane,bee,bullet,Hero 重寫outOfBounds()

    • 主類中宣告定義outOfBoundsAction()方法並將方法新增到action()中的run()方法中

      	/** 
      	 * 刪除越界的飛行物 
      	 */
      	public void outOfBoundsAction(){//10毫秒
      		int index = 0;//1)不越界敵人陣列下標 2)不越界敵人個數
      		FlyingObject[] flyingLives = new FlyingObject[flyings.length];
      		for(int i=0;i<flyings.length;i++){          //遍歷所有飛行物
      			FlyingObject f = flyings[i];            //獲取每個敵人
      			if(!f.outOfBounds()){                   //若不越界
      				flyingLives[index] = f;             //將不越界的物件放到陣列flyingLives
      				index++;                            //1)不越界的陣列下標增加一 2)不越界敵人的個數增加一
      			}
      		}
      		flyings = Arrays.copyOf(flyingLives, index);//將不越界的敵人複製到flyings中,flyings的新長度為index,即不越界的敵人個數
      		index = 0;
      		Bullet[] bulletsLives = new Bullet[bullets.length];
      		for(int i=0;i<bullets.length;i++){
      			Bulle