Java開發(fā)實(shí)現(xiàn)飛機(jī)大戰(zhàn)
本文實(shí)例為大家分享了Java實(shí)現(xiàn)飛機(jī)大戰(zhàn)的具體代碼,供大家參考,具體內(nèi)容如下
一、飛機(jī)大戰(zhàn)
1 封裝所有飛行物公共屬性和功能的父類
import java.awt.image.BufferedImag /** ?* 封裝所有飛行物的公共屬性和功能的父類 ?*/ public abstract class Flyer { ? ? protected int x; //飛行物左上角x坐標(biāo) ? ? protected int y; //飛行物左上角y坐標(biāo) ? ? protected int height; //飛行物的高度 ? ? protected int width; //飛行物的寬度 ? ? protected BufferedImage image; //飛行物的圖片 ? ? /** ? ? ?* 要求所有飛行物必須都能移動(dòng) ? ? ?* 但移動(dòng)的方式由子類自己實(shí)現(xiàn) ? ? ?*/ ? ? public abstract void step(); ? ? /** ? ? ?* 檢查越界的方法 ? ? ?* @return 是否越界 ? ? ?*/ ? ? public abstract boolean outOfBounds(); ? ? /** ? ? ?* 專門檢測(cè)兩個(gè)矩形飛行物是否碰撞的工具方法 ? ? ?* 和具體對(duì)象無關(guān),所以定義為靜態(tài)方法 ? ? ?* @param f1 飛行對(duì)象1 ? ? ?* @param f2 飛行對(duì)象2 ? ? ?* @return 是否碰撞 ? ? ?*/ ? ? public static boolean boom(Flyer f1,Flyer f2){ ? ? ? ? //step1: 求出兩個(gè)矩形的中心點(diǎn) ? ? ? ? int f1x = f1.x + f1.width/2; ? ? ? ? int f1y = f1.y + f1.height/2; ? ? ? ? int f2x = f2.x + f2.width/2; ? ? ? ? int f2y = f2.y + f2.height/2; ? ? ? ? //step2: 橫向和縱向碰撞檢測(cè) ? ? ? ? boolean H = Math.abs(f1x - f2x) < (f1.width + f2.width)/2; ? ? ? ? boolean V = Math.abs(f1y -f2y) < (f1.height + f2.height)/2; ? ? ? ? //step3: 必須兩個(gè)方向同時(shí)碰撞 ? ? ? ? return H&V; ? ? } }
2 封裝英雄機(jī)屬性和功能類
import java.util.Random; /** ?* 封裝英雄機(jī)的屬性和功能類 ?*/ public class Hero extends Flyer { ? ? private int doubleFire; //雙倍火力子彈數(shù) ? ? private int life; //生命值 ? ? private int score; //得分 ? ? //對(duì)外提供讀取生命值的方法 ? ? public int getLife(){ ? ? ? ? return life; ? ? } ? ? //對(duì)外提供的獲取得分的方法 ? ? public int getScore(){ ? ? ? ? return score; ? ? } ? ? /** ? ? ?* 英雄機(jī)對(duì)象的無參構(gòu)造方法 ? ? ?*/ ? ? public Hero(){ ? ? ? ? image = ShootGame.hero0; ? ? ? ? height = image.getHeight(); ? ? ? ? width = image.getWidth(); ? ? ? ? x = 127; ? ? ? ? y = 388; ? ? ? ? doubleFire = 0; ? ? ? ? life = 3; ? ? ? ? score = 0; ? ? } ? ? /** ? ? ?* 實(shí)現(xiàn)英雄機(jī)的動(dòng)畫效果的方法 ? ? ?* 讓英雄機(jī)的圖片在hero0和hero1之斗切換 ? ? ?*/ ? ? @Override ? ? public void step() { ? ? ? ? Random r = new Random(); ? ? ? ? if(r.nextInt(2) == 0){ ? ? ? ? ? ? image = ShootGame.hero0; ? ? ? ? }else{ ? ? ? ? ? ? image = ShootGame.hero1; ? ? ? ? } ? ? } ? ? @Override ? ? public boolean outOfBounds() { ? ? ? ? // TODO Auto-generated method stub ? ? ? ? return false; ? ? } ? ? /** ? ? ?* 英雄機(jī)隨鼠標(biāo)移動(dòng)的方法 ? ? ?* 要求傳入鼠標(biāo)當(dāng)前的位置 ? ? ?* @param x 鼠標(biāo)位置的x坐標(biāo) ? ? ?* @param y 鼠標(biāo)位置的y坐標(biāo) ? ? ?*/ ? ? public void move(int x,int y){ ? ? ? ? //傳入的x,y是鼠標(biāo)的坐標(biāo) ? ? ? ? //move的作用是讓英雄機(jī)的中心位置和鼠標(biāo)位置一致 ? ? ? ? this.x = x - width / 2; ? ? ? ? this.y = y - height / 2; ? ? } ? ? /** ? ? ?* 英雄機(jī)獲得分?jǐn)?shù)或獎(jiǎng)勵(lì)的方法 ? ? ?* @param f 是一個(gè)飛行物父類方法,可以指向敵機(jī)或者大飛機(jī) ? ? ?*/ ? ? public void getScore_Award(Flyer f){ ? ? ? ? //先判斷敵人對(duì)象的類型 ? ? ? ? if(f instanceof Airplane){ //如果敵人是敵機(jī) ? ? ? ? ? ? //獲得敵機(jī)對(duì)象中的分?jǐn)?shù),加到當(dāng)現(xiàn)分?jǐn)?shù)上 ? ? ? ? ? ? score += ((Airplane)f).getScore(); ? ? ? ? }else{ //如果對(duì)象是大飛機(jī) ? ? ? ? ? ? //繼續(xù)判斷大飛機(jī)對(duì)象中保存的獎(jiǎng)勵(lì)類型 ? ? ? ? ? ? if(((BigPlane)f).getAwardType() == BigPlane.DOUBLE_FIRE){ ? ? ? ? ? ? ? ? //如果保存的是雙倍火力 ? ? ? ? ? ? ? ? doubleFire += 20; ? ? ? ? ? ? }else{ ? ? ? ? ? ? ? ? //如果保存的是生命值獎(jiǎng)勵(lì) ? ? ? ? ? ? ? ? life += 1; ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? /** ? ? ?* 英雄機(jī)發(fā)射子彈的方法 ? ? ?* @return 新創(chuàng)建出來的子彈對(duì)名 ? ? ?* ? ? ? ? ?可能是一發(fā),也可能 是兩發(fā),用數(shù)組保存 ? ? ?*/ ? ? public Bullet[] shoot(){ ? ? ? ? Bullet[] bullets = null; ? ? ? ? //何時(shí)開啟雙倍火力: ? ? ? ? if(doubleFire != 0){ //創(chuàng)建雙倍火力 ? ? ? ? ? ? bullets = new Bullet[2]; ? ? ? ? ? ? Bullet b1 = new Bullet(x + width/4 - ShootGame.bullet.getWidth()/2,y + ShootGame.bullet.getWidth()); ? ? ? ? ? ? Bullet b2 = new Bullet(x + width*3/4 - ShootGame.bullet.getWidth()/2,y + ShootGame.bullet.getWidth()); ? ? ? ? ? ? bullets[0] = b1; ? ? ? ? ? ? bullets[1] = b2; ? ? ? ? ? ? //每創(chuàng)建一個(gè)雙倍火力,doubleFire-1 ? ? ? ? ? ? doubleFire -= 1; ? ? ? ? }else{ ? ? ? ? ? ? //單倍火力: ? ? ? ? ? ? //子彈x坐標(biāo):x+英雄機(jī)寬度/2-子彈寬度/2 ? ? ? ? ? ? //子彈y坐標(biāo):y-子彈高度 ? ? ? ? ? ? bullets = new Bullet[1]; ? ? ? ? ? ? bullets[0] = new Bullet(x + width/2 - ShootGame.bullet.getWidth()/2,y - ShootGame.bullet.getHeight()); ? ? ? ? } ? ? ? ? return bullets; ? ? } ? ? /** ? ? ?* 英雄機(jī)自帶和敵人碰撞檢測(cè)方法 ? ? ?* @param f 可能發(fā)生碰撞的敵人 ? ? ?* ? ? ? ? ?可能是敵機(jī)也可能是大飛機(jī) ? ? ?* @return 是否碰撞 ? ? ?*/ ? ? public boolean hit(Flyer f){ ? ? ? ? //調(diào)用碰撞檢測(cè)方法,檢測(cè)是否碰撞 ? ? ? ? boolean r = Flyer.boom(this, f); ? ? ? ? if(r){ //如果碰撞 ? ? ? ? ? ? life--; ? ? ? ? ? ? doubleFire = 0; ? ? ? ? } ? ? ? ? return r; ? ? } }
3 封裝敵機(jī)屬性和功能的類
import java.util.Random; /** ?* 封裝敵機(jī)屬性和功能的類 ?*/ public class Airplane extends Flyer { ? ? private int speed = 2; //敵機(jī)每次下落2個(gè)單位長(zhǎng)度 ? ? private int score = 5; //敵機(jī)包含的獎(jiǎng)勵(lì)分?jǐn)?shù) ? ? //對(duì)外提供的讀取敵機(jī)獎(jiǎng)勵(lì)分?jǐn)?shù)的方法 ? ? public int getScore(){ ? ? ? ? return score; ? ? } ? ? /** ? ? ?* 敵機(jī)類的無參構(gòu)造方法 ? ? ?*/ ? ? public Airplane(){ ? ? ? ? image = ShootGame.airplane; ? ? ? ? width = image.getWidth(); ? ? ? ? height = image.getHeight(); ? ? ? ? y = -height; ? ? ? ? Random r = new Random(); ? ? ? ? x = r.nextInt(ShootGame.WIDTH - width); ? ? } ? ? @Override ? ? public void step() { ? ? ? ? //敵機(jī)每次向下移動(dòng)一個(gè)speed長(zhǎng)度 ? ? ? ? y += speed; ? ? } ? ? @Override ? ? public boolean outOfBounds() { ? ? ? ? //敵機(jī)y坐標(biāo)>游戲界面,越界 ? ? ? ? return y > ShootGame.HEIGHT; ? ? } }
4 封裝大飛機(jī)屬性和功能的類
import java.util.Random; /** ?* 封裝大飛機(jī)屬性和功能的類 ?*/ public class BigPlane extends Flyer { ? ? /*定義獎(jiǎng)勵(lì)類型的備選項(xiàng)常量*/ ? ? public static final int DOUBLE_FIRE = 0; //獎(jiǎng)勵(lì)類型是0,說明獎(jiǎng)勵(lì)雙倍火力 ? ? public static final int FILE = 1; //獎(jiǎng)勵(lì)類型是1,說明獎(jiǎng)勵(lì)一次生命 ? ? /*大飛機(jī)類私有成員*/ ? ? private int xspeed = 1; //水平移動(dòng)的速度為1 ? ? private int yspeed = 2; //垂直移動(dòng)的速度為2 ? ? private int awardType; //當(dāng)前大飛機(jī)保存的獎(jiǎng)勵(lì)類型 ? ? //對(duì)外提供的讀取大飛機(jī)獎(jiǎng)勵(lì)類型的方法 ? ? public int getAwardType(){ ? ? ? ? return awardType; ? ? } ? ? /** ? ? ?* 大飛機(jī)的無參構(gòu)造方法 ? ? ?*/ ? ? public BigPlane(){ ? ? ? ? //step1: 從主程序中獲取大飛機(jī)圖片的靜態(tài)變量——bigplane ? ? ? ? image = ShootGame.bigplane; ? ? ? ? //step2: 使用圖片寬高設(shè)置對(duì)象寬高 ? ? ? ? width = image.getWidth(); ? ? ? ? height= image.getHeight(); ? ? ? ? //step3: 設(shè)置大飛機(jī)開始下落的高度 ? ? ? ? y = -height; ? ? ? ? //step4: ?大飛機(jī)對(duì)象開始下落的x坐標(biāo)在0~(界面寬度 - 大飛機(jī)圖片寬度)之前隨機(jī) ? ? ? ? Random r = new Random(); ? ? ? ? x = r.nextInt(ShootGame.WIDTH - width); ? ? ? ? //在0和1之間隨機(jī)先擇一種獎(jiǎng)勵(lì)類型 ? ? ? ? awardType = r.nextInt(2); ? ? } ? ? @Override ? ? public void step() { ? ? ? ? //每次x移動(dòng)一個(gè)xspeed,y移動(dòng)一個(gè)yspeed ? ? ? ? x += xspeed; ? ? ? ? y += yspeed; ? ? ? ? //大飛機(jī)不能起出邊界,一旦超出那么xspeed*(-1),相當(dāng)于反向移動(dòng) ? ? ? ? if(x < 0 || x > ShootGame.WIDTH - width){ ? ? ? ? ? ? xspeed *= -1; ? ? ? ? } ? ? } ? ? @Override ? ? public boolean outOfBounds() { ? ? ? ? //大飛機(jī)的y坐標(biāo)>游戲界面,越界 ? ? ? ? return y > ShootGame.HEIGHT; ? ? } }
5 子彈類
public class Bullet extends Flyer{ ? ? private int speed = 5; //子彈上升的速度為3 ? ? /** ? ? ?* 子彈類的帶參構(gòu)造方法 ? ? ?* 因?yàn)樽訌棇?duì)象創(chuàng)造的位置要根據(jù)英雄機(jī)的位置決定 ? ? ?* 所以子彈對(duì)名的x和y要從外界傳入 ? ? ?* @param x 英雄機(jī)指定子彈創(chuàng)造位置的x坐標(biāo) ? ? ?* @param y 英雄機(jī)指定子彈創(chuàng)造位置的y坐標(biāo) ? ? ?*/ ? ? public Bullet(int x,int y){ ? ? ? ? image = ShootGame.bullet; ? ? ? ? width = image.getWidth(); ? ? ? ? height = image.getHeight(); ? ? ? ? this.x = x; ? ? ? ? this.y = y; ? ? } ? ? @Override ? ? public void step() { ? ? ? ? //子彈每次向上移動(dòng)一個(gè)speed長(zhǎng)度 ? ? ? ? y -= speed; ? ? } ? ? @Override ? ? public boolean outOfBounds() { ? ? ? ? //子彈的y坐標(biāo)+子彈的高度<0,越界 ? ? ? ? return (y + height) < 0; ? ? } }
6 飛機(jī)大戰(zhàn)射擊的主方法
import java.awt.Font; import java.awt.Graphics; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Arrays; import java.util.Random; import java.util.Timer; import java.util.TimerTask; import javax.imageio.ImageIO; import javax.swing.JFrame; import javax.swing.JPanel; public class ShootGame extends JPanel { ? ? private static final long serialVersionUID = 1L; ? ? //背景圖片的大小320*568 ? ? public static final int WIDTH = 320; ? ? public static final int HEIGHT = 568; ? ? //游戲界面固定大小336*607 ? ? public static final int FRAME_WIDTH = 336; ? ? public static final int FRAME_HEIGHT = 607; ? ? /* ? ? ?* 游戲啟動(dòng)第一件事是從硬盤加載所有要用到的圖片到內(nèi)存當(dāng)中 ? ? ?* 而且僅在啟動(dòng)時(shí)加載一次——靜態(tài)塊 ? ? ?* 緩存在程序中的所有圖片,都會(huì)反復(fù)使用,僅保存一份——靜態(tài)變量 ? ? ?* 下面,為每張圖片加載一個(gè)靜態(tài)變量,然后在靜態(tài)塊加加載每張圖片 ? ? ?*/ ? ? public static BufferedImage background; //背景圖片 ? ? public static BufferedImage start; //開始圖片 ? ? public static BufferedImage airplane; //敵機(jī)圖片 ? ? public static BufferedImage bigplane; //大飛機(jī) ? ? public static BufferedImage hero0; //英雄機(jī)狀態(tài)0 ? ? public static BufferedImage hero1; //英雄機(jī)狀態(tài)1 ? ? public static BufferedImage bullet; //子彈 ? ? public static BufferedImage pause; //暫停圖片 ? ? public static BufferedImage gameover; //游戲結(jié)束 ? ? //靜態(tài)塊,在類加載到方法區(qū)時(shí)執(zhí)行一次,專門加載靜態(tài)資源 ? ? static{ ? ? ? ? /* ? ? ? ? ?* java從硬盤中加載圖片到內(nèi)存中: ? ? ? ? ?* ImageIO.read方法:專門從硬盤中加載圖片的靜態(tài)方法 ? ? ? ? ?* 不用實(shí)例化,直接調(diào)用 ? ? ? ? ?* ShootGame.class:獲得當(dāng)前類的加載器所在路徑 ? ? ? ? ?* ShootGame.class.getRerource("文件名"); 從當(dāng)前類所在路徑加載指定文件到程序中 ? ? ? ? ?*/ ? ? ? ? try { ? ? ? ? ? ? background = ImageIO.read(ShootGame.class.getResource("background.png")); ? ? ? ? ? ? airplane = ImageIO.read(ShootGame.class.getResource("airplane.png")); ? ? ? ? ? ? bigplane = ImageIO.read(ShootGame.class.getResource("bigplane.png")); ? ? ? ? ? ? bullet = ImageIO.read(ShootGame.class.getResource("bullet.png")); ? ? ? ? ? ? start = ImageIO.read(ShootGame.class.getResource("start.png")); ? ? ? ? ? ? pause = ImageIO.read(ShootGame.class.getResource("pause.png")); ? ? ? ? ? ? hero0 = ImageIO.read(ShootGame.class.getResource("hero0.png")); ? ? ? ? ? ? hero1 = ImageIO.read(ShootGame.class.getResource("hero1.png")); ? ? ? ? ? ? gameover = ImageIO.read(ShootGame.class.getResource("gameover.png")); ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? // TODO Auto-generated catch block ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? } ? ? /* ? ? ?* 為游戲中的角色定義數(shù)據(jù)結(jié)構(gòu),包括: ? ? ?* 1個(gè)英雄機(jī)對(duì)象 ? ? ?* 1個(gè)存儲(chǔ)所有敵人(敵機(jī)和大飛機(jī))的對(duì)象數(shù)組 ? ? ?* 1個(gè)存儲(chǔ)所有子彈的對(duì)象數(shù)組 ? ? ?*/ ? ? public Hero hero = new Hero(); ? ? public Flyer[] flyers = {}; //存儲(chǔ)所有敵人對(duì)象的數(shù)組 ? ? public Bullet[] bullets = {}; //存儲(chǔ)所有子彈對(duì)象的數(shù)組 ? ? //定義游戲狀態(tài):當(dāng)前狀態(tài)變量:默認(rèn)為開始狀態(tài) ? ? private int state = START; ? ? //定義游戲狀態(tài)的備選項(xiàng)常量: ? ? 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; ? ? public static void main(String[] args) { ? ? ? ? /* ? ? ? ? ?* java中繪制窗體:JFrame對(duì)象——窗框 ? ? ? ? ?* 要想在窗體中繪制內(nèi)容,還需要嵌入背景面板——JPanel ? ? ? ? ?*/ ? ? ? ? JFrame frame = new JFrame("ShootGame"); ? ? ? ? frame.setSize(FRAME_WIDTH,FRAME_HEIGHT);//(336, 607); ? ? ? ? frame.setAlwaysOnTop(true); //設(shè)置窗體置頂 ? ? ? ? //設(shè)置窗體關(guān)閉同時(shí),退出程序 ? ? ? ? frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); ? ? ? ? frame.setLocationRelativeTo(null); //設(shè)置窗體的位置,null表示居中 ? ? ? ? /*在窗體中嵌入背景面板對(duì)象——JPanel*/ ? ? ? ? ShootGame game = new ShootGame(); //創(chuàng)建背景面板對(duì)象 ? ? ? ? frame.add(game); //將背景面板對(duì)象嵌入到窗體對(duì)象中 ? ? ? ? /*窗體默認(rèn)不可見!必須調(diào)用setVisible方法才能顯示窗體*/ ? ? ? ? frame.setVisible(true); //自動(dòng)調(diào)用窗體的paint方法 ? ? ? ? game.action(); ? ? } ? ? /** ? ? ?* 游戲啟動(dòng)時(shí)要做的事 ? ? ?*/ ? ? public void action(){ ? ? ? ? /*游戲開始時(shí),要定義鼠標(biāo)事件的監(jiān)聽*/ ? ? ? ? //step1: 創(chuàng)建MouseAdapter匿名內(nèi)部類——事件的響應(yīng)程序 ? ? ? ? MouseAdapter l = new MouseAdapter(){ ? ? ? ? ? ? //step2: 重寫希望的鼠標(biāo)事件——鼠標(biāo)移動(dòng) ? ? ? ? ? ? @Override ? ? ? ? ? ? public void mouseMoved(MouseEvent e) { ? ? ? ? ? ? ? ? //只有在RUNNING狀態(tài)下英雄機(jī)才跟隨鼠標(biāo)移動(dòng) ? ? ? ? ? ? ? ? if(state == RUNNING){ ? ? ? ? ? ? ? ? ? ? //step3: 獲得鼠標(biāo)新位置 ? ? ? ? ? ? ? ? ? ? int x = e.getX(); ? ? ? ? ? ? ? ? ? ? int y = e.getY(); ? ? ? ? ? ? ? ? ? ? //step4: 將鼠標(biāo)位置傳給英雄機(jī)的move方法 ? ? ? ? ? ? ? ? ? ? hero.move(x, y); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? ? ? @Override ? ? ? ? ? ? public void mouseClicked(MouseEvent e) { ? ? ? ? ? ? ? ? if(state == START || state == PAUSE){ //START或者PAUSE狀態(tài),單擊才會(huì)改改為RUNNING狀態(tài) ? ? ? ? ? ? ? ? ? ? state = RUNNING; ? ? ? ? ? ? ? ? }else if(state == RUNNING){ //游戲點(diǎn)擊暫停 ? ? ? ? ? ? ? ? ? ? state = PAUSE; ? ? ? ? ? ? ? ? }else if(state == GAME_OVER){ //游戲結(jié)束后單擊,游戲初始化 ? ? ? ? ? ? ? ? ? ? state = START; ? ? ? ? ? ? ? ? ? ? //從GAME_OVER到START,要重新初始化游戲數(shù)據(jù) ? ? ? ? ? ? ? ? ? ? flyers = new Flyer[0]; ? ? ? ? ? ? ? ? ? ? bullets = new Bullet[0]; ? ? ? ? ? ? ? ? ? ? hero = new Hero(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? ? ? @Override ? ? ? ? ? ? public void mouseExited(MouseEvent e) { ? ? ? ? ? ? ? ? if(state == RUNNING){ ? ? ? ? ? ? ? ? ? ? //僅在處于RUNNING狀態(tài)下,鼠標(biāo)移出才暫停 ? ? ? ? ? ? ? ? ? ? state = PAUSE; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? ? ? @Override ? ? ? ? ? ? public void mouseEntered(MouseEvent e) { ? ? ? ? ? ? ? ? if(state == PAUSE){ ? ? ? ? ? ? ? ? ? ? state = RUNNING; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? }; //匿名內(nèi)部類要以分號(hào)結(jié)尾 ? ? ? ? /*step5: 要響應(yīng)鼠標(biāo)事件,必須將鼠標(biāo)事件添加到程序的監(jiān)聽器中*/ ? ? ? ? this.addMouseMotionListener(l); //支持鼠標(biāo)的移動(dòng)事件,不支持鼠標(biāo)單擊事件 ? ? ? ? this.addMouseListener(l);; //支持鼠標(biāo)單擊事件 ? ? ? ? //step1: 創(chuàng)建定時(shí)器 ? ? ? ? Timer timer = new Timer(); ? ? ? ? //step2: 調(diào)用定時(shí)器對(duì)象的schedule方法,做計(jì)劃 ? ? ? ? // ? ? ? 第一個(gè)參數(shù):TimerTask類型的匿名內(nèi)部類 ? ? ? ? // ? ? ? ? ? ? ? 必須重寫run方法——核心——要做什么事 ? ? ? ? timer.schedule(new TimerTask(){ ? ? ? ? ? ? //首先定義一個(gè)計(jì)時(shí)器變量index,記錄run方法運(yùn)行的次數(shù) ? ? ? ? ? ? private int runTimes = 0; ? ? ? ? ? ? @Override ? ? ? ? ? ? public void run() { ? ? ? ? ? ? ? ? //除了repaint方法,其余功能只在RUNNING狀態(tài)下執(zhí)行 ? ? ? ? ? ? ? ? if(state == RUNNING){ ? ? ? ? ? ? ? ? ? ? //每執(zhí)行一次run方法,runTimes就+1 ? ? ? ? ? ? ? ? ? ? runTimes++; ? ? ? ? ? ? ? ? ? ? //每500亳秒生成一次敵人 ? ? ? ? ? ? ? ? ? ? if(runTimes % 50 == 0){ ? ? ? ? ? ? ? ? ? ? ? ? nextOne(); //自動(dòng)隨機(jī)創(chuàng)建敵人對(duì)象 ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? //遍歷每一個(gè)對(duì)象,調(diào)用對(duì)象的step方法,移動(dòng)一次對(duì)象的位置 ? ? ? ? ? ? ? ? ? ? for(int i = 0;i < flyers.length;i++){ ? ? ? ? ? ? ? ? ? ? ? ? flyers[i].step(); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? //每300亳秒生成一次子彈 ? ? ? ? ? ? ? ? ? ? if(runTimes % 30 == 0){ ? ? ? ? ? ? ? ? ? ? ? ? shoot(); //創(chuàng)建一次子彈 ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? //遍歷子彈數(shù)組的每一個(gè)對(duì)象,移動(dòng)位置 ? ? ? ? ? ? ? ? ? ? for(int i = 0;i < bullets.length;i++){ ? ? ? ? ? ? ? ? ? ? ? ? bullets[i].step(); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? //英雄機(jī)動(dòng)畫效果 ? ? ? ? ? ? ? ? ? ? hero.step(); ? ? ? ? ? ? ? ? ? ? //添加子彈和敵人的碰撞檢測(cè) ? ? ? ? ? ? ? ? ? ? boom(); ? ? ? ? ? ? ? ? ? ? //英雄機(jī)碰撞檢測(cè) ? ? ? ? ? ? ? ? ? ? hit(); ? ? ? ? ? ? ? ? ? ? //添加越界檢測(cè) ? ? ? ? ? ? ? ? ? ? outOfBounds(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? /*強(qiáng)調(diào):只要界面發(fā)生變化,必須調(diào)用repaint方法重新繪制界面*/ ? ? ? ? ? ? ? ? repaint(); ? ? ? ? ? ? } ? ? ? ? }, 10,10); //界面每隔10亳秒變化一次 ? ? } ? ? @Override ? ? public void paint(Graphics g) { ? ? ? ? //step1: 繪制背景圖片 ? ? ? ? g.drawImage(background, 0, 0, null); ? ? ? ? //step2: 繪制英雄機(jī) ? ? ? ? paintHero(g); ? ? ? ? //step3: 批量繪制敵人數(shù)組 ? ? ? ? paintFlyers(g); ? ? ? ? //step4: 批量繪制子彈數(shù)組 ? ? ? ? paintBullets(g); ? ? ? ? //繪制分?jǐn)?shù)和生命值 ? ? ? ? paintScore_Life(g); ? ? ? ? //根據(jù)游戲狀態(tài)繪制不同圖片 ? ? ? ? if(state == START){ ? ? ? ? ? ? g.drawImage(start, 0, 0, null); ? ? ? ? }else if(state == PAUSE){ ? ? ? ? ? ? g.drawImage(pause, 0, 0, null); ? ? ? ? }else if(state == GAME_OVER){ ? ? ? ? ? ? g.drawImage(gameover, 0, 0, null); ? ? ? ? } ? ? } ? ? /** ? ? ?* 繪制英雄機(jī)對(duì)象的方法 ? ? ?* @param g 畫筆 ? ? ?*/ ? ? public void paintHero(Graphics g){ ? ? ? ? g.drawImage(hero.image, hero.x, hero.y, null); ? ? } ? ? /** ? ? ?* 遍歷敵人數(shù)組,批量繪制所有敵人的方法 ? ? ?* @param g ? ? ?*/ ? ? public void paintFlyers(Graphics g){ ? ? ? ? for(int i = 0;i < flyers.length;i++){ ? ? ? ? ? ? g.drawImage(flyers[i].image, flyers[i].x, flyers[i].y, null); ? ? ? ? } ? ? } ? ? /** ? ? ?* 遍歷子彈數(shù)組,批量繪制所有子彈的方法 ? ? ?* @param g ? ? ?*/ ? ? public void paintBullets(Graphics g){ ? ? ? ? for(int i = 0;i < bullets.length;i++){ ? ? ? ? ? ? g.drawImage(bullets[i].image, bullets[i].x, bullets[i].y, null); ? ? ? ? } ? ? } ? ? /** ? ? ?* 隨機(jī)生成1個(gè)敵人對(duì)象 ? ? ?* 每生成一個(gè)新敵人, flyers數(shù)組就要擴(kuò)容1 ? ? ?* 然后將新敵人放入數(shù)組最后一個(gè)元素 ? ? ?*/ ? ? public void nextOne(){ ? ? ? ? Random r = new Random(); ? ? ? ? Flyer f = null; ? ? ? ? if(r.nextInt(20) == 0){ //只有隨機(jī)數(shù)取0時(shí)才創(chuàng)建大飛機(jī) ? ? ? ? ? ? f = new BigPlane(); ? ? ? ? }else{ //其余全部生成敵機(jī) ? ? ? ? ? ? f = new Airplane(); ? ? ? ? } ? ? ? ? //對(duì)flyers數(shù)組擴(kuò)容1 ? ? ? ? flyers = Arrays.copyOf(flyers, flyers.length + 1); ? ? ? ? //將新敵人放入數(shù)組末尾 ? ? ? ? flyers[flyers.length - 1] = f; ? ? } ? ? /** ? ? ?* 獲得英雄機(jī)對(duì)象發(fā)射的子彈對(duì)象 ? ? ?* 將新的子彈對(duì)象保存到子彈數(shù)組中,統(tǒng)一管理 ? ? ?*/ ? ? public void shoot(){ ? ? ? ? Bullet[] newBullets = hero.shoot(); //獲得英雄機(jī)返回的新子彈數(shù)組 ? ? ? ? //根據(jù)返回新子彈的數(shù)量,擴(kuò)容子彈數(shù)組 ? ? ? ? bullets = Arrays.copyOf(bullets, bullets.length + newBullets.length); ? ? ? ? //從newBullets數(shù)組中拷貝所有元素到bullets數(shù)組末尾 ? ? ? ? System.arraycopy(newBullets, 0, bullets, bullets.length - newBullets.length, newBullets.length); ? ? } ? ? /** ? ? ?* 遍歷子彈數(shù)組和敵人數(shù)組,進(jìn)行碰撞檢測(cè) ? ? ?* 一旦發(fā)生碰撞,子彈和敵人都減少一個(gè) ? ? ?*/ ? ? public void boom(){ ? ? ? ? for(int i = 0;i < bullets.length;i++){ ? ? ? ? ? ? for(int j = 0;j < flyers.length;j++){ ? ? ? ? ? ? ? ? if(Flyer.boom(bullets[i], flyers[j])){ ? ? ? ? ? ? ? ? ? ? //為英雄機(jī)獲得分?jǐn)?shù)和獎(jiǎng)勵(lì) ? ? ? ? ? ? ? ? ? ? hero.getScore_Award(flyers[j]); ? ? ? ? ? ? ? ? ? ? //從敵人數(shù)組中刪除被擊中的敵機(jī) ? ? ? ? ? ? ? ? ? ? //step1: 使用敵人數(shù)組最后一個(gè)元素替換被擊中的敵機(jī) ? ? ? ? ? ? ? ? ? ? flyers[j] = flyers[flyers.length - 1]; ? ? ? ? ? ? ? ? ? ? //step2: 壓縮數(shù)組 ? ? ? ? ? ? ? ? ? ? flyers = Arrays.copyOf(flyers, flyers.length - 1); ? ? ? ? ? ? ? ? ? ? //從子彈數(shù)組中刪除擊中敵機(jī)的子彈 ? ? ? ? ? ? ? ? ? ? bullets[i] = bullets[bullets.length - 1]; ? ? ? ? ? ? ? ? ? ? bullets = Arrays.copyOf(bullets, bullets.length -1); ? ? ? ? ? ? ? ? ? ? i--; //第發(fā)現(xiàn)一次碰撞,子彈就要退一個(gè)元素,重新檢測(cè)當(dāng)前位置 ? ? ? ? ? ? ? ? ? ? break; //只要發(fā)現(xiàn)碰撞就退出當(dāng)前敵人數(shù)組的循環(huán) ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? /** ? ? ?* 繪制分?jǐn)?shù)和生命值的方法 ? ? ?* @param g ? ? ?*/ ? ? public void paintScore_Life(Graphics g){ ? ? ? ? int x = 10; //文字在左上角的x坐標(biāo) ? ? ? ? int y = 15; //文字在左上角的y坐標(biāo) ? ? ? ? Font font = new Font(Font.SANS_SERIF,Font.BOLD,14); ? ? ? ? g.setFont(font); //設(shè)置字體的畫筆對(duì)象 ? ? ? ? //繪制第一行:分?jǐn)?shù) ? ? ? ? g.drawString("SCORE: " + hero.getScore(), x, y); ? ? ? ? //繪制第二行:生命值,y坐標(biāo)下移20個(gè)單位 ? ? ? ? y += 20; ? ? ? ? g.drawString("LIFE: " + hero.getLife(), x, y); ? ? } ? ? /** ? ? ?* 檢查所有飛行物是否越界 ? ? ?*/ ? ? public void outOfBounds(){ ? ? ? ? //檢查所有敵人是否越界 ? ? ? ? Flyer[] Flives = new Flyer[flyers.length]; ? ? ? ? //遍歷敵人數(shù)組,將存活的敵人對(duì)象存到新數(shù)組中 ? ? ? ? //設(shè)置Flives數(shù)組的計(jì)數(shù)器index: 1.標(biāo)示下一個(gè)存活對(duì)象的位置 ? ? ? ? // ? ? ? ? ? ? ? ? ? ? ? ?2.統(tǒng)計(jì)Flives中一共有多少元素 ? ? ? ? int index = 0; ? ? ? ? for(int i = 0;i < flyers.length;i++){ ? ? ? ? ? ? if(!flyers[i].outOfBounds()){ //沒有越界的對(duì)象 ? ? ? ? ? ? ? ? Flives[index] = flyers[i]; ? ? ? ? ? ? ? ? index++; ? ? ? ? ? ? } //遍歷結(jié)束后: ? ? ? ? ? ? //index是存活對(duì)象的個(gè)數(shù) ? ? ? ? ? ? //Flives數(shù)組里是存活的對(duì)象,個(gè)數(shù)為index ? ? ? ? ? ? //把Flives數(shù)組壓縮為index大小 ? ? ? ? ? ? //壓縮后的新數(shù)組 應(yīng)替換回flyers數(shù)組 ? ? ? ? } ? ? ? ? flyers = Arrays.copyOf(Flives, index); ? ? ? ? //檢測(cè)所有子彈是否越界 ? ? ? ? Bullet[] Blives = new Bullet[bullets.length]; ? ? ? ? index = 0; ? ? ? ? for(int i = 0;i < bullets.length;i++){ ? ? ? ? ? ? if(!bullets[i].outOfBounds()){ ? ? ? ? ? ? ? ? Blives[index] = bullets[i]; ? ? ? ? ? ? ? ? index++; ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? bullets = Arrays.copyOf(Blives, index); ? ? } ? ? /** ? ? ?* 遍歷敵人數(shù)組,判斷英雄機(jī)和每個(gè)敵人是否碰撞 ? ? ?*/ ? ? public void hit(){ ? ? ? ? Flyer[] lives = new Flyer[flyers.length]; ? ? ? ? //記錄存活的敵人 ? ? ? ? int index = 0; ? ? ? ? for(int i = 0;i < flyers.length;i++){ ? ? ? ? ? ? if(!hero.hit(flyers[i])){ ? ? ? ? ? ? ? ? lives[index] = flyers[i]; ? ? ? ? ? ? ? ? index++; ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? if(hero.getLife() <= 0){ //如果英雄機(jī)生命值小于等于0,游戲結(jié)束 ? ? ? ? ? ? state = GAME_OVER; ? ? ? ? } ? ? ? ? //壓縮敵人數(shù)組,并替換數(shù)組 ? ? ? ? flyers = Arrays.copyOf(lives, index); ? ? } }
二、測(cè)試結(jié)果
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Java實(shí)現(xiàn)簡(jiǎn)單的飛機(jī)大戰(zhàn)游戲(控制主飛機(jī)篇)
- Java實(shí)現(xiàn)簡(jiǎn)單的飛機(jī)大戰(zhàn)游戲(敵機(jī)下落篇)
- 基于Java語(yǔ)言在窗體上實(shí)現(xiàn)飛機(jī)大戰(zhàn)小游戲的完整步驟
- Java實(shí)現(xiàn)游戲飛機(jī)大戰(zhàn)-III的示例代碼
- Java實(shí)現(xiàn)飛機(jī)大戰(zhàn)-II游戲詳解
- Java實(shí)現(xiàn)經(jīng)典游戲飛機(jī)大戰(zhàn)-I的示例代碼
- 一天時(shí)間用Java寫了個(gè)飛機(jī)大戰(zhàn)游戲,朋友直呼高手
- java實(shí)戰(zhàn)之飛機(jī)大戰(zhàn)小游戲(源碼加注釋)
- java實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲
- java實(shí)現(xiàn)簡(jiǎn)易飛機(jī)大戰(zhàn)
相關(guān)文章
java使用this調(diào)用構(gòu)造函數(shù)的實(shí)現(xiàn)方法示例
這篇文章主要介紹了java使用this調(diào)用構(gòu)造函數(shù)的實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了java面向?qū)ο蟪绦蛟O(shè)計(jì)中函數(shù)調(diào)用相關(guān)操作技巧,需要的朋友可以參考下2019-08-08解決Intellij IDEA運(yùn)行報(bào)Command line is too long的問題
這篇文章主要介紹了解決Intellij IDEA運(yùn)行報(bào)Command line is too long的問題,本文通過兩種方案給大家詳細(xì)介紹,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05解決java數(shù)值范圍以及float與double精度丟失的問題
下面小編就為大家?guī)硪黄鉀Qjava數(shù)值范圍以及float與double精度丟失的問題。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-06-06Java?Collections.sort()實(shí)現(xiàn)List排序的默認(rèn)方法和自定義方法
這篇文章主要介紹了Java?Collections.sort()實(shí)現(xiàn)List排序的默認(rèn)方法和自定義方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2017-06-06Java中將File轉(zhuǎn)化為MultipartFile的操作
這篇文章主要介紹了Java中將File轉(zhuǎn)化為MultipartFile的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-10-10基于resty orm的ActiveRecord操作數(shù)據(jù)指南
這篇文章主要為大家介紹了基于resty orm的ActiveRecord操作數(shù)據(jù)指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03