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

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

strac pos rgs sched time ets 步驟 oca style

day07

功能實現的步驟:

1.先寫行為:
    1)若是某個對象特有的行為,則將設計在派生類中
        若是所有對象共有的行為,則將設計在超類中
      1.1)所有派生類行為都一樣,設計為普通方法
      1.2)所有派生類行為都不一樣,設計為抽象方法,而後派生類重寫

2.窗口調用:
    1)定時觸發的,在run()中調用
    2)事件觸發的,在監聽器中調用
    3)畫出來的,在paint()中調用

項目功能:
    
1.敵人入場 ---------- 定時發生
    1)創建敵人對象
    敵人對象 --------------- 是由窗口創建出來的
    ---創建敵人對象的行為 ----設計在窗口類World中設計nextOne()

    /** 成員方法:生成敵人(小敵機、大敵機、小蜜蜂)對象 */
    public FlyingObject nextOne() {
        Random rand = new Random();    //隨機數對象
        int type = rand.nextInt(20);    //0~19之間的數
        if (type < 8) {                //0~7返回小敵機
            return new Airplane();
        } else if(type < 16){            //8~15返回小敵機
            return new BigAirplane();
        } else {                        //16~19返回小敵機
            return new Bee();
        }
    }

    2)將對象添加到enemies數組中
    敵人入場為定時發生的,在run()中調用enterAction()實現敵人入場,
  在enterAction()中,每400毫秒調用nextOne()方法獲取敵人,enemies數組擴容,裝在最後一個元素上。 /** 成員方法:敵人(小敵機、大敵機、小蜜蜂)入場 */ 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[enemies.length-1] = obj; } }

