2022最新java坦克大战+免费源码+坦克大战图片

游戏介绍

本次项目模仿了小时候玩的坦克大战小游戏,其中的功能基本实现,里面最重要的思想就是对象池,类似于前面所学的线程池,让对象重复的使用,减少资源的浪费。做的时候逻辑性很强,很不容易,不过总算是有所实现。
用到的知识点:
主要是:Frame窗体,Graphics绘图,
其次是:集合 多线程。

游戏的主窗体

/**
 * 主界面的绘制
 */
public class GameFrame extends Frame  implements Runnable{


    // 1.定义一张和屏幕大小一致的图片(双缓存)
    private BufferedImage bufImg=new BufferedImage(FRAME_WIDTH,FRAME_HEIGTH,BufferedImage.TYPE_4BYTE_ABGR);
    // 游戏的状态
    public static int gameStart;
    // 菜单指向
    private int menuIndex;
    // 创建坦克对象
    private Tank myTank;
    // 敌人坦克对象
    private List<Tank> enemies=new ArrayList<>();
    // 标题栏的高度
    public static int menuTitle;
    // 绘制游戏结束的方法,(用到的时候在加载)
    private static Image overImage =null;
    //定义地图相关的内容
    private GameMap gameMap;



    /**
     * 对窗口进行初始化
     */
    public GameFrame(){
        initFrame();
        iniEventListener();
        new Thread(this).start();

    }

    /**
     * 对窗口初始化
     */
    private void initFrame(){
        gameStart=START_MENU;

        setTitle(NAME_TANK);
        setSize(FRAME_WIDTH,FRAME_HEIGTH);
        setLocationRelativeTo(null);
        // 设置不可修改
        setResizable(false);
        menuTitle=getInsets().top;
        setVisible(true);

    }

    /**
     * 该方法负责了所有的绘制内容,该方法不能主动调用
     *  repaint去回调该方法
     */
    public void update(Graphics g2) {
        // 定义图片画笔
        Graphics g=bufImg.getGraphics();
        switch (gameStart){
            case START_MENU:
                drawMenus(g);
                break;
            case START_HELP:
                drawHelp(g);
                break;
            case START_ABOUT:
                drawAbout(g);
                break;
            case START_RUN:
                drawRun(g);
                break;
            case START_OVER:
                drawOver(g);
                break;
        }
        // 使用系统画笔将内容绘制在窗口上
        g2.drawImage(bufImg,0,0,FRAME_WIDTH, FRAME_HEIGTH,this);
    }
    
    // 主菜单的方法
    private void drawMenus(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g2.setFont(FONT_SIZE);
        // 绘制黑色背景颜色
        g2.setColor(Color.GRAY);
         g2.fillRect(0, 0, FRAME_WIDTH, FRAME_HEIGTH);
        // 把文字绘制成白色
        // 该方法默认设置字体
        g2.setColor(Color.black);
        final int STR_WIDTH = 50;
        final int x = FRAME_WIDTH / 2-50;
        final int y = FRAME_HEIGTH / 3;
        for (int i = 0; i < MENUS.length; i++) {
            // 设置菜单的触发颜色
            if (i == menuIndex) {
                g2.setColor(Color.pink);

            } else {
                g2.setColor(Color.white);
            }
            g2.drawString(MENUS[i], x, y + STR_WIDTH * i);

        }
    }

    /**
     * 负责存放所以监听事件
     */
    private void iniEventListener(){
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                // 获得事件相关联的整数
                int  keyCode=e.getKeyCode();
                //不同的游戏状态,给出不同的处理方法
                switch (gameStart){
                    case START_MENU:
                        keyEventMenu(keyCode);
                        break;
                    case START_HELP:
                        keyEventHELP(keyCode);
                        break;
                    case START_ABOUT:
                        keyEventABOUT(keyCode);
                        break;
                    case START_RUN:
                        keyEventRUN(keyCode);
                        break;
                    case START_OVER:
                        keyEventOVER(keyCode);
                        break;

                }

            }

