您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關如何使用Java制作飛機大戰游戲的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
創建窗口
首先創建一個游戲窗體類GameFrame,繼承至JFrame,用來顯示在屏幕上(window的對象),每個游戲都有一個窗口,設置好窗口標題、尺寸、布局等就可以。
/* * 游戲窗體類 */ public class GameFrame extends JFrame { public GameFrame() { setTitle("飛機大戰");//設置標題 setSize(526, 685);//設定尺寸 setLayout(new BorderLayout()); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//點擊關閉按鈕是關閉程序 setLocationRelativeTo(null); //設置居中 setResizable(false); //不允許修改界面大小 } }
創建面板容器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; //構造里面初始化相關參數 public GamePanel(JFrame frame){ this.setLayout(null); mainFrame = frame; mainFrame.setVisible(true); } @Override public void paint(Graphics g) { } }
再創建一個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);//設定顯示 } }
右鍵執行這個Main類,窗口建出來了
創建菜單
private void initMenu(){ // 創建菜單及菜單選項 jmb = new JMenuBar(); JMenu jm1 = new JMenu("游戲"); jm1.setFont(new Font("微軟雅黑", Font.BOLD, 15));// 設置菜單顯示的字體 JMenu jm2 = new JMenu("幫助"); jm2.setFont(new Font("微軟雅黑", Font.BOLD, 15));// 設置菜單顯示的字體 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"); }
實現ActionListener并重寫方法actionPerformed
actionPerformed方法的實現
@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, "您確認要退出嗎", "", 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, "游戲中,您確認要重新開始嗎", "", JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]); if (response == 0) { //需要先結束游戲 realGameEnd(1); restart(); } }else{ restart(); } }else if("help".equals(command)){ JOptionPane.showMessageDialog(null, "游戲開始后,要先動鼠標到飛機處,觸發移動效果,然后飛機就會跟隨鼠標移動!", "提示!", JOptionPane.INFORMATION_MESSAGE); }else if("win".equals(command)){ JOptionPane.showMessageDialog(null, "得分1000,獲得勝利!", "提示!", JOptionPane.INFORMATION_MESSAGE); } }
在GamePanel類中重寫paint方法,繪制背景圖即可
//繪圖方法 @Override public void paint(Graphics g) { gameHeight = this.getHeight(); gameWidth = this.getWidth(); //繪制背景 g.drawImage((BufferedImage)imageMap.get("bg"), 0, -150, null); }
主線程,用來重繪頁面,重繪全部交給主線程,主線程調用 repaint方法就行,要產生動畫就要靠這個repaint。
//刷新線程,用來重新繪制頁面 private class RefreshThread implements Runnable { @Override public void run() { while (startFlag) { repaint(); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } } }
在GamePanel的構造里面啟動這個主線程
有了這個主線程刷新,待會我們更新飛機的位置,飛機就會移動,不需要另外的代碼去調用repaint方法了(這是我的做法,僅供參考)。
創建MyPlane類,屬性有坐標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); } }
創建(這里只是創建好了飛機對象,需要繪制)
//創建自己飛機 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); } }
加入監聽是為了讓飛機跟隨鼠標移動,我這里定的規則是第一次鼠標必須移動到飛機上,然后飛機才會跟隨。
代碼里面用一個屬性canMove來控制,默認是false,只有鼠標第一次移入到飛機上時,這個屬性設置為true,然后就可以跟隨鼠標移動了。
//鼠標事件的創建 private void createMouseListener() { MouseAdapter mouseAdapter = new MouseAdapter() { @Override public 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; } //判斷鼠標的移入,如果移動到飛機上則canMove設置為true if(myPlane.isPoint(x,y)){ myPlane.setCanMove(true); } } }; addMouseMotionListener(mouseAdapter); addMouseListener(mouseAdapter); }
來實現一下MyPlane的move方法,這里處理了邊界,保證飛機不出界,同時保證鼠標在飛機的中間位置
//飛機跟隨鼠標移動 public void move(int x,int y) { //判斷范圍,當橫向移動在窗口范圍內 if(x-width/2>=0 && x<=panel.getWidth()-width/2){ this.x=x-width/2; } //判斷范圍,當縱向移動在窗口范圍內 if(y-height/2>=0 && y<=panel.getHeight()-height/2){ this.y=y-height/2; } }
屬性也就是坐標、寬高這些,給子彈加入移動方法
//移動 void move(){ new Thread(new Runnable() { @Override public void run() { while(alive){ y-=speed; if(y<=0){ clear(); } try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); }
飛機類加入射擊方法,200毫秒創建一發子彈
//射擊 void shoot() { new Thread(new Runnable() { @Override public void run() { while(alive){ //創建子彈 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); }
創建抽象類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(); }
創建敵機子類
有個特殊一點的地方: 因為有4種敵機,這里隨機1、2、3、4這4個數字作為屬性index,然后根據這個index來展現不同的飛機圖片,當然也可以通過這個index來設置敵機不同的移動速度,但是我為了偷懶,就全部一樣的移動速度,嘿嘿。
移動就是開啟線程讓y坐標增加,沒什么好講的,這里加一個飛機碰撞,就是當敵機跟我方飛機如何判斷碰撞的問題。
撞機分析(敵機與我機的撞機)
從上面幾個圖可看出什么?因為圖片是方形的,他們的4個頂點一定至少有一個在對方的范圍內。再看一下從左邊撞擊的圖:
從上圖看到也是這樣,其他兩個方向的也是一樣的道理,為了穩點我還加了一種情況:
1.判斷敵機的4個點是否在飛機范圍內,如果有則表示碰撞了。
2.如果1不成立,則反過來,判斷我機的4個點是否在敵機的范圍內,如果是表示碰撞了。
//判斷飛機與子彈是否碰撞 private boolean isPoint(MyPlane plane) { /* * * 兩種情況 * 1.需要判斷敵機的4個點是否在飛機范圍內,如果有則表示碰撞了 * 2.如果步驟1不成立,則反過來,判斷我機的4個點是否在敵機的范圍內,如果是標志碰撞了 */ //方式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; //只要有一個點在范圍內,則判斷為碰撞 if(comparePointMyPlane(x1,y1,plane)|| comparePointMyPlane(x2,y2,plane)||comparePointMyPlane(x3,y3,plane)||comparePointMyPlane(x4,y4,plane) ){ return true; } //方式1沒成立則用方式2判斷 //方式2 x1 = 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; } //用敵機的坐標來判斷 private boolean comparePointMyPlane(int x,int y,MyPlane plane){ //大于左上角,小于右下角的坐標則肯定在范圍內 if(x>plane.getX() && y >plane.getY() && x<plane.getX()+plane.getWidth() && y <plane.getY()+plane.getHeight() ){ return true; } return false; } //用我機的坐標來判斷 private boolean comparePoint(int x,int y){ //大于左上角,小于右下角的坐標則肯定在范圍內 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(); //刪除當前子彈 clear(); //飛機爆炸 enemyPlane.boom(); if(panel.curCount>=panel.totalCount){ panel.myPlane.setCanMove(false); panel.gameWin(); } } } } //判斷飛機與子彈是否碰撞 private boolean isPoint(EnemyPlane plane) { //因為子彈比飛機小,所以只需要判斷子彈的4個點是否在飛機范圍內,如果有則表示碰撞了 //左上角 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; //只要有一個點在范圍內,則判斷為碰撞 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){ //大于左上角,小于右下角的坐標則肯定在范圍內 if(x>plane.getX() && y >plane.getY() && x<plane.getX()+plane.getWidth() && y <plane.getY()+plane.getHeight() ){ return true; } return false; }
最后加上計分的、勝利、失敗等提示就完成了!
感謝各位的閱讀!關于“如何使用Java制作飛機大戰游戲”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。