1. 程式人生 > >Java學習二(飛機大戰項目)day09

Java學習二(飛機大戰項目)day09

h+ remove color 匿名 ktr day graphic score ride

day09

1.子彈與敵人的碰撞
    1)在超類中FlyingObject設計hit()實現敵人與子彈/英雄機得碰撞

    /** 成員方法:檢測敵人與子彈/英雄機的碰撞
     *  this:敵人    other:子彈 */
    public boolean hit(FlyingObject other) {
        int x1 = this.x - other.width;
        int x2 = this.x + this.width;        
        int y1 = this.y - other.height;    
        int y2 = this.y + this.height;    
        int x = other.x;                                
        int y = other.y;                                
        return x>=x1 && x<=x2 && y>=y1 && y<=y2;    
    }

    在超類中FlyingObject設計goDead()實現飛行物去死的

    /** 成員方法:飛行物去死 */
    public void goDead() {
        state = DEAD;    //將當前狀態修改為DEAD
    }
import java.util.Random;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.awt.Graphics;
/**
 * 飛行物--超類
 * @author soft01
 */
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; /** 成員變量:寬、高、x軸、y軸 */ protected int width; protected int height; protected int x; protected int y; /** 構造方法:專門給英雄機、天空、子彈用
*/ public FlyingObject(int width,int height,int x,int y) { this.width = width; this.height = height; this.x = x; this.y = y; } /** 構造方法:專門給小敵機、大敵機、小蜜蜂用 */ public FlyingObject(int width,int height) { this.width = width; this.height = height; Random rand = new Random(); x = rand.nextInt(World.WIDTH-width); y = -height; } /** 抽象方法:飛行物移動 */ public abstract void step(); /** 抽象方法:獲取圖片 */ public abstract BufferedImage getImage(); /** 抽象方法:檢查飛行物是否越界 */ public abstract boolean outOfBounds(); /** 靜態方法:讀取圖片 */ public static BufferedImage loadImage(String fileName) { try { BufferedImage img = ImageIO.read(FlyingObject.class.getResource(fileName)); //同包中讀圖片 return img; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(); } } /** 成員方法:判斷狀態(活著的、死了的、刪除的) */ public boolean isLife() { return state == LIFE; } public boolean isDead() { return state == DEAD; } public boolean isRemove() { return state == REMOVE; } /** 成員方法:畫對象的 g:畫筆 */ public void paintObject(Graphics g) { g.drawImage(getImage(),x,y,null); } /** 成員方法:檢測敵人與子彈/英雄機的碰撞 * this:敵人 other:子彈 */ public boolean hit(FlyingObject other) { int x1 = this.x - other.width; //敵人的x - 子彈/英雄機的寬 int x2 = this.x + this.width; //敵人的x + 敵人的寬 int y1 = this.y - other.height; //敵人的y - 子彈/英雄機的高 int y2 = this.y + this.height; //敵人的y + 敵人的高 int x = other.x; //子彈/英雄機的x int y = other.y; //子彈/英雄機的y return x>=x1 && x<=x2 && y>=y1 && y<=y2; //x在x1和x2之間,y在y1和y2之間 } /** 成員方法:飛行物去死 */ public void goDead() { state = DEAD; //將當前狀態修改為DEAD } }


    在Hero類中設計addLife()增命、addDoubleFire()增火力

    /**    成員方法:命數增加    */
    public void addLife() {
        life++;    //命數增1
    }
    
    /**    成員方法:火力值增加        */
    public void addDoubleFire() {
        doubleFire += 40;        //火力值增40
    }
import java.awt.image.BufferedImage;

/**
 * 英雄機
 * @author soft01
 */
public class Hero extends FlyingObject{
    /** 靜態變量:英雄機圖片    */
    private static BufferedImage[] images;
    static {
        images = new BufferedImage[2];
        for (int i = 0; i < images.length; i++) {
            images[i] = loadImage("hero" + i + ".png");
        }
    }
    
    /**    成員變量:生命、火力值    */
    private int life;        //生命
    private int doubleFire;        //火力值
    
    /**    構造方法    */
    public Hero(){
        super(97,124,140,400);
        life = 3;
        doubleFire = 0;
    }
    
    /**    成員方法:命數增加    */
    public void addLife() {
        life++;    //命數增1
    }
    
    /**    成員方法:獲取命數    */
    public int getLife() {
        return life;    //返回命
    }
    
    /**    成員方法:火力值增加        */
    public void addDoubleFire() {
        doubleFire += 40;        //火力值增40
    }
    
    /**    成員方法:英雄機移動        */
    public void step() {}
    
    /**    成員方法:英雄機隨鼠標移動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=鼠標的y-1/2英雄機的高
    }
    
    /**    成員方法:獲取圖片    */
    int index = 0;
    @Override
    public BufferedImage getImage() {
        if(isLife()) {
            return images[index++%2];        //(index++%2)余數為0或1
        }
        return null;
    }
    
    /**    成員方法:英雄機發射子彈(創建子彈對象)    */
    public Bullet[] shoot() {
        int xStep = this.width/4;    //xStep:1/4英雄機的寬
        int yStep = 20;            //yStep:固定的20
        if (doubleFire > 0) {        //
            Bullet[] bs = new Bullet[2];        //2發子彈
            //英雄機的x坐標加1/4英雄機的寬
        bs[0] = new Bullet(this.x + 1 * xStep,y-yStep);    
            //英雄機的x坐標加3/4英雄機的寬
        bs[1] = new Bullet(this.x + 3 * xStep, y-yStep);    
            doubleFire -= 2;    //發射一次雙倍火力,火力值減2
            return bs;
        } else {                    //
            Bullet[] bs = new Bullet[1];        //1發子彈
        //英雄機的x坐標加2/4英雄機的寬
        bs[0] = new Bullet(this.x + 2 * xStep, y-yStep);    
            return bs;
        }
    }
    
    /**    成員方法:英雄機永不越界    */
    @Override
    public boolean outOfBounds() {
        return false;
    }
}

  2)子彈與敵人的碰撞為定時發生的,所以在run()中調用BulletBangAction()方法
在BulletBangAction()中:
遍歷所有子彈,獲取每一個子彈,遍歷所有敵人,獲取每個敵人
判斷是否撞上了,若撞上了:
    1)子彈去死,敵人去死
    2)小敵機和大敵機 ----------得分
       小蜜蜂 ----------------英雄機得命或雙倍火力