            @Override
            public void keyReleased(KeyEvent e) {
                // 获得事件相关联的整数
                int  keyCode=e.getKeyCode();
                //不同的游戏状态,给出不同的处理方法
                    if(gameStart==START_RUN) {
                        keyReleaseEventMenu(keyCode);

                    }
            }
        });

    }
    // 按键松开的时候游戏处理的方法
    private void keyReleaseEventMenu(int keyCode) {
        switch (keyCode){
            case KeyEvent.VK_UP:
            case KeyEvent.VK_W:

            case KeyEvent.VK_DOWN:
            case KeyEvent.VK_S:

            case KeyEvent.VK_A:
            case KeyEvent.VK_LEFT:

            case KeyEvent.VK_D:
            case KeyEvent.VK_RIGHT:
                myTank.setState(Tank.STATE_STAND);
        }
    }

    // 菜单状态下的按键处理
    private void keyEventMenu(int keyCode) {
        switch (keyCode){
            case KeyEvent.VK_UP:
            case KeyEvent.VK_W:
                if(--menuIndex<0){
                    menuIndex=MENUS.length-1;
                }
                break;
            case KeyEvent.VK_DOWN:
            case KeyEvent.VK_S:
                if(++menuIndex>MENUS.length-1){
                    menuIndex=0;
                }
                break;
            case KeyEvent.VK_ENTER:

                newGame();
                break;
        }

    }
    // 游戏中行走时的监听
    private void keyEventRUN(int keyCode) {

        switch (keyCode){
            case KeyEvent.VK_UP:
            case KeyEvent.VK_W:
                myTank.setDir(Tank.UP);
                myTank.setState(Tank.STATE_MOVE);
                break;
            case KeyEvent.VK_DOWN:
            case KeyEvent.VK_S:
                myTank.setDir(Tank.DOWN);
                myTank.setState(Tank.STATE_MOVE);
                break;
            case KeyEvent.VK_A:
            case KeyEvent.VK_LEFT:
                myTank.setDir(Tank.LEFT);
                myTank.setState(Tank.STATE_MOVE);
                break;

            case KeyEvent.VK_D:
            case KeyEvent.VK_RIGHT:
                myTank.setDir(Tank.RIGHT);
                myTank.setState(Tank.STATE_MOVE);
                break;
            case KeyEvent.VK_SPACE:
                myTank.fire();
                break;
        }
    }
    private void keyEventHELP(int keyCode) {
    }
    private void keyEventABOUT(int keyCode) {
    }

    // 游戏结束后的执行
    private void keyEventOVER(int keyCode) {
        // 结束游戏
        if(keyCode==KeyEvent.VK_ESCAPE){
            System.exit(0);
        }else if(keyCode==KeyEvent.VK_ENTER){
            setGameStart(START_MENU);
            resetGame();
        }

    }


    /**
     * 游戏运行状态的内容绘制
     * @param g
     */
    private void drawRun(Graphics g) {
        g.setColor(Color.gray);
        g.fillRect(0,0,FRAME_WIDTH,FRAME_HEIGTH);
        // 绘制地图
        gameMap.drawBK(g);

        drawEnemies(g);

        myTank.draw(g);
        // 绘制地图遮挡
        gameMap.drawCover(g);
        // 子弹和坦克碰撞
        drawExplodes(g);

        bulletCollideTank();

        bulletAndTankCollideMapTile();


    }

    /**
     * 绘制敌人坦克
     * @param g
     */
    private void drawEnemies(Graphics g){

        for (int i = 0; i < enemies.size(); i++) {
            Tank enemy=enemies.get(i);
            if(enemy.isDie()){
                enemies.remove(i);
                i--;
                continue;
            }
            enemy.draw(g);
        }

    }

    private void drawAbout(Graphics g) {
    }


    /**
     * 游戏结束按键处理
     * @param g
     */
    private void drawOver(Graphics g) {
        // 保证只加载一次
        if(overImage ==null){
            overImage =MyUtil.creatImage(gameOver);
        }
        // 得到图片的宽和高
        int imgW=overImage.getWidth(null);
        int imgH=overImage.getHeight(null);
        g.drawImage(overImage,FRAME_WIDTH-imgW>>1,FRAME_HEIGTH-imgH>>1,null);
        // 添加按键提示信息
        g.setColor(Color.red);
        g.drawString(OVER_STA,10,FRAME_HEIGTH-40);
        g.drawString(OVER_STA1,FRAME_WIDTH-200,FRAME_HEIGTH-30);

    }



    private void drawHelp(Graphics g) {
    }

    @Override
    public void run() {
        while (true) {
            repaint();
            try {
                Thread.sleep(REPAIN_TIME);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 重置游戏状态
     */
    private void resetGame(){
        menuIndex=0;
        // 先让自己坦克的子弹还回对象池
        myTank.bulletsReturn();
        // 销毁自己坦克
        myTank=null;
        for (Tank enemy : enemies) {
            enemy.bulletsReturn();
        }
        // 清空敌人
        enemies.clear();
        gameMap=null;

    }

    /**
     * 开始游戏的方法
     */
     private void newGame(){
         gameStart=START_RUN;
         // 创建坦克对象
         myTank=new MyTank(FRAME_WIDTH/3,FRAME_HEIGTH-Tank.BAN_JIN ,Tank.UP);
         gameMap=new GameMap();
         // 使用一个单独的线程用于控制敌人的坦克
         new Thread(){
             @Override
             public void run() {
                 while (true){
                     if(enemies.size()<MAX_ENEMY_COUNT){
                         Tank enemy= EnemyTank.creatEnemy();
                         enemies.add(enemy);
                     }
                     // 产生敌人坦克间隔
                     try {
                         Thread.sleep(3000);
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
                     // 如果游戏不再运行中,我们就停止创建敌人坦克
                     if(gameStart!=START_RUN){
                         break;
                     }
                 }
             }
         }.start();
     }
     // 敌所有人坦克的子弹和我坦克的碰撞
    // 我的坦克子弹敌人的坦克碰撞
    private void bulletCollideTank(){
         // 我的坦克子弹碰撞所有敌人
        for (Tank enemy : enemies) {
            enemy.collideBullets((myTank.getBullets()));
        }

        // 所有敌人坦克子弹碰撞我坦克
        for (Tank enemy : enemies) {
            myTank.collideBullets((enemy.getBullets()));
        }

    }
    // 所有的子弹和地图块的碰撞
    private void bulletAndTankCollideMapTile(){
         // 自己子弹和砖块碰撞

        myTank.bulletCollideMapTile(gameMap.getTiles());
        // 敌人子弹和砖块碰撞
        for (Tank enemy : enemies) {
            enemy.bulletCollideMapTile(gameMap.getTiles());
        }
        // 坦克和地图的碰撞
       if( myTank.isCollideTile(gameMap.getTiles())){
           myTank.backLast();
       }
       // 敌人的坦克和地图的碰撞
        for (Tank enemy : enemies) {
            if(enemy.isCollideTile(gameMap.getTiles())){
                enemy.backLast();
            }
        }
        // 清理被销毁的地图块
        gameMap.clearDestoryTile();
    }
    // 所有坦克的爆炸效果
    private void drawExplodes(Graphics g){
        for (Tank enemy : enemies) {
            enemy.drawExplodes(g);
        }
        myTank.drawExplodes(g);
    }

    public static int getGameStart() {
        return gameStart;
    }

    public static void setGameStart(int gameStart) {
        GameFrame.gameStart = gameStart;
    }
}

坦克共同拥有的属性

package com.hg.tank;

import com.hg.MainJFrame.GameFrame;
import com.hg.TankBattle.Bullet;
import com.hg.TankBattle.Explode;
import com.hg.Util.*;
import com.hg.map.MapTile;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import static com.hg.Util.ConsDemo.*;

/**
 * 坦克共有的属性
 */
public abstract class Tank  {


    public static final int UP=0;
    public static final int DOWN=1;
    public static final int LEFT=2;
    public static final int RIGHT=3;
    // 坦克状态
    public static final int STATE_STAND=0;
    public static final int STATE_MOVE=1;
    // 死亡
    private static final int DIE=2;
    // 坦克初始生命
    public static final int DEFAULT_HP=1000;
    // 坐标
    private int x;
    private int y;
    // 半径
    public static final int BAN_JIN=23;
    // 坦克的默认状态
    private int state;
    // 默认速度,每一帧30ms 4速度
    public static final int DEFAULT_SPEED=6;
    // 血量
    private int hp=DEFAULT_HP;
    // 攻击力
    private int atk;
    public int ATK_MAX=500;
    public int ATK_MIN=90;
    // 颜色
    private Color color;
    // 方向
    private int dir;
    // 速度
    private int speed=DEFAULT_SPEED;
    // 是否是敌人
    private boolean isEnemy =false;
    // TODO炮弹
    private List<Bullet> bullets=new ArrayList();
    // 使用容器来保持当前坦克上的所有爆炸效果
    private List<Explode> explodes=new ArrayList<>();
    // 名字
    private String name;
    // 血条对象
    private BloodBar bar=new BloodBar();



    // 坦克的初始状态
    public Tank(int x,int y,int dir){
        this.x=x;
        this.y=y;
        this.dir=dir;
        initTank();
    }

    public Tank() {
        // 初始化坦克
        initTank();
    }
    public void initTank(){
        color= MyUtil.getRamdomColor();
        name=MyUtil.getRandomName();
        atk=MyUtil.getRamdomNumber(ATK_MIN,ATK_MAX);
    }


    /**
     * 坦克的逻辑处理
     */
    public void tankLogic(){
        switch (state){
            case STATE_MOVE:
                move();
                break;
            case STATE_STAND:
                break;
        }
    }

    /**
     * 坦克的移动
     */
    private int oldX=-1,oidY=-1;

    public void move(){
        oldX=x;
        oidY=y;
        switch (dir){
            case UP:
                y-=speed;
                if(y<(3*BAN_JIN))
                    y=3*BAN_JIN;
                break;
            case DOWN:
                y+=speed;
                if(y>(ConsDemo.FRAME_HEIGTH-BAN_JIN))
                    y=(ConsDemo.FRAME_HEIGTH-BAN_JIN);
                break;
            case LEFT:
                x-=speed;
                if(x<BAN_JIN)
                    x=BAN_JIN;
                break;
            case RIGHT:
                x+=speed;
                if(x>(ConsDemo.FRAME_WIDTH-BAN_JIN))
                    x =(ConsDemo.FRAME_WIDTH-BAN_JIN);
                break;
        }
    }

    /**
     * @param g 绘制坦克图片,使用图片
     */
    public abstract void drawTankImg(Graphics g);

    public void draw(Graphics g){

        tankLogic();

        drawBullet(g);

        drawTankImg(g);

        drawName(g);

        bar.drawBlood(g);


    }

    /**
     * 绘制坦克的名字
     * @param g
     */
    private void drawName(Graphics g){
        g.setColor(color);
        g.drawString(name,x-(2*BAN_JIN),y-40);
        g.setFont(GAME_FONT);
    }

    /**
     * 对坦克进行绘画->使用系统的方式绘制
     * @param g2
     */
    public void drawTank(Graphics g2){
        Graphics2D g=(Graphics2D)g2;
        g.setColor(color);
        int endX=x;
        int endY=y;
        // 设置画笔的宽度
        Stroke stroke=new BasicStroke(4.0f);
        g.setStroke(stroke);
        // 绘制坦克的圆,是以矩形的一个端点开始
        g.fillOval(x-BAN_JIN,y-BAN_JIN,BAN_JIN<<1,BAN_JIN<<1);
        // 判断坦克走向

        switch (dir){
            case UP:
                endY=y-2*BAN_JIN;
                break;
            case DOWN:
                endY=y+2*BAN_JIN;
                break;
            case LEFT:
                endX=x-2*BAN_JIN;
                break;
            case RIGHT:
                endX=x+2*BAN_JIN;
                break;

        }

        g.drawLine(x,y,endX,endY);

    }
    /**
     * 坦克开火的功能
     */
    // 上一次开火的时间
    private long millis;
    // 发射最小间隔
    public static final int FIRE_INTEN=350;
    public void fire(){
        if(System.currentTimeMillis()-millis>FIRE_INTEN){
            int bulletX=x;
            int bulletY=y;
            switch (dir){
                case UP:
                    bulletY-=2*BAN_JIN;
                    break;
                case DOWN:
                    bulletY+=2*BAN_JIN;
                    break;
                case LEFT:
                    bulletX-=2*BAN_JIN;
                    break;
                case RIGHT:
                    bulletX+=2*BAN_JIN;
                    break;
            }
            // 从池塘中拿取
            Bullet bullet= BulletsPool.get();
            bullet.setX(bulletX);
            bullet.setY(bulletY);
            bullet.setDir(dir);
            bullet.setAtk(atk);
            bullet.setColor(color);
            bullet.setVisible(true);
            //Bullet bullet = new Bullet(bulletX,bulletY,dir,atk,color);
            // 将子弹添加到坦克管理的容器中。
            bullets.add(bullet);
            // 发射子弹后,记录本次发射子弹的时间
            millis=System.currentTimeMillis();
        }


    }
    // 发射的所有子弹绘制出来
    public void drawBullet(Graphics g){
        for (Bullet bullet : bullets) {
            bullet.draw(g);
        }
        // 遍历所有的子弹,把不可见的子弹移除还原对象池
        for (int i = 0; i < bullets.size(); i++) {
            Bullet bullet=bullets.get(i);
            if(!bullet.isVisible()){
                Bullet re=bullets.remove(i);
                i--;
                BulletsPool.back(re);
            }
        }
    }

    /**
     * 坦克销毁时处理坦克所有的子弹
     */
    public void bulletsReturn(){
        for (Bullet bullet : bullets) {
            // 把每个子弹还回去
            BulletsPool.back(bullet);
        }
        bullets.clear();
        }


    /**
     * 坦克和敌人子弹碰撞的方法。
     * @param bullets
     */
    public void collideBullets(List<Bullet> bullets){
        for (Bullet bullet : bullets) {
            int bulletX=bullet.getX();
            int bulletY=bullet.getY();
            // 子弹和坦克碰撞
            if(MyUtil.isCollide(x,y,BAN_JIN,bulletX,bulletY)){
                // 子弹消失,坦克减血
                bullet.setVisible(false);
                hurt(bullet);
                // 爆炸效果,就是坦克边沿的位置
                addExplode(x,y+BAN_JIN);
            }
        }
    }

    /**
     * 坦克受到伤害
     * @param bullet
     */
    private void hurt(Bullet bullet){
        // 坦克受到伤害
         int atk= bullet.getAtk();
        hp-=atk;
        if (hp < 0){
            hp=0;
            die();
        }
    }

    /**
     * 坦克死亡的内容
     */
    private void die(){
        if(isEnemy()){
            // 坦克死亡归回对象池
            EnemyTanksPool.back(this);
        }else{
            // 自己坦克死亡,游戏结束或者回到主菜单
            delaySecondsToOver();

        }
    }

    /**
     * 判断当前坦克是否死亡了
     * @return
     */
    public boolean isDie(){
        return hp<=0;
    }

    /**
     * 绘制当前坦克上的所有爆炸效果
     * @param g
     */
    public void drawExplodes(Graphics g){
        for (Explode explode : explodes) {
            explode.draw(g);
        }
        // 把不可见的爆炸效果删除,返回对象池
        for (int i = 0; i < explodes.size(); i++) {
            Explode explode=explodes.get(i);
            explodes.remove(i);
            ExplodePool.back(explode);
            i--;
        }
    }

    /**
     * 坦克回退的方法
     */
    public void backLast() {
        x=oldX;
        y=oidY;
    }

    class BloodBar{
        // 血条的宽和高
        public static final int BAY_LENGTH=50;
        public static final int BAY_HEIGHT=5;
        public void drawBlood(Graphics g){
            // 血条颜色填充
            g.setColor(Color.yellow);
            g.fillRect(x-(BAN_JIN+10),y-BAN_JIN-BAY_HEIGHT*2,BAY_LENGTH,BAY_HEIGHT);
            // 当前血条颜色
            g.setColor(Color.red);
            g.fillRect(x-(BAN_JIN+10),y-BAN_JIN-BAY_HEIGHT*2,hp*BAY_LENGTH/DEFAULT_HP,BAY_HEIGHT);
            // 血条边框
            g.setColor(Color.white);
            g.drawRect(x-(BAN_JIN+10) ,y-BAN_JIN-BAY_HEIGHT*2,BAY_LENGTH,BAY_HEIGHT);
        }
    }

    // 所有的子弹和地图块的碰撞
    public void bulletCollideMapTile(List<MapTile> tiles){
        // 自己子弹和砖块碰撞
        for (MapTile tile : tiles) {
            if(tile.isCollideBullet(bullets)){
                // 添加爆炸效果
                addExplode(tile.getX(),tile.getY());
                // 银块不被击毁
                if(tile.getType()==MapTile.TYPE_HARD)
                    continue;
                // 设置地图块销毁
                tile.setVisible(false);
                // 归还对象池
                MapTitlePool.back(tile);
                // 老巢被击毁,1s后切换到游戏结束界面
                if(tile.isHouse()){
                    delaySecondsToOver();
                }


            }

        }
    }

    /**
     * 延迟若干毫秒切换到游戏结束
     */
    public void delaySecondsToOver(){
        new Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                GameFrame.setGameStart(START_OVER);
            }
        }.start();
    }
    private void addExplode(int x,int y){
        // 爆炸效果,就是坦克边沿的位置
        Explode explode=ExplodePool.get();
        explode.setX(x);
        explode.setY(y);
        explode.setVisible(true);
        explode.setIndex(0);
        explodes.add(explode);
    }
    // 一个地图和当前坦克碰撞的方法

    /**
     * 从tile`中提取八个点来判断坦克是否和地图碰撞,按照顺时针
     * @param
     * @return
     */
    public boolean isCollideTile(List<MapTile> tiles){
        for (MapTile tile : tiles) {
            if(!tile.isVisible() || tile.getType()==MapTile.TYPE_COVER)
                continue;
            // 1左上角的点
            int tileX=tile.getX();
            int tileY=tile.getY();
            boolean collide = MyUtil.isCollide(x, y, BAN_JIN, tileX, tileY);
            // 碰上直接返回否则判断下一个点
            if(collide){
                return true;
            }
            // 点二,中上
            tileX+=MapTile.radius;
            collide = MyUtil.isCollide(x, y, BAN_JIN, tileX, tileY);
            if(collide){
                return true;
            }
            // 3 右上角
            tileX+=MapTile.radius;
            collide = MyUtil.isCollide(x, y, BAN_JIN, tileX, tileY);
            if(collide){
                return true;
            }
            // 4 右中脚
            tileY+=MapTile.radius;
            collide = MyUtil.isCollide(x, y, BAN_JIN, tileX, tileY);
            if(collide){
                return true;
            }
            // 5 右下角
            tileY+=MapTile.radius;
            collide = MyUtil.isCollide(x, y, BAN_JIN, tileX, tileY);
            if(collide){
                return true;
            }
            // 6 中下
            tileX-=MapTile.radius;
            collide = MyUtil.isCollide(x, y, BAN_JIN, tileX, tileY);
            if(collide){
                return true;
            }
            // 7 左下
            tileX-=MapTile.radius;
            collide = MyUtil.isCollide(x, y, BAN_JIN, tileX, tileY);
            if(collide){
                return true;
            }
            // 8 左中
            tileY-=MapTile.radius;;
            collide = MyUtil.isCollide(x, y, BAN_JIN, tileX, tileY);
            if(collide){
                return true;
            }
        }

        return false;
    }
    public int getSpeed() {
        return speed;
    }

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

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


    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 getHp() {
        return hp;
    }


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


    public int getAtk() {
        return atk;
    }


    public void setAtk(int atk) {
        this.atk = atk;
    }


    public Color getColor() {
        return color;
    }


    public void setColor(Color color) {
        this.color = color;
    }


    public int getDir() {
        return dir;
    }


    public void setDir(int dir) {
        this.dir = dir;
    }
    public boolean isEnemy() {
        return isEnemy;
    }

    public void setEnemy(boolean enemy) {
        isEnemy = enemy;
    }

    public List<Bullet> getBullets() {
        return bullets;
    }

    public void setBullets(List<Bullet> bullets) {
        this.bullets = bullets;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

自己坦克

package com.hg.tank;

import com.hg.Util.MyUtil;
import com.hg.tank.Tank;

import java.awt.*;

import static com.hg.Util.ConsDemo.*;
import static com.hg.Util.ConsDemo.enemyUrl4;

/**
 * 自己的坦克
 */
public class MyTank extends Tank {
    // 自己坦克图片数组
    private static Image[] tankImg;
    // 静态代码块中初始化
    static {
        tankImg = new Image[4];
        tankImg[0]= MyUtil.creatImage(url);
        tankImg[1]=MyUtil.creatImage(url1);
        tankImg[2]=MyUtil.creatImage(url2);
        tankImg[3]=MyUtil.creatImage(url3);

    }
    public MyTank(int x, int y, int dir) {
        super(x, y, dir);

    }
    public MyTank(){

    }

    @Override
    public void drawTankImg(Graphics g) {
        g.drawImage(tankImg[getDir()],getX()-BAN_JIN,getY()-BAN_JIN,null);
    }

}

敌人坦克

1.敌人坦克类

package com.hg.tank;

import com.hg.Util.EnemyTanksPool;
import com.hg.Util.MyUtil;
import java.awt.*;

import static com.hg.Util.ConsDemo.*;
import static com.hg.Util.ConsDemo.enemyUrl4;

/**
 * 敌人的坦克
 */
public class EnemyTank extends Tank {
    public static final int TYPE_1=0;
    public static final int TYPE_2=1;
    // 敌人图片数组
    private static Image[] enemyImg;
    private static Image[] enemyImg2;
    private int type=TYPE_1;
    // 记录坦克开始的时间
    private long aiTime;
    // 静态代码块中初始化
    static {
        enemyImg = new Image[4];
        enemyImg[0]=MyUtil.creatImage(enemyUrl1);
        enemyImg[1]=MyUtil.creatImage(enemyUrl2);
        enemyImg[2]=MyUtil.creatImage(enemyUrl3);
        enemyImg[3]=MyUtil.creatImage(enemyUrl4);

        enemyImg2 = new Image[4];
        enemyImg2[0]=MyUtil.creatImage(enemy2Url1);
        enemyImg2[1]=MyUtil.creatImage(enemy2Url2);
        enemyImg2[2]=MyUtil.creatImage(enemy2Url3);
        enemyImg2[3]=MyUtil.creatImage(enemy2Url4);
    }

    public EnemyTank() {
        aiTime=System.currentTimeMillis();
        type=MyUtil.getRamdomNumber(0,2);
    }

    /**
     *
     * @return 用于创建敌人的坦克
     */
    public static Tank creatEnemy(){
        int x= MyUtil.getRamdomNumber(0,2)==0?BAN_JIN: (FRAME_WIDTH- BAN_JIN);
        int y=2*BAN_JIN;
        int dir=DOWN;
        Tank enemy= EnemyTanksPool.get();
        enemy.setX(x);
        enemy.setY(y);
        enemy.setDir(dir);
        enemy.setEnemy(true);
        enemy.setState(STATE_MOVE);
        enemy.setHp(Tank.DEFAULT_HP);
        return enemy;
    }

    public EnemyTank(int x, int y, int dir) {
        super(x, y, dir);
        // 敌人创建就开始计时
        aiTime=System.currentTimeMillis();
        type=MyUtil.getRamdomNumber(0,2);


    }

    @Override
    public void drawTankImg(Graphics g) {
        AI();
        g.drawImage(type==TYPE_1?enemyImg[getDir()]:enemyImg2[getDir()],getX()-BAN_JIN,getY()-BAN_JIN,null);
    }
    private void AI(){
        if(System.currentTimeMillis()-aiTime> ENEMY_AI){
            // 间隔五秒随机切换状态
            setDir(MyUtil.getRamdomNumber(UP,4));
            setState(MyUtil.getRamdomNumber(0,2)==0?STATE_STAND:STATE_MOVE);
            aiTime=System.currentTimeMillis();
            // 开火概率
            if(Math.random()< ENEMY_FIRE)
                fire();
        }

    }
}

2.敌人坦克对象池

package com.hg.Util;

import com.hg.tank.EnemyTank;
import com.hg.tank.Tank;
import java.util.ArrayList;
import java.util.List;

/**
 * 敌人坦克对象池
 */
public class EnemyTanksPool {

        // 总的坦克数量
        public static final int ALL_BULLET=15;
        // 用于保存所有子弹的容器
        private static List<Tank> pool =new ArrayList<>();
        // 在类加载的时候就创建出200个子弹添加到容器中
        static {
            for (int i = 0; i < ALL_BULLET; i++) {
                pool.add(new EnemyTank());
            }
        }

        /**
         *
         * @return 从池塘中拿出坦克
         */
        public static Tank get(){
            Tank tank;
            // 如果池塘被掏空
            if(pool.size()==0){
                tank=new EnemyTank();
            }else{
                tank= pool.remove(0);
            }
            return tank;

        }

        /**
         * 子弹别销毁的时候,归还到池塘中
         * @return
         */
        public static void  back(Tank tank){
            // 池塘中的子弹已经达到最大
            if(pool.size()==5){
                return;
            }
            pool.add(tank);
        }
    }


子弹类

  1. 子弹属性
package com.hg.TankBattle;

import com.hg.Util.ConsDemo;
import com.hg.tank.Tank;
import java.awt.*;

/**
 * 子弹类
 */
public class Bullet {
    // 子弹默认速度为坦克两倍<<1
    public static final int DEFAULT_SPEED=14;
    // 炮弹的半径
    public static final int BAN_JIN =4;
    private int x;
    private int y;
    private int speed=DEFAULT_SPEED;
    // 方向
    private int dir;
    // 攻击力
    private int atk;
    private Color color;
    // 子弹默认可见
    private boolean visible=true;

    public Bullet(int x, int y, int dir, int atk ,Color color) {
        this.x = x;
        this.y = y;
        this.dir = dir;
        this.atk = atk;
        this.color=color;
    }
    // 给对象池使用的无参构造器
    public Bullet(){

    }

    /**
     * 炮弹的绘制
     * @param g
     */
    public void draw(Graphics g){
        // 不可见就停止绘画
        if(!visible)return;
        g.setColor(color);
        g.fillOval(x-BAN_JIN,y-BAN_JIN,BAN_JIN<<1,BAN_JIN<<1);
        logicBullet();

    }

    /**
     * 子弹的逻辑
     */
    public void logicBullet(){
        move();
    }

    /**
     * 子弹的移动
     */
    public void move() {
        switch (dir) {
            case Tank.UP:
                y -= speed;
                if(y<=0)
                    visible=false;
                break;
            case Tank.DOWN:
                y += speed;
                if(y>ConsDemo.FRAME_HEIGTH)
                    visible=false;
                break;
            case Tank.LEFT:
                x -= speed;
                if(x<=0)
                    visible=false;
                break;
            case Tank.RIGHT:
                x += speed;
                if(x>ConsDemo.FRAME_WIDTH)
                    visible=false;
                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 getDir() {
        return dir;
    }

    public void setDir(int dir) {
        this.dir = dir;
    }

    public int getAtk() {
        return atk;
    }

    public void setAtk(int atk) {
        this.atk = atk;
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public boolean isVisible() {
        return visible;
    }

    public void setVisible(boolean visible) {
        this.visible = visible;
    }
}

  1. 子弹的对象池
package com.hg.Util;

import com.hg.TankBattle.Bullet;
import java.util.ArrayList;
import java.util.List;

/**
 *  子弹的对象池
 */
public class BulletsPool {
    // 初始子弹数量
    public static final int ALL_BULLET=200;
    // 用于保存所有子弹的容器
    private static List<Bullet> pool =new ArrayList<>();
    // 在类加载的时候就创建出200个子弹添加到容器中
    static {
        for (int i = 0; i < ALL_BULLET; i++) {
            pool.add(new Bullet());
        }
    }

    /**
     *
     * @return 从池塘中拿出子弹
     */
    public static Bullet get(){
        Bullet bullet=null;
        // 如果池塘被掏空
        if(pool.size()==0){
            bullet=new Bullet();
        }else{
              bullet= pool.remove(0);
        }
        return bullet;

    }

    /**
     * 子弹别销毁的时候,归还到池塘中
     * @return
     */
    public static void  back(Bullet bullet){
        // 池塘中的子弹已经达到最大,那就不再归还
        if(pool.size()==300){
            return;
        }
        pool.add(bullet);
    }
}

爆炸效果

1.爆炸类

package com.hg.TankBattle;

import com.hg.Util.ConsDemo;
import com.hg.Util.MyUtil;
import java.awt.*;

/**
 * 控制爆炸效果
 */
public class Explode {
    public static final int EXPLODE_FRAME=8;
    private static Image[] img;
    static {
        img=new Image[EXPLODE_FRAME];
        for (int i = 0; i < img.length; i++) {
            img[i]= MyUtil.creatImage(ConsDemo.BOOM);
        }
    }
    // 爆炸效果的属性
    private int x,y;
    // 当前播放帧的下表
    private int index=0;
    // 设置是否可见
    private boolean visible=true;

    // 对爆炸效果图片的宽高
    private static int imgHeight;
    private static int imgWidth;

    public Explode(){

    }

    public Explode(int x, int y) {
        this.x = x;
        this.y = y;
    }

    /**
     * 绘制爆炸效果
     * @param g
     */
    public void draw(Graphics g){
        if(imgHeight<=0){
            imgHeight =img[0].getHeight(null);
            imgWidth =img[0].getWidth(null)>>2;
        }
        if(!visible)return;
        g.drawImage(img[index],x,y,null);
        index++;
        // 播放完最后一帧设置为不可见
        if(index>=EXPLODE_FRAME){
            visible=false;
        }
    }

    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 getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public boolean isVisible() {
        return visible;
    }

    public void setVisible(boolean visible) {
        this.visible = visible;
    }

    public int getImgHeight() {
        return imgHeight;
    }

    public void setImgHeight(int imgHeight) {
        this.imgHeight = imgHeight;
    }

    public int getImgWidth() {
        return imgWidth;
    }

    public void setImgWidth(int imgWidth) {
        this.imgWidth = imgWidth;
    }

}

2.爆炸效果对象池

package com.hg.Util;

import com.hg.TankBattle.Bullet;
import java.util.ArrayList;
import java.util.List;

/**
 *  爆炸效果的对象池
 */
public class BulletsPool {
    // 初始爆炸效果数量
    public static final int ALL_BULLET=50;
    // 用于保存所有子弹的容器
    private static List<Bullet> pool =new ArrayList<>();
    // 在类加载的时候就创建出200个子弹添加到容器中
    static {
        for (int i = 0; i < ALL_BULLET; i++) {
            pool.add(new Bullet());
        }
    }

    /**
     *
     * @return 从池塘中拿出爆炸效果
     */
    public static Bullet get(){
        Bullet bullet=null;
        // 如果池塘被掏空
        if(pool.size()==0){
            bullet=new Bullet();
        }else{
              bullet= pool.remove(0);
        }
        return bullet;

    }

    /**
     * 销毁的时候,归还到池塘中
     * @return
     */
    public static void  back(Bullet bullet){
        // 池塘中的子弹已经达到最大,那就不再归还
        if(pool.size()==ALL_BULLET){
            return;
        }
        pool.add(bullet);
    }
}

地图砖块类

package com.hg.map;

import com.hg.TankBattle.Bullet;
import com.hg.Util.BulletsPool;
import com.hg.Util.ConsDemo;
import com.hg.Util.MyUtil;
import java.util.List;
import java.awt.*;

/**
 * 地图砖块
 */
public class MapTile {
    public static final int TYPE_NORMAL=0;
    public static final int TYPE_HOUSE=1;
    public static final int TYPE_COVER=2;
    public static final int TYPE_HARD=3;
    public static int tileW=20;
    public static int radius=(tileW>>1);
    private int type=TYPE_NORMAL;
    private static Image[] titleImg;
    static {
        titleImg=new Image[4];
        titleImg[TYPE_NORMAL]= MyUtil.creatImage(ConsDemo.BRICK);
        titleImg[TYPE_COVER]=MyUtil.creatImage(ConsDemo.GRASS);
        titleImg[TYPE_HOUSE]=MyUtil.creatImage(ConsDemo.BOSS);
        titleImg[TYPE_HARD]=MyUtil.creatImage(ConsDemo.IRON);
        if(tileW<=0){
            tileW=titleImg[TYPE_HOUSE].getWidth(null);
        }

    }
    // 图片资源的左上角坐标
    private int x,y;
    private boolean visible=true;

    public boolean isVisible() {
        return visible;
    }

    public void setVisible(boolean visible) {
        this.visible = visible;
    }

    /**
     * 地图块和子弹是否有碰撞
     * @param
     * @return
     */
    public boolean isCollideBullet(List<Bullet> bullets){
        if(!visible || type==TYPE_COVER)
            return false;
        for (Bullet bullet : bullets) {
            int bulletX=bullet.getX();
            int bulletY= bullet.getY();
            boolean collide = MyUtil.isCollide((x + radius), (y + radius), radius, bulletX, bulletY);
            if(collide){
                // 子弹销毁
                bullet.setVisible(false);
                BulletsPool.back(bullet);
                return true;
            }
        }
        return false;
    }


    public MapTile(int x, int y){
        this.x=x;
        this.y=y;
        if(tileW<=0){
            tileW=titleImg[TYPE_HOUSE].getWidth(null);
        }
    }

    public MapTile() {
    }

    // 判断当前地图块是否是老巢
    public boolean isHouse(){
        return type==TYPE_HOUSE;
    }
    public void draw(Graphics g){
        if(!visible)
            return;
        if(tileW<=0){
            tileW=titleImg[TYPE_HOUSE].getWidth(null);
        }
        g.drawImage(titleImg[type],x,y,null);
    }

    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 getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }
}

游戏地图类

package com.hg.map;

import com.hg.MainJFrame.GameFrame;
import com.hg.Util.ConsDemo;
import com.hg.Util.MapTitlePool;
import com.hg.Util.MyUtil;
import com.hg.tank.Tank;

import java.awt.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 游戏地图类
 */
public class GameMap {
    // 地图坐标
    public static final int MAP_X = Tank.BAN_JIN*3;
    public static final int MAP_Y = Tank.BAN_JIN*3+ GameFrame.menuTitle;
    public static final int MAP_WIDTH = ConsDemo.FRAME_WIDTH-Tank.BAN_JIN*6;
    public static final int MAP_HEIGHT = (ConsDemo.FRAME_HEIGTH-Tank.BAN_JIN*8-GameFrame.menuTitle);
    // 地图大小
    private int width,height;
    private TankHouse house;
    // 地图元素块容器
    private List<MapTile> tiles=new ArrayList<>();

    public GameMap() {
        initMap();
    }

    /**
     * 初始化地图元素块
     */
    private void initMap(){
        // 可以加上,可以不加
         // 随机添加一个地图块元素,添加到容器中
//        final int COUNT=30;
//        for (int i = 0; i < COUNT; i++) {
//            MapTile title= MapTitlePool.get();
//            int x= MyUtil.getRamdomNumber(MAP_X,MAP_X+MAP_WIDTH-MapTile.tileW);
//            int y= MyUtil.getRamdomNumber(MAP_Y,MAP_Y+MAP_HEIGHT-MapTile.tileW);
//            title.setX(x);
//            title.setY(y);
//            tiles.add(title);
//        }
        // 三行地图
        addRow(MAP_X,MAP_Y,MAP_X+MAP_WIDTH,MapTile.TYPE_NORMAL,0);
        addRow(MAP_X,MAP_Y+MapTile.tileW*6,MAP_X+MAP_WIDTH,MapTile.TYPE_COVER,0);
        addRow(MAP_X,MAP_Y+MapTile.tileW*20,MAP_X+MAP_WIDTH,MapTile.TYPE_HARD,MapTile.tileW*3);
        house=new TankHouse();
        addHouse();
    }

    /**
     * 往地图块容器中添加一行指定类型的地图块
     * @param startX 地图块起始坐标
     * @param startY
     * @param endX 新增地图块的结束坐标
     * @param type 地图块类型
     * @param DIS 地图块的间隔
     */
    public void addRow(int startX,int startY,int endX,int type,final int DIS){
        int count=0;
            count=(endX-startX)/MapTile.tileW;
            for (int i = 0; i < count; i++) {
                MapTile tile=MapTitlePool.get();
                tile.setType(type);
                tile.setX(startX+i*(MapTile.tileW+DIS));
                tile.setY(startY);
                tiles.add(tile);
            }
        }


    /**
     * 某一个点是否和 titles 集合中的所有块用重叠部分,有返回true
     * @param tiles
     * @param x
     * @param y
     * @return
     */
    private boolean isCollide(List<MapTile> tiles,int x,int y){
        for (MapTile tile : tiles) {
            int tiltX=tile.getX();
            int tiltY=tile.getY();
            if(Math.abs(tiltX-x)<MapTile.tileW && Math.abs(tiltY-y)<MapTile.tileW);
            return true;
        }
        return false;
    }
    // 对没有遮挡效果的块绘制
    public void drawBK(Graphics g){
        for (MapTile tile : tiles) {
            if(tile.getType()!=MapTile.TYPE_COVER)
            tile.draw(g);
        }
        // 初始化大本营
        //house.draw(g);
    }
    // 只绘制有遮挡的块
    public void drawCover(Graphics g){
        for (MapTile tile : tiles) {
            if(tile.getType()==MapTile.TYPE_COVER)
                tile.draw(g);
        }
        // 初始化大本营
        //house.draw(g);
    }

    /**
     * 把老巢元素块添加到地图的容器中
     */
    private void addHouse(){
        tiles.addAll(house.getTiles());

    }

    /**
     * 将所有不可见的地图块全部移除
     */
    public void clearDestoryTile(){
        for (int i = 0; i < tiles.size(); i++) {
            MapTile tile=tiles.get(i);
            if(!tile.isVisible()){
                tiles.remove(i);
            }
        }
    }

    public List<MapTile> getTiles() {
        return tiles;
    }

    public void setTiles(List<MapTile> tiles) {
        this.tiles = tiles;
    }
}

砖块所在对象池

package com.hg.Util;

import com.hg.map.MapTile;
import java.util.ArrayList;
import java.util.List;

public class MapTitlePool {
    // 初始数量
    public static final int ALL_BULLET=50;
    // 最大数量
    public static final int POOL_MAX_SIZE=70;
    // 用于保存所有砖块
    private static List<MapTile> pool =new ArrayList<>();
    static {
        for (int i = 0; i < ALL_BULLET; i++) {
            pool.add(new MapTile());
        }
    }

    /**
     *
     * @return 从池塘中拿出砖块
     */
    public static MapTile get(){
        MapTile tile;
        // 如果池塘被掏空
        if(pool.size()==0){
            tile=new MapTile();
        }else{
            tile= pool.remove(0);
        }
        return tile;

    }

    /**
     * 销毁的时候,归还到池塘中
     * @return
     */
    public static void  back(MapTile tile){
        // 池塘中的砖块已经达到最大
        if(pool.size()==POOL_MAX_SIZE){
            return;
        }
        pool.add(tile);
    }
}

BOSS所在类

package com.hg.map;

import com.hg.Util.ConsDemo;
import com.hg.Util.MyUtil;

import java.awt.*;
import java.util.ArrayList;
import java.util.List;

/**
 * Boss所在地方
 */
public class TankHouse {
    public static final int HOUSE_X= (ConsDemo.FRAME_WIDTH-4*MapTile.tileW>>1);
    public static final int HOUSE_Y= (ConsDemo.FRAME_HEIGTH-3*MapTile.tileW)-5;
    public static Image bossImg= MyUtil.creatImage(ConsDemo.BOSS);
    // 一共7块老鬼地图
    private List<MapTile> tiles=new ArrayList<>();

    public TankHouse() {
        tiles.add(new MapTile(HOUSE_X,HOUSE_Y));
        tiles.add(new MapTile(HOUSE_X,HOUSE_Y+MapTile.tileW));
        tiles.add(new MapTile(HOUSE_X,HOUSE_Y+MapTile.tileW*2));

        tiles.add(new MapTile(HOUSE_X+MapTile.tileW,HOUSE_Y));
        tiles.add(new MapTile(HOUSE_X+MapTile.tileW*2,HOUSE_Y));
        tiles.add(new MapTile(HOUSE_X+MapTile.tileW*3,HOUSE_Y));
        tiles.add(new MapTile(HOUSE_X+MapTile.tileW*3,HOUSE_Y+MapTile.tileW));
        tiles.add(new MapTile(HOUSE_X+MapTile.tileW*3,HOUSE_Y+MapTile.tileW*2));
        //tiles.add(new MapTile(HOUSE_X+MapTile.tileW+6,HOUSE_Y+MapTile.tileW+15));
        tiles.add(new MapTile(HOUSE_X+MapTile.tileW,HOUSE_Y+MapTile.tileW));
        // 设置老巢地图块类型
        tiles.get(tiles.size()-1).setType(MapTile.TYPE_HOUSE);
    }
    public void draw(Graphics g){
        for (MapTile tile : tiles) {
            tile.draw(g);
        }
        //g.drawImage(bossImg,HOUSE_X+MapTile.tileW,HOUSE_Y+MapTile.tileW,null);
    }

    public List<MapTile> getTiles() {
        return tiles;
    }

    public void setTiles(List<MapTile> tiles) {
        this.tiles = tiles;
    }
}

工具类

package com.hg.Util;

import java.awt.*;
import java.net.URL;

/**
 * 工具类
 */
public class MyUtil {
    private MyUtil(){

    }

    /**
     *
     * @param min 区间最小值
     * @param max 区间最大值 (左闭右开)
     * @return 随机数
     */
    public static final int getRamdomNumber(int min,int max){
        //return (int)(Math.random()*max-min);
        return (int)(Math.random()*(max-min)+min);
    }

    /**

     * @return 获取随机三原色
     */
    public static final Color getRamdomColor(){
        int red=getRamdomNumber(0,256);
        int blue=getRamdomNumber(0,256);
        int green=getRamdomNumber(0,256);
        return new Color(red,blue,green);

    }

    /**
     * 判断一个点是否在一个正方形中心点的内部
     * @param retX 正方形中心点x
     * @param retY 正方形中心点y
     * @param radius 正方形边长的一半
     * @param pointX 圆的x坐标
     * @param pointY 圆的y坐标
     * @return 如果点在正方形内部返回true
     */
    public static final boolean isCollide(int retX,int retY,int radius,int pointX,int pointY){
        // 正方形中心点的 x和 y的距离
        int disX=Math.abs(retX-pointX);
        int disY=Math.abs(retY-pointY);
        if(disX<radius && disY< radius)
            return true;
        return false;
    }

    /**
     *
     * @param path 图片路径
     * @return
     */
    public static final Image creatImage(URL path){
        return Toolkit.getDefaultToolkit().createImage(path);
    }

    public static final String[] AI_Name={

            "行人","乐园", "花草","人才","左手","目的","课文","优点","年代","灰尘","沙子","小说","儿女","难题","明星","本子",
            "彩色", "水珠","路灯","把握","房屋","心愿","左边","新闻","早点", "市场","雨点", "细雨","书房","毛巾","画家",
            "元旦","绿豆","本领" , "起点","青菜","土豆","总结","礼貌","右边"

};
    public static final String[] AI_NAME={
            "可爱","傻傻","萌萌","羞羞","笨笨","呆呆","美丽","聪明" ,"伶俐","狡猾","胖乎乎","粉嫩嫩","白胖胖","漂亮"
            ,"可爱","聪明","懂事","乖巧","淘气","淘气","顽劣","调皮","顽皮", "天真","可爱","无邪","单纯","纯洁","无暇","纯真"
    };
    /**
     * 随机获取一个名字
     */
    public static final String getRandomName(){
        return AI_NAME[getRamdomNumber(0,AI_NAME.length)]+"的"+AI_Name[getRamdomNumber(0,AI_Name.length)];
    }

}

静态资源类

package com.hg.Util;

import com.hg.tank.Tank;

import java.awt.*;
import java.net.URL;

/**
 *  游戏中的常量都在该类中,方便后期管理
 */
public class ConsDemo {
    public static final String NAME_TANK="坦克大战";
    public static final int FRAME_WIDTH=1200;
    public static final int FRAME_HEIGTH=800;

    /**
     * 游戏菜单相关常量
     */
    public static final int START_MENU=0;
    public static final int START_HELP=1;
    public static final int START_ABOUT=2;
    public static final int START_RUN=3;
    public static final int START_OVER =4;

    public static final String[] MENUS={
      "开始游戏","继续游戏","游戏帮助","游戏关于","退出游戏"
    };
    public static final String OVER_STA="ESC退出游戏";
    public static final String OVER_STA1="Enter回到主菜单";
    // 坦克名字
    public static final Font GAME_FONT=new Font("楷体",Font.BOLD,14);

    public static final Font FONT_SIZE=new Font("楷体",Font.PLAIN,25);
    // 重绘时间
    public static final int REPAIN_TIME=30;
    // 坦克图片的地址
    public static final URL url= Tank.class.getResource("/tank/player1_up.png");
    public static final URL url1=Tank.class.getResource("/tank/player1_down.png");
    public static final URL url2=Tank.class.getResource("/tank/player1_left.png");
    public static final URL url3=Tank.class.getResource("/tank/player1_right.png");

    // 敌人坦克图片地址
    public static final URL enemyUrl1= Tank.class.getResource("/tank/bot_up.png");
    public static final URL enemyUrl2=Tank.class.getResource("/tank/bot_down.png");
    public static final URL enemyUrl3=Tank.class.getResource("/tank/bot_left.png");
    public static final URL enemyUrl4=Tank.class.getResource("/tank/bot_right.png");

    // 敌人坦克图片地址
    public static final URL enemy2Url1= Tank.class.getResource("/tank/player2_up.png");
    public static final URL enemy2Url2=Tank.class.getResource("/tank/player2_down.png");
    public static final URL enemy2Url3=Tank.class.getResource("/tank/player2_left.png");
    public static final URL enemy2Url4=Tank.class.getResource("/tank/player2_right.png");

    // 最大敌人数量
    public static final int MAX_ENEMY_COUNT=10;
    // 敌人随机切换状态的时间
    public static final int ENEMY_AI=1000;
    // 敌人开火的几率
    public static final double ENEMY_FIRE=0.6;
    // 爆炸的路径
    public static final URL BOOM= Tank.class.getResource("/img/boom/boom.png");
    // 结束游戏图片路径
    public static final URL gameOver= Tank.class.getResource("/tank/gameover.jpg");
    // 砖块路径
    public static final URL BRICK= Tank.class.getResource("/img/wall/brick.png");
    public static final URL GRASS= Tank.class.getResource("/img/wall/grass.png");
    public static final URL IRON= Tank.class.getResource("/img/wall/iron.png");
    // BOSS
    public static final URL BOSS= Tank.class.getResource("/img/wall/base.png");


}

main方法

package com.hg.TankBattle;

import com.hg.MainJFrame.GameFrame;

public class TextMain {
    public static void main(String[] args) {
        new GameFrame();
    }
}

图片目录

大家有图片的可以自行设置路径
在这里插入图片描述

游戏效果截图:

在这里插入图片描述第一次做还有很多不足之处,欢迎大家指出,大家有什么问题也可以留言咨询!

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值