JAVA实现飞机大战详解
小游戲制作——飛機大戰
java 實現耗時四天,通過借鑒學習別人,到自己寫代碼。比較費頭發。但最終也還是肝了出來。本來還想弄一個 菜單欄,用該改變戰機和子彈,但迫于時間有限。能先寫到這里了。等過段時間,我再來完善它!
1.首先 我將英雄機,敵機,子彈,玩家。都分別當做對象來處理。單獨寫.java文件。
2. 寫一個窗口(GUI編程)。存放所有的對象。并行多線程,因為敵機 英雄機 子彈,都需要同時運行。不斷檢測敵機是否被子擊中,英雄機是否碰到敵機。所以:這些對象 都要繼承 Thread 重寫 run 方法
3. 事件監聽器也有寫,在英雄機碰到敵機時觸發,彈出窗口Gameover 并且關閉所有的窗口。結束進程。
4. 因為 敵機和子彈,在窗口中都會同時出現多個。我使用了vector 集合用來存放對象。 敵機和子彈都會消失,使用集合的 remove 方法就可以。
vector 和 list 的區別:
vector:連續存儲結構:vector是可以實現動態增長的對象數組,支持對數組高效率的訪問和在數組尾端的刪除和插入操作,在中間和頭部刪除和插入相對不易,需要挪動大量的數據。
它與數組最大的區別就是vector不需程序員自己去考慮容量問題,庫里面本身已經實現了容量的動態增長,而數組需要程序員手動寫入擴容函數進形擴容。
list:非連續存儲結構:list是一個雙鏈表結構,支持對鏈表的雙向遍歷。每個節點包括三個信息:元素本身,指向前一個元素的節點(prev)和指向下一個元素的節點(next)。
因此list可以高效率的對數據元素任意位置進行訪問和插入刪除等操作。由于涉及對額外指針的維護,所以開銷比較大。
5. 對方向鍵 的鍵值 做出了解。 玩家通過方向鍵來操控英雄機。需要,switch 語句進行識別 玩家按了哪個鍵。但同時,英雄機的移動范圍也是有限的。不能移出窗口。
6. 將所有的java文件 存放在同一目錄下,來自同一個包。
其余的小點:我在代碼中有注釋。大家多加理解吧!不理解可以私信我哦!
GameFrame.java 文件 窗口文件
package VacationTest.PlaneFight.src;import javax.swing.ImageIcon; import javax.swing.JFrame; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.util.Random; import java.util.Vector;public class GameFrame extends JFrame {//對英雄機和敵機作提前聲明HeroPlane heroplane;EnemyPlane enemyPlane;// 定義子彈集合Vector<bullet> bullets = new Vector<>();//敵機集合Vector<EnemyPlane> enemys = new Vector<>();GameFrame frame;public GameFrame() {frame = this ;// 后面 敵機的線程中要使用// 創建英雄機heroplane = new HeroPlane();//啟動英雄機線程heroplane.start();// 設置窗體的寬高this.setSize(500, 760);this.setTitle("飛機大戰---小帥制作");this.setResizable(false);//設置 用戶是否可以調整窗口的大小 這里設置為 否this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setLocationRelativeTo(null);//設置窗口 相對于屏幕的位置,null 指:處于屏幕中央// 窗口可見this.setVisible(true);// 新建線程,讓 畫筆 不斷 重復new Thread(new Runnable() {//內部類。@Overridepublic void run() {while (true) {repaint();//不斷重復畫 try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}}).start();//產生敵機的線程new Thread(new Runnable(){//產生隨機數Random r = new Random();@Override//重寫run 方法public void run(){while(true){EnemyPlane enemyPlane = new EnemyPlane(r.nextInt(500), 0,frame);// 隨機產生敵機,并創建敵機對象enemyPlane.start(); // 啟動線程//隨機產生敵機enemys.add(enemyPlane); // 將 敵機對象 添加到 enemy 集合中 try{Thread.sleep(500);}catch(InterruptedException e){e.printStackTrace();}}}}).start();}/*** 在窗口上畫圖片,需要不斷重復的畫,使用API中 paint 畫筆 重寫其中的方法* * @param g*/public void paint(Graphics g) {//System.out.println("繪制畫板");// 畫背景BufferedImage image = (BufferedImage) this.createImage(this.getSize().width, this.getSize().height);// 高效緩存畫筆Graphics pen = image.getGraphics();pen.drawImage(new ImageIcon("G:\\Users\\Administrator\\eclipse-workspace\\test\\src\\VacationTest\\PlaneFight\\Image\\Background.jpg").getImage(),0, 0, null);// 畫英雄機pen.drawImage(heroplane.img, heroplane.x, heroplane.y, heroplane.width, heroplane.height, null);// 飛機發射子彈for (int i = 0; i < bullets.size(); i++) {//System.out.println("bullet");// 實例化 子彈對象 b bullet b = bullets.get(i);if (b.y > 0)pen.drawImage(b.img, b.x, b.y -= b.speed, b.width, b.height, null);else// 子彈超出上邊界 移除bullets.remove(b);}//產生敵機for (int i = 0; i < enemys.size(); i++) {//實例化 敵機對象 epEnemyPlane ep = enemys.get(i);if (ep.y < 760)pen.drawImage(ep.img, ep.x, ep.y += ep.speed, ep.width, ep.height, null);elseenemys.remove(ep);}// 生效g.drawImage(image, 0, 0, null);}public static void main(String[] args) {GameFrame frame = new GameFrame();Player player = new Player(frame);//給 玩家注冊事件監聽器frame.addKeyListener(player);} }HeroPlane.java 文件 英雄機文件
package VacationTest.PlaneFight.src;import java.awt.Image; import javax.swing.ImageIcon;public class HeroPlane extends Thread {int x = 230, y = 650;int width = 50, height = 50;int speed = 8;Image img = new ImageIcon("G:\\Users\\Administrator\\eclipse-workspace\\test\\src\\VacationTest\\PlaneFight\\Image\\HeroPlane.png").getImage();// 定義方向鍵標志 up down left rightboolean up, down, left, right;// 兩種 構造器public HeroPlane() {}public HeroPlane(int x, int y, int width, int height) {this.x = x;this.y = y;this.width = width;this.height = height;}public void run() {while (true) {// 實現 英雄機的 移動if (up) {if (y > 20) {y -= speed;} else {y -= 0;}}if (down) {if (y < 700)y += speed;elsey += 0;}if (left) {if (x > 10)x -= speed;elsex -= 0;}if (right) {if (x < 440)x += speed;elsex += 0;}try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}} }EnemyPlane.java 文件 敵機文件
package VacationTest.PlaneFight.src;import java.awt.Image; import java.awt.Rectangle; import javax.swing.*;import VacationTest.PlaneFight.src.Gameover.MyFrame;// 導入 游戲結束的 包 自己寫的java 文件public class EnemyPlane extends Thread {public GameFrame gf;// 敵機的位置 大小 速度int x, y;int width = 50, height = 50;int speed = 3;Image img = new ImageIcon("G:\\Users\\Administrator\\eclipse-workspace\\test\\src\\VacationTest\\PlaneFight\\Image\\EmenyPlane.png").getImage();// 構造器public EnemyPlane(int x, int y, GameFrame gf) {super();this.x = x;this.y = y;this.gf = gf;}// 構造器public EnemyPlane(int x, int y, int width, int height, GameFrame gf) {super();this.x = x;this.y = y;this.width = width;this.height = height;this.gf = gf;}// 重寫run方法 在線程啟動時 執行public void run() {while (true) {if (hit()) {// System.out.println("hit.............");// 敵機被擊毀后,速度變為0 圖片更換為 爆炸圖片this.speed = 0;this.img = new ImageIcon("G:\\Users\\Administrator\\eclipse-workspace\\test\\src\\VacationTest\\PlaneFight\\Image\\boom3.png").getImage();try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}// 子彈擊毀 移除敵機gf.enemys.remove(this);break;}// 敵機超出下邊界 移除敵機if (this.y > 760) {gf.enemys.remove(this);break;}try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}if (crash()) {this.speed = 0;this.img = new ImageIcon().getImage();new MyFrame(); //實例化MyFrame對象gf.enemys.remove(this);gf.heroplane.img = new ImageIcon("G:\\Users\\Administrator\\eclipse-workspace\\test\\src\\VacationTest\\PlaneFight\\Image\\HeroPlaneBoom.png").getImage();try {Thread.sleep(1500);} catch (InterruptedException e) {e.printStackTrace();}//gf.heroplane.addActionListener(new broken());System.exit(0);}}}// 檢測碰撞public boolean hit() {// Swing技術中,已經實現相關算法// 給出敵機的矩形Rectangle myrect = new Rectangle(this.x, this.y, this.width, this.height);Rectangle rect = null;// 給出子彈的矩形for (int i = 0; i < gf.bullets.size(); i++) {bullet b = gf.bullets.get(i);rect = new Rectangle(b.x, b.y, b.width, b.height);// 碰撞檢測if (myrect.intersects(rect)) {return true;}}return false;}// 檢測 英雄機和 敵機碰撞public boolean crash() {Rectangle myrect = new Rectangle(this.x, this.y, this.width, this.height);Rectangle rect2 = new Rectangle(gf.heroplane.x, gf.heroplane.y, gf.heroplane.width, gf.heroplane.height);if (myrect.intersects(rect2)) {return true;}return false;}}bullet.java文件 子彈文件
package VacationTest.PlaneFight.src;import java.awt.Image;import javax.swing.ImageIcon;public class bullet {int x;int y;int width=30;int height=40;int speed = 15;Image img = new ImageIcon("G:\\Users\\Administrator\\eclipse-workspace\\test\\src\\VacationTest\\PlaneFight\\Image\\bullet2.png").getImage();public bullet(int x,int y){this.x = x;this.y = y;}public bullet(int x,int y ,int width , int height){this.x = x;this.y = y;this.width = width;this.height = height;}}Player.java 文件 玩家文件
package VacationTest.PlaneFight.src;import java.awt.event.*;public class Player extends KeyAdapter{//傳入 frame 對象 也就是 整個窗體中的所有屬性值 使用 對象名.方法 進行調用GameFrame frame;public Player(GameFrame frame){this.frame = frame;}/*** 定義一個玩家,操作鍵盤的上下左右。以及 發射子彈 空格 * 38 40 37 39 對應 上下左右* 重寫 keyPressed 和 keyReleased 方法 并使用監聽器 判斷玩家按哪個鍵 */public void keyPressed(KeyEvent e){int keycode = e.getKeyCode();//System.out.println(keycode);//利用該語句 可以 知道 鍵盤上的按鍵 值是多少。switch(keycode){case 38: frame.heroplane.up = true;break;case 40: frame.heroplane.down = true;break;case 37: frame.heroplane.left = true;break;case 39:frame.heroplane.right = true;break;case 32:addBullet();break;}}public void keyReleased(KeyEvent e){int keycode = e.getKeyCode();switch(keycode){case 38: frame.heroplane.up = false;break;case 40: frame.heroplane.down = false;break;case 37: frame.heroplane.left = false;break;case 39:frame.heroplane.right = false;break;}}// 發射子彈方法 在 鍵值為 32 時 觸發public void addBullet(){frame.bullets.add(new bullet(frame.heroplane.x+15, frame.heroplane.y-20));} }Gameover.java文件 游戲結束文件
package VacationTest.PlaneFight.src;import java.awt.Container; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.WindowConstants;public class Gameover{static GameFrame frame;public static class MyFrame extends JFrame { //創建新類,繼承自JFrameprivate static final long serialVersionUID = 1L;public MyFrame() {Container container = getContentPane(); //創建一個容器container.setLayout(null);//JLabel jl = new JLabel("這是一個JFrame窗體"); //在窗體中設置標簽//jl.setHorizontalAlignment(SwingConstants.CENTER); //將標簽的文字至于標簽中間的位置 //container.add(jl); //將標簽添加到容器中JButton jb = new JButton(""); //定義一個按鈕ImageIcon img = new ImageIcon("G:\\Users\\Administrator\\eclipse-workspace\\test\\src\\VacationTest\\PlaneFight\\Image\\Gameover.jpg");img.setImage(img.getImage().getScaledInstance(350,150,0));jb.setBounds(0, 0, 350, 150); //設置按鈕的大小jb.setIcon(img);jb.addActionListener(new ActionListener() { //為按鈕添加點擊事件@Overridepublic void actionPerformed(ActionEvent e){try {Thread.sleep(1500);} catch (InterruptedException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}System.exit(0);} });container.add(jb);setSize(360,180);setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);setVisible(true);setLocationRelativeTo(null);//設置窗口 相對于屏幕的位置,null 指:處于屏幕中央}} }在代碼中使用的圖片,以及素材,已經放在百度網盤里了。
注意: 使用的圖片路徑 要改。
https://pan.baidu.com/s/1L70YtfqrBg8iWqFxmxB1jA
提取碼:p6o2
總結
以上是生活随笔為你收集整理的JAVA实现飞机大战详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python绘制不带颜色曲线图_Pyth
- 下一篇: CCNP精粹系列之十八--路由映射实战二