/** 成員方法:子彈與敵人的碰撞 */
int score = 0;
public void bulletBangAction() {    //每10個毫秒走一次
    //遍歷子彈數組        
    for (int i = 0; i < bullets.length; i++) {    
        Bullet b = bullets[i];//得到每一個子彈
        //遍歷敵人數組
        for (int j = 0; j < enemies.length; j++) {    
            FlyingObject f = enemies[j];    //得到每一個敵人
            //如果活著的子彈和活著的敵人撞上了
            if(b.isLife() && f.isLife() && f.hit(b)) {        
                b.goDead();            //子彈去死
                f.goDead();            //敵人去死            
                if (f instanceof Enemy) {//若被撞對象是敵人
                    Enemy e = (Enemy)f;//強轉為得分接口        
                    score += e.getScore();//玩家得分
                }
                if (f instanceof Award) {//若被撞對象是獎勵
                  Award a = (Award)f;//    強轉為獎勵接口
                  int type = a.getType();//獲取獎勵類型                      //基於不同的類型來得到不同的獎勵
                  switch (type) {
                  //若獎勵為火力值                
                  case Award.DOUBLE_FIRE:
                    hero.addDoubleFire();    //則增加火力值        
                    break;
                    case Award.LIFE:        //若獎勵為命        
                    hero.addLife();        //則增加命        
                    break;                                              }
                }
            }
        }
    }
}


2.畫分和畫命
    1)在Hero類中設計getLife()獲取命

    /**    成員方法:獲取命數    */
    public int getLife() {
        return life;    //返回命
    }

    2)在paint()方法中,畫分和畫命

    g.drawString("SCORE:" + score,10,25);
    g.drawString("LIFE:" + hero.getLife(), 10, 45);

import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Random;
import java.util.Arrays;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;;

/**
 * 整個世界
 * @author soft01
 */
public class World extends JPanel{
    /** 常量:窗口寬、窗口高 */
    public static final int WIDTH = 400;
    public static final int HEIGHT = 700;

    /**    成員變量:天空、英雄機、飛行物敵人數組、子彈數組    */
    private Sky sky = new Sky();                            
    private Hero hero = new Hero();                        
    private FlyingObject[] enemies = {};
    private Bullet[] bullets = {};        
    