2.子彈入場 ---------- 定時發生
    1)創建子彈對象
    子彈對象 --------------- 是由英雄機發射出來的
    ---創建子彈對象的行為 ----設計在英雄機類Hero中
    /**    成員方法:英雄機發射子彈(創建子彈對象)    */
    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;
        }
    }
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 step() {} /** 成員方法:英雄機隨鼠標移動 */ void moveTo(int x,int y) { } /** 成員方法:獲取圖片 */ 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; } } }

 2)將對象添加到bullets數組中
    子彈入場為定時發生的,在run()中調用shootAction()實現敵人入場,
  在shootAction()中,每300毫秒調用shoot()方法獲取子彈,bullets數組擴容,數組追加。 /** 成員方法:子彈入場,英雄機發射子彈 */ int shootIndex = 0; //子彈入場計數 public void shootAction() { //每10個毫秒走一次 shootIndex++; //每10毫秒增1 if(shootIndex%30 == 0) { //每300(10*30)毫秒走一次 //獲取英雄機發射出來的子彈對象 Bullet[] bs = hero.shoot(); //擴容(bs有幾個元素就擴大幾個) bullets = Arrays.copyOf(bullets,bullets.length+bs.length); //數組的追加 System.arraycopy(bs, 0, bullets,bullets.length - bs.length, bs.length); } } 3.飛行物移動 ---------- 定時發生 1)移動是所有對象所共有的行為,並且每個對象移動的行為都是不一樣的,
  所以在超類FlyingObject中設計了抽象方法step(), /** 抽象方法:飛行物移動 */ public abstract void step(); 派生類重寫step()方法 /** 成員方法:英雄機移動 */ public void step() {} /** 成員方法:小敵機移動 */ /** 成員方法:大敵機移動 */ public void step() { y += speed; //y+(向下) }
import java.awt.image.BufferedImage;

/**
 * 小敵機
 * @author soft01
 */
public class Airplane  extends FlyingObject{
    /** 靜態變量:小敵機圖片*/
    private static BufferedImage[] images;
    static {
        images = new BufferedImage[5];
        for (int i = 0; i < images.length; i++) {
            images[i] = loadImage("airplane" + i + ".png");
        }
    }
    
    /**    成員變量:移動速度    */
    private int speed;        //移動速度
    
    /**    構造方法    */
    public Airplane() {
        super(49,36);
        speed = 2;
    }
    
    /**    成員方法:小敵機移動        */
    public void step() {
        y += speed;    //y+(向下)
    }
    
    /**    成員方法:獲取圖片    */
    int index = 1;    //輪換圖片的起始位置
    @Override
    public BufferedImage getImage() {    //每10個毫秒輪換一次
        if(isLife()) {                    //若活著的
            return images[0];            //返回第一張圖
        } else if(isDead()) {        //若死了的
            BufferedImage img = images[index++];    //從第2張圖片到最後一張圖片輪換
            if (index == images.length) {    //如果是最後一張圖片時
                state = REMOVE;                //狀態改為刪除
            }    
            return img;                        //返回對應下標的圖片
        }
        return null;                        //死了的和刪除的,都返回null
    }
}
/**
 * 大敵機
 * @author soft01
 */
public class BigAirplane extends FlyingObject{
    /** 靜態變量:大敵機圖片*/
    private static BufferedImage[] images;
    static {
        images = new BufferedImage[2];
        for (int i = 0; i < images.length; i++) {
            images[i] = loadImage("bigplane" + i + ".png");
        }
    }
    
    /**    成員變量:移動速度    */
    private int speed;        //移動速度
    
    /**    構造方法    */
    public BigAirplane() {
        super(69,99);
        speed = 2;
    }
    
    /**    成員方法:大敵機移動        */
    @Override
    public void step() {
        y += speed;        //y+(向下)
    }
    
    /**    成員方法:獲取圖片    */
    int index = 1;    //輪換圖片的起始位置
    @Override
    public BufferedImage getImage() {    //每10個毫秒輪換一次
        if(isLife()) {                    //若活著的
            return images[0];            //返回第一張圖
        } else if(isDead()) {        //若死了的
            BufferedImage img = images[index++];    //從第2張圖片到最後一張圖片輪換
            if (index == images.length) {    //如果是最後一張圖片時
                state = REMOVE;                //狀態改為刪除
            }    
            return img;                        //返回對應下標的圖片
        }
        return null;                        //死了的和刪除的,都返回null
    }
}

    /**    成員方法:子彈移動    */
    @Override
    public void step() {
        y -= speed;    //y-(向上)
    }
import java.awt.image.BufferedImage;

/**
 * 子彈
 * @author soft01
 */
public class Bullet extends FlyingObject{
    /** 靜態變量:子彈圖片*/
    private static BufferedImage image;
    static {
        image = loadImage("bullet.png");
    }
    
    /**    成員變量:移動速度    */
    private int speed;            //移動速度
    
    /**    構造方法    */
    public Bullet(int x,int y) {
        super(8,14,x,y);
        speed = 3;
    }
    
    /**    成員方法:子彈移動    */
    @Override
    public void step() {
        y -= speed;    //y-(向上)
    }
    
    /**    成員方法:獲取圖片    */
    @Override
    public BufferedImage getImage() {
        if(isLife()) {                    //若活著的
            return image;                    //返回image
        } else if(isDead()) {        //若死了的
            state= REMOVE;                //狀態改為刪除
        }
        return null;                        //死了的和刪除的,都返回null
    }
}

    /**    成員方法:小蜜蜂移動        */
    @Override
    public void step() {
        x += xSpeed;
        y += ySpeed;
        if(x <= 0 || x >= World.WIDTH-this.width) {        
            xSpeed *= -1;
        }
    }
import java.awt.image.BufferedImage;
import java.util.Random;

/**
 * 小蜜蜂
 * @author soft01
 */
public class Bee  extends FlyingObject{
    /** 靜態變量:小蜜蜂圖片*/
    private static BufferedImage[] images;
    static {
        images = new BufferedImage[2];
        for (int i = 0; i < images.length; i++) {
            images[i] = loadImage("bee" + i + ".png");
        }
    }
    
    /**    成員變量:移動速度    */
    private int xSpeed;            //x坐標移動速度
    private int ySpeed;            //y坐標移動速度
    private int awardType;        //獎勵類型
    
    /**    構造方法    */
    public Bee() {
        super(60,50);
        xSpeed = 1;
        ySpeed = 2;
        Random rand = new Random();
        awardType = rand.nextInt(2);        //0~1之間的隨機數
    }
    /**    成員方法:小蜜蜂移動        */
    @Override
    public void step() {
        x += xSpeed;
        y += ySpeed;
        if(x <= 0 || x >= World.WIDTH-this.width) {        
            xSpeed *= -1;
        }
    }
    
    /**    成員方法:獲取圖片    */
    int index = 1;    //輪換圖片的起始位置
    @Override
    public BufferedImage getImage() {    //每10個毫秒輪換一次
        if(isLife()) {                    //若活著的
            return images[0];            //返回第一張圖
        } else if(isDead()) {        //若死了的
            BufferedImage img = images[index++];    //從第2張圖片到最後一張圖片輪換
            if (index == images.length) {    //如果是最後一張圖片時
                state = REMOVE;                //狀態改為刪除
            }    
            return img;                        //返回對應下標的圖片
        }
        return null;                        //死了的和刪除的,都返回null
    }
}

    /**    成員方法:天空移動    */
    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的值為負的窗口的高
        }    
    }

