日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

老Java程序员花一天时间写了个飞机大战,很舒服!

發(fā)布時間:2023/12/10 java 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 老Java程序员花一天时间写了个飞机大战,很舒服! 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

老Java程序員花1天時間做了個飛機大戰(zhàn)



熱門專欄推薦

【1】Java小游戲(俄羅斯方塊、飛機大戰(zhàn)、植物大戰(zhàn)僵尸等)
【2】JavaWeb項目實戰(zhàn)(圖書管理、在線考試、宿舍管理等)
【3】JavaScript精彩實例(飛機大戰(zhàn)、貪吃蛇、驗證碼等)
【4】Java小白入門200例
【5】從零學(xué)Java、趣學(xué)Java
【6】Idea從零到精通

系列目錄

1. Java俄羅斯方塊
2. 老Java程序員花2天寫了個連連看
3. 老Java程序員花一天時間寫了個飛機大戰(zhàn)
4. Java五子棋人機版
5. Java植物大戰(zhàn)僵尸
6. Java消消樂(天天愛消除)
7. Java貪吃蛇小游戲
8. Java掃雷小游戲
9. Java坦克大戰(zhàn)

引言:

前兩天我發(fā)現(xiàn)CSDN上有兩篇飛機大戰(zhàn)的文章異常火爆,各種指標(biāo)都很高(閱讀、點贊、評論、收藏等),但都是python寫的,竟然不是我大Java,說實話作為老java選手,我心里是有那么一些失落的,難道我大java打飛機不行?就算大java打飛機不行,那我用單身30年的打飛機手速,我肯定行(反正我的代碼我做主,就是玩!),于是我決定一展伸手,用java寫了一個飛機大戰(zhàn)。我就問你們我打飛機行不行,我媳婦都說行,你們呢?歡迎我親愛的大Java選手們 點贊+評論+收藏!給我沖、沖、沖。。。

代碼實現(xiàn)

創(chuàng)建窗口

首先創(chuàng)建一個游戲窗體類GameFrame,繼承至JFrame,用來顯示在屏幕上(window的對象),每個游戲都有一個窗口,設(shè)置好窗口標(biāo)題、尺寸、布局等就可以。