    /**    啟動程序的執行    */
    public void action() {
        Timer timer = new Timer();                                    //創建定時器對象
        int interval = 10;                                                //定時間隔(以毫秒為單位)
        timer.schedule(new TimerTask() {                        //匿名內部類
            @Override
            public void run() {                                            //定時幹的事(每10個毫秒走一次)
                enterAction();                                                //敵人入場,子彈入場,飛行物移動
                shootAction();                                                //子彈入場,英雄機發射子彈
                stepAction();                                                    //飛行物入場
                outOfBoundsAction();                                    //刪除越界
                bulletBangAction();                                        //子彈與敵人的碰撞
                repaint();                                                     //重畫(重新調用paint()方法)
            }
        },interval,interval);                                            //定時計劃
        
        /** 鼠標偵聽器 */
        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);    //處理鼠標滑動事件
    }
    
    
    /** 成員方法:生成敵人(小敵機、大敵機、小蜜蜂)對象 */
    public FlyingObject nextOne() {
        Random rand = new Random();    //隨機數對象
        int type = rand.nextInt(20);    //0~19之間的數
        if (type < 11) {                            //0~7返回小敵機
            return new Airplane();
        } else if(type < 17){                //8~15返回小敵機
            return new BigAirplane();
        } else {                                        //16~19返回小敵機
            return new Bee();
        }
    }
    
    /** 成員方法:敵人(小敵機、大敵機、小蜜蜂)入場 */
    int enterIndex = 0;                            //敵人入場計數
    public void enterAction() {            //每10個毫秒走一次
        enterIndex++;                                    //每10毫秒增1
        if(enterIndex%40 == 0) {            //每400(10*40)毫秒走一次
            FlyingObject obj = nextOne();
            enemies = Arrays.copyOf(enemies, enemies.length+1);    //數組擴容
            enemies[enemies.length-1] = obj;                //將敵人對象填充到enemies數組的最後一個元素上
        }
    }
    
    /** 成員方法:子彈入場,英雄機發射子彈 */
    int shootIndex = 0;                            //子彈入場計數
    public void shootAction() {            //每10個毫秒走一次
        shootIndex++;                                    //每10毫秒增1
        if(shootIndex%20 == 0) {            //每300(10*30)毫秒走一次
            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() {
        sky.step();                    //天空移動
        for (int i = 0; i < enemies.length; i++) {
            enemies[i].step();    //飛行物移動
        }
        for (int i = 0; i < bullets.length; i++) {
            bullets[i].step();    //子彈移動
        }
    }
    
    /** 成員方法:刪除越界 */
    public void outOfBoundsAction() {    //每10個毫秒走一次
        int index = 0;        //1)不越界敵人下標    2)不越界敵人個數
        FlyingObject[] enemyLives = new FlyingObject[enemies.length];     //不越界敵人數組
        for (int i = 0; i < enemies.length; i++) {    //獲取敵人數組
            FlyingObject f = enemies[i];        //獲取每一個敵人
            if(!f.outOfBounds()) {    //不越界
                enemyLives[index] = f;    //將不越界敵人放到不越界數組中
                index++;        //1)不越界敵人數組下標增一        2)不越界敵人個數增1
            }
        }
        enemies = Arrays.copyOf(enemyLives, index);    //將不越界數組中的元素復制到敵人數組之中,數組的長度為index
        
        index = 0;
        Bullet[] bulletLives = new Bullet[bullets.length];
        for (int i = 0; i < bullets.length; i++) {
            Bullet b = bullets[i];
            if(!b.outOfBounds()) {
                bulletLives[index] = b;
                index++;
            }
        }
        bullets = Arrays.copyOf(bulletLives, index);
    }
    
    /** 成員方法:子彈與敵人的碰撞 */
    int score = 0;
    public void bulletBangAction() {                                        //每10個毫秒走一次
        for (int i = 0; i < bullets.length; i++) {                //遍歷子彈數組
            Bullet b = bullets[i];                                                //得到每一個子彈
            for (int j = 0; j < enemies.length; j++) {            //遍歷敵人數組
                FlyingObject f = enemies[j];                                    //得到每一個敵人
                if(b.isLife() && f.isLife() && f.hit(b)) {        //如果活著的子彈和活著的敵人撞上了
                    b.goDead();                                                            //子彈去死
                    f.goDead();                                                            //敵人去死                
                    if (f instanceof Enemy) {                                    //若被撞對象是敵人
                        Enemy e = (Enemy)f;                                            //強轉為得分接口
                        score += e.getScore();                                    //玩家得分
                    }
                    if (f instanceof Award) {                                    //    若被撞對象是獎勵
                        Award a = (Award)f;                                            //    強轉為獎勵接口
                        int type = a.getType();                                    //獲取獎勵類型
                        switch (type) {                                                    //基於不同的類型來得到不同的獎勵
                        case Award.DOUBLE_FIRE:                                    //若獎勵為火力值
                            hero.addDoubleFire();                                    //則增加火力值
                            break;
                        case Award.LIFE:                                                //若獎勵為命
                            hero.addLife();                                                //則增加命
                            break;                                                                
                        }
                    }
                }
            }
        }
    }
    
    
    /** 成員方法:paint()方法 */
    @Override
    public void paint(Graphics g) {
        sky.paintObject(g);                                                //畫天空
        hero.paintObject(g);                                            //畫英雄機
        for (int i = 0; i < enemies.length; i++) {    //遍歷所有敵人
            enemies[i].paintObject(g);                                //畫敵對飛行物
        }
        for (int i = 0; i < bullets.length; i++) {    //遍歷子彈
            bullets[i].paintObject(g);                                //畫子彈
        }
        g.drawString("SCORE:" + score,10,25);
        g.drawString("LIFE:" + hero.getLife(), 10, 45);
    }
    
    /** main主方法 */
    public static void main(String[] args) {
        JFrame frame = new JFrame();                                                    //創建窗口
        World world = new World();                                                        //創建面板
        frame.add(world);                                                                        //將面板添加到窗口
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //設置關閉窗口即停止運行程序
        frame.setSize(WIDTH,HEIGHT);                                                    //設置窗口大小
        frame.setLocationRelativeTo(null);                                     //設置窗口居中顯示
        frame.setVisible(true);                                                         //1)設置窗口可見        2)盡快調用paint()方法
        
        world.action();                                                                            //啟動程序
    }

}

 

Java學習二(飛機大戰項目)day09