<option id="mwy0y"><strong id="mwy0y"></strong></option>
  • <ul id="mwy0y"><sup id="mwy0y"></sup></ul>
  • <ul id="mwy0y"></ul>
  • <del id="mwy0y"><dfn id="mwy0y"></dfn></del><ul id="mwy0y"><sup id="mwy0y"></sup></ul>
  • <abbr id="mwy0y"></abbr>

    千鋒教育-做有情懷、有良心、有品質的職業教育機構

    400-811-9990
    手機站
    千鋒教育

    千鋒學習站 | 隨時隨地免費學

    千鋒教育

    掃一掃進入千鋒手機站

    領取全套視頻
    千鋒教育

    關注千鋒學習站小程序
    隨時隨地免費學習課程

    上海
    • 北京
    • 鄭州
    • 武漢
    • 成都
    • 西安
    • 沈陽
    • 廣州
    • 南京
    • 深圳
    • 大連
    • 青島
    • 杭州
    • 重慶
    當前位置:長沙千鋒IT培訓  >  技術要點  >  Java培訓新手實戰必備!單機版坦克大戰分步實現項目源碼

    Java培訓新手實戰必備!單機版坦克大戰分步實現項目源碼

    來源:千鋒教育
    發布人:千鋒長沙
    時間: 2022-03-29 17:16:42

           很多java初學者,在學習一段時間java后,都想寫一個項目練練手來檢測一下學習成果,而坦克大戰就是一個非常好的試手項目。坦克大戰本身就是一個非常經典的單機項目,其次使用java來實現,技術點幾乎能夠涉及到java所有的基礎知識。

    src=http___pic4.zhimg.com_v2-48388a17e9d61ac740611d2c7c9791fb_1200x500.jpg&refer=http___pic4.zhimg.webp

           那么千鋒老謝就從最開始手把手的教你實現坦克大戰,簡單明了,步驟詳細,絕對讓你寫出自己的坦克大戰,同時加深對java知識的理解。那我們就開始吧。

    1. 窗體繪制

    JFrame是指一個計算機語言-java的GUI程序的基本思路是以JFrame為基礎,它是屏幕上window的對象,能夠最大化、最小化、關閉。

    1.1 創建窗口

    創建類繼承JFrame

    創建啟動方法launch()

    setTitle() 設置標題

    setSize(width, height); 設置寬高

    setLocationRelativeTo(null); 設置位置,null為居中

    setResizable(); 是否可拉伸

    setVisible(); 是否可見

    setDefaultCloseOperation(3); 1,2,3 (點差號,關閉程序)

    package com.qf;

    import javax.swing.JFrame;

    public class GamePanel extends JFrame {

    private static final long serialVersionUID = 7471238471259660459L;

    //窗口寬高

    int width = 800;

    int height = 610;

    public void launch() {

    //設置窗口標題

    setTitle("千鋒坦克大戰");

    //設置寬高

    setSize(width, height);

    //居中

    setLocationRelativeTo(null);

    //差掉窗口,結束

    setDefaultCloseOperation(3);

    //窗口不可拉伸

    setResizable(false);

    //可見

    setVisible(true);

    }

    public static void main(String[] args) {

    GamePanel gp = new GamePanel();

    gp.launch();

    }

    }

    1.2 為窗口上色

    重寫paint()方法,參數g為圖形

    設置圖形顏色

    設置圖形大小

    package com.qf;

    import java.awt.Color;

    import java.awt.Graphics;

    import javax.swing.JFrame;

    public class GamePanel extends JFrame {

    private static final long serialVersionUID = 7471238471259660459L;

    //窗口寬高

    int width = 800;

    int height = 610;

    //獲取畫筆(為窗口上色)

    @Override

    public void paint(Graphics g) {

    //設置顏色

    g.setColor(Color.GRAY);

    //填充窗口

    g.fillRect(0, 0, width, height);

    }

    public void launch() {

    setTitle("千鋒坦克大戰");

    //設置寬高

    setSize(width, height);

    //居中

    setLocationRelativeTo(null);

    //差掉窗口,結束

    setDefaultCloseOperation(3);

    //窗口不可拉伸

    setResizable(false);

    //可見

    setVisible(true);

    }

    public static void main(String[] args) {

    GamePanel gp = new GamePanel();

    gp.launch();

    }

    }

    1.3 添加選項文字

    設置字體顏色,不要和背景色一樣

    設置字體,字體大小

    添加文字,及文字位置

    package com.qf;

    import java.awt.Color;

    import java.awt.Font;

    import java.awt.Graphics;

    import javax.swing.JFrame;

    public class GamePanel extends JFrame {

    private static final long serialVersionUID = 7471238471259660459L;

    //窗口寬高

    int width = 800;

    int height = 610;

    //獲取畫筆

    @Override

    public void paint(Graphics g) {

    g.setColor(Color.GRAY);

    g.fillRect(0, 0, width, height);

    //添加游戲選項

    g.setColor(Color.BLUE);

    g.setFont(new Font("仿宋", Font.BOLD, 50));

    g.drawString("選擇游戲模式", 220, 100);

    g.drawString("單人模式", 220, 200);

    g.drawString("雙人模式", 220, 300);

    }

    public void launch() {

    setTitle("千鋒坦克大戰");

    //設置寬高

    setSize(width, height);

    //居中

    setLocationRelativeTo(null);

    //差掉窗口,結束

    setDefaultCloseOperation(3);

    //窗口不可拉伸

    setResizable(false);

    //可見

    setVisible(true);

    }

    public static void main(String[] args) {

    GamePanel gp = new GamePanel();

    gp.launch();

    }

    }

    1.4 為窗口添加鍵盤事件

    添加內部類,實現KeyAdapter類,重寫keyPressed方法,監聽按鈕

    class KeyMonitor extends KeyAdapter {

    @Override

    public void keyPressed(KeyEvent e) {

    System.out.println(e.getKeyChar());

    }

    }

    窗口添加鍵盤監視器

    this.addKeyListener(new GamePanel.KeyMonitor());

    package com.qf;

    import java.awt.Color;

    import java.awt.Font;

    import java.awt.Graphics;

    import java.awt.event.KeyAdapter;

    import java.awt.event.KeyEvent;

    import javax.swing.JFrame;

    public class GamePanel extends JFrame {

    private static final long serialVersionUID = 7471238471259660459L;

    //窗口寬高

    int width = 800;

    int height = 610;

    //獲取畫筆

    @Override

    public void paint(Graphics g) {

    g.setColor(Color.GRAY);

    g.fillRect(0, 0, width, height);

    //添加游戲選項

    g.setColor(Color.BLUE);

    g.setFont(new Font("仿宋", Font.BOLD, 50));

    g.drawString("選擇游戲模式", 220, 100);

    g.drawString("單人模式", 220, 200);

    g.drawString("雙人模式", 220, 300);

    }

    //添加內部類,實現KeyAdapter類,重寫keyPressed方法

    class KeyMonitor extends KeyAdapter {

    @Override

    public void keyPressed(KeyEvent e) {

    System.out.println(e.getKeyChar());

    }

    }

    public void launch() {

    setTitle("千鋒坦克大戰");

    //設置寬高

    setSize(width, height);

    //居中

    setLocationRelativeTo(null);

    //差掉窗口,結束

    setDefaultCloseOperation(3);

    //窗口不可拉伸

    setResizable(false);

    //可見

    setVisible(true);

    this.addKeyListener(new GamePanel.KeyMonitor());

    }

    public static void main(String[] args) {

    GamePanel gp = new GamePanel();

    gp.launch();

    }

    }

    1.5 鍵盤控制選擇游戲模式

    添加指針圖片

    在項目文件夾下創建文件夾images,關于項目的圖片,插件都放在這個文件夾內

    創建圖片對象

    Image select = Toolkit.getDefaultToolkit().getImage("images/mytank_right.gif");

    設置初始縱坐標為150

    int y = 150;

    在paint()方法,添加此圖片

    g.drawImage(select, 160, y, null);

    在launch()方法中重繪圖形(每隔30毫秒)

    //重繪

    while(true) {

    repaint();

    try {

    Thread.sleep(25);

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    重寫鍵盤事件,1選擇單人模式,2選擇雙人模式

    //添加內部類,實現KeyAdapter類,重寫keyPressed方法

    class KeyMonitor extends KeyAdapter {

    @Override

    public void keyPressed(KeyEvent e) {

    int key = e.getKeyCode();

    switch(key) {

    case KeyEvent.VK_1 :

    y = 150;

    break;

    case KeyEvent.VK_2 :

    y = 250;

    break;

    case KeyEvent.VK_ENTER :

    break;

    default:

    break;

    }

    }

    }

    定義選擇相應模式后,點擊回車鍵,顯示響應窗口

    定義模式state 0:未選擇,1:單人 2:雙人

    //模式state 0:未選擇,1:單人 2:雙人

    int state = 0;

    int a = 0;

    重寫點擊事件

    //添加內部類,實現KeyAdapter類,重寫keyPressed方法

    class KeyMonitor extends KeyAdapter {

    @Override

    public void keyPressed(KeyEvent e) {

    int key = e.getKeyCode();

    switch(key) {

    case KeyEvent.VK_1 :

    a = 1; // 單人

    y = 150;

    break;

    case KeyEvent.VK_2 :

    a = 2; //雙人

    y = 250;

    break;

    case KeyEvent.VK_ENTER :

    state = a;

    break;

    default:

    break;

    }

    }

    }

    寫入圖形判斷

    if (state == 0 ) {

    g.drawString("選擇游戲模式", 220, 100);

    g.drawString("單人模式", 220, 200);

    g.drawString("雙人模式", 220, 300);

    //繪制指針

    g.drawImage(select, 160, y, null);

    } else if (state ==1 || state ==2) {

    g.drawString("游戲開始", 220, 100);

    if (state ==1) {

    g.drawString("單人模式", 220, 200);

    } else if(state ==2) {

    g.drawString("雙人模式", 220, 200);

    }

    }

    整體代碼

    package com.qf;

    import java.awt.Color;

    import java.awt.Font;

    import java.awt.Graphics;

    import java.awt.Image;

    import java.awt.Toolkit;

    import java.awt.event.KeyAdapter;

    import java.awt.event.KeyEvent;

    import javax.swing.JFrame;

    public class GamePanel extends JFrame {

    private static final long serialVersionUID = 7471238471259660459L;

    //指針圖片

    Image select = Toolkit.getDefaultToolkit().getImage("images/mytank_right.gif");

    int y =150; //縱坐標

    //模式state 0:未選擇,1:單人 2:雙人

    int state = 0;

    int a = 0;

    //窗口寬高

    int width = 800;

    int height = 610;

    //獲取畫筆

    @Override

    public void paint(Graphics g) {

    g.setColor(Color.GRAY);

    g.fillRect(0, 0, width, height);

    //添加游戲選項

    g.setColor(Color.BLUE);

    g.setFont(new Font("仿宋", Font.BOLD, 50));

    if (state == 0 ) {

    g.drawString("選擇游戲模式", 220, 100);

    g.drawString("單人模式", 220, 200);

    g.drawString("雙人模式", 220, 300);

    //繪制指針

    g.drawImage(select, 160, y, null);

    } else if (state ==1 || state ==2) {

    g.drawString("游戲開始", 220, 100);

    if (state ==1) {

    g.drawString("單人模式", 220, 200);

    } else if(state ==2) {

    g.drawString("雙人模式", 220, 200);

    }

    }

    }

    //添加內部類,實現KeyAdapter類,重寫keyPressed方法

    class KeyMonitor extends KeyAdapter {

    @Override

    public void keyPressed(KeyEvent e) {

    int key = e.getKeyCode();

    switch(key) {

    case KeyEvent.VK_1 :

    a = 1; // 單人

    y = 150;

    break;

    case KeyEvent.VK_2 :

    a = 2; //雙人

    y = 250;

    break;

    case KeyEvent.VK_ENTER :

    state = a;

    break;

    default:

    break;

    }

    }

    }

    public void launch() {

    setTitle("千鋒坦克大戰");

    //設置寬高

    setSize(width, height);

    //居中

    setLocationRelativeTo(null);

    //差掉窗口,結束

    setDefaultCloseOperation(3);

    //窗口不可拉伸

    setResizable(false);

    //可見

    setVisible(true);

    this.addKeyListener(new GamePanel.KeyMonitor());

    //重繪

    while(true) {

    repaint();

    try {

    Thread.sleep(25);

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    }

    public static void main(String[] args) {

    GamePanel gp = new GamePanel();

    gp.launch();

    }

    }

    1.6 解決閃頻

    創建一個圖片

    //解決閃動問題

    Image offScreemImage = null;

    重寫paint()方法

    創建一個和彈出窗口寬高相同的圖片,

    獲取該圖片的圖形對象,把所有內容添加到該圖片中

    //創建和容器一樣大小的Image圖片

    if(offScreemImage == null) {

    offScreemImage = this.createImage(width,height);

    }

    //獲該圖片的圖形

    Graphics gImage = offScreemImage.getGraphics();

    gImage.setColor(Color.GRAY);

    gImage.fillRect(0, 0, width, height);

    //添加游戲選項

    gImage.setColor(Color.BLUE);

    gImage.setFont(new Font("仿宋", Font.BOLD, 50));

    if (state == 0 ) {

    gImage.drawString("選擇游戲模式", 220, 100);

    gImage.drawString("單人模式", 220, 200);

    gImage.drawString("雙人模式", 220, 300);

    //繪制指針

    gImage.drawImage(select, 160, y, null);

    } else if (state ==1 || state ==2) {

    gImage.drawString("游戲開始", 220, 100);

    if (state ==1) {

    gImage.drawString("單人模式", 220, 200);

    } else if(state ==2) {

    gImage.drawString("雙人模式", 220, 200);

    }

    }

    把該圖片寫入到窗口中

    g.drawImage(offScreemImage, 0, 0,null);

    package com.qf;

    import java.awt.Color;

    import java.awt.Font;

    import java.awt.Graphics;

    import java.awt.Image;

    import java.awt.Toolkit;

    import java.awt.event.KeyAdapter;

    import java.awt.event.KeyEvent;

    import javax.swing.JFrame;

    public class GamePanel extends JFrame {

    private static final long serialVersionUID = 7471238471259660459L;

    //解決閃動問題

    Image offScreemImage = null;

    //指針圖片

    Image select = Toolkit.getDefaultToolkit().getImage("images/mytank_right.gif");

    int y =150; //縱坐標

    //模式state 0:未選擇,1:單人 2:雙人

    int state = 0;

    int a = 0;

    //窗口寬高

    int width = 800;

    int height = 610;

    //獲取畫筆

    @Override

    public void paint(Graphics g) {

    //創建和容器一樣大小的Image圖片

    if(offScreemImage == null) {

    offScreemImage = this.createImage(width,height);

    }

    //獲該圖片的圖形

    Graphics gImage = offScreemImage.getGraphics();

    gImage.setColor(Color.GRAY);

    gImage.fillRect(0, 0, width, height);

    //添加游戲選項

    gImage.setColor(Color.BLUE);

    gImage.setFont(new Font("仿宋", Font.BOLD, 50));

    if (state == 0 ) {

    gImage.drawString("選擇游戲模式", 220, 100);

    gImage.drawString("單人模式", 220, 200);

    gImage.drawString("雙人模式", 220, 300);

    //繪制指針

    gImage.drawImage(select, 160, y, null);

    } else if (state ==1 || state ==2) {

    gImage.drawString("游戲開始", 220, 100);

    if (state ==1) {

    gImage.drawString("單人模式", 220, 200);

    } else if(state ==2) {

    gImage.drawString("雙人模式", 220, 200);

    }

    }

    g.drawImage(offScreemImage, 0, 0,null);

    }

    //添加內部類,實現KeyAdapter類,重寫keyPressed方法

    class KeyMonitor extends KeyAdapter {

    @Override

    public void keyPressed(KeyEvent e) {

    int key = e.getKeyCode();

    switch(key) {

    case KeyEvent.VK_1 :

    a = 1; // 單人

    y = 150;

    break;

    case KeyEvent.VK_2 :

    a = 2; //雙人

    y = 250;

    break;

    case KeyEvent.VK_ENTER :

    state = a;

    break;

    default:

    break;

    }

    }

    }

    public void launch() {

    setTitle("千鋒坦克大戰");

    //設置寬高

    setSize(width, height);

    //居中

    setLocationRelativeTo(null);

    //差掉窗口,結束

    setDefaultCloseOperation(3);

    //窗口不可拉伸

    setResizable(false);

    //可見

    setVisible(true);

    this.addKeyListener(new GamePanel.KeyMonitor());

    //重繪

    while(true) {

    repaint();

    try {

    Thread.sleep(25);

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    }

    public static void main(String[] args) {

    GamePanel gp = new GamePanel();

    gp.launch();

    }

    }

    2. 鍵盤控制坦克移動

    2.1 添加游戲類父類

    屬性

    圖片

    位置(坐標)

    面板

    方法

    構造方法

    在圖形中構建自己

    獲取自身矩形(用于比較中彈)

    package com.qf;

    import java.awt.Graphics;

    import java.awt.Image;

    import java.awt.Rectangle;

    import java.awt.Toolkit;

    //游戲父類

    public abstract class GameObject {

    //圖片

    public Image img;

    //位置(坐標) 縱坐標 豎坐標

    public int x;

    public int y;

    //在哪個面板

    public GamePanel gamePanel;

    //有參構造器 img參數為字符串,圖片路徑

    public GameObject(String img, int x, int y, GamePanel gamePanel) {

    super();

    this.img = Toolkit.getDefaultToolkit().getImage(img);

    this.x = x;

    this.y = y;

    this.gamePanel = gamePanel;

    }

    //畫自己

    public abstract void paintSelf(Graphics g);

    //獲取自身矩形

    public abstract Rectangle getRec();

    }

    2.2 添加坦克類

    尺寸(寬高)

    速度

    方向

    不同方向圖片

    package com.qf;

    import java.awt.Point;

    import java.awt.Toolkit;

    //坦克父類

    public abstract class Tank extends GameObject {

    //尺寸

    public int width = 40;

    public int height = 50;

    //速度

    public int speed = 3;

    //方向

    public Direction direction = Direction.UP;

    //四個方向圖片

    public String upImg;

    public String leftImg;

    public String rightImg;

    public String downImg;

    public Tank(String img, int x, int y, GamePanel gamePanel,

    String upImg, String leftImg, String rightImg, String downImg) {

    super(img, x, y, gamePanel);

    this.upImg = upImg;

    this.leftImg = leftImg;

    this.rightImg = rightImg;

    this.downImg = downImg;

    }

    }

    2.3 添加玩家類

    package com.qf;

    import java.awt.Graphics;

    import java.awt.Rectangle;

    import java.awt.event.KeyEvent;

    //玩家

    public class PlayerOne extends Tank {

    public PlayerOne(String img, int x, int y, GamePanel gamePanel, String upImg, String leftImg, String rightImg,

    String downImg) {

    super(img, x, y, gamePanel, upImg, leftImg, rightImg, downImg);

    }

    @Override

    public void paintSelf(Graphics g) {

    g.drawImage(img, x, y, null);

    }

    @Override

    public Rectangle getRec() {

    return new Rectangle(x, y, width, height);

    }

    }

    2.4 在窗口中添加玩家

    創建玩家對象

    //添加玩家一到面板

    PlayerOne playerOne = new PlayerOne("images/mytank_up.gif", 125, 510,

    this,

    "images/mytank_up.gif",

    "images/mytank_left.gif",

    "images/mytank_right.gif",

    "images/mytank_down.gif");

    把玩家對象添加到圖形中

    playerOne.paintSelf(g);

    package com.qf;

    import java.awt.Color;

    import java.awt.Font;

    import java.awt.Graphics;

    import java.awt.Image;

    import java.awt.Toolkit;

    import java.awt.event.KeyAdapter;

    import java.awt.event.KeyEvent;

    import java.util.ArrayList;

    import java.util.List;

    import java.util.Random;

    import javax.swing.JFrame;

    /*

    * 已解決閃動

    */

    public class GamePanel extends JFrame {

    private static final long serialVersionUID = -9194828502749643640L;

    //解決閃動問題

    Image offScreemImage = null;

    //窗口長寬

    int width = 800;

    int height = 610;

    //指針圖片

    Image select = Toolkit.getDefaultToolkit().getImage("images/mytank.gif");

    int y =150; //縱坐標

    //定義游戲模式 0:游戲未開始 1:單人模式 2:雙人模式

    int state = 0;

    int a = 0; //根據輸入的鍵值,修改a值,再賦值給state

    //添加玩家一到面板

    PlayerOne playerOne = new PlayerOne("images/mytank_up.gif", 125, 510,

    this,

    "images/mytank_up.gif",

    "images/mytank_left.gif",

    "images/mytank_right.gif",

    "images/mytank_down.gif");

    //窗口的啟動方法

    public void launch() {

    setTitle("千鋒坦克大戰");

    //設置寬高

    setSize(width, height);

    //居中

    setLocationRelativeTo(null);

    //差掉窗口,結束

    setDefaultCloseOperation(3);

    //窗口不可拉伸

    setResizable(false);

    //可見

    setVisible(true);

    //添加鍵盤監視器

    this.addKeyListener(new GamePanel.KeyMonitor());

    //重繪

    while(true) {

    repaint();

    try {

    Thread.sleep(25); //間隔時間

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    }

    //畫 圖形

    @Override

    public void paint(Graphics g) {

    //創建和容器一樣大小的Image圖片

    if(offScreemImage == null) {

    offScreemImage = this.createImage(width,height);

    }

    //獲的該圖片的畫筆

    Graphics gImage = offScreemImage.getGraphics();

    //把窗口背景色設置為灰色

    gImage.setColor(Color.GRAY);

    //把這個背景色填充整個窗口

    gImage.fillRect(0, 0, width, height);

    //設置顏色

    gImage.setColor(Color.BLUE);

    //設置字體

    gImage.setFont(new Font("仿宋", Font.BOLD, 50));

    if(state == 0 ) {

    //添加文字

    gImage.drawString("選擇游戲模式", 220, 100);

    gImage.drawString("單人游戲", 220, 200);

    gImage.drawString("雙人游戲", 220, 300);

    //繪制指針

    gImage.drawImage(select, 160, y, null);

    } else if (state == 1 || state == 2) {

    gImage.drawString("游戲開始", 220, 100);

    if(state == 1) {

    gImage.drawString("單人游戲", 220, 200);

    } else {

    gImage.drawString("雙人游戲", 220, 200);

    }

    //添加玩家

    playerOne.paintSelf(gImage);

    }

    g.drawImage(offScreemImage, 0, 0,null);

    }

    //鍵盤監視器,需要添加到窗口中

    class KeyMonitor extends KeyAdapter {

    //按下鍵盤的回調方法

    @Override

    public void keyPressed(KeyEvent e) {

    //返回按鈕的值

    int key = e.getKeyChar();

    switch(key) {

    case KeyEvent.VK_1 :

    a = 1;

    y = 150;

    break;

    case KeyEvent.VK_2 :

    a = 2;

    y = 250;

    break;

    case KeyEvent.VK_ENTER :

    state = a;

    break;

    default:

    }

    }

    }

    public static void main(String[] args) {

    GamePanel gp = new GamePanel();

    gp.launch();

    }

    }

    2.5使用鍵盤控制坦克移動

    在坦克類(Tank)中添加上下左右四個方法

    不同方向設置不同圖片

    不同的方向

    //移動方法

    public void leftward() {

    x -=speed;

    direction = Direction.LEFT;

    setImg(leftImg);

    }

    public void rightward() {

    x +=speed;

    direction = Direction.RIGHT;

    setImg(rightImg);

    }

    public void upward() {

    y -=speed;

    direction = Direction.UP;

    setImg(upImg);

    }

    public void downward() {

    y +=speed;

    direction = Direction.DOWN;

    setImg(downImg);

    }

    public void setImg(String img) {

    this.image = Toolkit.getDefaultToolkit().getImage(img);

    }

    在PlayerOne類中按鈕點擊,松開方法,及移動方法

    W上,A左,S下,D右

    boolean left, right, up, down;

    //鍵盤按下去方法

    public void keyPressed(KeyEvent e) {

    int key = e.getKeyCode();

    switch(key) {

    case KeyEvent.VK_A : left=true; break;

    case KeyEvent.VK_S : down=true; break;

    case KeyEvent.VK_D : right=true; break;

    case KeyEvent.VK_W : up=true; break;

    }

    }

    //鍵盤松開方法

    public void keyReleased(KeyEvent e) {

    int key = e.getKeyCode();

    switch(key) {

    case KeyEvent.VK_A : left=false; break;

    case KeyEvent.VK_S : down=false; break;

    case KeyEvent.VK_D : right=false; break;

    case KeyEvent.VK_W : up=false; break;

    }

    }

    //移動的方法,每次在繪制的時候移動

    public void move() {

    if(left) {

    leftward();

    } else if (right) {

    rightward();

    } else if (up) {

    upward();

    } else if(down) {

    downward();

    }

    }

    @Override

    public void paintSelf(Graphics g) {

    g.drawImage(image, x, y, null);

    //每次繪圖的時候,根據最新的屬性,繪圖

    move();

    }

    在主窗口類中,添加對A,S,D,W按鍵的監控

    //鍵盤監控

    class KeyMonitor extends KeyAdapter {

    //點擊鍵盤的回調方法

    @Override

    public void keyPressed(KeyEvent e) {

    int key = e.getKeyChar();

    switch(key) {

    case KeyEvent.VK_1:

    y = 150;

    a = 1;

    break;

    case KeyEvent.VK_2:

    y = 250;

    a = 2;

    break;

    case KeyEvent.VK_ENTER : //點擊回車,選擇相應的模式

    state = a;

    default:

    playerOne.keyPressed(e); //這里

    }

    }

    @Override

    public void keyReleased(KeyEvent e) { //監聽按鈕的松開事件

    playerOne.keyReleased(e); //這里

    }

    }

    3. 坦克發射子彈

    3.1 創建子彈類

    屬性

    尺寸

    速度

    方向

    //尺寸

    int width = 10;

    int height =10;

    //速度

    int speed = 7;

    //方向,方向和坦克方向一致

    Direction direction;

    方法

    左移,右移,下移,上移

    根據坦克方向不同,移動方向不同

    //移動方法

    public void leftward() {

    x -=speed;

    }

    public void rightward() {

    x +=speed;

    }

    public void upward() {

    y -=speed;

    }

    public void downward() {

    y +=speed;

    }

    //根據方向移動,繪制自己時,調用

    public void go() {

    switch(direction) {

    case LEFT: leftward(); break;

    case DOWN: downward(); break;

    case RIGHT: rightward();break;

    case UP: upward(); break;

    }

    }

    全部代碼:

    package com.qf;

    import java.awt.Graphics;

    import java.awt.Rectangle;

    public class Bullet extends GameObject {

    //尺寸

    int width = 10;

    int height =10;

    //速度

    int speed = 7;

    //方向,方向和坦克方向一致

    Direction direction;

    //移動方法

    public void leftward() {

    x -=speed;

    }

    public void rightward() {

    x +=speed;

    }

    public void upward() {

    y -=speed;

    }

    public void downward() {

    y +=speed;

    }

    //繪制自己時,調用

    public void go() {

    switch(direction) {

    case LEFT: leftward(); break;

    case DOWN: downward(); break;

    case RIGHT: rightward();break;

    case UP: upward(); break;

    }

    }

    public Bullet(String imageUrl, int x, int y, GamePanal gamePanal,Direction direction) {

    super(imageUrl, x, y, gamePanal);

    this.direction = direction;

    }

    @Override

    public void paintSelf(Graphics g) {

    g.drawImage(image, x, y, null);

    //繪制子彈時,可以移動

    go();

    }

    @Override

    public Rectangle getRec() {

    return new Rectangle(x, y, width, height);

    }

    }

    3.2 實現坦克發射子彈

    在坦克類中

    獲取坦克的頭部坐標

    public Point getHeadPoint() {

    switch(direction) {

    case LEFT: return new Point(x, y+height/2);

    case DOWN: return new Point(x+width/2, y+height);

    case RIGHT: return new Point(x+width, y+height/2);

    case UP: return new Point(x+width/2, y);

    default: return null;

    }

    }

    添加發射方法

    根據坦克頭坐標,及坦克方向創建子彈

    把創建的子彈添加到面板中創建子彈集合中

    //發射子彈

    public void attack() {

    //獲取頭坐標

    Point point = getHeadPoint();

    //創建子彈

    Bullet bullet = new Bullet("images/bullet.gif", point.x, point.y,

    this.gamePanal, this.direction);

    //可以一次按很多次發射,把產生的子彈存儲在面板的子彈集合中

    this.gamePanal.bulletList.add(bullet);

    }

    //子彈集合 在面板類中定義

    List<Bullet> bulletList = new ArrayList<Bullet>();

    //繪制玩家

    playerOne.paintSelf(gImage);

    //繪制子彈 在面板類中操作

    for(Bullet bullet : bulletList) {

    bullet.paintSelf(gImage);

    }

    在PlayerOne類中添加鍵盤事件

    當點擊空格按鈕,就會調用射擊方法

    //鍵盤按下去方法

    public void keyPressed(KeyEvent e) {

    int key = e.getKeyCode();

    switch(key) {

    case KeyEvent.VK_A : left=true; break;

    case KeyEvent.VK_S : down=true; break;

    case KeyEvent.VK_D : right=true; break;

    case KeyEvent.VK_W : up=true; break;

    case KeyEvent.VK_SPACE: attack(); //添加發送子彈方法

    }

    }

    3.3 添加子彈冷卻時間

    在坦克類中添加冷卻狀態,冷卻時間

    //冷卻狀態

    boolean attackCoolDown = true;

    //冷卻時間

    int attackCoolTime = 1000;

    創建冷卻線程

    //冷卻線程

    class AttackCool extends Thread {

    public void run() {

    attackCoolDown = false;

    try {

    Thread.sleep(attackCoolTime);

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    attackCoolDown = true;

    }

    }

    修改發射方法,每發射一次,啟動冷卻線程

    //發射子彈

    public void attack() {

    if (attackCoolDown) {

    //獲取頭坐標

    Point point = getHeadPoint();

    //創建子彈

    Bullet bullet = new Bullet("images/bullet.gif", point.x, point.y,

    this.gamePanal, this.direction);

    //可以一次按很多次發射,把產生的子彈存儲在面板的子彈集合中

    this.gamePanal.bulletList.add(bullet);

    //啟動冷卻線程

    new AttackCool().start();

    }

    }

    4. 敵方坦克

    4.1 隨機添加敵方坦克

    添加敵方坦克類

    //敵方坦克

    public class Bot extends Tank{

    public Bot(String imageUrl, int x, int y, GamePanal gamePanal, String upImg, String leftImg, String rightImg,

    String downImg) {

    super(imageUrl, x, y, gamePanal, upImg, leftImg, rightImg, downImg);

    }

    @Override

    public void paintSelf(Graphics g) {

    g.drawImage(image, x, y, null);

    }

    @Override

    public Rectangle getRec() {

    return new Rectangle(x, y, width, height);

    }

    }

    批量把敵方坦克圖片添加到面板上

    把敵方坦克的圖片添加到項目中(4個方向各一個)

    在面板中創建敵方坦克集合

    面板每重新加載100次,添加一個敵方坦克,敵方坦克最多有10各

    //重繪次數

    int count =0;

    //敵方坦克個數

    int enemyCount = 0;

    在重新繪制循環中,添加敵方坦克

    //重新載入窗口

    while(true) {

    if(count%100 ==1 && enemyCount<5 ) {

    //添加敵方坦克

    Random r = new Random();

    int rnum = r.nextInt(800);

    botList.add(new Bot("images/enemy_up.png", rnum, 110,

    this, "images/enemy_up.png", "images/enemy_left.png",

    "images/enemy_right.png", "images/enemy_down.gif"));

    enemyCount++;

    }

    this.repaint();

    try {

    Thread.sleep(25);

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    在開始游戲加載面板中顯示敵方坦克并對count自增(paint方法)

    if (state ==0) {

    //220離左邊的距離, 100離上面的距離

    gImage.drawString("選擇游戲模式", 220, 100);

    gImage.drawString("單人模式", 220, 200);

    gImage.drawString("雙人模式", 220, 300);

    //畫入圖像

    gImage.drawImage(select, 140, y, null);

    } else {

    gImage.drawString("開始游戲", 220, 100);

    if(state == 1) {

    gImage.drawString("單人模式", 220, 200);

    } else if (state == 2) {

    gImage.drawString("雙人模式", 220, 200);

    }

    //繪制玩家

    playerOne.paintSelf(gImage);

    //繪制子彈

    for(Bullet bullet : bulletList) {

    bullet.paintSelf(gImage);

    }

    //繪制敵方坦克

    for(Bot bot : botList) {

    bot.paintSelf(gImage);

    }

    count++;

    }

    4.2 敵方坦克隨機移動

    隨機生成方向(Bot)

    //隨機生成個數,表示方向

    public Direction getRandomDirection() {

    Random random = new Random();

    int rnum = random.nextInt(4); //0-3

    switch(rnum) {

    case 0 : return Direction.LEFT;

    case 1 : return Direction.RIGHT;

    case 2 : return Direction.UP;

    case 3 : return Direction.DOWN;

    default: return null;

    }

    }

    添加運動方法,每20次,轉化一次方向(Bot)

    //每間隔20,轉換方向一次

    int moveTime = 20;

    //行走方法

    public void go() {

    if (moveTime >=20) {

    direction = getRandomDirection();

    moveTime=0;

    } else {

    moveTime++;

    }

    switch(direction) {

    case LEFT: leftward(); break;

    case DOWN: downward(); break;

    case RIGHT: rightward();break;

    case UP: upward(); break;

    }

    }

    //勿忘把重繪方法添加到繪制自己方法中

    @Override

    public void paintSelf(Graphics g) {

    g.drawImage(image, x, y, null);

    go();

    }

    4.3 敵方坦克射擊

    創建敵方子彈類,直接繼承Bullet即可

    package com.qf;

    import java.awt.Graphics;

    import java.awt.Rectangle;

    //敵方子彈類

    public class EnemyBullet extends Bullet {

    public EnemyBullet(String imageUrl, int x, int y, GamePanal gamePanal, Direction direction) {

    super(imageUrl, x, y, gamePanal, direction);

    }

    @Override

    public void paintSelf(Graphics g) {

    g.drawImage(image, x, y, null);

    //在圖形繪制自己時移動

    go();

    }

    @Override

    public Rectangle getRec() {

    return new Rectangle(x, y, width, height);

    }

    }

    在機器人坦克類中添加攻擊發射方法

    機器人自行發射,把該方法添加到go()方法中

    //攻擊類,添加到go方法中

    public void attack() {

    Point p = getHeadPoint();

    Random random = new Random();

    int num = random.nextInt(100); // [0,99]

    if(num <4) { //4%設計概率,可自行調節發射頻率 0,1,2,3

    this.gamePanal.bulletList.add(new EnemyBullet("images/bullet.gif",

    p.x, p.y, this.gamePanal, this.direction));

    }

    }

    //機器人坦克自行行走

    public void go() {

    attack(); // 添加到這里,邊走邊發射子彈

    if (moveTime>=20) {

    direction = getRandomDirection();

    moveTime =0;

    } else {

    moveTime++;

    }

    switch(direction) {

    case LEFT : leftward(); break;

    case RIGHT : rightward(); break;

    case DOWN : downward(); break;

    case UP : upward(); break;

    }

    }

    5. 碰撞檢測

    5.1 我方子彈(Bullet)和敵方坦克(Bot)碰撞

    在面板類中定義要刪除/消失的子彈(GamePanal)

    在每次重繪時,把刪除的子彈從繪制子彈集合中刪除

    //碰撞后要刪除的子彈

    List<Bullet> removeList = new ArrayList<Bullet>();

    //繪制子彈

    for(Bullet bullet : bulletList) {

    bullet.paintSelf(gImage);

    }

    //去除要刪除的子彈

    bulletList.removeAll(removeList);

    在子彈類中添加碰撞方法(Bullet)

    在繪制每個子彈時,把當前子彈對象和所有計算機坦克比較是否碰撞

    該方法要添加到繪制方法中

    //碰撞 添加到paintSelf方法中,每次繪制時,檢測

    public void hitBot() {

    List<Bot> bots = this.gamePanal.botList;

    for(Bot bot : bots) {

    if (this.getRec().intersects(bot.getRec())) {

    this.gamePanal.botList.remove(bot); // 坦克消失

    this.gamePanal.removeList.add(this); //子彈消失

    break;

    }

    }

    }

    @Override

    public void paintSelf(Graphics g) {

    g.drawImage(image, x, y, null);

    //在圖形繪制自己時移動

    go();

    //每次繪制時,檢測碰撞

    hitBot();

    }

    5.2 敵方子彈和我方坦克碰撞

    添加我方坦克集合(為后續擴展使用)

    把玩家都添加到此集合中,在選擇游戲模式時添加

    玩家的繪制,修改成遍歷該集合

    不要忘記把原繪制玩家代碼刪除

    //玩家坦克集合

    List<Tank> playerList = new ArrayList<Tank>();

    //鍵盤監控

    class KeyMonitor extends KeyAdapter {

    //點擊鍵盤的回調方法

    @Override

    public void keyPressed(KeyEvent e) {

    int key = e.getKeyChar();

    switch(key) {

    case KeyEvent.VK_1:

    y = 150;

    a = 1;

    break;

    case KeyEvent.VK_2:

    y = 250;

    a = 2;

    break;

    case KeyEvent.VK_ENTER : //點擊回車,選擇相應的模式

    state = a;

    //添加玩家,雙人待做

    playerList.add(playerOne); //----這里添加

    default:

    playerOne.keyPressed(e); //坦克的移動

    }

    }

    //繪制玩家

    // playerOne.paintSelf(gImage);

    for(Tank player : playerList) {

    player.paintSelf(gImage);

    }

    在敵方子彈類中添加碰撞方法

    該方法添加到繪制方法中

    //碰撞 添加到paintSelf方法中,每次繪制時,檢測

    public void hitPlayer() {

    List<Tank> tanks = this.gamePanel.playerList;

    for(Tank t : tanks) {

    if (this.getRec().intersects(t.getRec())) {

    this.gamePanel.playerList.remove(t); // 玩家坦克消失

    this.gamePanel.removeList.add(this); //子彈消失

    break;

    }

    }

    }

    @Override

    public void paintSelf(Graphics g) {

    g.drawImage(image, x, y, null);

    //在圖形繪制自己時移動

    go();

    //檢測碰撞

    hitPlayer();

    }

    5.3 與圍墻的碰撞檢測

    5.3.1面板中添加圍墻

    添加圍墻類

    package com.qf;

    import java.awt.Graphics;

    import java.awt.Rectangle;

    public class Wall extends GameObject {

    //圍墻尺寸

    int length = 60;

    public Wall(String imageUrl, int x, int y, GamePanel gamePanal) {

    super(imageUrl, x, y, gamePanel);

    }

    @Override

    public void paintSelf(Graphics g) {

    g.drawImage(image, x, y, null);

    }

    @Override

    public Rectangle getRec() {

    return new Rectangle(x, y, length, length);

    }

    }

    在面板中添加圍墻集合,在lunch方法中添加圍墻,然后把集合繪制到面板中

    //圍墻列表

    List<Wall> wallList = new ArrayList<Wall>();

    //在lunch方法中

    //添加圍墻

    for(int i = 0; i<14; i++) {

    wallList.add(new Wall("images/wall.png", i*60, 170, this));

    }

    wallList.add(new Wall("images/wall.png", 305, 560, this));

    wallList.add(new Wall("images/wall.png", 305, 500, this));

    wallList.add(new Wall("images/wall.png", 365, 500, this));

    wallList.add(new Wall("images/wall.png", 425, 500, this));

    wallList.add(new Wall("images/wall.png", 425, 560, this));

    //在paint方法中繪制圍墻

    for(Wall wall : wallList) {

    wall.paintSelf(gImage);

    }

    5.3.2 添加圍墻和子彈碰撞檢測

    子彈類添加和圍墻碰撞方法(Bullet)

    把該方法添加到go()方法中,讓敵方子彈也可以和圍墻碰撞

    //子彈和圍墻碰撞,添加到go方法中,讓敵方子彈也可以擊破圍墻

    public void hitWall() {

    List<Wall> walls = this.gamePanal.wallList;

    for(Wall wall : walls) {

    if (this.getRec().intersects(wall.getRec())) {

    this.gamePanal.wallList.remove(wall); // 圍墻消失

    this.gamePanal.removeList.add(this); //子彈消失

    break;

    }

    }

    }

    public void go() {

    switch(direction) {

    case LEFT : leftward(); break;

    case RIGHT : rightward(); break;

    case DOWN : downward(); break;

    case UP : upward(); break;

    }

    hitWall(); //---------------添加到這里

    }

    5.3.3 坦克和圍墻碰撞

    當坦克和圍墻碰撞時,坦克無法移動

    在坦克類中添加圍墻碰撞方法

    然后在移動類中判斷是否會和圍墻碰撞,如果碰撞則不移動

    //與圍墻碰撞檢測

    public boolean hitWall(int x, int y) {

    List<Wall> wallList = this.gamePanal.wallList;

    //坦克下一步將要移動后的矩形

    Rectangle next = new Rectangle(x, y, width, height);

    for(Wall wall : wallList) {

    if(next.intersects(wall.getRec())) {

    return true;

    }

    }

    return false;

    }

    修改所有移動的方法

    //移動方法 左移

    public void leftward() {

    if(!hitWall(x-speed, y)) {

    x -=speed;

    }

    direction = Direction.LEFT;

    setImg(leftImg);

    }

    //移動方法 右移

    public void rightward() {

    if(!hitWall(x+speed, y)) {

    x +=speed;

    }

    direction = Direction.RIGHT;

    setImg(rightImg);

    }

    //移動方法 上移

    public void upward() {

    if(!hitWall(x, y-speed)) {

    y -=speed;

    }

    direction = Direction.UP;

    setImg(upImg);

    }

    //移動方法 下移

    public void downward() {

    if(!hitWall(x, y+speed)) {

    y +=speed;

    }

    direction = Direction.DOWN;

    setImg(downImg);

    }

    5.4 判斷坦克邊緣的碰撞

    坦克類中添加邊緣碰撞判斷(Tank)

    該判斷添加到移動方法中

    //判斷和邊緣的碰撞

    public boolean moveToBorder(int x,int y) {

    if(x<0) {

    return true;

    } else if (x+width > this.gamePanal.width) {

    return true;

    } else if (y <0) {

    return true;

    } else if (y+height > this.gamePanal.height) {

    return true;

    }

    return false;

    }

    //移動方法 左移

    public void leftward() {

    if(!hitWall(x-speed, y) && !moveToBorder(x-speed, y)) {

    x -=speed;

    }

    direction = Direction.LEFT;

    setImg(leftImg);

    }

    //移動方法 右移

    public void rightward() {

    if(!hitWall(x+speed, y) && !moveToBorder(x+speed, y)) {

    x +=speed;

    }

    direction = Direction.RIGHT;

    setImg(rightImg);

    }

    //移動方法 上移

    public void upward() {

    if(!hitWall(x, y-speed)&&!moveToBorder(x, y-speed)) {

    y -=speed;

    }

    direction = Direction.UP;

    setImg(upImg);

    }

    //移動方法 下移

    public void downward() {

    if(!hitWall(x, y+speed)&&!moveToBorder(x, y+speed)) {

    y +=speed;

    }

    direction = Direction.DOWN;

    setImg(downImg);

    }

    5.5判斷子彈是否出界

    判斷子彈坐標是否出界,如果出界則刪除

    該方法添加到go方法中

    //如果子彈出界,該方法添加在go方法中,敵人子彈也可以刪除 刪除子彈,節省資源

    public void moveToBorder() {

    if(x<0 || x+width > this.gamePanel.width) {

    this.gamePanel.removeList.add(this);

    }

    if(y<0 || y+height > this.gamePanel.height) {

    this.gamePanel.removeList.add(this);

    }

    }

    //子彈的移動是根據方向來的

    public void go() {

    switch(direction) {

    case LEFT : leftward(); break;

    case RIGHT : rightward(); break;

    case DOWN : downward(); break;

    case UP : upward(); break;

    }

    hitWall(); //子彈撞墻

    moveToBorder(); //子彈出界刪除

    }

    6. 添加基地

    6.1 創建并添加基地

    創建基地類

    package com.qf;

    import java.awt.Graphics;

    import java.awt.Rectangle;

    //基地類

    public class Base extends GameObject {

    int length = 60;

    public Base(String imageUrl, int x, int y, gamePanel gamePanal) {

    super(imageUrl, x, y, gamePanal);

    }

    @Override

    public void paintSelf(Graphics g) {

    g.drawImage(image, x, y, null);

    }

    @Override

    public Rectangle getRec() {

    return new Rectangle(x, y, length, length);

    }

    }

    在面板中添加基地

    //基地集合

    List<Base> baseList = new ArrayList<Base>();

    //在lunch方法添加創建一個基地

    Base base = new Base("images/base.png", 365, 560, this);

    baseList.add(base);

    //繪制基地

    for(Base base : baseList) {

    base.paintSelf(gImage);

    }

    6.2 子彈與基地的碰撞測試

    在子彈類中添加碰撞方法

    該方法添加到go方法中

    //與基地碰撞方法

    public void hitBase() {

    List<Base> bases = this.gamePanel.baseList;

    for(Base base : bases) {

    if (this.getRec().intersects(base.getRec())) {

    this.gamePanel.baseList.remove(base); // 基地消失

    this.gamePanel.removeList.add(this); //子彈消失

    break;

    }

    }

    }

    public void go() {

    switch(direction) {

    case LEFT : leftward(); break;

    case RIGHT : rightward(); break;

    case DOWN : downward(); break;

    case UP : upward(); break;

    }

    hitWall(); //子彈撞墻

    moveToBorder(); //子彈出界刪除

    hitBase(); //---銷毀基地

    }

    7. 游戲規則

    我方勝利

    把所有的敵人干倒

    機器贏了

    玩家坦克被干掉

    基地被倒了

    //判斷規則,在每次重繪時

    //玩家贏了

    if(botList.size() == 0 && enemyCount == 3) {

    state = 3;

    }

    //機器贏了

    if((playerList.size()==0&&(state ==1 || state ==2))

    || baseList.size() ==0) {

    state = 4;

    }

    //獲取畫筆

    @Override

    public void paint(Graphics g) {

    if(offScreemImage==null) {

    offScreemImage = this.createImage(width, height);

    }

    Graphics gImage = offScreemImage.getGraphics();

    //設置圖形的顏色

    gImage.setColor(Color.GRAY);

    //把設置的顏色,填充整個矩形

    gImage.fillRect(0, 0, width, height);

    //重新設置字體顏色

    gImage.setColor(Color.BLUE);

    gImage.setFont(new Font("楷體", Font.BOLD, 50));

    if (state ==0) {

    //220離左邊的距離, 100離上面的距離

    gImage.drawString("選擇游戲模式", 220, 100);

    gImage.drawString("單人模式", 220, 200);

    gImage.drawString("雙人模式", 220, 300);

    //畫入圖像

    gImage.drawImage(select, 140, y, null);

    } else if (state == 1 || state ==2){

    gImage.drawString("開始游戲", 220, 100);

    if(state == 1) {

    gImage.drawString("單人模式", 220, 200);

    } else if (state == 2) {

    gImage.drawString("雙人模式", 220, 200);

    }

    //繪制玩家

    // playerOne.paintSelf(gImage);

    //繪制玩家列表

    for(Tank tank : playerList) {

    tank.paintSelf(gImage);

    }

    //繪制子彈

    for(Bullet bullet : bulletList) {

    bullet.paintSelf(gImage);

    }

    //刪除發生碰撞的子彈

    bulletList.removeAll(removeList);

    //繪制機器人坦克

    for (Bot bot : botList) {

    bot.paintSelf(gImage);

    }

    //繪制城墻

    for (Wall wall : wallList) {

    wall.paintSelf(gImage);

    }

    //繪制基地

    for (Base base : baseList) {

    base.paintSelf(gImage);

    }

    count++;

    } else if(state ==3) {

    gImage.drawString("我贏了", 220, 100);

    } else if(state == 4) {

    gImage.drawString("機器贏了", 220, 100);

    }

    //把重新繪制的圖片放到窗口中(從左上角開始放)

    g.drawImage(offScreemImage, 0, 0, null);

    }

    聲明:本站稿件版權均屬千鋒教育所有,未經許可不得擅自轉載。

    猜你喜歡LIKE

    最新文章NEW

    相關推薦HOT

    更多>>

    快速通道 更多>>

    最新開班信息 更多>>

    網友熱搜 更多>>