/** 游戲窗體類*/ public class GameFrame extends JFrame {public GameFrame() {setTitle("飛機大戰(zhàn)");//設(shè)置標(biāo)題setSize(526, 685);//設(shè)定尺寸setLayout(new BorderLayout());setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//點擊關(guān)閉按鈕是關(guān)閉程序setLocationRelativeTo(null); //設(shè)置居中setResizable(false); //不允許修改界面大小} }

創(chuàng)建面板容器GamePanel繼承至JPanel

package main;import java.awt.Graphics; import javax.swing.JFrame; import javax.swing.JPanel; /** 畫布類*/ public class GamePanel extends JPanel{GamePanel gamePanel=this;private JFrame mainFrame=null;//構(gòu)造里面初始化相關(guān)參數(shù)public GamePanel(JFrame frame){this.setLayout(null);mainFrame = frame;mainFrame.setVisible(true);}@Overridepublic void paint(Graphics g) {} }

再創(chuàng)建一個Main類,來啟動這個窗口,用來啟動。

package main; public class Main {//主類public static void main(String[] args) {GameFrame frame = new GameFrame();GamePanel panel = new GamePanel(frame);frame.add(panel);frame.setVisible(true);//設(shè)定顯示} }

右鍵執(zhí)行這個Main類,窗口建出來了
??

創(chuàng)建菜單及菜單選項

創(chuàng)建菜單

private void initMenu(){// 創(chuàng)建菜單及菜單選項jmb = new JMenuBar();JMenu jm1 = new JMenu("游戲");jm1.setFont(new Font("微軟雅黑", Font.BOLD, 15));// 設(shè)置菜單顯示的字體JMenu jm2 = new JMenu("幫助");jm2.setFont(new Font("微軟雅黑", Font.BOLD, 15));// 設(shè)置菜單顯示的字體JMenuItem jmi1 = new JMenuItem("開始新游戲");JMenuItem jmi2 = new JMenuItem("退出");jmi1.setFont(new Font("微軟雅黑", Font.BOLD, 15));jmi2.setFont(new Font("微軟雅黑", Font.BOLD, 15));JMenuItem jmi3 = new JMenuItem("操作說明");jmi3.setFont(new Font("微軟雅黑", Font.BOLD, 15));JMenuItem jmi4 = new JMenuItem("勝利條件");jmi4.setFont(new Font("微軟雅黑", Font.BOLD, 15));jm1.add(jmi1);jm1.add(jmi2);jm2.add(jmi3);jm2.add(jmi4);jmb.add(jm1);jmb.add(jm2);mainFrame.setJMenuBar(jmb);// 菜單Bar放到JFrame上jmi1.addActionListener(this);jmi1.setActionCommand("Restart");jmi2.addActionListener(this);jmi2.setActionCommand("Exit");jmi3.addActionListener(this);jmi3.setActionCommand("help");jmi4.addActionListener(this);jmi4.setActionCommand("win"); }

實現(xiàn)ActionListener并重寫方法actionPerformed

actionPerformed方法的實現(xiàn)

@Override public void actionPerformed(ActionEvent e) {String command = e.getActionCommand();UIManager.put("OptionPane.buttonFont", new FontUIResource(new Font("宋體", Font.ITALIC, 18)));UIManager.put("OptionPane.messageFont", new FontUIResource(new Font("宋體", Font.ITALIC, 18)));if ("Exit".equals(command)) {Object[] options = { "確定", "取消" };int response = JOptionPane.showOptionDialog(this, "您確認(rèn)要退出嗎", "",JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null,options, options[0]);if (response == 0) {System.exit(0);} }else if("Restart".equals(command)){if(startFlag){Object[] options = { "確定", "取消" };int response = JOptionPane.showOptionDialog(this, "游戲中,您確認(rèn)要重新開始嗎", "",JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null,options, options[0]);if (response == 0) {//需要先結(jié)束游戲realGameEnd(1);restart();} }else{restart();}}else if("help".equals(command)){JOptionPane.showMessageDialog(null, "游戲開始后,要先動鼠標(biāo)到飛機處,觸發(fā)移動效果,然后飛機就會跟隨鼠標(biāo)移動!","提示!", JOptionPane.INFORMATION_MESSAGE);}else if("win".equals(command)){JOptionPane.showMessageDialog(null, "得分1000,獲得勝利!","提示!", JOptionPane.INFORMATION_MESSAGE);} }

創(chuàng)建背景

在GamePanel類中重寫paint方法,繪制背景圖即可

//繪圖方法 @Override public void paint(Graphics g) {gameHeight = this.getHeight();gameWidth = this.getWidth();//繪制背景g.drawImage((BufferedImage)imageMap.get("bg"), 0, -150, null); }

開啟主線程

主線程,用來重繪頁面,重繪全部交給主線程,主線程調(diào)用 repaint方法就行,要產(chǎn)生動畫就要靠這個repaint。

//刷新線程,用來重新繪制頁面 private class RefreshThread implements Runnable {@Overridepublic void run() {while (startFlag) {repaint();try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}}} }

在GamePanel的構(gòu)造里面啟動這個主線程

有了這個主線程刷新,待會我們更新飛機的位置,飛機就會移動,不需要另外的代碼去調(diào)用repaint方法了(這是我的做法,僅供參考)。

創(chuàng)建我方飛機

創(chuàng)建MyPlane類,屬性有坐標(biāo)x、y,寬高、圖片、是否存活、是否可以移動等;方法主要有繪制、移動、射擊等。

public class MyPlane {private int x = 0;private int y = 0;private int width = 0;private int height = 0;private BufferedImage image = null;private GamePanel panel=null;private HashMap imageMap=null;private boolean alive=true;private boolean canMove=false;private int key=1;private HashMap boomImageMap=null;private boolean hitFlag=false;//正在碰撞public MyPlane(int x,int y,int width,int height,GamePanel panel) {this.x=x;this.y=y;this.width=width;this.height=height;this.panel=panel;this.imageMap=panel.imageMap;this.image=(BufferedImage)imageMap.get("myplane1");this.boomImageMap=panel.mypalneBoomImageMap;}//繪制public void draw(Graphics g) {g.drawImage(image, x, y, width,height, null);} }

創(chuàng)建(這里只是創(chuàng)建好了飛機對象,需要繪制)

//創(chuàng)建自己飛機 private void initMyPlane() {myPlane = new MyPlane(200, 530, 132, 86, this); }

在paint方法中繪制

//繪圖方法 @Override public void paint(Graphics g) {gameHeight = this.getHeight();gameWidth = this.getWidth();//繪制背景g.drawImage((BufferedImage)imageMap.get("bg"), 0, -150, null);//繪制飛機if(myPlane!=null){myPlane.draw(g);} }

鼠標(biāo)事件監(jiān)聽

加入監(jiān)聽是為了讓飛機跟隨鼠標(biāo)移動,我這里定的規(guī)則是第一次鼠標(biāo)必須移動到飛機上,然后飛機才會跟隨。

代碼里面用一個屬性canMove來控制,默認(rèn)是false,只有鼠標(biāo)第一次移入到飛機上時,這個屬性設(shè)置為true,然后就可以跟隨鼠標(biāo)移動了。

//鼠標(biāo)事件的創(chuàng)建 private void createMouseListener() {MouseAdapter mouseAdapter = new MouseAdapter() {@Overridepublic void mouseMoved(MouseEvent e) {int x = e.getX();int y = e.getY();if(myPlane==null) return ;//飛機第一次是不允許移動的,只有飛機的canMove為true才去跟隨if(myPlane.isCanMove()){myPlane.move(x,y);return;}//判斷鼠標(biāo)的移入,如果移動到飛機上則canMove設(shè)置為trueif(myPlane.isPoint(x,y)){myPlane.setCanMove(true);}}};addMouseMotionListener(mouseAdapter);addMouseListener(mouseAdapter); }

來實現(xiàn)一下MyPlane的move方法,這里處理了邊界,保證飛機不出界,同時保證鼠標(biāo)在飛機的中間位置

//飛機跟隨鼠標(biāo)移動 public void move(int x,int y) {//判斷范圍,當(dāng)橫向移動在窗口范圍內(nèi)if(x-width/2>=0 && x<=panel.getWidth()-width/2){this.x=x-width/2;}//判斷范圍,當(dāng)縱向移動在窗口范圍內(nèi)if(y-height/2>=0 && y<=panel.getHeight()-height/2){this.y=y-height/2;} }

創(chuàng)建子彈類

屬性也就是坐標(biāo)、寬高這些,給子彈加入移動方法

//移動 void move(){new Thread(new Runnable() {@Overridepublic void run() {while(alive){y-=speed;if(y<=0){clear();}try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}}}}).start(); }

飛機類加入射擊方法,200毫秒創(chuàng)建一發(fā)子彈

//射擊 void shoot() {new Thread(new Runnable() {@Overridepublic void run() {while(alive){//創(chuàng)建子彈createBullet();try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}}}private void createBullet() {Bullet bullet = new Bullet(x+width/2-10, y, 20, 30, panel);panel.bulletList.add(bullet);new MusicPlayer("/music/shoot.wav").play();}}).start(); }

別忘記在paint方法里面繪制子彈出來

//繪制子彈 Bullet bullet=null; for (int i = 0; i < bulletList.size(); i++) {bullet = (Bullet)bulletList.get(i);bullet.draw(g); }

創(chuàng)建敵機

創(chuàng)建抽象類Plane

package main;import java.awt.Graphics;public abstract class Plane {public abstract void move();public abstract void draw(Graphics g);public abstract void boom();public abstract void clear();abstract int getX();abstract int getY();abstract int getWidth();abstract int getHeight(); }

創(chuàng)建敵機子類

有個特殊一點的地方: 因為有4種敵機,這里隨機1、2、3、4這4個數(shù)字作為屬性index,然后根據(jù)這個index來展現(xiàn)不同的飛機圖片,當(dāng)然也可以通過這個index來設(shè)置敵機不同的移動速度,但是我為了偷懶,就全部一樣的移動速度,嘿嘿。
移動就是開啟線程讓y坐標(biāo)增加,沒什么好講的,這里加一個飛機碰撞,就是當(dāng)敵機跟我方飛機如何判斷碰撞的問題。

撞機分析(敵機與我機的撞機)



從上面幾個圖可看出什么?因為圖片是方形的,他們的4個頂點一定至少有一個在對方的范圍內(nèi)。再看一下從左邊撞擊的圖:



從上圖看到也是這樣,其他兩個方向的也是一樣的道理,為了穩(wěn)點我還加了一種情況:

1.判斷敵機的4個點是否在飛機范圍內(nèi),如果有則表示碰撞了。
2.如果1不成立,則反過來,判斷我機的4個點是否在敵機的范圍內(nèi),如果是表示碰撞了。

//判斷飛機與子彈是否碰撞 private boolean isPoint(MyPlane plane) {/** * 兩種情況* 1.需要判斷敵機的4個點是否在飛機范圍內(nèi),如果有則表示碰撞了* 2.如果步驟1不成立,則反過來,判斷我機的4個點是否在敵機的范圍內(nèi),如果是標(biāo)志碰撞了*///方式1//左上角int x1 = x;int y1 = y;//右上角int x2 = x+width;int y2 = y;//右下角int x3 = x+width;int y3 = y+height;//左下角int x4 = x;int y4 = y+height;//只要有一個點在范圍內(nèi),則判斷為碰撞if(comparePointMyPlane(x1,y1,plane)|| comparePointMyPlane(x2,y2,plane)||comparePointMyPlane(x3,y3,plane)||comparePointMyPlane(x4,y4,plane) ){return true;}//方式1沒成立則用方式2判斷//方式2x1 = plane.getX();y1 = plane.getY();//右上角x2 = plane.getX()+plane.getWidth();y2 = plane.getY();//右下角x3 = plane.getX()+plane.getWidth();y3 =plane.getY()+plane.getHeight();//左下角x4 = plane.getX();y4 = plane.getY()+plane.getHeight();if(comparePoint(x1,y1)|| comparePoint(x2,y2)||comparePoint(x3,y3)||comparePoint(x4,y4) ){return true;}return false; } //用敵機的坐標(biāo)來判斷 private boolean comparePointMyPlane(int x,int y,MyPlane plane){//大于左上角,小于右下角的坐標(biāo)則肯定在范圍內(nèi)if(x>plane.getX() && y >plane.getY()&& x<plane.getX()+plane.getWidth() && y <plane.getY()+plane.getHeight() ){return true;}return false; } //用我機的坐標(biāo)來判斷 private boolean comparePoint(int x,int y){//大于左上角,小于右下角的坐標(biāo)則肯定在范圍內(nèi)if(x>this.x && y >this.y&& x<this.x+this.width && y <this.y+this.height){return true;}return false; }

測試一下效果

忘記說擊中敵機的了(原理跟剛才差不多,代碼直接放了)

//判斷擊中敵機 protected void hitEnemy() {EnemyPlane enemyPlane=null;List enemys = panel.enemyList;for (int i = 0; i < enemys.size(); i++) {try {enemyPlane = (EnemyPlane)enemys.get(i);} catch (Exception e) {}if(enemyPlane==null) continue;if(this.isPoint(enemyPlane)){panel.curCount+=enemyPlane.getCount();//刪除當(dāng)前子彈clear();//飛機爆炸enemyPlane.boom();if(panel.curCount>=panel.totalCount){panel.myPlane.setCanMove(false);panel.gameWin();}}} }//判斷飛機與子彈是否碰撞 private boolean isPoint(EnemyPlane plane) {//因為子彈比飛機小,所以只需要判斷子彈的4個點是否在飛機范圍內(nèi),如果有則表示碰撞了//左上角int x1 = x;int y1 = y;//右上角int x2 = x+width;int y2 = y;//右下角int x3 = x+width;int y3 = y+height;//左下角int x4 = x;int y4 = y+height;//只要有一個點在范圍內(nèi),則判斷為碰撞if(comparePoint(x1,y1,plane)|| comparePoint(x2,y2,plane)||comparePoint(x3,y3,plane)||comparePoint(x4,y4,plane) ){return true;}return false; }private boolean comparePoint(int x,int y,EnemyPlane plane){//大于左上角,小于右下角的坐標(biāo)則肯定在范圍內(nèi)if(x>plane.getX() && y >plane.getY()&& x<plane.getX()+plane.getWidth() && y <plane.getY()+plane.getHeight() ){return true;}return false; }

最后加上計分的、勝利、失敗等提示就完成了!

看到這里的大佬,動動發(fā)財?shù)男∈?點贊 + 回復(fù) + 收藏,能【 關(guān)注 】一波就更好了。

代碼獲取方式
訂閱我的專欄《Java游戲大全》后,可以查看專欄內(nèi)所有的文章,并且聯(lián)系博主免費獲取其中1-3份你心儀的源代碼,專欄的文章都是上過csdn熱榜的,值得信賴!專欄內(nèi)目前有[13]篇實例,未來2個月內(nèi)專欄會更新到15篇以上,一般2周一更,了解一下我的專欄。

熱門專欄推薦

【1】Java小游戲(俄羅斯方塊、飛機大戰(zhàn)、植物大戰(zhàn)僵尸等)
【2】JavaWeb項目實戰(zhàn)(圖書管理、在線考試、宿舍管理等)
【3】JavaScript精彩實例(飛機大戰(zhàn)、貪吃蛇、驗證碼等)
【4】Java小白入門200例
【5】從零學(xué)Java、趣學(xué)Java
【6】Idea從零到精通

★ 更多精彩

1. Java俄羅斯方塊
2. 老Java程序員花2天寫了個連連看
3. 老Java程序員花一天時間寫了個飛機大戰(zhàn)
4. Java五子棋人機版
5. Java植物大戰(zhàn)僵尸
6. Java消消樂(天天愛消除)
7. Java貪吃蛇小游戲
8. Java掃雷小游戲
9. Java坦克大戰(zhàn)

總結(jié)

以上是生活随笔為你收集整理的老Java程序员花一天时间写了个飞机大战,很舒服!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。