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; //圖片的高
-
敵機得分介面(interface Enemy)
package com.loveoyh.shoot; /** * 得分 * @author HP * */ public interface Enemy { /** * 擊敗敵機獲得分 * @return */ public int getScore(); }
-
獎勵介面(interface Award)
package com.loveoyh.shoot; /** * 獎勵 * @author HP * */
-
敵機:是飛行物,也是敵人所以繼承飛行物類實現得分介面(class Airplane extends FlyingObject implements Enemy)
package com.loveoyh.shoot; import java.util.Random;
-
小蜜蜂: 是飛行物,也是獎勵 繼承飛行物類實現獎勵介面(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
-