概述
本文將使用java語言以面向對象的編程方式一步一步實現飛機大戰這個小游戲
本篇文章僅供參考,如有寫的不好的地方或者各位讀者哪里沒看懂可以在評論區給我留言
或者郵件8274551712@qq.com
源碼地址 :https://github.com/sc2885112/AircraftWars.git
項目結構分析
在這個游戲中,所有的物體都是飛行物所以有一個總的抽象類類:飛行物體類(FlyingObject)
飛行物的子級划分:獎勵飛行物(*Prize),飛機(Plane),武器(Bullet)
飛機的子級划分:敵人飛機(enemy),英雄機(hero)
敵人的飛機又分普通敵人和特殊敵人,武器又分普通武器和特殊武器,英雄機又分a,b,c。。。等英雄機
話不多說上代碼。。。。。。。
飛行物體類FlyingObject
public abstract class FlyingObject implements Flying{ private int x; private int y; private BufferedImage img; private int imgWidth; private int imgHeight; private int flySpeed; //移動速度 public FlyingObject(int x, int y, int flySpeed,BufferedImage img) { this.x = x; this.y = y; this.flySpeed = flySpeed; this.img = img; } public FlyingObject(int x, int y, int flySpeed) { this.x = x; this.y = y; this.flySpeed = flySpeed; } public FlyingObject() {} @Override public void fly(int x,int y) { this.setX(x); this.setY(y); } /** * 走一步 * @return */ public void step(){ this.setY(this.getY() + this.getFlySpeed()); } /** * 越界檢查 */ public boolean isTransboundary(){ return this.y > PlayMain.GAME_HEIGHT; }
/**
* 碰撞檢查
* 這個碰撞算法是我拷貝的別人的
* 有些許誤差
* @return
*/
public boolean inspectCollision(FlyingObject flyObj){ int x1 = flyObj.x - this.getImgWidth()/2; //x坐標最小距離 int x2 = flyObj.x + this.getImgWidth()/2 + flyObj.getImgWidth(); //x坐標最大距離 int y1 = flyObj.y - this.getImgHeight()/2; //y坐標最小距離 int y2 = flyObj.y + this.getImgHeight()/2 + flyObj.getImgHeight(); //y坐標最大距離 int herox = this.x + this.getImgWidth()/2; //英雄機x坐標中心點距離 int heroy = this.y + this.getImgHeight()/2; //英雄機y坐標中心點距離 return herox>x1 && herox<x2 && heroy>y1 && heroy<y2; //區間范圍內為撞上了 } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public BufferedImage getImg() { return img; } public void setImg(String imgPath){ try { this.img = ImageIO.read(FlyingObject.class.getResource(imgPath)); this.imgWidth = this.getImg().getWidth(); this.imgHeight = this.getImg().getHeight(); } catch (IOException e) { System.out.println("讀取圖片出錯!"); e.printStackTrace(); } } public int getFlySpeed() { return flySpeed; } public void setFlySpeed(int flySpeed) { this.flySpeed = flySpeed; } public int getImgWidth() { return imgWidth; } public void setImgWidth(int imgWidth) { this.imgWidth = imgWidth; } public int getImgHeight() { return imgHeight; } public void setImgHeight(int imgHeight) { this.imgHeight = imgHeight; } }
飛機類(Plane)
public abstract class Plane extends FlyingObject implements Attack{ private int attackSpeed; //攻擊速度 private int life; //生命值 private Bullet bullet; //裝載的武器 private int firepower; //火力值 public Plane() {} @Override public ArrayList<Bullet> launch() { return bullet.getBullet(this.getX() + this.getImgWidth() / 2 - 8 ,this.getY() - 10,firepower); } public int getAttackSpeed() { return attackSpeed; } public void setAttackSpeed(int attackSpeed) { this.attackSpeed = attackSpeed; } public int getLife() { return life; } public void setLife(int life) { this.life = life; } public Bullet getBullet() { return bullet; } public void setBullet(Bullet bullet) { this.bullet = bullet; } public int getFirepower() { return firepower; } public void setFirepower(int firepower) { this.firepower = firepower; } }
生命獎勵類(LifePrize)
public class LifePrize extends FlyingObject implements Prize{ public LifePrize(){ this.setFlySpeed(3); this.setImg("../img/prize/bee.png"); } @Override public PrizeCategory getCategory() { // TODO Auto-generated method stub return PrizeCategory.Life; } }
火力加成獎勵類(FirePrize)
public class FirePrize extends FlyingObject implements Prize{ public FirePrize(){ this.setFlySpeed(3); this.setImg("../img/prize/fire.png"); } @Override public PrizeCategory getCategory() { // TODO Auto-generated method stub return PrizeCategory.Fire; } }
武器類(Bullet)
/** * 武器總類 * 依賴在飛機類的屬性上 * @author sand monk */ public abstract class Bullet extends FlyingObject{ private int hurt; //傷害值 private boolean type; //武器的類別,是敵機發出還是英雄機發出 public Bullet(int x, int y, int flySpeed,int hurt,BufferedImage img, boolean type) { super(x, y, flySpeed, img); this.hurt = hurt; this.type = type; } public Bullet(int x, int y, int flySpeed,int hurt,boolean type) { super(x, y, flySpeed); this.hurt = hurt; this.type = type; } public Bullet() {} /** * 生成子彈 * 留給子類覆蓋 * @return */ public abstract ArrayList<Bullet> getBullet(int x , int y ,int firepower); @Override public void step() { if(this.getType()) this.setY(this.getY() - this.getFlySpeed()); else this.setY(this.getY() + this.getFlySpeed()); }; @Override public boolean isTransboundary() { if(type) return this.getY() < 0; else return this.getY() > PlayMain.GAME_HEIGHT; }; public int getHurt() { return hurt; } public void setHurt(int hurt) { this.hurt = hurt; } public boolean getType() { return type; } public void setType(boolean type) { this.type = type; } }
敵人總類(Enemy)
/** * 敵人的總類 * 有一個獲取分數的方法 * @author lenovo */ public abstract class Enemy extends Plane{ public abstract int getScope(); }
敵人小兵(CommonEnemy)
/** * 普通的敵機 0號機 * @author sand monk */ public class CommonEnemy extends Enemy{ public CommonEnemy(){ this.setBullet(new CommonBullet(false,"../img/bullet/bullet2.png",6)); this.setAttackSpeed(1); this.setFlySpeed(3); this.setLife(1); this.setFirepower(1); this.setImg("../img/enemy/enemy11.png"); } @Override public int getScope() { // TODO Auto-generated method stub return 10; } }
中級敵人(EnemyThree)
/** * 敵機三號 * @author sand monk * */ public class EnemyThree extends Enemy{ public EnemyThree(){ this.setBullet(new CommonBullet(false,"../img/bullet/bullet2.png",6)); this.setAttackSpeed(1); this.setFlySpeed(1); this.setLife(20); this.setFirepower(2); this.setImg("../img/enemy/enemy3.png"); } @Override public int getScope() { return 100; } }
普通的武器類(CommonBullet)
/** * 普通的子彈 * @author sand monk */ public class CommonBullet extends Bullet{ public CommonBullet(int x, int y, int flySpeed, int hurt, BufferedImage img, boolean type) { super(x, y, flySpeed, hurt , img , type); } public CommonBullet(boolean type ,String imagePath,int flySpeed){ this.setFlySpeed(flySpeed); this.setHurt(1); this.setImg(imagePath); this.setType(type); } @Override public ArrayList<Bullet> getBullet(int x, int y ,int firepower) { ArrayList<Bullet> result = new ArrayList<Bullet>(); if(!this.getType()){ y = y + this.getImgHeight(); } if( firepower >= 3){ result.add(new CommonBullet((x - 15),y,this.getFlySpeed(),this.getHurt(),this.getImg(),this.getType())); result.add(new CommonBullet((x),y,this.getFlySpeed(),this.getHurt(),this.getImg(),this.getType())); result.add(new CommonBullet((x + 15),y,this.getFlySpeed(),this.getHurt(),this.getImg(),this.getType())); } if( firepower == 2){ result.add(new CommonBullet((x + 15),y,this.getFlySpeed(),this.getHurt(),this.getImg(),this.getType())); result.add(new CommonBullet((x - 15),y,this.getFlySpeed(),this.getHurt(),this.getImg(),this.getType())); } if(firepower == 1){ result.add(new CommonBullet(x,y,this.getFlySpeed(),this.getHurt(),this.getImg(),this.getType())); } return result; } }
英雄機(ZeroRedHero)這個名字是根據我找的素材圖片取的。。。。。。。。
/** * 零號紅色機 * @author sand monk * */ public class ZeroRedHero extends Plane{ /** * 初始化零號機 */ public ZeroRedHero(){ this.setImg("../img/hero/ship-Common.png"); this.setLife(3); // 設置生命值 this.setFlySpeed(999); // 設置飛行速度 this.setAttackSpeed(5);// 設置攻擊速度 this.setFirepower(1); // 設置火力值 上限為3 this.setBullet(new CommonBullet(true,"../img/bullet/bullet.png",3)); // 設置武器 this.setX(PlayMain.GAME_WIDTH / 2 / this.getImgWidth() * this.getImgWidth()); this.setY(PlayMain.GAME_HEIGHT - this.getImgHeight()); } }
主方法
@SuppressWarnings("serial") public class PlayMain extends JPanel { // 游戲主界面尺寸 public static final int GAME_WIDTH = 700; public static final int GAME_HEIGHT = 900; private GameStatus gameStatus; // 記錄游戲狀態 private HeroStatus heroStatus = HeroStatus.Common; // 英雄狀態 public static BufferedImage backgroundImg; // 游戲界面背景圖 public static BufferedImage pushImg; // 游戲界面背景圖 public static BufferedImage gameOverImg; // 游戲界面背景圖 private static int heroImgWidth; // 英雄機圖片的寬,用來計算畫筆的角度 private static int heroImgHeight; // 英雄機圖片的高,用來計算畫筆的角度 private ArrayList<Bullet> bullets ; // 全圖子彈集合 private ArrayList<FlyingObject> flyObjList ; // 飛行物集合 private Plane hero; // 英雄飛機 private Timer timer = new Timer(); // 定時器 public static int intervel = 10; // 界面運動定時器間隔 單位毫秒 10毫秒運動一次,相當於一秒100幀 private int enemyPlanInterver = 0;// 生成敵人飛機定時器 private int launchInterver = 1; // 射擊間隔定時器 private int garbageRecoveryInterver = 1000; // 垃圾清理定時器 private long heroVirtualStart = 0; // 英雄虛化狀態的開始時間 private int heroAttSpeed = 0;// 英雄的攻擊速度 private int score = 0; // 得分 private Random random = new Random(); private JFrame frame; // 窗口框架 private JMenuBar bar; // 菜單 private JMenu game; // 菜單項 private JMenuItem[] items; // 菜單下拉項 private JTextArea textArea; // 右邊框 // 初始化背景圖在類加載的時候執行一次 static { try { backgroundImg = ImageIO.read(PlayMain.class.getResource("../img/backgrand/back2.jpg")); pushImg = ImageIO.read(PlayMain.class.getResource("../img/status/push.png")); gameOverImg = ImageIO.read(PlayMain.class.getResource("../img/status/gameOver.png")); } catch (IOException e) { e.printStackTrace(); } } public PlayMain() throws IOException { init(); } /** * 初始化所有數據 * @throws IOException */ public void init() throws IOException { // 初始化英雄機 initHeroPlan(); // 初始化UI initUI(); // 游戲狀態為啟動 gameStatus = GameStatus.Runing; bullets = new ArrayList<Bullet>(); flyObjList = new ArrayList<FlyingObject>(); score = 0; } /** * 初始化UI組件 */ public void initUI() { frame = new JFrame("飛機大戰懷舊版"); // 實現窗口框架 textArea = new JTextArea(); bar = new JMenuBar(); // 建立菜單欄 game = new JMenu("菜單"); // 建立名為“游戲”的菜單 items = new JMenuItem[2]; // game菜單下創建2個子菜單項 game.add(items[0] = new JMenuItem("重新開始"));// 第一個子菜單為“重新開始” game.add(items[1] = new JMenuItem("退出")); // 第二個子菜單為“退出” } /** * 初始化英雄機參數 * @throws IOException */ public void initHeroPlan() throws IOException { hero = new ZeroRedHero(); heroImgWidth = hero.getImgWidth(); heroImgHeight = hero.getImgHeight(); heroAttSpeed = hero.getAttackSpeed(); } /** * 畫 */ @Override public void paint(Graphics g) { try { drawMainView(g); // 畫主界面 drawHero(g); // 畫英雄機 drawBullet(g); // 畫子彈 drawFlyObject(g); // 畫飛行物 drawScore(g); // 畫分數 drawGameStatus(g);//畫狀態 } catch (IOException e) { e.printStackTrace(); } } public void drawMainView(Graphics g) throws IOException { g.drawImage(backgroundImg, 0, 0, null); } public void drawGameStatus(Graphics g){ if(gameStatus == GameStatus.End){ g.drawImage(gameOverImg, 0, 0, null); } if(gameStatus == GameStatus.Suspend){ g.drawImage(pushImg, 0, 0, null); } } public void drawHero(Graphics g) { // 判斷是否是虛化狀態 boolean commen = true; if (heroStatus != HeroStatus.Common) { // 判斷是否是虛化狀態 if (heroStatus == HeroStatus.Virtual) { //判斷時間有沒有超過三秒 if (System.currentTimeMillis() - heroVirtualStart < 3000) { hero.setImg("../img/hero/ship-Virtual.png"); commen = false; } } // 判斷是否是無敵狀態 if (heroStatus == HeroStatus.Virtual) { if (System.currentTimeMillis() - heroVirtualStart < 3000) { hero.setImg("../img/hero/ship-Virtual.png"); commen = false; } } } if (commen) { heroStatus = HeroStatus.Common; hero.setImg("../img/hero/ship-Common.png"); } g.drawImage(hero.getImg(), hero.getX(), hero.getY(), null); } public void drawBullet(Graphics g) { Bullet bullet; for (int i = 0; i < bullets.size(); i++) { bullet = bullets.get(i); g.drawImage(bullet.getImg(), bullet.getX(), bullet.getY(), null); } } public void drawFlyObject(Graphics g) { FlyingObject flyObj; for (int i = 0; i < flyObjList.size(); i++) { flyObj = flyObjList.get(i); g.drawImage(flyObj.getImg(), flyObj.getX(), flyObj.getY(), null); } } public void drawScore(Graphics g) { int x = 10; // x坐標 int y = 25; // y坐標 Font font = new Font(Font.SANS_SERIF, Font.BOLD, 16); // 字體 g.setColor(Color.RED); g.setFont(font); // 設置字體 g.drawString("得分:" + score, x, y += 20); // 畫分數 g.drawString("生命:" + hero.getLife(), x, y += 20); // 畫命 g.drawString("攻擊速度 :" + heroAttSpeed , x, y += 20); g.drawString("火力值 :" + hero.getFirepower(), x, y += 20); } //打開窗口開始游戲 public void startFrame() { // 鼠標移動事件 addMouseMotionListener(new MouseMotionListener() { @Override public void mouseMoved(MouseEvent e) { int x = e.getX(); int y = e.getY(); textArea.setText(null); textArea.append("PX: ( X:" + x + ", Y:" + y + ")\n"); hero.setX(x - heroImgWidth / 2); hero.setY(y - heroImgHeight / 2); repaint(); } @Override public void mouseDragged(MouseEvent e) { } }); //鼠標移入移出事件 addMouseListener(new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { // 鼠標進入 if(gameStatus != GameStatus.End){ gameStatus = GameStatus.Runing; } } @Override public void mouseExited(MouseEvent e) { // 鼠標退出 if(gameStatus != GameStatus.End){ gameStatus = GameStatus.Suspend; } } }); // 點關閉按鈕事件 frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { String str = "是否要退出游戲?"; // 添加消息對話框 if (JOptionPane.showConfirmDialog(null, str, "退出游戲", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { System.exit(0); // 退出 } } }); // 點擊重新開始事件 items[0].addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String str = "是否要重新開始游戲?"; // 添加消息對話框 if (JOptionPane.showConfirmDialog(null, str, "重新開始", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { try { init(); } catch (IOException e1) { e1.printStackTrace(); } } } }); // 點擊退出事件 items[1].addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String str = "是否要退出游戲?"; // 添加消息對話框 if (JOptionPane.showConfirmDialog(null, str, "退出游戲", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { System.exit(0); // 退出 } } }); // 界面運動定時器 timer.schedule(new TimerTask() { @Override public void run() { nextStep(); // 開始運動 randomEnemyPlany(); // 生成敵機 heroShooting(); // 英雄射擊 garbageRecovery(); // 垃圾清理 duangGG();// 子彈的碰撞檢查 isGameOver();// 檢查游戲是否結束 repaint(); // 重繪,調用paint()方法 } }, intervel, intervel); this.setPreferredSize(new Dimension(GAME_WIDTH, GAME_HEIGHT)); // 設置游戲界面的寬高 // 設置右邊文本框 textArea.setEditable(false); // 不可編輯 JScrollPane scrollPane = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); scrollPane.setPreferredSize(new Dimension(200, GAME_HEIGHT)); scrollPane.setVisible(true); frame.setLayout(new BorderLayout());// 設置布局方式為流式布局 frame.add(this, BorderLayout.WEST); frame.add(scrollPane, BorderLayout.EAST); bar.add(game); frame.setJMenuBar(bar); frame.pack(); frame.setLocation(0, 0); // 電腦窗口的定位 frame.setResizable(false);// 設置此窗口是否可由用戶調整大小 frame.setVisible(true); // 設置窗口顯示狀態 frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); } /** * 隨機生成飛行物 */ public void randomEnemyPlany() { if(gameStatus != GameStatus.Runing) return; if (enemyPlanInterver % 50 == 0) { int ran = random.nextInt(20); if (ran == 1) { FlyingObject prize = new LifePrize(); prize.setX(random.nextInt(GAME_WIDTH - prize.getImgWidth())); prize.setY(0); flyObjList.add(prize); } else if (ran == 2) { FlyingObject prize = new FirePrize(); prize.setX(random.nextInt(GAME_WIDTH - prize.getImgWidth())); prize.setY(0); flyObjList.add(prize); } else if (ran > 17) { EnemyThree eplane = new EnemyThree(); eplane.setX(random.nextInt(GAME_WIDTH - eplane.getImgWidth())); eplane.setY(0); flyObjList.add(eplane); } else { CommonEnemy eplane = new CommonEnemy(); eplane.setX(random.nextInt(GAME_WIDTH - eplane.getImgWidth())); eplane.setY(0); flyObjList.add(eplane); } } enemyPlanInterver++; } /** * 運動一步 */ public void nextStep() { if(gameStatus != GameStatus.Runing) return; // 子彈運動 for (int i = 0; i < bullets.size(); i++) bullets.get(i).step(); // 飛行物運動 for (int i = 0; i < flyObjList.size(); i++) flyObjList.get(i).step(); } /** * 射擊 */ public void heroShooting() { if(gameStatus != GameStatus.Runing) return; /** * 英雄機射擊 */ if (launchInterver % ((1000 / PlayMain.intervel) / heroAttSpeed) == 0) { bullets.addAll(hero.launch()); } /** * 敵機射擊 */ Enemy enemy; for (int i = 0; i < flyObjList.size(); i++) { if (flyObjList.get(i) instanceof Enemy) { enemy = (Enemy) flyObjList.get(i); if (launchInterver % ((1000 / PlayMain.intervel) / enemy.getAttackSpeed()) == 0) { bullets.addAll(enemy.launch()); } } } launchInterver++; } /** * 移除越界的飛行物和子彈 */ public void garbageRecovery() { //一秒執行一次 if (garbageRecoveryInterver % (1000 / intervel) == 0) { ArrayList<Bullet> bulletsBak = new ArrayList<Bullet>(); ArrayList<FlyingObject> flyObjListBak = new ArrayList<FlyingObject>(); // 遍歷所有子彈 Bullet bullet; for (int i = 0; i < bullets.size(); i++) { bullet = bullets.get(i); if (!bullet.isTransboundary()) bulletsBak.add(bullet); } // 遍歷所有飛行物 FlyingObject flyObj; for (int i = 0; i < flyObjList.size(); i++) { flyObj = flyObjList.get(i); if (!flyObj.isTransboundary()) flyObjListBak.add(flyObj); } // 替換集合 bullets = bulletsBak; flyObjList = flyObjListBak; } garbageRecoveryInterver++; } /** * 檢查游戲是否結束 */ public void isGameOver(){ if(collision()) gameStatus = GameStatus.End; } /** * 英雄機碰撞檢測 * 如果命數為1則游戲結束返回true * @return */ public boolean collision() { /** * 如果是普通狀態則進行碰撞檢測,碰撞檢測成功后,檢查命數 如果命數不為0則進入虛化狀態,如果為0則游戲結束 */ if (heroStatus == HeroStatus.Common) { //與敵機和獎勵的碰撞檢查 for (int i = 0; i < flyObjList.size(); i++) { if (flyObjList.get(i).inspectCollision(hero)) { if (flyObjList.get(i) instanceof Prize) { Prize prize = (Prize) flyObjList.get(i); setPrize(prize); // 設置獎勵 // 移除飛行物 removeEnemy(i); } else { if (hero.getLife() == 1) { return true; } else { Plane enemy = (Plane) flyObjList.get(i); hero.setLife(hero.getLife() - enemy.getBullet().getHurt()); heroStatus = HeroStatus.Virtual; heroVirtualStart = System.currentTimeMillis(); } } } } //與子彈的碰撞檢查 for (int i = 0; i < bullets.size(); i++) { if(!bullets.get(i).getType()){ if (bullets.get(i).inspectCollision(hero)) { if (hero.getLife() == 1) { return true; } else { hero.setLife(hero.getLife() - bullets.get(i).getHurt()); heroStatus = HeroStatus.Virtual; heroVirtualStart = System.currentTimeMillis(); removeBullet(i); } } } } } return false; } /** * 子彈與敵機的碰撞檢查 */ public void duangGG() { Bullet bullet; Enemy enemy; Prize prize; // ArrayList<FlyingObject> flyObjBak; // ArrayList<Bullet> bulletsBak; if (!bullets.isEmpty()) { for (int i = 0; i < bullets.size(); i++) { bullet = bullets.get(i); if (!flyObjList.isEmpty()) { flyObj: for (int j = 0; j < flyObjList.size(); j++) { // 如果子彈是英雄機發出 if (bullet.getType()) { if (bullet.inspectCollision(flyObjList.get(j))) { if (flyObjList.get(j) instanceof Prize) {// 判斷敵機是傷害敵機還是獎勵 /** * 獲取獎勵內容 設置對應獎勵 */ prize = (Prize) flyObjList.get(j); setPrize(prize);// 設置獎勵 removeEnemy(j); } else { /** * 用子彈的傷害值與敵機生命值相減 如果敵機生命值為0,刪除敵機 */ enemy = (Enemy) flyObjList.get(j); enemy.setLife(enemy.getLife() - bullet.getHurt()); if (enemy.getLife() <= 0) { removeEnemy(j); score += enemy.getScope(); } } // 移除子彈 removeBullet(i); break flyObj; } } } } } } } /** * 設置對應獎勵 */ public void setPrize(Prize prize) { if (prize.getCategory() == PrizeCategory.Life) { hero.setLife(hero.getLife() + 1); } if (prize.getCategory() == PrizeCategory.Fire) { hero.setFirepower(hero.getFirepower() + 1); } //懶得寫了 - - if (prize.getCategory() == PrizeCategory.Attackspeed) { } if (prize.getCategory() == PrizeCategory.Invincible) { } } /** * 移除飛行物 */ public void removeEnemy(int index) { ArrayList<FlyingObject> listBak = new ArrayList<>(); flyObjList.set(index, flyObjList.get(flyObjList.size() - 1)); for (int i = 0; i < flyObjList.size() - 1; i++) listBak.add(flyObjList.get(i)); flyObjList = listBak; } /** * 移除子彈 */ public void removeBullet(int index){ ArrayList<Bullet> listBak = new ArrayList<>(); bullets.set(index, bullets.get(bullets.size() - 1)); for (int i = 0; i < bullets.size() - 1; i++) listBak.add(bullets.get(i)); bullets = listBak; } public static void main(String[] args) throws IOException { PlayMain plMain = new PlayMain(); plMain.startFrame(); } }