国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java游戲開發(fā) —— 坦克大戰(zhàn)

這篇具有很好參考價值的文章主要介紹了Java游戲開發(fā) —— 坦克大戰(zhàn)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

Java游戲開發(fā) —— 坦克大戰(zhàn)
Java游戲開發(fā) —— 坦克大戰(zhàn)

引言:

坦克大戰(zhàn)也是小時一個比較經(jīng)典的游戲了,我在網(wǎng)上也是參考了韓順平老師寫的坦克大戰(zhàn),并做了一下完善,編寫出來作為兒時的回憶吧!

思路:

  1. 創(chuàng)建主窗口,加載菜單及游戲面板。

  1. 在游戲面板中初始化各種參數(shù),并建立各種功能組件。

  1. 利用線程固定刷新游戲界面。

  1. 處理各種碰撞問題

  1. 游戲結(jié)束。

代碼:

Java游戲開發(fā) —— 坦克大戰(zhàn)

本游戲用的是JDK1.8,編碼UTF-8;

我這里用的IDE是Intellij Idea,新建了一個game的空項目,tankwar作為其中的一個模塊(當(dāng)然這個不重要,個人喜好罷了)。類比較多,TankWar.java是游戲入口類。GameFrame.java是主窗口類。GamePanel.java是游戲面板類。GameLogic.java是游戲邏輯類。先一口氣把所有的代碼貼上來再說。

  1. TankWar.java 游戲入口類

package lag.game.tankwar;

/**
 * 功能:坦克大戰(zhàn)<br>
 * 作者:我是小木魚(Lag)
 */
public class TankWar
{
    public static void main(String[] args)
    {
        new GameFrame();
    }
}
  1. GameFrame.java游戲窗口

package lag.game.tankwar;

import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * 游戲窗口
 */
public class GameFrame extends JFrame implements ActionListener
{
    /** 游戲面板 */
    private GamePanel gamePanel;

    /**
     * 構(gòu)造函數(shù)
     */
    public GameFrame()
    {
        try
        {
            // 定制菜單
            JMenuBar mb_main = new JMenuBar();      // 菜單欄
            JMenu m_game = new JMenu("游戲");     // 游戲菜單
            m_game.setFont(new Font("微軟雅黑",Font.PLAIN,12));    // 游戲菜單字體
            JMenuItem mi_new = new JMenuItem("新游戲");    // 游戲菜單中的新游戲子菜單
            mi_new.setFont(new Font("微軟雅黑",Font.PLAIN,12));     // 子菜單字體
            mi_new.addActionListener(this);       // 為窗口增加新游戲菜單的事件監(jiān)聽
            mi_new.setActionCommand("new");         // 設(shè)置新游戲菜單的監(jiān)聽標(biāo)識
            m_game.add(mi_new);                     // 將新游戲子菜單附加到游戲菜單上
            JMenuItem mi_grade = new JMenuItem("選關(guān)卡");
            mi_grade.setFont(new Font("微軟雅黑",Font.PLAIN,12));
            mi_grade.addActionListener(this);
            mi_grade.setActionCommand("grade");
            m_game.add(mi_grade);
            m_game.addSeparator();                  // 菜單分隔符
            JMenuItem mi_exit = new JMenuItem("退出");
            mi_exit.setFont(new Font("微軟雅黑",Font.PLAIN,12));
            mi_exit.addActionListener(this);
            mi_exit.setActionCommand("exit");
            m_game.add(mi_exit);
            mb_main.add(m_game);
            JMenu m_help = new JMenu("幫助");
            m_help.setFont(new Font("微軟雅黑",Font.PLAIN,12));
            JMenuItem mi_about = new JMenuItem("關(guān)于");
            mi_about.setFont(new Font("微軟雅黑",Font.PLAIN,12));
            mi_about.addActionListener(this);
            mi_about.setActionCommand("about");
            m_help.add(mi_about);
            mb_main.add(m_help);
            this.setJMenuBar(mb_main);

            // 定制面板
            this.gamePanel = new GamePanel();
            this.add(this.gamePanel);

            // 定制窗口
            this.setTitle("坦克大戰(zhàn)");                   // 標(biāo)題
            this.setLayout(null);                       // 清空布局管理器
            this.setSize(this.gamePanel.getWidth() + 10,this.gamePanel.getHeight() + 60);   // 根據(jù)游戲面板大小設(shè)置游戲窗口大小
            this.setResizable(false);                   // 程序運行時禁止改變窗口大小尺寸
            this.setLocationRelativeTo(null);           // 窗口居中
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    // 點擊窗口X按鈕時默認(rèn)關(guān)閉程序
            this.setVisible(true);                      // 顯示窗口
            //音樂(用線程播放)
//            new Thread(()->{
//                GameMusic gameMusic = new GameMusic(this.getClass().getClassLoader().getResourceAsStream("audio/start.wav"));
//                gameMusic.play(false);
//            }).start();
        }
        catch (Exception e)
        {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this,"程序出現(xiàn)異常錯誤,即將退出!\r\n\r\n"+e.toString(),"提示",JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
    }

    /**
     * 事件監(jiān)聽
     */
    @Override
    public void actionPerformed(ActionEvent e)
    {
        // 監(jiān)聽事件的標(biāo)識
        String command = e.getActionCommand();
        switch (command)
        {
            case "new":     // 開始新游戲
                this.gamePanel.newGame();
                break;
            case "grade":
                int gradeCount = GameMap.getGradeCount();
                String[] options = new String[gradeCount];
                for (int i = 0; i < gradeCount; i++)
                {
                    options[i] = i + 1 + "";
                }
                String grade = (String)JOptionPane.showInputDialog(this, "請選擇你要進行的關(guān)卡:","選關(guān)", JOptionPane.INFORMATION_MESSAGE, null, options, options[0]);
                gamePanel.setGrade(Integer.parseInt(grade));
                gamePanel.newGame();
                break;
            case "exit":
                System.exit(0);
                break;
            case "about":
                JOptionPane.showMessageDialog(this,"我是小木魚(Lag)","提示",JOptionPane.INFORMATION_MESSAGE);
                break;

        }
    }

}
  1. GamePanel.java游戲面板

package lag.game.tankwar;

import java.awt.*;
import javax.swing.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Vector;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;

/**
 * 游戲面板
 */
public class GamePanel extends JPanel implements KeyListener
{
    /** 游戲狀態(tài)常量 */
    private final static int GAME_STATE_READY = 0;       // 游戲未開始
    private final static int GAME_STATE_RUNNING = 1;     // 游戲運行中
    private final static int GAME_STATE_OVER = 9;        // 游戲已結(jié)束

    /** 游戲運行場景范圍常量 */
    public final static int GAME_ACTION_WIDTH = Block.BLOCK_WIDTH * 26;     // 游戲運行場景寬度
    public final static int GAME_ACTION_HEIGHT = Block.BLOCK_HEIGHT * 26;    // 游戲運行場景寬度

    /** 游戲面板范圍常量 */
    public final static int GAME_PANEL_WIDTH = GAME_ACTION_WIDTH + 150;     // 游戲面板寬度
    public final static int GAME_PANEL_HEIGHT = GAME_ACTION_HEIGHT;         // 游戲面板高度

    /** 利用雙緩沖機制防止畫面閃爍(創(chuàng)建一張與面板畫面一樣大小的圖片,所有的元素先繪制到該圖片上,再將該圖片一次性繪制到面板畫面上) */
    private BufferedImage bufferedImage = new BufferedImage(GAME_ACTION_WIDTH,GAME_ACTION_HEIGHT,BufferedImage.TYPE_4BYTE_ABGR);

    /** 游戲刷新頻率 */
    private int repaintInterval = 50;      // 游戲每秒刷新(1000/repaintInterval)次

    /** 游戲狀態(tài) */
    private int gameState = GAME_STATE_READY;

    /** 我方的坦克 */
    private Hero hero;

    /** 我方坦克模型(顯示在計分榜上) */
    private Hero heroModel = new Hero(GAME_ACTION_WIDTH + 30,200,Tank.TANK_DIRECTION_RIGHT);

    /** 敵方坦克池(考慮線程安全用Vector,沒用ArrayList) */
    private Vector<Enemy> enemyPool = new Vector<>();

    /** 敵方坦克池最大數(shù)量 */
    private int enemyPoolMaxNum = 0;

    /** 敵方坦克死亡數(shù)量 */
    private int enemyDeadNum = 0;

    /** 敵方坦克模型(顯示在計分榜上) */
    private Enemy enemyModel = new Enemy(GAME_ACTION_WIDTH + 30,20,Tank.TANK_DIRECTION_RIGHT);

    /** 創(chuàng)建敵方坦克線程是否運行標(biāo)識 */
    private boolean createEnemyTankThreadRunning = false;

    /** 上次投放時間(用來設(shè)置投放坦克最小時間間隔) */
    private long lastCreateEnemyTankTime = System.currentTimeMillis();

    /** 塊列表 */
    private List<Block> blockList = new ArrayList<>();

    /** 爆炸列表 */
    private List<Bomb> bombList = new ArrayList<>();

    /** 游戲關(guān)卡 */
    private int grade = 1;

    /** 游戲某關(guān)地圖 */
    private byte[][] gameGradeMap;

    /** 大本營 */
    private Camp camp = new Camp(12 * Block.BLOCK_WIDTH,24 * Block.BLOCK_HEIGHT);

    /**
     * 構(gòu)造函數(shù)
     */
    public GamePanel()
    {
        // 設(shè)置面板大小
        this.setSize(GAME_PANEL_WIDTH,GAME_PANEL_HEIGHT);

        // 監(jiān)聽鍵盤事件
        this.setFocusable(true);           // 先讓面板得到焦點
        this.addKeyListener(this);      // 將監(jiān)聽鍵盤事件附加到面板上

        // 創(chuàng)建游戲邏輯實例
        GameLogic.setInstance(new GameLogic(this));
    }

    /**
     * 開始新游戲
     */
    public void newGame()
    {
        // 游戲清空重置
        gameReset();

        // 設(shè)置游戲狀態(tài)為運行中
        this.gameState = GAME_STATE_RUNNING;

        // 加載游戲地圖
        loadGameMap();

        // 設(shè)置大本營
        camp.setState(Camp.CAMP_STATE_RUNNING);

        // 創(chuàng)建我方坦克
        int heroX = 8 * Block.BLOCK_WIDTH;
        int heroY = (this.gameGradeMap.length - 2) * Block.BLOCK_HEIGHT;
        hero = new Hero(heroX,heroY,Tank.TANK_DIRECTION_UP);
        hero.work();

        // 創(chuàng)建敵方坦克
        createEnemyTank();

        // 啟動線程來定時刷新畫面
        refresh();

    }