import java.awt.Graphics;
import java.awt.image.BufferedImage;


/**
 * 天空
 * @author soft01
 */
public class Sky extends FlyingObject{
    /** 靜態變量:天空圖片 */
    private static BufferedImage image;
    static {
        image = loadImage("background.png");
    }
    
    /**    成員變量:移動速度    */
    private int y1;            //第二張圖片的y坐標
    private int speed;        //移動速度
    
    /**    構造方法    */
    public Sky(){
        super(World.WIDTH,World.HEIGHT,0,0);
        y1 = -height;
        speed = 1;
    }
    
    /**    成員方法:天空移動    */
    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的值為負的窗口的高
        }    
    }
    
    /**    成員方法:獲取圖片    */
    
    public BufferedImage getImage() {
        return image;
    }
    
    /** 成員方法:畫對象的 g:畫筆 */
    
    public void paintObject(Graphics g) {
        g.drawImage(getImage(),x,y,null);
        g.drawImage(getImage(),x,y1,null);
    }
    
}

    2)飛行物移動為定時發生的,在run()中調用stepAction()實現飛行物移動,
  在stepAction()中,天空動,遍歷敵人而後敵人動,遍歷子彈而後子彈動 /** 成員方法:飛行物入場 */ 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 action() { Timer timer = new Timer(); //創建定時器對象 int interval = 10; //定時間隔(以毫秒為單位) timer.schedule(new TimerTask() { @Override public void run() {//定時幹的事(每10個毫秒走一次) enterAction(); //敵人入場,子彈入場,飛行物移動 shootAction(); //子彈入場,英雄機發射子彈 stepAction(); //飛行物入場 repaint(); //重畫(重新調用paint()方法) } },interval,interval); //定時計劃 }

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;

/**
 * 整個世界
 * @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();                    //飛行物入場
                repaint();                       //重畫(重新調用paint()方法)
            }
        },interval,interval);                     //定時計劃
    }
    
    
    /** 成員方法:生成敵人(小敵機、大敵機、小蜜蜂)對象 */
    public FlyingObject nextOne() {
        Random rand = new Random();    //隨機數對象
        int type = rand.nextInt(20);    //0~19之間的數
        if (type < 8) {                            //0~7返回小敵機
            return new Airplane();
        } else if(type < 16){                //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%30 == 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();    //子彈移動
        }
    }
    
    /** 成員方法: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);                                //畫子彈
        }
    }
    
    /** 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學習二(飛機大戰項目)day07