    /**
     * 加載游戲地圖
     */
    private void loadGameMap()
    {
        // 得到本關(guān)地圖
        this.gameGradeMap = GameMap.getGameMap(this.grade);

        // 得到地圖位置(幾行幾列)
        int row = this.gameGradeMap.length;
        int column = this.gameGradeMap[0].length;

        // 開始循環(huán)
        for (int i = 0; i < row; i++)
        {
            for (int j = 0; j < column; j++)
            {
                int mapValue = this.gameGradeMap[i][j];
                switch (mapValue)
                {
                    case Block.BLOCK_KIND_BRICK:
                        Brick brick = new Brick(Block.BLOCK_WIDTH * j,Block.BLOCK_HEIGHT * i);
                        this.blockList.add(brick);
                        break;
                    case Block.BLOCK_KIND_IRON:
                        Iron iron = new Iron(Block.BLOCK_WIDTH * j,Block.BLOCK_HEIGHT * i);
                        this.blockList.add(iron);
                        break;
                }
            }
        }

        this.enemyPoolMaxNum = GameMap.getEnemyTankNum(this.grade);     // 本關(guān)敵方坦克數(shù)量
    }

    /**
     * 游戲重置
     */
    private void gameReset()
    {
        // 停止上局正在運行的線程
        if(this.gameState == GAME_STATE_RUNNING){this.gameState = GAME_STATE_READY;}
        while (true)
        {
            if(this.createEnemyTankThreadRunning)
            {
                try
                {
                    Thread.sleep(10);
                }
                catch (InterruptedException e)
                {
                    throw new RuntimeException(e);
                }
            }
            else
            {
                break;
            }
        }

        // 清空敵方坦克池中的所有坦克及其子彈
        for (int i = 0; i < enemyPool.size(); i++)
        {
            Enemy enemy = enemyPool.get(i);
            enemy.reset();
            for (int j = 0; j < enemy.getBulletPool().size(); j++)
            {
                Bullet bullet = enemy.getBulletPool().get(j);
                bullet.reset();
            }
            enemy.getBulletPool().clear();
        }
        enemyPool.clear();
        enemyDeadNum = 0;

        // 清空我方坦克及其子彈
        if(hero != null)
        {
            hero.reset();
            for (int i = 0; i < hero.getBulletPool().size(); i++)
            {
                Bullet bullet = hero.getBulletPool().get(i);
                bullet.reset();
            }
            hero.getBulletPool().clear();
        }

        // 清空塊池中的所有塊
        blockList.clear();

    }

    /**
     * 創(chuàng)建敵方坦克
     */
    private void createEnemyTank()
    {
        this.createEnemyTankThreadRunning = true;   // 線程運行中
        new Thread(()->{
            //System.out.println("創(chuàng)建敵方坦克線程開始啟動...");
            // 記錄已投放的坦克數(shù)量
            int createEnemyTankNum = 0;
            try
            {
                while (this.gameState == GAME_STATE_RUNNING)
                {
                    // 休眠一會
                    try
                    {
                        Thread.sleep(repaintInterval);      // 休眠時間短主要是考慮可以迅速退出本線程
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                    // 控制連續(xù)投放間隔
                    long curCreateEnemyTankTime = System.currentTimeMillis();
                    if((curCreateEnemyTankTime - this.lastCreateEnemyTankTime) >= 3000)  // 3秒投放
                    {
                        this.lastCreateEnemyTankTime = curCreateEnemyTankTime;
                    }
                    else
                    {
                        continue;
                    }
                    // 投放敵方坦克到達最大值后退出本線程
                    if(createEnemyTankNum >= enemyPoolMaxNum){break;}
                    // 在敵方坦克池中尋找空閑的坦克隨機顯示在左上角或右上角
                    Enemy enemy = null;
                    for (int i = 0; i < enemyPool.size(); i++)
                    {
                        Enemy tmpEnemy = enemyPool.get(i);
                        if(tmpEnemy.getState() == Tank.TANK_STATE_FREE)
                        {
                            enemy = tmpEnemy;
                            //System.out.println("找到空閑的敵方坦克了..................");
                            break;
                        }
                    }
                    // 沒有就增加一個
                    if(enemy == null)
                    {
                        enemy = new Enemy(-100,-100,Tank.TANK_DIRECTION_DOWN);
                        enemyPool.add(enemy);
                        //System.out.println("新建敵方坦克了.................");
                    }
                    // 開始投放(隨機投放到左上角與右上角,坦克不能重疊)
                    int enemyX;     // 坦克X坐標(biāo)
                    int enemyDirection = Tank.TANK_DIRECTION_DOWN;  // 坦克方向默認(rèn)向下
                    int randomPos = GameLogic.getRandomInt(0,1);    // 隨機生成位置(0-左上角,1-右上角)
                    if(randomPos == 0)  // 左上角(方向下/右)
                    {
                        enemyX = 0;
                        if(GameLogic.getRandomInt(0,1) == 1){enemyDirection = Tank.TANK_DIRECTION_RIGHT;}
                    }
                    else    // 右上角(方向下/左)
                    {
                        enemyX = GAME_ACTION_WIDTH - Tank.TANK_WIDTH;
                        if(GameLogic.getRandomInt(0,1) == 1){enemyDirection = Tank.TANK_DIRECTION_LEFT;}
                    }
                    enemy.setX(enemyX);
                    enemy.setY(0);
                    enemy.setDirection(enemyDirection);
                    // 判斷該范圍內(nèi)是否可以投放運行
                    boolean workFlag = true;
                    for (int i = 0; i < enemyPool.size(); i++)
                    {
                        Enemy tmpEnemy = enemyPool.get(i);
                        if(tmpEnemy.getState() == Tank.TANK_STATE_RUNNING && enemy != tmpEnemy)
                        {
                            if(GameLogic.getInstance().tankCollideTank(enemy,tmpEnemy))  // 敵方坦克占位,不能投放
                            {
                                workFlag = false;
                                continue;
                            }
                        }
                    }
                    if(GameLogic.getInstance().tankCollideTank(enemy,hero))      // 我方坦克占位,不能投放
                    {
                        workFlag = false;
                    }
                    // 不能投放準(zhǔn)備下一次
                    if(!workFlag){continue;}
                    // 可以投放了
                    enemy.work();   // 啟動線程開始工作了
                    createEnemyTankNum++;
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            finally
            {
                this.createEnemyTankThreadRunning = false;      // 線程結(jié)束
            }
            //System.out.println("創(chuàng)建敵方坦克線程退出歷史舞臺了......");
        }).start();

    }

    /**
     * 游戲結(jié)束
     */
    private void gameOver()
    {

        // 設(shè)置游戲狀態(tài)
        this.gameState = GAME_STATE_OVER;

        // 游戲清空重置
        gameReset();

    }

    /**
     * 游戲勝利
     */
    private void gameWin()
    {
        if(enemyPoolMaxNum - enemyDeadNum <= 0)
        {
            this.grade++;
            newGame();
        }
    }

    /**
     * 碰撞處理
     */
    private void collide()
    {
        // 判斷我方子彈是否與敵方坦克或塊或大本營碰撞
        for (int i = 0; i < hero.getBulletPool().size(); i++)
        {
            Bullet bullet = hero.getBulletPool().get(i);
            if(bullet.getState() == Bullet.BULLET_STATE_RUNNING)    // 我方子彈飛行中
            {
                // 判斷是否與敵方坦克碰撞
                for (int j = 0; j < enemyPool.size(); j++)
                {
                    Enemy enemy = enemyPool.get(j);
                    if(enemy.getState() == Tank.TANK_STATE_RUNNING)     // 敵方坦克爬行中
                    {
                        // 開始判斷
                        if(GameLogic.getInstance().bulletCollideTank(bullet,enemy))   // 這還真碰上了
                        {
                            // 記錄坦克坐標(biāo),因為坦克銷毀時會改變其坐標(biāo)
                            int bombX = enemy.getX();
                            int bombY = enemy.getY();
                            // 子彈銷毀
                            bullet.reset();
                            // 坦克受到傷害
                            enemy.hurt(bullet);
                            // 判斷坦克是否死亡
                            if(enemy.isDead())
                            {
                                // 坦克銷毀
                                enemy.reset();
                                enemyDeadNum++;
                                // 坦克爆炸
                                addBomb(bombX,bombY,Tank.TANK_WIDTH,Tank.TANK_HEIGHT);
                                // 判斷是否勝利
                                gameWin();
                            }
                        }
                    }
                }
                // 判斷是否與塊碰撞
                for (int m = blockList.size() - 1; m >= 0; m--)
                {
                    Block block = blockList.get(m);
                    // 開始判斷
                    if(GameLogic.getInstance().bulletCollideBlock(bullet,block))   // 這還真碰上了
                    {
                        // 記錄塊坐標(biāo)
                        int bombX = block.getX();
                        int bombY = block.getY();
                        // 子彈銷毀
                        bullet.reset();
                        if(block.getBlockKind() == Block.BLOCK_KIND_BRICK)
                        {
                            // 磚塊銷毀
                            blockList.remove(m);
                            // 磚塊爆炸
                            addBomb(bombX,bombY,Block.BLOCK_WIDTH,Block.BLOCK_HEIGHT);
                        }
                        else
                        {
                            addBomb(bombX,bombY,Block.BLOCK_WIDTH,Block.BLOCK_HEIGHT);
                        }
                    }
                }
                // 判斷是否與大本營碰撞
                if(camp.getState() == Camp.CAMP_STATE_RUNNING)
                {
                    if(GameLogic.getInstance().bulletCollideCamp(bullet,camp))   // 完蛋了啊
                    {
                        // 子彈銷毀
                        bullet.reset();
                        // 大本營銷毀
                        camp.setState(Camp.CAMP_STATE_FREE);
                        // 大本營爆炸
                        addBomb(camp.getX(),camp.getY(),camp.getWidth(),camp.getHeight());
                        // 游戲結(jié)束
                        gameOver();
                    }
                }
            }
        }

        // 判斷敵方子彈是否與我方坦克或塊或大本營碰撞(不需要判斷敵方坦克狀態(tài),因為即使坦克銷毀子彈可能仍然在飛)
        for (int i = 0; i < enemyPool.size(); i++)
        {
            // 判斷是否與我方坦克碰撞
            Enemy enemy = enemyPool.get(i);
            for (int j = 0; j < enemy.getBulletPool().size(); j++)
            {
                Bullet bullet = enemy.getBulletPool().get(j);
                if(bullet.getState() == Bullet.BULLET_STATE_RUNNING)
                {
                    // 判斷子彈是否與坦克碰撞
                    if(GameLogic.getInstance().bulletCollideTank(bullet,hero))   // 完蛋了啊
                    {
                        // 記錄坦克坐標(biāo),因為坦克銷毀時會改變其坐標(biāo)
                        int bombX = hero.getX();
                        int bombY = hero.getY();
                        // 子彈銷毀
                        bullet.reset();
                        // 坦克受到傷害
                        hero.hurt(bullet);
                        // 判斷坦克是否死亡
                        if(hero.isDead())
                        {
                            // 坦克銷毀
                            hero.reset();
                            // 坦克爆炸
                            addBomb(bombX,bombY,Tank.TANK_WIDTH,Tank.TANK_HEIGHT);
                            // 游戲結(jié)束
                            gameOver();
                        }
                    }
                    // 判斷子彈是否與塊碰撞
                    for (int m = blockList.size() - 1; m >= 0; m--)
                    {
                        Block block = blockList.get(m);
                        // 開始判斷
                        if(GameLogic.getInstance().bulletCollideBlock(bullet,block))   // 這還真碰上了
                        {
                            // 記錄塊坐標(biāo)
                            int bombX = block.getX();
                            int bombY = block.getY();
                            // 子彈銷毀
                            bullet.reset();
                            if(block.getBlockKind() == Block.BLOCK_KIND_BRICK)
                            {
                                // 磚塊銷毀
                                blockList.remove(m);
                                // 磚塊爆炸
                                addBomb(bombX,bombY,Block.BLOCK_WIDTH,Block.BLOCK_HEIGHT);
                            }
                            else
                            {
                                addBomb(bombX,bombY,Block.BLOCK_WIDTH,Block.BLOCK_HEIGHT);
                            }
                        }
                    }
                    // 判斷子彈是否與大本營碰撞
                    if(camp.getState() == Camp.CAMP_STATE_RUNNING)
                    {
                        if(GameLogic.getInstance().bulletCollideCamp(bullet,camp))   // 完蛋了啊
                        {
                            // 子彈銷毀
                            bullet.reset();
                            // 大本營銷毀
                            camp.setState(Camp.CAMP_STATE_FREE);
                            // 大本營爆炸
                            addBomb(camp.getX(),camp.getY(),camp.getWidth(),camp.getHeight());
                            // 游戲結(jié)束
                            gameOver();
                        }
                    }
                }
            }
        }

    }

    /**
     * 添加爆炸
     */
    private void addBomb(int x,int y,int w,int h)
    {
        // 查找空閑的爆炸
        Bomb bomb = null;
        for (int i = 0; i < bombList.size(); i++)
        {
            Bomb tmpBomb = bombList.get(i);
            if(tmpBomb.getState() == Bomb.BOMB_STATE_FREE)
            {
                bomb = tmpBomb;
                //System.out.println("找到空閑的爆炸了..................");
                break;
            }
        }
        // 沒有就增加一個
        if(bomb == null)
        {
            bomb = new Bomb(-100,-100);
            bombList.add(bomb);
            //System.out.println("新建爆炸了.................");
        }
        bomb.setX(x);
        bomb.setY(y);
        bomb.setWidth(w);
        bomb.setHeight(h);
        bomb.work();
    }

    /**
     * 字符被輸入
     */
    @Override
    public void keyTyped(KeyEvent e){}

    /**
     * 某鍵被按下
     */
    @Override
    public void keyPressed(KeyEvent e)
    {
        // 游戲未開始或結(jié)束禁止按鍵
        if(this.gameState != GAME_STATE_RUNNING){return;}

        int keyCode = e.getKeyCode();
        switch (keyCode)
        {
            case KeyEvent.VK_W:
            case KeyEvent.VK_UP:
                hero.move(Tank.TANK_DIRECTION_UP);
                break;
            case KeyEvent.VK_D:
            case KeyEvent.VK_RIGHT:
                hero.move(Tank.TANK_DIRECTION_RIGHT);
                break;
            case KeyEvent.VK_S:
            case KeyEvent.VK_DOWN:
                hero.move(Tank.TANK_DIRECTION_DOWN);
                break;
            case KeyEvent.VK_A:
            case KeyEvent.VK_LEFT:
                hero.move(Tank.TANK_DIRECTION_LEFT);
                break;
            case KeyEvent.VK_SPACE:
                hero.shoot();
                break;
        }
    }

    /**
     * 某鍵被釋放
     */
    @Override
    public void keyReleased(KeyEvent e){}

    /**
     * 利用線程來定時刷新重繪游戲畫面,適用于飛機類刷新頻率較高的游戲。<br>
     * 動畫原理就是在極短時間內(nèi)連續(xù)顯示多個圖片,給人眼一種畫面動起來的錯覺(人眼的識別靜態(tài)圖時間為0.1秒)。<br>
     * 屏幕刷新頻率(FPS->幀/每秒),單位赫茲(Hz)。<br>
     * 20Hz ->每秒刷新畫面20次,即每隔(1000/20)毫秒刷新一次畫面。<br>
     */
    private void refresh()
    {
        // 利用Lambda表達式替代內(nèi)部類更方便
        new Thread(() ->
        {
            //System.out.println("游戲自動刷新線程開始啟動...");
            while (this.gameState == GAME_STATE_RUNNING)
            {
                // 碰撞處理
                collide();

                // 開始刷新
                repaint();

                // 延時睡眠
                try
                {
                    Thread.sleep(repaintInterval);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
            //System.out.println("游戲自動刷新線程退出歷史舞臺了......");
        }).start();

    }

    /**
     * 繪制游戲畫面(利用雙緩沖機制防止畫面閃爍)
     */
    @Override
    public void paint(Graphics g)
    {
        // 完成初始化工作,該語句千萬不要動
        super.paint(g);

        // 準(zhǔn)備開始游戲
        if(this.gameState == GAME_STATE_READY)
        {
            // 清一下背景
            g.setColor(Color.BLACK);
            g.fillRect(0,0,this.getWidth(),this.getHeight());
            // 顯示Logo
            g.setColor(Color.ORANGE);
            g.setFont(new Font("微軟雅黑",Font.BOLD,60));
            g.drawString("坦  克  大  戰(zhàn)", 160,170);
            g.setColor(Color.CYAN);
            g.setFont(new Font("微軟雅黑",Font.BOLD,40));
            g.drawString("2023", 280,280);
            g.setColor(Color.WHITE);
            g.setFont(new Font("宋體",Font.PLAIN,20));
            g.drawString("我是小木魚(Lag)制作", 240,420);
            return;
        }

        // 游戲結(jié)束
        if(this.gameState == GAME_STATE_OVER)
        {
            g.setColor(Color.BLACK);
            g.fillRect(0,0,this.getWidth(),this.getHeight());
            g.setColor(Color.RED);
            g.setFont(new Font("宋體",Font.BOLD,60));
            g.drawString("游戲結(jié)束", 200,170);
            g.drawString("大蝦請重新來過吧!", 70,280);
        }

        // 游戲進行中
        if(this.gameState == GAME_STATE_RUNNING)
        {
            // 設(shè)置游戲面板區(qū)域
            g.setColor(Color.LIGHT_GRAY);
            g.fillRect(0,0,this.getWidth(),this.getWidth());
            g.setColor(Color.WHITE);
            g.fill3DRect(GAME_ACTION_WIDTH,0,2,GAME_ACTION_HEIGHT,true);

            // 繪制分?jǐn)?shù)
            // 敵方坦克信息
            enemyModel.draw(g);
            g.setColor(Tank.TANK_COLOR_ENEMY);
            g.setFont(new Font("微軟雅黑",Font.BOLD,20));
            g.drawString("總數(shù):" + enemyPoolMaxNum,enemyModel.getX() ,enemyModel.getY() + 70);
            g.drawString("死亡:" + enemyDeadNum,enemyModel.getX() ,enemyModel.getY() + 100);
            g.drawString("剩余:" + (enemyPoolMaxNum - enemyDeadNum),enemyModel.getX() ,enemyModel.getY() + 130);
            // 我方坦克信息
            heroModel.draw(g);
            g.setColor(Tank.TANK_COLOR_HERO);
            g.setFont(new Font("微軟雅黑",Font.BOLD,20));
            g.drawString("總數(shù):1" ,heroModel.getX() ,heroModel.getY() + 70);
            g.drawString("生命:" + hero.getHp() ,heroModel.getX() ,heroModel.getY() + 100);
            // 關(guān)口信息
            g.setColor(Color.BLACK);
            int gradeModelX = heroModel.getX();
            int gradeModelY = heroModel.getY() + 150;
            g.fillRect(gradeModelX,gradeModelY,3,40);
            Polygon triangle = new Polygon();
            triangle.addPoint(gradeModelX + 3, gradeModelY);
            triangle.addPoint(gradeModelX + 3, gradeModelY + 20);
            triangle.addPoint(gradeModelX  + 40, gradeModelY + 20);
            g.setColor(Color.RED);
            g.fillPolygon(triangle);
            g.setColor(Color.WHITE);
            g.setFont(new Font("微軟雅黑",Font.BOLD,20));
            g.drawString("關(guān)數(shù):" + this.grade ,gradeModelX ,gradeModelY + 70);

            // 利用雙緩沖機制來重繪畫面,防止畫面閃爍(先把所有的元素繪制到緩沖圖片上,再將該圖片一次性繪制到畫面上)
            Graphics ig = bufferedImage.getGraphics();      // 得到緩沖圖片的畫筆

            // 設(shè)置游戲面板區(qū)域
            ig.setColor(Color.BLACK);
            ig.fillRect(0,0,GAME_ACTION_WIDTH,GAME_ACTION_HEIGHT);

            // 繪制地圖
            for (Block block : this.blockList){block.draw(ig);}

            // 繪制大本營
            if(camp.getState() == Camp.CAMP_STATE_RUNNING){camp.draw(ig);}

            // 繪制我方坦克
            hero.draw(ig);

            // 繪制我方子彈
            for (Bullet bullet : hero.getBulletPool()){if(bullet.getState() == Bullet.BULLET_STATE_RUNNING){bullet.draw(ig);}}

            // 繪制敵方坦克、子彈
            for (int i = 0; i < enemyPool.size(); i++)
            {
                Enemy enemy = enemyPool.get(i);
                // 繪制坦克
                if(enemy.getState() == Tank.TANK_STATE_RUNNING){enemy.draw(ig);}
                // 繪制子彈
                for (Bullet bullet : enemy.getBulletPool()){if(bullet.getState() == Bullet.BULLET_STATE_RUNNING){bullet.draw(ig);}}
            }

            // 繪制爆炸
            for (Bomb bomb : bombList){if(bomb.getState() == Bomb.BOMB_STATE_RUNNING){bomb.draw(ig);}}

            // 將緩沖圖片一次性顯示到畫面上
            g.drawImage(bufferedImage,0,0,null);
        }

    }

    public Hero getHero(){return hero;}

    public Vector<Enemy> getEnemyPool(){return enemyPool;}

    public List<Block> getBlockList(){return blockList;}

    public Camp getCamp(){return camp;}

    public void setGrade(int grade){this.grade = grade;}

}
  1. GameLogic.java游戲邏輯

package lag.game.tankwar;

/**
 * 游戲邏輯(牛逼類)
 */
public class GameLogic
{
    /** 唯一實例 */
    private static GameLogic instance;

    /** 游戲面板 */
    private GamePanel gamePanel;

    /**
     * 構(gòu)造函數(shù)
     * @param gamePanel 游戲面板
     */
    public GameLogic(GamePanel gamePanel)
    {
        this.gamePanel = gamePanel;
    }

    /**
     * 得到唯一實例
     */
    public static GameLogic getInstance()
    {
        return instance;
    }

    /**
     * 設(shè)置唯一實例
     * @param gameLogic 游戲邏輯
     */
    public static void setInstance(GameLogic gameLogic)
    {
        instance = gameLogic;
    }

    /**
     * 判斷矩形1是否碰撞到矩形2
     * @param x1 矩形1左上角X坐標(biāo)
     * @param y1 矩形1左上角Y坐標(biāo)
     * @param w1 矩形1寬度
     * @param h1 矩形1高度
     * @param x2 矩形2左上角X坐標(biāo)
     * @param y2 矩形2左上角Y坐標(biāo)
     * @param w2 矩形2寬度
     * @param h2 矩形2高度
     */
    public boolean rectCollideRect(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2)
    {
        // 判斷原理(1、矩形1的四個頂點是否落在矩形2里;2、矩形2的四個頂點是否落在矩形1里。若高度或?qū)掗熛嗟葧r特殊判斷)

        // 這個碰撞判斷比較嚴(yán),必須進入才算碰撞,挨著不算

        // 判斷矩形1的四個頂點是否落在矩形2里
        if((x1 > x2 && x1 < x2 + w2 && y1 > y2 && y1 < y2 + h2)
                || (x1 + w1 > x2 && x1 + w1 < x2 + w2 && y1 > y2 && y1 < y2 + h2)
                || (x1 > x2 && x1 < x2 + w2 && y1 + h1 > y2 && y1 + h1 < y2 + h2)
                || (x1 + w1 > x2 && x1 + w1 < x2 + w2 && y1 + h1 > y2 && y1 + h1 < y2 + h2))
        {return true;}

        // 判斷矩形2的四個頂點是否落在矩形1里
        if((x2 > x1 && x2 < x1 + w1 && y2 > y1 && y2 < y1 + h1)
                || (x2 + w2 > x1 && x2 + w2 < x1 + w1 && y2 > y1 && y2 < y1 + h1)
                || (x2 > x1 && x2 < x1 + w1 && y2 + h2 > y1 && y2 + h2 < y1 + h1)
                || (x2 + w2 > x1 && x2 + w2 < x1 + w1 && y2 + h2 > y1 && y2 + h2 < y1 + h1))
        {return true;}

        // 特殊情況處理

        // 若2個矩形的寬度相等時
        if(w1 == w2){if(x1 == x2 && x1 + w1 == x2 + w2 && ((y1 > y2 && y1 < y2 + h2) || (y1 + h1 > y2 && y1 + h1 < y2 + h2))){return true;}}

        // 若2個矩形的高度相等時
        if(h1 == h2){if(y1 == y2 && y1 + h1 == y2 + h2 && ((x1 > x2 && x1 < x2 + w2) || (x1 + w1 > x2 && x1 + w1 < x2 + w2))){return true;}}

        // 2個矩形完全重合
        if(x1 == x2 && y1 == y2 && w1 == w2 && h1 == h2){return true;}

        return false;
    }

    /**
     * 判斷坦克移動時的下一個位置是否碰撞到任何對象
     */
    public boolean tankMoveCollide(Tank tank)
    {
        int newX = tank.getX();
        int newY = tank.getY();

        // 得到移動后的新坐標(biāo)
        switch (tank.getDirection())
        {
            case Tank.TANK_DIRECTION_UP:
                newY = tank.getY() - tank.getSpeed();
                break;
            case Tank.TANK_DIRECTION_RIGHT:
                newX = tank.getX() + tank.getSpeed();
                break;
            case Tank.TANK_DIRECTION_DOWN:
                newY = tank.getY() + tank.getSpeed();
                break;
            case Tank.TANK_DIRECTION_LEFT:
                newX = tank.getX() - tank.getSpeed();
                break;
        }

        // 判斷是否碰撞到邊界
        switch (tank.getDirection())
        {
            case Tank.TANK_DIRECTION_UP:
                if(newY < 0){return true;}
                break;
            case Tank.TANK_DIRECTION_RIGHT:
                if(newX + Tank.TANK_WIDTH > GamePanel.GAME_ACTION_WIDTH){return true;}
                break;
            case Tank.TANK_DIRECTION_DOWN:
                if(newY + Tank.TANK_HEIGHT > GamePanel.GAME_ACTION_HEIGHT){return true;}
                break;
            case Tank.TANK_DIRECTION_LEFT:
                if(newX < 0){return true;}
                break;
        }

        // 判斷是否碰撞到敵方坦克
        for (int i = 0; i < gamePanel.getEnemyPool().size(); i++)
        {
            Enemy enemy = gamePanel.getEnemyPool().get(i);
            if(enemy.getState() == Tank.TANK_STATE_RUNNING && tank != enemy)
            {
                if(rectCollideRect(newX,newY,Tank.TANK_WIDTH,Tank.TANK_HEIGHT,enemy.getX(),enemy.getY(),Tank.TANK_WIDTH,Tank.TANK_HEIGHT)){return true;}
            }
        }

        // 判斷是否碰撞到我方坦克
        if(tank.getTankKind() == Tank.TANK_KIND_ENEMY)
        {
            if(rectCollideRect(newX,newY,Tank.TANK_WIDTH,Tank.TANK_HEIGHT,gamePanel.getHero().getX(),gamePanel.getHero().getY(),Tank.TANK_WIDTH,Tank.TANK_HEIGHT)){return true;}
        }

        // 判斷是否碰撞到塊
        for (Block block : gamePanel.getBlockList())
        {
            if(rectCollideRect(newX,newY,Tank.TANK_WIDTH,Tank.TANK_HEIGHT,block.getX(),block.getY(),Block.BLOCK_WIDTH,Block.BLOCK_HEIGHT)){return true;}
        }

        // 判斷是否碰撞大本營
        if(gamePanel.getCamp().getState() == Camp.CAMP_STATE_RUNNING)
        {
            if(rectCollideRect(newX,newY,Tank.TANK_WIDTH,Tank.TANK_HEIGHT,gamePanel.getCamp().getX(),gamePanel.getCamp().getY(),gamePanel.getCamp().getWidth(),gamePanel.getCamp().getHeight())){return true;}
        }

        return false;
    }

    /**
     * 判斷坦克是否碰撞到坦克<br>
     * @param tank1 坦克1
     * @param tank2 坦克2
     */
    public boolean tankCollideTank(Tank tank1,Tank tank2)
    {
        return rectCollideRect(tank1.getX(),tank1.getY(),Tank.TANK_WIDTH,Tank.TANK_HEIGHT,tank2.getX(),tank2.getY(),Tank.TANK_WIDTH,Tank.TANK_HEIGHT);
    }

    /**
     * 判斷子彈是否碰撞到坦克<br>
     */
    public boolean bulletCollideTank(Bullet bullet,Tank tank)
    {
        return rectCollideRect(bullet.getX(),bullet.getY(),bullet.getWidth(),bullet.getHeight(),tank.getX(),tank.getY(),Tank.TANK_WIDTH,Tank.TANK_HEIGHT);
    }

    /**
     * 判斷子彈是否碰撞到塊
     */
    public boolean bulletCollideBlock(Bullet bullet,Block block)
    {
        return rectCollideRect(bullet.getX(),bullet.getY(),bullet.getWidth(),bullet.getHeight(),block.getX(),block.getY(),Block.BLOCK_WIDTH,Block.BLOCK_HEIGHT);
    }

    /**
     * 判斷子彈是否碰撞到大本營
     */
    public boolean bulletCollideCamp(Bullet bullet,Camp camp)
    {
        return rectCollideRect(bullet.getX(),bullet.getY(),bullet.getWidth(),bullet.getHeight(),camp.getX(),camp.getY(),camp.getWidth(),camp.getHeight());
    }

    /**
     * 得到某范圍內(nèi)的隨機整數(shù)
     * @param min 最小值
     * @param max 最大值
     */
    public static int getRandomInt(int min,int max)
    {
        return (int)(min + Math.random() * (max - min + 1));
    }

}
  1. GameMap.java游戲地圖

package lag.game.tankwar;

/**
 * 游戲地圖
 */
public class GameMap
{
    /** 各關(guān)地圖[26行26列](0-空地,1-磚塊,2-鐵塊) */
    private static byte[][][] gradeMap =
        {
            // 第1關(guān)地圖
            {
                {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
                {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
                {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,1,1,2,2,1,1,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,1,1,2,2,1,1,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0},
                {0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},
                {0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},
                {1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,1,1},
                {2,2,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,2,2},
                {0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},
                {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0},
                {0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,0,1,1,1,1,0,0,0,1,1,0,0,1,1,0,0},
                {0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
                {0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0}
            },
            // 第2關(guān)地圖
            {
                {0,0,0,0,0,0,2,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0},
                {0,0,0,0,0,0,2,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0},
                {0,0,1,1,0,0,2,2,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,2,2,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,1,1,2,2,1,1,0,0},
                {0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,1,1,2,2,1,1,0,0},
                {0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0},
                {0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0},
                {0,0,0,0,0,0,1,1,0,0,0,0,2,2,0,0,0,0,1,1,0,0,1,1,2,2},
                {0,0,0,0,0,0,1,1,0,0,0,0,2,2,0,0,0,0,1,1,0,0,1,1,2,2},
                {0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,2,2,0,0,0,0,0,0,0,0},
                {0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,2,2,0,0,0,0,0,0,0,0},
                {0,0,1,1,1,1,1,1,0,0,0,0,0,0,2,2,0,0,0,0,0,0,1,1,0,0},
                {0,0,1,1,1,1,1,1,0,0,0,0,0,0,2,2,0,0,0,0,0,0,1,1,0,0},
                {0,0,0,0,0,0,2,2,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
                {0,0,0,0,0,0,2,2,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
                {2,2,1,1,0,0,2,2,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,0,0},
                {2,2,1,1,0,0,2,2,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,1,1,2,2,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,1,1,2,2,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0},
                {0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0},
                {0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,0,0,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,1,1,1,1,0,0},
                {0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,1,1,1,1,0,0}
            }
            // 其他關(guān)地圖...
        };

    /** 總關(guān)卡數(shù) */
    private static int gradeCount = gradeMap.length;

    /** 各關(guān)敵方坦克數(shù)量 */
    private static int[] enemyTankNum = {10,20};

    /**
     * 返回某關(guān)地圖
     * @param grade 關(guān)數(shù)
     */
    public static byte[][] getGameMap(int grade)
    {
        // 由于數(shù)組是個對象,而原始地圖是不允許被修改的,所以不能直接賦值(引用地址),得復(fù)制一個新的地圖讓游戲隨便修改。
        byte[][] tempMap = null;
        if(grade > 0 && grade <= gradeCount)
        {
            tempMap = gradeMap[grade - 1];
        }
        else
        {
            tempMap = gradeMap[0];
        }
        //開始復(fù)制
        int row = tempMap.length;
        int column = tempMap[0].length;
        byte[][] returnMap = new byte[row][column];
        for (int i = 0; i < row; i++)
        {
            for (int j = 0; j < column; j++)
            {
                returnMap[i][j] = tempMap[i][j];
            }
        }

        return returnMap;
    }

    /**
     * 功能:返回總關(guān)卡數(shù)<br>
     */
    public static int getGradeCount(){return gradeCount;}

    /**
     * 返回某關(guān)敵方坦克數(shù)量
     * @param grade 關(guān)數(shù)
     */
    public static int getEnemyTankNum(int grade)
    {
        if(grade < 1 || grade > gradeCount){grade = gradeCount;}
        return enemyTankNum[grade - 1];
    }

}
  1. GameMusic.java

package lag.game.tankwar;

import java.io.File;
import java.io.InputStream;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.AudioInputStream;

/**
 * 游戲音樂<br>
 * 支持音樂格式(AITF、AU、WAV),就是加載有點慢啊。
 */
public class GameMusic
{
    /** 音頻輸入流 */
    private AudioInputStream stream;

    /** 音頻格式 */
    private AudioFormat format;

    /** 音頻剪輯 */
    private Clip clip;

    /**
     * 功能:構(gòu)造函數(shù)<br>
     */
    public GameMusic(String fileName)
    {
        try
        {
            File file = new File(fileName);
            //將音樂文件轉(zhuǎn)為音頻輸入流
            this.stream = AudioSystem.getAudioInputStream(file);
            //得到音頻格式
            this.format = stream.getFormat();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    /**
     * 構(gòu)造函數(shù)
     * @param fileName URL文件名
     */
    public GameMusic(InputStream fileName)
    {
        try
        {
            //將音樂文件轉(zhuǎn)為音頻輸入流
            this.stream = AudioSystem.getAudioInputStream(fileName);
            //得到音頻格式
            this.format = stream.getFormat();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    /**
     * 功能:播放音樂<br>
     * 參數(shù):boolean _loop -> 是否循環(huán)(True-無限循環(huán),F(xiàn)alse-不循環(huán))<br>
     */
    public void play(boolean _loop)
    {
        try
        {
            //設(shè)置音頻行信息
            DataLine.Info info = new DataLine.Info(Clip.class,this.format);
            //建立音頻行信息
            this.clip = (Clip)AudioSystem.getLine(info);
            this.clip.open(this.stream);
            if(_loop)    //無限循環(huán)
            {
                this.clip.loop(Clip.LOOP_CONTINUOUSLY);
            }
            else
            {
                this.clip.loop(0);
            }
            this.clip.start();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    /**
     * 功能:停止音樂<br>
     */
    public void stop()
    {
        try
        {
            if(this.clip.isRunning())
            {
                this.clip.stop();
                this.clip.close();
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

}
  1. Tank.java坦克父類

package lag.game.tankwar;

import java.awt.*;
import java.util.Vector;

/**
 * 坦克父類
 */
public class Tank
{
    /** 坦克類別常量 */
    public final static int TANK_KIND_HERO = 0;                 // 我方坦克
    public final static int TANK_KIND_ENEMY = 1;                // 敵方坦克

    /** 坦克顏色常量 */
    public final static Color TANK_COLOR_HERO = Color.YELLOW;   // 我方坦克顏色
    public final static Color TANK_COLOR_ENEMY = Color.CYAN;    // 敵方坦克顏色

    /** 坦克方向常量 */
    public final static int TANK_DIRECTION_UP = 0;              // 向上
    public final static int TANK_DIRECTION_RIGHT = 1;           // 向右
    public final static int TANK_DIRECTION_DOWN = 2;            // 向下
    public final static int TANK_DIRECTION_LEFT = 3;            // 向左

    /** 坦克狀態(tài)常量 */
    public final static int TANK_STATE_FREE = 0;                // 空閑中
    public final static int TANK_STATE_RUNNING = 1;             // 運行中

    /** 坦克最大血量值 */
    public final static int TANK_MAX_BLOOD = 100;

    /** 坦克尺寸常量 */
    public final static int TANK_WIDTH = 40;
    public final static int TANK_HEIGHT = 40;

    /** 坦克左上角X坐標(biāo) */
    private int x;

    /** 坦克左上角Y坐標(biāo) */
    private int y;

    /** 坦克速度 */
    private int speed = 8;

    /** 坦克血量 */
    private int hp = TANK_MAX_BLOOD;

    /** 坦克方向 */
    private int direction = TANK_DIRECTION_UP;

    /** 坦克類別 */
    private int tankKind = TANK_KIND_HERO;

    /** 坦克狀態(tài) */
    private int state = TANK_STATE_FREE;

    /** 子彈池(考慮線程安全用Vector,沒用ArrayList) */
    private Vector<Bullet> bulletPool = new Vector<>();

    /** 上次射擊時間(用來設(shè)置2次射擊最小時間間隔,禁止連續(xù)射擊) */
    private long lastShootTime = System.currentTimeMillis();

    /**
     * 構(gòu)造函數(shù)
     * @param tankKind 坦克類別
     * @param x 坦克左上角X坐標(biāo)
     * @param y 坦克左上角Y坐標(biāo)
     * @param direction 坦克方向
     */
    public Tank(int tankKind, int x, int y, int direction)
    {
        this.tankKind = tankKind;
        this.x = x;
        this.y = y;
        this.direction = direction;
    }

    /**
     * 畫坦克
     */
    public void draw(Graphics g)
    {
        // 繪制血條
        g.setColor(Color.YELLOW);
        g.fill3DRect(this.x,this.y,TANK_WIDTH,3,false);   // 底色
        g.setColor(Color.RED);
        g.fill3DRect(this.x,this.y,(hp * TANK_WIDTH)/TANK_MAX_BLOOD,3,false);   // 血量(計算寬度時由于都是int類型,因此除法是放到最后計算的,防止出現(xiàn)結(jié)果為0的問題【int取整了】)
        g.setColor(Color.WHITE);
        g.draw3DRect(this.x,this.y,TANK_WIDTH,3,false);   // 邊框
        int tankToBloodHeight = 5;  // 坦克到血條的高度
        // 設(shè)置坦克顏色
        if(this.tankKind == TANK_KIND_HERO)    // 我方坦克顏色
        {
            g.setColor(TANK_COLOR_HERO);
        }
        else    // 敵方坦克顏色
        {
            g.setColor(TANK_COLOR_ENEMY);
        }
        // 繪制四周虛線
        for (int i = 0; i <= 10; i++)
        {
            g.drawOval(x - 1,y + 4 * i - 1, 1,1);
            g.drawOval(x + TANK_WIDTH - 1,y + 4 * i - 1, 1,1);
            if(i < 10){g.drawOval(x + 4 * i - 1,y + TANK_HEIGHT - 1, 1,1);}
        }
        // 根據(jù)方向開始繪制坦克
        switch (direction)
        {
            case TANK_DIRECTION_UP:
                g.fill3DRect(this.x + tankToBloodHeight,this.y + tankToBloodHeight,7,30,false);            // 左邊輪子
                g.fill3DRect(this.x + 23 + tankToBloodHeight,this.y + tankToBloodHeight,7,30,false);       // 右邊輪子
                g.fill3DRect(this.x + 7 + tankToBloodHeight,this.y + 5 + tankToBloodHeight,16,20,false);   // 駕駛室
                g.fillOval(this.x + 9 + tankToBloodHeight,this.y + 9 + tankToBloodHeight,12,12);                  // 炮臺
                g.fill3DRect(x + 14 + tankToBloodHeight,y + tankToBloodHeight,3,15,false);                 // 炮管
                break;
            case TANK_DIRECTION_RIGHT:
                g.fill3DRect(this.x + tankToBloodHeight,this.y + tankToBloodHeight,30,7,false);            // 上邊輪子
                g.fill3DRect(this.x + tankToBloodHeight,this.y + 23 + tankToBloodHeight,30,7,false);       // 下邊輪子
                g.fill3DRect(this.x + 5 + tankToBloodHeight,this.y + 7 + tankToBloodHeight,20,16,false);   // 駕駛室
                g.fillOval(this.x + 9 + tankToBloodHeight,this.y + 9 + tankToBloodHeight,12,12);                  // 炮臺
                g.fill3DRect(x + 15 + tankToBloodHeight,y + 14 + tankToBloodHeight,15,3,false);            // 炮管
                break;
            case TANK_DIRECTION_DOWN:
                g.fill3DRect(this.x + tankToBloodHeight,this.y + tankToBloodHeight,7,30,false);            // 左邊輪子
                g.fill3DRect(this.x + 23 + tankToBloodHeight,this.y + tankToBloodHeight,7,30,false);       // 右邊輪子
                g.fill3DRect(this.x + 7 + tankToBloodHeight,this.y + 5 + tankToBloodHeight,16,20,false);   // 駕駛室
                g.fillOval(this.x + 9 + tankToBloodHeight,this.y + 9 + tankToBloodHeight,12,12);                  // 炮臺
                g.fill3DRect(x + 14 + tankToBloodHeight,y + 15 + tankToBloodHeight,3,15,false);            // 炮管
                break;
            case TANK_DIRECTION_LEFT:
                g.fill3DRect(this.x + tankToBloodHeight,this.y + tankToBloodHeight,30,7,false);            // 上邊輪子
                g.fill3DRect(this.x + tankToBloodHeight,this.y + 23 + tankToBloodHeight,30,7,false);       // 下邊輪子
                g.fill3DRect(this.x + 5 + tankToBloodHeight,this.y + 7 + tankToBloodHeight,20,16,false);   // 駕駛室
                g.fillOval(this.x + 9 + tankToBloodHeight,this.y + 9 + tankToBloodHeight,12,12);                  // 炮臺
                g.fill3DRect(x + tankToBloodHeight,y + 14 + tankToBloodHeight,15,3,false);                 // 炮管
                break;
        }

    }

    /**
     * 坦克移動
     * @param direction 移動方向
     */
    public void move(int direction)
    {
        if(this.direction == direction)     // 方向相同,加速前進(要判斷邊界及是否碰撞到別的對象)
        {
            if(!GameLogic.getInstance().tankMoveCollide(this))   // 沒有碰撞,可以移動
            {
                switch (direction)
                {
                    case TANK_DIRECTION_UP:
                        this.y -= this.speed;
                        break;
                    case TANK_DIRECTION_RIGHT:
                        this.x += this.speed;
                        break;
                    case TANK_DIRECTION_DOWN:
                        this.y += this.speed;
                        break;
                    case TANK_DIRECTION_LEFT:
                        this.x -= this.speed;
                        break;
                }
            }
        }
        else    // 方向不同,僅調(diào)整方向不前進
        {
            this.direction = direction;
        }
    }

    /**
     * 坦克射擊
     */
    public void shoot()
    {
        // 禁止連續(xù)射擊
        long curShootTime = System.currentTimeMillis();
        if((curShootTime - this.lastShootTime) >= 500)  // 2發(fā)/秒
        {
            this.lastShootTime = curShootTime;
        }
        else
        {
            return;
        }

        // 在子彈池中尋找空閑的子彈
        Bullet bullet = null;
        for (int i = 0; i < bulletPool.size(); i++)
        {
            Bullet tmpBullet = bulletPool.get(i);
            if(tmpBullet.getState() == Bullet.BULLET_STATE_FREE)
            {
                bullet = tmpBullet;
                //System.out.println("找到空閑的子彈了..................");
                break;
            }
        }

        // 沒有就增加一個
        if(bullet == null)
        {
            bullet = new Bullet(this);
            //System.out.println("新建子彈了.................");
            bulletPool.add(bullet);
        }

        // 設(shè)置子彈位置
        switch (this.direction)
        {
            case TANK_DIRECTION_UP:
                bullet.setPosition(this.x + TANK_WIDTH/2 - bullet.getWidth()/2,this.y - bullet.getHeight(),this.direction);
                break;
            case TANK_DIRECTION_RIGHT:
                bullet.setPosition(this.x + TANK_WIDTH,this.y + TANK_HEIGHT/2 - bullet.getHeight()/2,this.direction);
                break;
            case TANK_DIRECTION_DOWN:
                bullet.setPosition(this.x + TANK_WIDTH/2 - bullet.getWidth()/2,this.y + TANK_HEIGHT,this.direction);
                break;
            case TANK_DIRECTION_LEFT:
                bullet.setPosition(this.x - bullet.getWidth(),this.y + TANK_HEIGHT/2 - bullet.getHeight()/2,this.direction);
                break;
        }

        // 讓子彈飛一會
        bullet.fly();
    }

    /** 坦克受到傷害 */
    public void hurt(Bullet bullet)
    {
        this.hp -= bullet.getAtk();
        if(this.hp < 0){this.hp = 0;}
    }

    /**
     * 坦克是否死亡
     */
    public boolean isDead()
    {
        return this.hp <= 0;
    }

    /**
     * 坦克開始工作了
     */
    public void work()
    {
        this.state = TANK_STATE_RUNNING;
    }

    /** 坦克重置 */
    public void reset()
    {
        this.setX(-100);
        this.setY(-100);
        this.setHp(Tank.TANK_MAX_BLOOD);
        this.setState(TANK_STATE_FREE);
    }

    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 int getSpeed(){return speed;}

    public void setSpeed(int speed){this.speed = speed;}

    public int getHp(){return hp;}

    public void setHp(int hp){this.hp = hp;}

    public int getDirection(){return direction;}

    public void setDirection(int direction){this.direction = direction;}

    public int getState(){return state;}

    public void setState(int state){this.state = state;}

    public int getTankKind(){return tankKind;}

    public Vector<Bullet> getBulletPool(){return bulletPool;}

}
  1. Hero.java我方的坦克

package lag.game.tankwar;

/**
 * 我方的坦克
 */
public class Hero extends Tank
{
    /**
     * 構(gòu)造函數(shù)
     * @param x 坦克左上角X坐標(biāo)
     * @param y 坦克左上角Y坐標(biāo)
     * @param direction 坦克方向
     */
    public Hero(int x, int y, int direction)
    {
        super(TANK_KIND_HERO, x, y, direction);
    }

}
  1. Enemy.java敵方的坦克

package lag.game.tankwar;

/**
 * 敵方的坦克
 */
public class Enemy extends Tank
{
    /**
     * 構(gòu)造函數(shù)
     * @param x 坦克左上角X坐標(biāo)
     * @param y 坦克左上角Y坐標(biāo)
     * @param direction 坦克方向
     */
    public Enemy(int x, int y, int direction)
    {
        super(TANK_KIND_ENEMY, x, y, direction);
    }

    /**
     * 起來干活了
     */
    @Override
    public void work()
    {
        super.work();
        // 啟動線程讓坦克跑(看看敵方坦克的AI)
        new Thread(()->{
            //System.out.println("坦克線程啟動...");
            while (this.getState() == TANK_STATE_RUNNING)
            {
                try
                {
                    Thread.sleep(200);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                // 隨機確認(rèn)是原地不動還是移動(0-不動,其它-移動)
                if(GameLogic.getRandomInt(0,8) != 0)   // 移動(概率設(shè)大點)
                {
                    // 隨機確認(rèn)是改變方向還是向前移動(0-改變方向,其它-向前移動)
                    if(GameLogic.getRandomInt(0,12) == 0)   // 改變方向(概率設(shè)小點)
                    {
                        int newDirection = GameLogic.getRandomInt(TANK_DIRECTION_UP, TANK_DIRECTION_LEFT + 3);
                        if(newDirection > TANK_DIRECTION_LEFT){newDirection = TANK_DIRECTION_DOWN;}    // 向下概率設(shè)大點
                        this.setDirection(newDirection);
                    }
                    else    // 向前移動
                    {
                        // 如果到邊界了就別頂牛了,趕緊換方向
                        boolean toBorder = false;     // 默認(rèn)未到邊界
                        switch (this.getDirection())
                        {
                            case TANK_DIRECTION_UP:
                                if((this.getY() - this.getSpeed() < 0))
                                {
                                    toBorder = true;
                                }
                                break;
                            case TANK_DIRECTION_RIGHT:
                                if((this.getX() + TANK_WIDTH + this.getSpeed() > GamePanel.GAME_ACTION_WIDTH))
                                {
                                    toBorder = true;
                                }
                                break;
                            case TANK_DIRECTION_DOWN:
                                if((this.getY() + TANK_HEIGHT + this.getSpeed() > GamePanel.GAME_ACTION_HEIGHT))
                                {
                                    toBorder = true;
                                }
                                break;
                            case TANK_DIRECTION_LEFT:
                                if((this.getX() - this.getSpeed() < 0))
                                {
                                    toBorder = true;
                                }
                                break;
                        }
                        if(toBorder)  // 到邊界了趕緊換方向
                        {
                            int newDirection = GameLogic.getRandomInt(TANK_DIRECTION_UP, TANK_DIRECTION_LEFT);
                            this.setDirection(newDirection);
                        }
                        else    // 繼續(xù)前進
                        {
                            this.move(this.getDirection());
                        }
                    }
                }
                // 隨機確認(rèn)是發(fā)射子彈還是省子彈(1-發(fā)射,其它-不發(fā)射)
                if(GameLogic.getRandomInt(0,8) == 1)
                {
                    this.shoot();
                }
            }
            //System.out.println("坦克線程退出歷史舞臺了...");
        }).start();
    }

}
  1. Bullet.java子彈類

package lag.game.tankwar;

import java.awt.*;

/**
 * 子彈類<br>
 */
public class Bullet
{
    /** 子彈狀態(tài)常量 */
    public final static int BULLET_STATE_FREE = 0;      // 空閑中
    public final static int BULLET_STATE_RUNNING = 1;   // 運行中

    /** 子彈攻擊力常量 */
    public final static int BULLET_MAX_ATTACK = 100;    // 最大攻擊力
    public final static int BULLET_MIN_ATTACK = 20;     // 最小攻擊力

    /** 子彈左上角X坐標(biāo) */
    private int x;

    /** 子彈左上角Y坐標(biāo) */
    private int y;

    /** 子彈寬度 */
    private int width = 10;

    /** 子彈高度 */
    private int height = 10;

    /** 子彈方向 */
    private int direction;

    /** 子彈速度 */
    private int speed = 16;

    /** 子彈狀態(tài) */
    private int state = BULLET_STATE_FREE;

    /** 所屬坦克 */
    private Tank tank;

    /** 子彈攻擊力 */
    private int atk;

    /**
     * 構(gòu)造函數(shù)
     * @param tank 所屬坦克
     */
    public Bullet(Tank tank)
    {
        this.tank = tank;
        this.atk = GameLogic.getRandomInt(BULLET_MIN_ATTACK,BULLET_MAX_ATTACK);
    }

    /**
     * 設(shè)置子彈位置
     */
    public void setPosition(int x,int y,int direction)
    {
        this.x = x;
        this.y = y;
        this.direction = direction;
    }

    /**
     * 功能:子彈重置<br>
     */
    public void reset()
    {
        this.x = -100;
        this.y = -100;
        this.atk = GameLogic.getRandomInt(BULLET_MIN_ATTACK,BULLET_MAX_ATTACK);     // 重新隨機生成攻擊力
        this.state = BULLET_STATE_FREE;
    }

    /**
     * 讓子彈飛一會
     */
    public void fly()
    {
        // 設(shè)置子彈狀態(tài)為運行中
        this.state = BULLET_STATE_RUNNING;

        // 啟動線程讓子彈飛
        new Thread(()->{
            //System.out.println(tank.getTankKind() + "子彈線程啟動...");
            while (this.state == BULLET_STATE_RUNNING)  //tank.getState() == Tank.TANK_STATE_RUNNING &&
            {
                try
                {
                    Thread.sleep(50);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }

                switch (direction)
                {
                    case Tank.TANK_DIRECTION_UP:
                        if(this.y - this.speed >= 0)
                        {
                            this.y -= this.speed;
                        }
                        else
                        {
                            this.reset();
                        }
                        break;
                    case Tank.TANK_DIRECTION_RIGHT:
                        if(this.x + this.width + this.speed <= GamePanel.GAME_ACTION_WIDTH)
                        {
                            this.x += this.speed;
                        }
                        else
                        {
                            this.reset();
                        }
                        break;
                    case Tank.TANK_DIRECTION_DOWN:
                        if(this.y + this.height + this.speed <= GamePanel.GAME_ACTION_HEIGHT)
                        {
                            this.y += this.speed;
                        }
                        else
                        {
                            this.reset();
                        }
                        break;
                    case Tank.TANK_DIRECTION_LEFT:
                        if(this.x >= this.speed)
                        {
                            this.x -= this.speed;
                        }
                        else
                        {
                            this.reset();
                        }
                        break;
                }
            }
            //System.out.println("子彈線程退出歷史舞臺了......");
        }).start();
    }

    /**
     * 畫子彈
     */
    public void draw(Graphics g)
    {
        // 開始畫子彈
        if(tank.getTankKind() == Tank.TANK_KIND_HERO)    // 我方子彈
        {
            g.setColor(Tank.TANK_COLOR_HERO);
        }
        else    // 敵方子彈
        {
            g.setColor(Tank.TANK_COLOR_ENEMY);
        }
        g.fillOval(this.x,this.y,this.width,this.height);
        // 根據(jù)攻擊力畫加強子彈
        g.setColor(Color.RED);
        if(this.atk == 100)
        {
            g.fillOval(this.x,this.y,this.width,this.height);
        }
        else if(this.atk >= 90)
        {
            g.fillOval(this.x + 1,this.y + 1,this.width - 2,this.height - 2);
        }
        else if(this.atk >= 70)
        {
            g.fillOval(this.x + 2,this.y + 2,this.width - 4,this.height - 4);
        }
        else if(this.atk >= 50)
        {
            g.fillOval(this.x + 3,this.y + 3,this.width - 6,this.height - 6);
        }
    }

    public int getX(){return x;}

    public int getY(){return y;}

    public int getWidth(){return width;}

    public int getHeight(){return height;}

    public int getDirection(){return direction;}

    public int getSpeed(){return speed;}

    public int getState(){return state;}

    public int getAtk(){return atk;}

}
  1. Bomb.java爆炸效果

package lag.game.tankwar;

import java.awt.*;

/**
 * 爆炸效果
 */
public class Bomb
{
    /** 爆炸狀態(tài)常量 */
    public final static int BOMB_STATE_FREE = 0;      // 空閑中
    public final static int BOMB_STATE_RUNNING = 1;   // 運行中

    /** 爆炸左上角X坐標(biāo) */
    private int x;

    /** 爆炸左上角Y坐標(biāo) */
    private int y;

    /** 爆炸寬度 */
    private int width = 20;

    /** 爆炸高度 */
    private int height = 20;

    /** 狀態(tài) */
    private int state = BOMB_STATE_FREE;

    /** 爆炸進度,根據(jù)它來決定顯示哪種爆炸形狀(-1-不顯示任何爆炸形狀,0-準(zhǔn)備顯示,1-顯示第一種爆炸形狀,2-顯示第二種爆炸形狀,3-顯示第三種爆炸形狀) */
    public int bombProgress = -1;

    /**
     * 構(gòu)造函數(shù)
     * @param x 爆炸左上角X坐標(biāo)
     * @param y 爆炸左上角Y坐標(biāo)
     */
    public Bomb(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    /**
     * 起來干活,準(zhǔn)備爆炸。
     */
    public void work()
    {
        // 設(shè)置爆炸狀態(tài)為運行中
        this.state = BOMB_STATE_RUNNING;

        // 爆炸進度,準(zhǔn)備顯示
        bombProgress = 0;
    }

    /**
     * 爆炸重置
     */
    public void reset()
    {
        this.setX(-100);
        this.setY(-100);
        this.state = BOMB_STATE_FREE;
        this.bombProgress = -1;
    }

    /**
     * 畫爆炸<br>
     * 每幀顯示一種形狀,共三種,即3幀結(jié)束爆炸<br>
     */
    public void draw(Graphics g)
    {
        // 進度走起
        this.bombProgress++;

        // 根據(jù)進度顯示某種爆炸形狀
        switch (this.bombProgress)
        {
            case 1:         // 第一種形狀
                g.setColor(Color.WHITE);
                g.fillRoundRect(this.x + 5,this.y + 5,20,20,10,10);
                g.fillOval(this.x + 10,this.y,10,30);
                g.setColor(Color.YELLOW);
                g.drawOval(this.x + 10,this.y,10,30);
                g.setColor(Color.WHITE);
                g.fillOval(this.x,this.y + 10,30,10);
                g.setColor(Color.YELLOW);
                g.drawOval(this.x,this.y + 10,30,10);
                break;
            case 2:         // 第二種形狀
                g.setColor(Color.WHITE);
                g.fillOval(this.x + 12,this.y + 5,6,20);
                g.setColor(Color.YELLOW);
                g.drawOval(this.x + 12,this.y + 5,6,20);
                g.setColor(Color.WHITE);
                g.fillOval(this.x + 5,this.y + 12,20,6);
                g.setColor(Color.YELLOW);
                g.drawOval(this.x + 5,this.y + 12,20,6);
                break;
            case 3:         // 第三種形狀
                g.setColor(Color.WHITE);
                g.fillOval(this.x + 10,this.y + 10,10,10);
                g.setColor(Color.YELLOW);
                g.drawOval(this.x + 10,this.y + 10,10,10);
                break;
            default:
                this.reset();
                break;
        }
    }

    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 int getWidth(){return width;}

    public void setWidth(int width){this.width = width;}

    public int getHeight(){return height;}

    public void setHeight(int height){this.height = height;}

    public int getState(){return state;}

}
  1. Block.java磚塊與鐵塊的父類

package lag.game.tankwar;

import java.awt.*;

/**
 * 磚塊與鐵塊的父類
 */
public class Block
{
    /** 塊類別常量 */
    public final static int BLOCK_KIND_BRICK = 1;     // 磚塊
    public final static int BLOCK_KIND_IRON = 2;      // 鐵塊

    /** 塊尺寸常量(默認(rèn)4個塊=1坦克大?。?*/
    public final static int BLOCK_WIDTH = Tank.TANK_WIDTH / 2;
    public final static int BLOCK_HEIGHT = Tank.TANK_HEIGHT / 2;

    /** 塊左上角X坐標(biāo) */
    private int x;

    /** 塊左上角Y坐標(biāo) */
    private int y;

    /** 塊類別 */
    private int blockKind = BLOCK_KIND_BRICK;

    /**
     * 構(gòu)造函數(shù)
     * @param blockKind 塊類別
     * @param x 塊左上角X坐標(biāo)
     * @param y 塊左上角Y坐標(biāo)
     */
    public Block(int blockKind,int x, int y)
    {
        this.blockKind = blockKind;
        this.x = x;
        this.y = y;
    }

    /**
     * 畫塊
     */
    public void draw(Graphics g)
    {
        if(this.blockKind == BLOCK_KIND_BRICK)   // 畫磚塊
        {
            g.setColor(new Color(210, 105, 30));
            g.fillRect(this.x,this.y,BLOCK_WIDTH,BLOCK_HEIGHT);
            g.setColor(new Color(244, 164, 96));
            g.drawLine(this.x,this.y,this.x + BLOCK_WIDTH - 1,this.y);
            g.drawLine(this.x,this.y + BLOCK_HEIGHT / 2,this.x + BLOCK_WIDTH - 1,this.y + BLOCK_HEIGHT / 2);
            g.drawLine(this.x,this.y,this.x,this.y + BLOCK_HEIGHT / 2);
            g.drawLine(this.x + BLOCK_WIDTH / 2,this.y + BLOCK_HEIGHT / 2, this.x + BLOCK_WIDTH / 2, this.y + BLOCK_HEIGHT - 1);
        }
        else if(this.blockKind == BLOCK_KIND_IRON)      // 畫鐵塊
        {
            g.setColor(new Color(190, 190, 190));
            g.fillRect(this.x,this.y,BLOCK_WIDTH,BLOCK_HEIGHT);
            g.setColor(Color.WHITE);
            g.fillRect(this.x + 3,this.y + 3,BLOCK_WIDTH - 6,BLOCK_HEIGHT - 6);
            g.draw3DRect(this.x + 3,this.y + 3,BLOCK_WIDTH - 6,BLOCK_HEIGHT - 6,true);
            g.drawLine(this.x + 1,this.y + 1,this.x + 3,this.y + 3);
            g.drawLine(this.x + BLOCK_WIDTH - 1,this.y + 1,this.x + BLOCK_WIDTH - 3,this.y + 3);
            g.drawLine(this.x + 1,this.y + BLOCK_HEIGHT - 1,this.x + 3,this.y + BLOCK_HEIGHT - 3);
            g.drawLine(this.x + BLOCK_WIDTH - 1,this.y + BLOCK_HEIGHT - 1,this.x + BLOCK_WIDTH - 3,this.y + BLOCK_HEIGHT - 3);
        }
    }

    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 int getBlockKind(){return blockKind;}

}
  1. Brick.java磚塊

package lag.game.tankwar;

/**
 * 磚塊
 */
public class Brick extends Block
{
    /**
     * 構(gòu)造函數(shù)
     * @param x 磚塊左上角X坐標(biāo)
     * @param y 磚塊左上角Y坐標(biāo)
     */
    public Brick(int x, int y)
    {
        super(BLOCK_KIND_BRICK, x, y);
    }

}
  1. Iron.java鐵塊

package lag.game.tankwar;

/**
 * 鐵塊
 */
public class Iron extends Block
{
    /**
     * 構(gòu)造函數(shù)
     * @param x 鐵塊左上角X坐標(biāo)
     * @param y 鐵塊左上角Y坐標(biāo)
     */
    public Iron(int x, int y)
    {
        super(BLOCK_KIND_IRON, x, y);
    }

}
  1. Camp.java營地

package lag.game.tankwar;

import java.awt.*;

/**
 * 營地
 */
public class Camp
{
    /** 營地狀態(tài)常量 */
    public final static int CAMP_STATE_FREE = 0;                // 空閑中
    public final static int CAMP_STATE_RUNNING = 1;             // 運行中

    /** 營地左上角X坐標(biāo) */
    private int x;

    /** 營地左上角Y坐標(biāo) */
    private int y;

    /** 營地寬度 */
    private int width = Tank.TANK_WIDTH;

    /** 營地高度 */
    private int height = Tank.TANK_HEIGHT;

    /** 營地狀態(tài) */
    private int state = CAMP_STATE_FREE;

    /** 元素寬度 */
    private int elementWidth = 2;

    /** 元素高度 */
    private int elementHeight = 2;

    /** 營地地圖(20 * 20) */
    private static byte[][] campMap =
        {
            {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
            {0,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0},
            {1,1,1,1,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1},
            {0,2,1,1,1,0,0,0,1,0,0,1,1,0,0,1,1,1,2,0},
            {1,1,2,0,1,0,0,0,1,1,1,1,0,0,0,1,0,2,1,1},
            {0,0,1,2,1,1,0,0,1,1,1,1,0,0,1,1,2,1,0,0},
            {0,1,1,1,2,1,0,0,1,1,1,1,0,0,1,2,1,1,1,0},
            {0,0,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,0,0},
            {0,0,0,1,1,1,2,1,1,1,1,1,1,2,1,1,1,0,0,0},
            {0,0,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,0,0},
            {0,0,0,1,1,1,1,1,1,2,1,2,1,1,1,1,1,0,0,0},
            {0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0},
            {0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0},
            {0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0},
            {0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0},
            {0,0,0,0,0,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0},
            {0,0,0,0,0,1,1,1,1,0,1,1,1,1,0,0,0,0,0,0},
            {0,0,0,0,0,1,1,0,1,0,1,0,1,1,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
        };

    /**
     * 構(gòu)造函數(shù)
     */
    public Camp(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    /**
     * 畫營地
     */
    public void draw(Graphics g)
    {
        int row = campMap.length;
        int column = campMap[0].length;
        for (int i = 0; i < row; i++)
        {
            for (int j = 0; j < column; j++)
            {
                int mapValue = campMap[i][j];
                if(mapValue == 1)
                {
                    g.setColor(Color.WHITE);
                    drawElement(g,this.x + elementWidth * j,this.y + elementHeight * i);
                }
                else if(mapValue == 2)
                {
                    g.setColor(Color.LIGHT_GRAY);
                    drawElement(g,this.x + elementWidth * j,this.y + elementHeight * i);
                }
            }
        }
    }

    /**
     * 畫元素
     * @param x 元素左上角X坐標(biāo)
     * @param y 元素左上角Y坐標(biāo)
     */
    private void drawElement(Graphics g,int x,int y)
    {
        g.fillRect(x,y,elementWidth,elementHeight);
        g.setColor(Color.WHITE);
        g.draw3DRect(x,y,elementWidth,elementHeight,true);
    }

    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 int getWidth(){return width;}

    public int getHeight(){return height;}

    public int getState(){return state;}

    public void setState(int state){this.state = state;}

}

下載:

鏈接:https://pan.baidu.com/s/1aqNjqATCjteiAdv90YDByw?pwd=mylx

提取碼:mylx

感言:

本游戲并沒有使用圖片,都是用Java畫的,有興趣的朋友可以自己改用圖片,圖片素材我已經(jīng)打包了。使用圖片的朋友要注意一個問題,就是圖片加載是需要時間的,第一次可能還未加載成功就直接刷新下一次界面了,這也是韓順平老師那個第一次射擊坦克不出現(xiàn)爆炸效果的原因。Toolkit.getDefaultToolkit().createImage這個方法有BUG,改用new ImageIcon(圖片路徑)).getImage()就可以了。文章來源地址http://www.zghlxwxcb.cn/news/detail-461671.html

到了這里,關(guān)于Java游戲開發(fā) —— 坦克大戰(zhàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • python小游戲畢設(shè) 坦克大戰(zhàn)游戲設(shè)計與實現(xiàn)

    python小游戲畢設(shè) 坦克大戰(zhàn)游戲設(shè)計與實現(xiàn)

    ?? Hi,各位同學(xué)好呀,這里是L學(xué)長! ??今天向大家分享一個今年(2022)最新完成的畢業(yè)設(shè)計項目作品 python小游戲畢設(shè) 坦克大戰(zhàn)小游戲設(shè)計與實現(xiàn) (源碼) ?? 學(xué)長根據(jù)實現(xiàn)的難度和等級對項目進行評分(最低0分,滿分5分) 難度系數(shù):3分 工作量:3分 創(chuàng)新點:4分 《坦克大戰(zhàn)》

    2024年02月05日
    瀏覽(26)
  • Unity游戲程序設(shè)計——3D雙人坦克大戰(zhàn)

    Unity游戲程序設(shè)計——3D雙人坦克大戰(zhàn)

    3D多人坦克大戰(zhàn) ·Unity2019.4.29?? ·Visual Studio 2019 雙人坦克游戲: 坦克:可移動旋轉(zhuǎn),發(fā)射炮彈 子彈:按一定方向一定速度發(fā)射;炮彈周圍會產(chǎn)生沖擊波,擊中坦克或接觸地面后爆炸 坦克生命:坦克被擊中后血條相應(yīng)變化;血條不隨坦克的旋轉(zhuǎn)而旋轉(zhuǎn);血條減到小于等于0后爆

    2024年04月28日
    瀏覽(27)
  • 畢業(yè)設(shè)計 python坦克大戰(zhàn)小游戲

    畢業(yè)設(shè)計 python坦克大戰(zhàn)小游戲

    ?? Hi,各位同學(xué)好呀,這里是L學(xué)長! ??今天向大家分享一個今年(2022)最新完成的畢業(yè)設(shè)計項目作品 python小游戲畢設(shè) 坦克大戰(zhàn)小游戲設(shè)計與實現(xiàn) (源碼) ?? 學(xué)長根據(jù)實現(xiàn)的難度和等級對項目進行評分(最低0分,滿分5分) 難度系數(shù):3分 工作量:3分 創(chuàng)新點:4分 項目獲取:

    2024年02月21日
    瀏覽(28)
  • python項目分享 - python坦克大戰(zhàn)小游戲

    python項目分享 - python坦克大戰(zhàn)小游戲

    ?? Hi,各位同學(xué)好呀,這里是L學(xué)長! ??今天向大家分享一個今年(2022)最新完成的畢業(yè)設(shè)計項目作品 python小游戲畢設(shè) 坦克大戰(zhàn)小游戲設(shè)計與實現(xiàn) (源碼) ?? 學(xué)長根據(jù)實現(xiàn)的難度和等級對項目進行評分(最低0分,滿分5分) 難度系數(shù):3分 工作量:3分 創(chuàng)新點:4分 項目獲?。?/p>

    2024年02月03日
    瀏覽(26)
  • python畢設(shè)分享 python坦克大戰(zhàn)小游戲

    python畢設(shè)分享 python坦克大戰(zhàn)小游戲

    ?? Hi,各位同學(xué)好呀,這里是L學(xué)長! ??今天向大家分享一個今年(2022)最新完成的畢業(yè)設(shè)計項目作品 python小游戲畢設(shè) 坦克大戰(zhàn)小游戲設(shè)計與實現(xiàn) (源碼) ?? 學(xué)長根據(jù)實現(xiàn)的難度和等級對項目進行評分(最低0分,滿分5分) 難度系數(shù):3分 工作量:3分 創(chuàng)新點:4分 項目獲?。?/p>

    2024年02月03日
    瀏覽(32)
  • python項目分享 坦克大戰(zhàn)小游戲設(shè)計與實現(xiàn) (源碼)

    python項目分享 坦克大戰(zhàn)小游戲設(shè)計與實現(xiàn) (源碼)

    ?? Hi,各位同學(xué)好呀,這里是L學(xué)長! ??今天向大家分享一個今年(2022)最新完成的畢業(yè)設(shè)計項目作品 python小游戲畢設(shè) 坦克大戰(zhàn)小游戲設(shè)計與實現(xiàn) (源碼) ?? 學(xué)長根據(jù)實現(xiàn)的難度和等級對項目進行評分(最低0分,滿分5分) 難度系數(shù):3分 工作量:3分 創(chuàng)新點:4分 項目獲?。?/p>

    2024年01月25日
    瀏覽(32)
  • python項目分享 - 坦克大戰(zhàn)小游戲設(shè)計與實現(xiàn) (源碼)

    python項目分享 - 坦克大戰(zhàn)小游戲設(shè)計與實現(xiàn) (源碼)

    ?? Hi,各位同學(xué)好呀,這里是L學(xué)長! ??今天向大家分享一個今年(2022)最新完成的畢業(yè)設(shè)計項目作品 python小游戲畢設(shè) 坦克大戰(zhàn)小游戲設(shè)計與實現(xiàn) (源碼) ?? 學(xué)長根據(jù)實現(xiàn)的難度和等級對項目進行評分(最低0分,滿分5分) 難度系數(shù):3分 工作量:3分 創(chuàng)新點:4分 項目獲?。?/p>

    2024年02月01日
    瀏覽(31)
  • python畢設(shè)分享 坦克大戰(zhàn)小游戲設(shè)計與實現(xiàn) (源碼)

    python畢設(shè)分享 坦克大戰(zhàn)小游戲設(shè)計與實現(xiàn) (源碼)

    ?? Hi,各位同學(xué)好呀,這里是L學(xué)長! ??今天向大家分享一個今年(2022)最新完成的畢業(yè)設(shè)計項目作品 python小游戲畢設(shè) 坦克大戰(zhàn)小游戲設(shè)計與實現(xiàn) (源碼) ?? 學(xué)長根據(jù)實現(xiàn)的難度和等級對項目進行評分(最低0分,滿分5分) 難度系數(shù):3分 工作量:3分 創(chuàng)新點:4分 項目獲?。?/p>

    2024年02月03日
    瀏覽(30)
  • 【經(jīng)典游戲】坦克大戰(zhàn) Unity2D項目實戰(zhàn)(保姆級教程)

    【經(jīng)典游戲】坦克大戰(zhàn) Unity2D項目實戰(zhàn)(保姆級教程)

    主要內(nèi)容: 1.Unity3D引擎中的基礎(chǔ)設(shè)置。 2.2D場景的搭建,預(yù)制體制作。 3.2D動畫的制作。 4.圖片圖集的有關(guān)知識。 5.碰撞器,觸發(fā)器,碰撞檢測與觸發(fā)檢測。 6.2D游戲渲染的一些知識。 7.敵人AI的編寫。 8.UGUI有關(guān)內(nèi)容,場景切換等。 所需資源包鏈接:https://pan.baidu.com/s/199wuwM

    2024年02月06日
    瀏覽(33)
  • Java筆記037-坦克大戰(zhàn)【3】

    Java筆記037-坦克大戰(zhàn)【3】

    目錄 坦克大戰(zhàn)【3】 坦克大戰(zhàn)0.6 增加功能 思路分析 坦克大戰(zhàn)【0.7】 增加功能 思路分析 坦克大戰(zhàn)【3】(0.7) 運行結(jié)果 增加功能 防止敵人坦克重疊運動 記錄玩家的成績(累計擊毀敵方坦克數(shù)),暫存盤【IO流】? 記錄當(dāng)時的敵人坦克坐標(biāo)/方向,存盤退出【IO流】 玩游戲時,可以

    2023年04月09日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包