Java tank battle follow teacher Han Shunping video development

TankBigWarGame

introduce

TankBigWar, Tank Wars, followed the 30-day Java basic course taught by Mr. Han Shunping. I typed it up bit by bit. I felt a sense of accomplishment after finishing it.

The source code of the project is put on the code cloud, and you can pick up
the tank war project if you need it

interface display

The overall design layout shows
interface display
the player information bar on the right, as shown in the figure below:
player information

project structure

Description of software architecture: The tank and interface drawn by JFrame components are very helpful for multi-threading, object-oriented programming, and the use of JFrame. It is a good practice project for beginners.
Software Architecture

Installation Tutorial

  1. After downloading, you only need to execute the Main method
  2. The sound and txt files are placed under the src directory, and the code is written with a relative path, so don't worry about not being able to run
  3. After starting the Main method, you need to select whether it is a new game or a file load on the console, keyboard input 1: new game; keyboard input 2: load file
    start tutorial

game instructions

  1. The right side is the number of destroyed enemy tanks and the remaining number of player tanks
  2. After entering the game, the general input method will switch to Chinese, you need to switch it by default before operating
  3. The direction keys of the keyboard control the direction of the tank, and the space bar shoots.
  4. After entering the game, press the number key 1 to call the enemy tank
  5. After entering the game, if our tank is destroyed by the enemy, you can press the number key 2 to revive it in situ
  6. After entering the game, there will be BGM background music, sound effects when our side fires bullets, and explosion sound effects when our or enemy tanks are destroyed

The project involves a technical function

  1. Player tank moves, fires, and hits the wall
  2. Enemy tanks move, fire, collide and turn when moving in multiple threads
  3. Background music
  4. game progress archive
  5. Players revive in place after being destroyed
  6. Summon enemy tanks
  7. Display the remaining life of the player's tank, and the number of destroyed enemy tanks
  8. Click the fork to close the window and save the position of the enemy tank, and the position of the enemy tank can be restored when the file is loaded later

game over judgment

  1. The enemy defeats our tank with 3 lives, the game is over
    end judgment

Insufficient projects and room for optimization

  1. No background music after the game
  2. Collision handling: When the enemy tank is running, the steering will be correct after the collision, but if the collision occurs during the steering, the two tanks will be stuck
  3. The game end mechanism can be added: for example, the victory condition can be added, how many enemy tanks can be destroyed to win, or our home can be added, once the enemy destroys my home, it will fail
  4. On the basis of summoning the enemy, trigger timed tasks and summon a certain number of enemy tanks every once in a while
  5. Increase the collision handling of our tanks
  6. When you directly click the cross to close the window, save the position of our tank, and restore the position of our tank, the position of the enemy bullet, and the position of our bullet when loading the file next time
  7. Add certain obstacles: walls, rivers, greenery, etc.
  8. Displays the number of remaining enemy tanks

Related code display

Main method Main

package com.View;

import javax.swing.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Scanner;

/**
 * @author wty
 * @date 2022/10/21 0:07
 * 主方法启动
 */
public class Main extends JFrame {
    
    
    MyPanelForGame mypanel = null;
     static Scanner scanner = new Scanner(System.in);


    public static void main(String[] args) {
    
    
        new Main();
    }

    public Main() {
    
    
        System.out.println("请输入选择:");
        System.out.println("1:开始新游戏");
        System.out.println("2:读取存档");
        String key = scanner.nextLine();

        mypanel = new MyPanelForGame(key);
        // 将mypanel启动
        new Thread(mypanel).start();
        this.add(mypanel);
        // 窗口的大小(窗口大小)
        this.setSize(1300, 800);
        this.addKeyListener(mypanel);
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        this.setVisible(true);
        this.setTitle("Tank Big Game");

        // 在JFram增加相应和关闭窗口的处理:
        this.addWindowListener(new WindowAdapter() {
    
    
            @Override
            public void windowClosing(WindowEvent windowEvent) {
    
    
                System.out.println("监听到关闭窗口");
                Record.saveRecordEnemy();
                Record.saveRecordPlayer();
                System.exit(0);
            }
        });
    }
}

Drawing interface MyPanelForGame

package com.View;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.util.Vector;

/**
 * @author wty
 * @date 2022/10/21 0:01
 * 绘图区
 * 为了不停的重绘子弹,必须要MyPanelForGame实现一个Runnable接口,当作线程使用
 */
public class MyPanelForGame extends JPanel implements KeyListener, Runnable {
    
    
    // 定义我的坦克
    PlayerTank playerTank = null;

    Vector<EnemyTank> enemyTanks = new Vector<>();
    int enemyTankSize = 3; // 敌人 坦克的数量

    // 炸弹
    Vector<Boom> booms = new Vector<>();

    // 定义三张炸弹图片,用于显示爆炸效果
    // 当子弹击中敌人时,就加载图片
    Image image_boom1 = null;
    Image image_boom2 = null;
    Image image_boom3 = null;
    // 我方坦克生命值
    Image image_heart = null;

    // 定义一个nodes存放Record中的node信息
    private static Vector<Node> nodes = new Vector<>();
    private String key = "";

    public String getKey() {
    
    
        return key;
    }

    public void setKey(String key) {
    
    
        this.key = key;
    }

    public Vector<EnemyTank> getEnemyTanks() {
    
    
        return enemyTanks;
    }

    public void setEnemyTanks(Vector<EnemyTank> enemyTanks) {
    
    
        this.enemyTanks = enemyTanks;
    }

    public MyPanelForGame(String key) {
    
    
        // 先判断记录的文件是否存在
        // 如果存在,就正常执行,如果不存在,提示只能开启新游戏,并把key = 1
        File fileEnemy = new File(Record.getRecordFile());
        File filePlayer = new File(Record.getRecordFilePlay());
        if (fileEnemy.exists() && filePlayer.exists()) {
    
    
            nodes = Record.getNodesandCountEnemy(); // 初始化时,将右侧敌人游戏数据读取
            Record.getNodesandCountPlayer();// 初始化时,将右侧玩家游戏数据读取
        } else {
    
    
            System.out.println("文件不存在,只能开启新游戏!");
            key = "1";
        }

        setKey(key); // 设置是否是新游戏

        // 针对是新游戏还是读取存档
        switch (key) {
    
    
            case "1":
                initEnemyTank(); // 新游戏
                Record.setAllEnemyTankCount(0);
                Record.setAllPlayerTankCount(3);
                break;
            case "2":
                loadEnemyTank(); // 读取存档
                loadPlayerTank();
                break;
            default:
                System.out.println("您的输入有误,请重新输入");
        }


        // 加在这里(初始化敌人的坦克)
        initPlayerTank();

        // 初始化炸弹的图片
        image_boom1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_1.gif"));
        image_boom2 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_2.gif"));
        image_boom3 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_3.gif"));
        image_heart = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/heart.png"));


        // 播放音乐
        new AePlayWave("src\\111.wav").start();
    }

    // 初始化敌人的坦克
    public void initEnemyTank() {
    
    
        // 将MyPanelForGame的VectorenemyTanks赋值给Record的enemyTanks
        Record.setEnemyTanks(enemyTanks);

        // 初始化敌人的坦克
        for (int i = 0; i < enemyTankSize; i++) {
    
    
            // 每创建一个敌人坦克,就设定速度和方向
            EnemyTank enemyTank = new EnemyTank(200 * (i + 1), 0);
            enemyTank.setSpeed(4);
            enemyTank.setDirection(2);
            // 给敌人坦克增加子弹初始位置
            Shot shot = new Shot(enemyTank.getX() + 37, enemyTank.getY() + 70, enemyTank.getDirection());
            // 并且把子弹加入EnemyTank的enemy_Shoots管理
            enemyTank.getEnemy_Shoots().add(shot);

            // 将enemyTank集合设置给setEnemyTanks
            enemyTank.setEnemyTanks(enemyTanks);

            // 启动shot对象
            new Thread(shot).start();

            enemyTanks.add(enemyTank);

            // 启动敌人坦克自动移动的线程
            new Thread(enemyTank).start();
        }
    }

    // 读取存档敌人的坦克
    public void loadEnemyTank() {
    
    
        // 将MyPanelForGame的VectorenemyTanks赋值给Record的enemyTanks
        Record.setEnemyTanks(enemyTanks);

        // 初始化敌人的坦克
        for (int i = 0; i < nodes.size(); i++) {
    
    
            Node node = nodes.get(i);
            // 每创建一个敌人坦克,就设定速度和方向
            EnemyTank enemyTank = new EnemyTank(node.getX(), node.getY());
            enemyTank.setSpeed(4);
            enemyTank.setDirection(node.getDirection());
            // 给敌人坦克增加子弹初始位置
            Shot shot = new Shot(enemyTank.getX() + 37, enemyTank.getY() + 70, enemyTank.getDirection());
            // 并且把子弹加入EnemyTank的enemy_Shoots管理
            enemyTank.getEnemy_Shoots().add(shot);

            // 将enemyTank集合设置给setEnemyTanks
            enemyTank.setEnemyTanks(enemyTanks);

            // 启动shot对象
            new Thread(shot).start();

            enemyTanks.add(enemyTank);

            // 启动敌人坦克自动移动的线程
            new Thread(enemyTank).start();
        }
    }

    public void initPlayerTank() {
    
    
        // 初始化玩家坦克
        playerTank = new PlayerTank(300, 400);
        //playerTank = new PlayerTank(30, 40);
        // 设置速度
        playerTank.setSpeed(4);
        playerTank.setDirection(0);

        // 存储玩家坐标
        Record.setX_player(playerTank.getX());
        Record.setY_player(playerTank.getY());
        Record.setDirection_player(playerTank.getDirection());
    }

    // 读取存档中玩家坦克的信息
    public void loadPlayerTank() {
    
    
        // 初始化玩家坦克
        playerTank = new PlayerTank(Record.getX_player(), Record.getY_player());
        //playerTank = new PlayerTank(30, 40);
        // 设置速度
        playerTank.setSpeed(4);
        playerTank.setDirection(Record.getDirection_player());
    }

    // 展示玩家信息
    public void showGameInfo(Graphics graphics) {
    
    
        graphics.setColor(Color.BLACK);
        Font font = new Font("宋体", Font.BOLD, 25);
        graphics.setFont(font);
        graphics.drawString("您累积击毁坦克", 1020, 30);

        // 击毁敌方坦克
        drawTank(1020, 60, graphics, 0, 0); // 方向朝上,己方坦克
        graphics.setColor(Color.BLACK);
        graphics.drawString(Record.getAllEnemyTankCount() + " ", 1170, 100);
        // 我方坦克生命
        graphics.drawImage(image_heart, 1020, 200, 84, 84, this);
        graphics.setColor(Color.BLACK);
        graphics.drawString("X " + Record.getAllPlayerTankCount() + " ", 1170, 250);

        // 游戏提示
        graphics.setColor(Color.BLACK);
        Font font2 = new Font("黑体", Font.PLAIN, 23);
        graphics.setFont(font2);
        graphics.drawString("操作指引:", 1020, 400);
        graphics.drawString("方向键控制方向", 1020, 450);
        graphics.drawString("空格开火", 1020, 500);
        graphics.drawString("数字键1增加敌方坦克", 1020, 550);
        graphics.drawString("数字键2初始我方坦克", 1020, 600);

    }

    @Override
    public void paint(Graphics graphics) {
    
    
        super.paint(graphics);
        // 背景(黑色的) 游戏场景
        graphics.fillRect(0, 0, 1000, 750);

        // 右侧玩家信息栏
        showGameInfo(graphics);

        // 玩家坦克
        if (playerTank.isLive() && playerTank != null) {
    
    
            drawTank(playerTank.getX(), playerTank.getY(), graphics, playerTank.getDirection(), 0);
        }
        //drawTank(playerTank.getX() + 100, playerTank.getY(), graphics, 1, 0);
        //drawTank(playerTank.getX() + 100, playerTank.getY() + 100, graphics, 2, 0);
        //drawTank(playerTank.getX(), playerTank.getY() + 100, graphics, 3, 0);

        // 绘制敌人坦克
        for (int i = 0; i < enemyTanks.size(); i++) {
    
    
            // enemyTank是Vector里面存储的是EnemyTank对象
            EnemyTank enemyTank = enemyTanks.get(i);
            // 判断当前坦克是否存活,存活才能画
            if (enemyTank.isLive() == true) {
    
    
                drawTank(enemyTank.getX(), enemyTank.getY(), graphics, enemyTank.getDirection(), 1);
                // 敌人坦克的子弹
                for (int j = 0; j < enemyTank.getEnemy_Shoots().size(); j++) {
    
    
                    Shot shot = enemyTank.getEnemy_Shoots().get(j);
                    if (shot != null && false != shot.isLive()) {
    
    
                        System.out.println("敌人子弹被绘制");
                        graphics.setColor(new Color(210, 180, 140));
                        graphics.fill3DRect(shot.getX(), shot.getY(), 6, 6, false);
                    } else {
    
    
                        enemyTank.getEnemy_Shoots().remove(shot); // 移除子弹
                    }
                }
            } else {
    
    
                enemyTanks.remove(enemyTank);
            }
        }
        //drawTank(playerTank.getX() - 100, playerTank.getY() - 300, graphics, 2, 1);
        //drawTank(playerTank.getX(), playerTank.getY() - 300, graphics, 2, 1);
        //drawTank(playerTank.getX(), playerTank.getY() + 200, graphics, 3, 1);

        // 绘制子弹
        // 子弹在边界内且仍然存活,就绘制子弹
        if (playerTank.getShot() != null && false != playerTank.getShot().isLive()) {
    
    
            System.out.println("子弹被绘制");
            graphics.setColor(new Color(135, 206, 250));
            graphics.fill3DRect(playerTank.getShot().getX(), playerTank.getShot().getY(), 6, 6, false);
//            if (playerTank.getDirection() == 0 || playerTank.getDirection() == 2){
    
    
//                graphics.fill3DRect(playerTank.getShot().getX(),playerTank.getShot().getY(),6,13,false);
//            }else if(playerTank.getDirection() == 1 || playerTank.getDirection() == 3){
    
    
//                graphics.fill3DRect(playerTank.getShot().getX(),playerTank.getShot().getY(),13,6,false);
//            }
        }
        // 我方坦克发射多枚子弹
        if (playerTank.getManyShoots().size() > 0) {
    
    
            for (int i = 0; i < playerTank.getManyShoots().size(); i++) {
    
    
                Shot shot = playerTank.getManyShoots().get(i);
                if (shot != null && false != shot.isLive()) {
    
    
                    // 这里指的是每一个集合中的坦克对象发射子弹的位置,比较关键,容易写错
                    graphics.fill3DRect(shot.getX(), shot.getY(), 6, 6, false);
                } else {
    
    
                    // 子弹碰壁或者已经消亡,就从集合里去掉
                    playerTank.getManyShoots().remove(shot);
                }
            }
        }

        // 休眠一下确保炸弹爆炸
        try {
    
    
            Thread.sleep(70);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }

        // 绘制爆炸,如果Vector集合中有元素,那么就画炸弹
        for (int i = 0; i < booms.size(); i++) {
    
    
            // 取出炸弹
            Boom boom = booms.get(i);
            // 根据当前bomb对象的life数,画出对应图片
            if (boom.getLife() > 6) {
    
    
                System.out.println("触发爆炸动画3");
                graphics.drawImage(image_boom1, boom.getX(), boom.getY(), 80, 80, this);
            } else if (boom.getLife() > 3) {
    
    
                System.out.println("触发爆炸动画2");
                graphics.drawImage(image_boom2, boom.getX(), boom.getY(), 80, 80, this);
            } else {
    
    
                System.out.println("触发爆炸动画1");
                graphics.drawImage(image_boom3, boom.getX(), boom.getY(), 80, 80, this);
            }
            boom.lifeKill();

            // 如果生命值为0,那么就从集合中移除
            if (boom.getLife() == 0) {
    
    
                booms.remove(boom);
            }
        }

    }

    /**
     * 绘制坦克
     *
     * @param x         横坐标
     * @param y         纵坐标
     * @param graphics  画笔
     * @param direction 方向
     * @param type      坦克类型(玩家、敌人)
     */
    public void drawTank(int x, int y, Graphics graphics, int direction, int type) {
    
    
        // 绘制坦克
        // 绘制对应的形状
        switch (direction) {
    
    
            case 0: // 向上方向
                if (0 == type) {
    
     // 玩家坦克
                    drawPlayerTankUp(x, y, graphics, direction);
                } else {
    
     // 敌方坦克
                    drawEnemyTankUp(x, y, graphics, direction);
                }

                break;
            case 1: // 向右的方向
                if (0 == type) {
    
    // 玩家坦克
                    drawPlayerTankRight(x, y, graphics, direction);
                } else {
    
     // 敌方坦克
                    drawEnemyTankRight(x, y, graphics, direction);
                }

                break;
            case 2: // 向下的方向
                if (0 == type) {
    
    // 玩家坦克
                    drawPlayerTankDown(x, y, graphics, direction);
                } else {
    
     // 敌方坦克
                    drawEnemyTankDown(x, y, graphics, direction);
                }
                break;
            case 3:// 向左的方向
                if (0 == type) {
    
    // 玩家坦克
                    drawPlayerTankLeft(x, y, graphics, direction);
                } else {
    
     // 敌方坦克
                    drawEnemyTankLeft(x, y, graphics, direction);
                }
                break;

            default:
                System.out.println("其他情况暂时不处理");
        }
    }

    /**
     * 自己坦克的颜色--朝上
     *
     * @param x
     * @param y
     * @param graphics
     * @param direction
     */
    public void drawPlayerTankUp(int x, int y, Graphics graphics, int direction) {
    
    
        // 左边履带
        graphics.setColor(new Color(173, 216, 230));
        graphics.fill3DRect(x, y, 20, 80, false);
        //graphics.fillRect(30, 40, 20, 80);
        graphics.fillOval(x - 5, y, 10, 20);
        graphics.fillOval(x - 5, y + 20, 10, 20);
        graphics.fillOval(x - 5, y + 40, 10, 20);
        graphics.fillOval(x - 5, y + 60, 10, 20);

        // 左边履带条纹
        graphics.setColor(new Color(0, 0, 0));
        graphics.drawLine(x, y + 20, x + 10, y + 20);
        graphics.drawLine(x, y + 40, x + 10, y + 40);
        graphics.drawLine(x, y + 60, x + 10, y + 60);

        // 中间驾驶舱
        graphics.setColor(new Color(135, 206, 250));
        graphics.fillRect(x + 20, y + 20, 40, 40);
        // 炮膛
        graphics.setColor(new Color(70, 130, 180));
        graphics.drawLine(x + 40, y, x + 40, y + 30);

        // 炮膛前面一个圆
        graphics.setColor(new Color(95, 158, 160));
        graphics.fillOval(x + 37, y - 10, 6, 13);

        // 圆形盖子
        graphics.setColor(new Color(95, 158, 160));
        graphics.fillOval(x + 30, y + 30, 20, 20);
        // 右边履带
        graphics.setColor(new Color(173, 216, 230));
        graphics.fill3DRect(x + 60, y, 20, 80, false);
        graphics.fillOval(x + 75, y, 10, 20);
        graphics.fillOval(x + 75, y + 20, 10, 20);
        graphics.fillOval(x + 75, y + 40, 10, 20);
        graphics.fillOval(x + 75, y + 60, 10, 20);

        // 右边履带条纹
        graphics.setColor(new Color(0, 0, 0));
        graphics.drawLine(x + 70, y + 20, x + 80, y + 20);
        graphics.drawLine(x + 70, y + 40, x + 80, y + 40);
        graphics.drawLine(x + 70, y + 60, x + 80, y + 60);
    }


    /**
     * 自己坦克的颜色--朝右
     *
     * @param x
     * @param y
     * @param graphics
     * @param direction
     */
    public void drawPlayerTankRight(int x, int y, Graphics graphics, int direction) {
    
    
        // 左边履带
        graphics.setColor(new Color(173, 216, 230));
        graphics.fill3DRect(x, y, 80, 20, false);
        //graphics.fillRect(30, 40, 20, 80);
        graphics.fillOval(x, y - 5, 20, 10);
        graphics.fillOval(x + 20, y - 5, 20, 10);
        graphics.fillOval(x + 40, y - 5, 20, 10);
        graphics.fillOval(x + 60, y - 5, 20, 10);

        // 左边履带条纹
        graphics.setColor(new Color(0, 0, 0));
        graphics.drawLine(x + 20, y, x + 20, y + 10);
        graphics.drawLine(x + 40, y, x + 40, y + 10);
        graphics.drawLine(x + 60, y, x + 60, y + 10);

        // 中间驾驶舱
        graphics.setColor(new Color(135, 206, 250));
        graphics.fillRect(x + 20, y + 20, 40, 40);
        // 炮膛
        graphics.setColor(new Color(70, 130, 180));
        graphics.drawLine(x + 50, y + 40, x + 80, y + 40);

        // 炮膛前面一个圆
        graphics.setColor(new Color(95, 158, 160));
        graphics.fillOval(x + 80, y + 37, 13, 6);

        // 圆形盖子
        graphics.setColor(new Color(95, 158, 160));
        graphics.fillOval(x + 30, y + 30, 20, 20);
        // 右边履带
        graphics.setColor(new Color(173, 216, 230));
        graphics.fill3DRect(x, y + 60, 80, 20, false);
        graphics.fillOval(x, y + 75, 20, 10);
        graphics.fillOval(x + 20, y + 75, 20, 10);
        graphics.fillOval(x + 40, y + 75, 20, 10);
        graphics.fillOval(x + 60, y + 75, 20, 10);

        // 右边履带条纹
        graphics.setColor(new Color(0, 0, 0));
        graphics.drawLine(x + 20, y + 80, x + 20, y + 70);
        graphics.drawLine(x + 40, y + 80, x + 40, y + 70);
        graphics.drawLine(x + 60, y + 80, x + 60, y + 70);
    }

    /**
     * 自己坦克的颜色--向下
     *
     * @param x
     * @param y
     * @param graphics
     * @param direction
     */
    public void drawPlayerTankDown(int x, int y, Graphics graphics, int direction) {
    
    
        // 左边履带
        graphics.setColor(new Color(173, 216, 230));
        graphics.fill3DRect(x, y, 20, 80, false);
        //graphics.fillRect(30, 40, 20, 80);
        graphics.fillOval(x - 5, y, 10, 20);
        graphics.fillOval(x - 5, y + 20, 10, 20);
        graphics.fillOval(x - 5, y + 40, 10, 20);
        graphics.fillOval(x - 5, y + 60, 10, 20);

        // 左边履带条纹
        graphics.setColor(new Color(0, 0, 0));
        graphics.drawLine(x, y + 20, x + 10, y + 20);
        graphics.drawLine(x, y + 40, x + 10, y + 40);
        graphics.drawLine(x, y + 60, x + 10, y + 60);

        // 中间驾驶舱
        graphics.setColor(new Color(135, 206, 250));
        graphics.fillRect(x + 20, y + 20, 40, 40);
        // 炮膛
        graphics.setColor(new Color(70, 130, 180));
        graphics.drawLine(x + 40, y + 30, x + 40, y + 60);

        // 炮膛前面一个圆
        graphics.setColor(new Color(95, 158, 160));
        graphics.fillOval(x + 37, y + 70, 6, 13);

        // 圆形盖子
        graphics.setColor(new Color(95, 158, 160));
        graphics.fillOval(x + 30, y + 30, 20, 20);
        // 右边履带
        graphics.setColor(new Color(173, 216, 230));
        graphics.fill3DRect(x + 60, y, 20, 80, false);
        graphics.fillOval(x + 75, y, 10, 20);
        graphics.fillOval(x + 75, y + 20, 10, 20);
        graphics.fillOval(x + 75, y + 40, 10, 20);
        graphics.fillOval(x + 75, y + 60, 10, 20);

        // 右边履带条纹
        graphics.setColor(new Color(0, 0, 0));
        graphics.drawLine(x + 70, y + 20, x + 80, y + 20);
        graphics.drawLine(x + 70, y + 40, x + 80, y + 40);
        graphics.drawLine(x + 70, y + 60, x + 80, y + 60);
    }

    /**
     * 自己坦克的颜色--朝左
     *
     * @param x
     * @param y
     * @param graphics
     * @param direction
     */
    public void drawPlayerTankLeft(int x, int y, Graphics graphics, int direction) {
    
    
        // 左边履带
        graphics.setColor(new Color(173, 216, 230));
        graphics.fill3DRect(x, y, 80, 20, false);
        //graphics.fillRect(30, 40, 20, 80);
        graphics.fillOval(x, y - 5, 20, 10);
        graphics.fillOval(x + 20, y - 5, 20, 10);
        graphics.fillOval(x + 40, y - 5, 20, 10);
        graphics.fillOval(x + 60, y - 5, 20, 10);

        // 左边履带条纹
        graphics.setColor(new Color(0, 0, 0));
        graphics.drawLine(x + 20, y, x + 20, y + 10);
        graphics.drawLine(x + 40, y, x + 40, y + 10);
        graphics.drawLine(x + 60, y, x + 60, y + 10);

        // 中间驾驶舱
        graphics.setColor(new Color(135, 206, 250));
        graphics.fillRect(x + 20, y + 20, 40, 40);
        // 炮膛
        graphics.setColor(new Color(70, 130, 180));
        graphics.drawLine(x + 30, y + 40, x, y + 40);

        // 炮膛前面一个圆
        graphics.setColor(new Color(95, 158, 160));
        graphics.fillOval(x - 10, y + 37, 13, 6);

        // 圆形盖子
        graphics.setColor(new Color(95, 158, 160));
        graphics.fillOval(x + 30, y + 30, 20, 20);
        // 右边履带
        graphics.setColor(new Color(173, 216, 230));
        graphics.fill3DRect(x, y + 60, 80, 20, false);
        graphics.fillOval(x, y + 75, 20, 10);
        graphics.fillOval(x + 20, y + 75, 20, 10);
        graphics.fillOval(x + 40, y + 75, 20, 10);
        graphics.fillOval(x + 60, y + 75, 20, 10);

        // 右边履带条纹
        graphics.setColor(new Color(0, 0, 0));
        graphics.drawLine(x + 20, y + 80, x + 20, y + 70);
        graphics.drawLine(x + 40, y + 80, x + 40, y + 70);
        graphics.drawLine(x + 60, y + 80, x + 60, y + 70);
    }
    //--------敌人的坦克-----------//

    /**
     * 敌人坦克的颜色--朝上
     *
     * @param x
     * @param y
     * @param graphics
     * @param direction
     */
    public void drawEnemyTankUp(int x, int y, Graphics graphics, int direction) {
    
    
        // 左边履带
        graphics.setColor(new Color(255, 215, 0));
        graphics.fill3DRect(x, y, 20, 80, false);
        //graphics.fillRect(30, 40, 20, 80);
        graphics.fillOval(x - 5, y, 10, 20);
        graphics.fillOval(x - 5, y + 20, 10, 20);
        graphics.fillOval(x - 5, y + 40, 10, 20);
        graphics.fillOval(x - 5, y + 60, 10, 20);

        // 左边履带条纹
        graphics.setColor(new Color(0, 0, 0));
        graphics.drawLine(x, y + 20, x + 10, y + 20);
        graphics.drawLine(x, y + 40, x + 10, y + 40);
        graphics.drawLine(x, y + 60, x + 10, y + 60);

        // 中间驾驶舱
        graphics.setColor(new Color(218, 165, 32));
        graphics.fillRect(x + 20, y + 20, 40, 40);
        // 炮膛
        graphics.setColor(new Color(210, 180, 140));
        graphics.drawLine(x + 40, y, x + 40, y + 30);

        // 炮膛前面一个圆
        graphics.setColor(new Color(210, 180, 140));
        graphics.fillOval(x + 37, y - 10, 6, 13);

        // 圆形盖子
        graphics.setColor(new Color(210, 180, 140));
        graphics.fillOval(x + 30, y + 30, 20, 20);
        // 右边履带
        graphics.setColor(new Color(255, 215, 0));
        graphics.fill3DRect(x + 60, y, 20, 80, false);
        graphics.fillOval(x + 75, y, 10, 20);
        graphics.fillOval(x + 75, y + 20, 10, 20);
        graphics.fillOval(x + 75, y + 40, 10, 20);
        graphics.fillOval(x + 75, y + 60, 10, 20);

        // 右边履带条纹
        graphics.setColor(new Color(0, 0, 0));
        graphics.drawLine(x + 70, y + 20, x + 80, y + 20);
        graphics.drawLine(x + 70, y + 40, x + 80, y + 40);
        graphics.drawLine(x + 70, y + 60, x + 80, y + 60);
    }

    /**
     * 敌人坦克的颜色--朝右
     *
     * @param x
     * @param y
     * @param graphics
     * @param direction
     */
    public void drawEnemyTankRight(int x, int y, Graphics graphics, int direction) {
    
    
        // 左边履带
        graphics.setColor(new Color(255, 215, 0));
        graphics.fill3DRect(x, y, 80, 20, false);
        //graphics.fillRect(30, 40, 20, 80);
        graphics.fillOval(x, y - 5, 20, 10);
        graphics.fillOval(x + 20, y - 5, 20, 10);
        graphics.fillOval(x + 40, y - 5, 20, 10);
        graphics.fillOval(x + 60, y - 5, 20, 10);

        // 左边履带条纹
        graphics.setColor(new Color(0, 0, 0));
        graphics.drawLine(x + 20, y, x + 20, y + 10);
        graphics.drawLine(x + 40, y, x + 40, y + 10);
        graphics.drawLine(x + 60, y, x + 60, y + 10);

        // 中间驾驶舱
        graphics.setColor(new Color(218, 165, 32));
        graphics.fillRect(x + 20, y + 20, 40, 40);
        // 炮膛
        graphics.setColor(new Color(210, 180, 140));
        graphics.drawLine(x + 50, y + 40, x + 80, y + 40);

        // 炮膛前面一个圆
        graphics.setColor(new Color(210, 180, 140));
        graphics.fillOval(x + 80, y + 37, 13, 6);

        // 圆形盖子
        graphics.setColor(new Color(210, 180, 140));
        graphics.fillOval(x + 30, y + 30, 20, 20);
        // 右边履带
        graphics.setColor(new Color(255, 215, 0));
        graphics.fill3DRect(x, y + 60, 80, 20, false);
        graphics.fillOval(x, y + 75, 20, 10);
        graphics.fillOval(x + 20, y + 75, 20, 10);
        graphics.fillOval(x + 40, y + 75, 20, 10);
        graphics.fillOval(x + 60, y + 75, 20, 10);

        // 右边履带条纹
        graphics.setColor(new Color(0, 0, 0));
        graphics.drawLine(x + 20, y + 80, x + 20, y + 70);
        graphics.drawLine(x + 40, y + 80, x + 40, y + 70);
        graphics.drawLine(x + 60, y + 80, x + 60, y + 70);
    }

    /**
     * 敌人的坦克的颜色--向下
     *
     * @param x
     * @param y
     * @param graphics
     * @param direction
     */
    public void drawEnemyTankDown(int x, int y, Graphics graphics, int direction) {
    
    
        // 左边履带
        graphics.setColor(new Color(255, 215, 0));
        graphics.fill3DRect(x, y, 20, 80, false);
        //graphics.fillRect(30, 40, 20, 80);
        graphics.fillOval(x - 5, y, 10, 20);
        graphics.fillOval(x - 5, y + 20, 10, 20);
        graphics.fillOval(x - 5, y + 40, 10, 20);
        graphics.fillOval(x - 5, y + 60, 10, 20);

        // 左边履带条纹
        graphics.setColor(new Color(0, 0, 0));
        graphics.drawLine(x, y + 20, x + 10, y + 20);
        graphics.drawLine(x, y + 40, x + 10, y + 40);
        graphics.drawLine(x, y + 60, x + 10, y + 60);

        // 中间驾驶舱
        graphics.setColor(new Color(218, 165, 32));
        graphics.fillRect(x + 20, y + 20, 40, 40);
        // 炮膛
        graphics.setColor(new Color(210, 180, 140));
        graphics.drawLine(x + 40, y + 40, x + 40, y + 70);

        // 炮膛前面一个圆
        graphics.setColor(new Color(210, 180, 140));
        graphics.fillOval(x + 37, y + 70, 6, 13);

        // 圆形盖子
        graphics.setColor(new Color(210, 180, 140));
        graphics.fillOval(x + 30, y + 30, 20, 20);
        // 右边履带
        graphics.setColor(new Color(255, 215, 0));
        graphics.fill3DRect(x + 60, y, 20, 80, false);
        graphics.fillOval(x + 75, y, 10, 20);
        graphics.fillOval(x + 75, y + 20, 10, 20);
        graphics.fillOval(x + 75, y + 40, 10, 20);
        graphics.fillOval(x + 75, y + 60, 10, 20);

        // 右边履带条纹
        graphics.setColor(new Color(0, 0, 0));
        graphics.drawLine(x + 70, y + 20, x + 80, y + 20);
        graphics.drawLine(x + 70, y + 40, x + 80, y + 40);
        graphics.drawLine(x + 70, y + 60, x + 80, y + 60);
    }

    /**
     * 敌人坦克的颜色--朝左
     *
     * @param x
     * @param y
     * @param graphics
     * @param direction
     */
    public void drawEnemyTankLeft(int x, int y, Graphics graphics, int direction) {
    
    
        // 左边履带
        graphics.setColor(new Color(255, 215, 0));
        graphics.fill3DRect(x, y, 80, 20, false);
        //graphics.fillRect(30, 40, 20, 80);
        graphics.fillOval(x, y - 5, 20, 10);
        graphics.fillOval(x + 20, y - 5, 20, 10);
        graphics.fillOval(x + 40, y - 5, 20, 10);
        graphics.fillOval(x + 60, y - 5, 20, 10);

        // 左边履带条纹
        graphics.setColor(new Color(0, 0, 0));
        graphics.drawLine(x + 20, y, x + 20, y + 10);
        graphics.drawLine(x + 40, y, x + 40, y + 10);
        graphics.drawLine(x + 60, y, x + 60, y + 10);

        // 中间驾驶舱
        graphics.setColor(new Color(218, 165, 32));
        graphics.fillRect(x + 20, y + 20, 40, 40);
        // 炮膛
        graphics.setColor(new Color(210, 180, 140));
        graphics.drawLine(x + 30, y + 40, x, y + 40);

        // 炮膛前面一个圆
        graphics.setColor(new Color(210, 180, 140));
        graphics.fillOval(x - 10, y + 37, 13, 6);

        // 圆形盖子
        graphics.setColor(new Color(210, 180, 140));
        graphics.fillOval(x + 30, y + 30, 20, 20);
        // 右边履带
        graphics.setColor(new Color(255, 215, 0));
        graphics.fill3DRect(x, y + 60, 80, 20, false);
        graphics.fillOval(x, y + 75, 20, 10);
        graphics.fillOval(x + 20, y + 75, 20, 10);
        graphics.fillOval(x + 40, y + 75, 20, 10);
        graphics.fillOval(x + 60, y + 75, 20, 10);

        // 右边履带条纹
        graphics.setColor(new Color(0, 0, 0));
        graphics.drawLine(x + 20, y + 80, x + 20, y + 70);
        graphics.drawLine(x + 40, y + 80, x + 40, y + 70);
        graphics.drawLine(x + 60, y + 80, x + 60, y + 70);
    }

    // 出现问题:只有1颗子弹打到敌人的坦克,解决方案如下:
    // 如果我们的坦克可以发射多发子弹
    // 再判断我方子弹是否击中敌人坦克时,就需要把我们的子弹集合中所有的子弹
    // 都取出来和敌人的所有坦克遍历
    public void hitEnemyAllTank() {
    
    
        // 遍历我们的子弹集合
        for (int i = 0; i < playerTank.getManyShoots().size(); i++) {
    
    
            // 拿出集合中的一颗子弹
            Shot shot = playerTank.getManyShoots().get(i);
            // 判断这一颗子弹是否击中敌人坦克
            if (shot != null && shot.isLive()) {
    
    
                // 遍历敌人所有的坦克是否别击中
                for (int j = 0; j < enemyTanks.size(); j++) {
    
    
                    EnemyTank enemyTank = enemyTanks.get(j);
                    // 调用判断方法
                    hitTank(shot, enemyTank);
                    if (enemyTank.isLive() == false) {
    
    
                        enemyTanks.remove(enemyTank);
                        Record.addTankCout(); // 击毁敌方坦克后就给击毁数量+1
                        new AePlayWave("src\\Explosion_03.wav").start();
                    }
                }
            }
        }

    }

    // 编写方法判断我方的子弹是否击中敌人的坦克
    // 什么时候判断,-->run方法比较好
    @SuppressWarnings({
    
    "all"})
    public void hitTank(Shot shot, Tank tank) {
    
    
        // 判断子弹击中坦克
        switch (tank.getDirection()) {
    
    
            case 0: // 坦克向上 被击中
            case 2: // 坦克向下 被击中
                if (shot.getX() > tank.getX()
                        && shot.getX() < tank.getX() + 80
                        && shot.getY() > tank.getY()
                        && shot.getY() < tank.getY() + 80) {
    
    
                    shot.setLive(false);
                    tank.setLive(false);


                    // 创建Boom对象加入到booms集合中
                    Boom boom = new Boom(tank.getX(), tank.getY());
                    booms.add(boom);

                }
                break;
            case 1:
            case 3:
                if (shot.getX() > tank.getX()
                        && shot.getX() < tank.getX() + 80
                        && shot.getY() > tank.getY()
                        && shot.getY() < tank.getY() + 80) {
    
    
                    shot.setLive(false);
                    tank.setLive(false);

                    // 创建Boom对象加入到booms集合中
                    Boom boom = new Boom(tank.getX(), tank.getY());
                    booms.add(boom);
                }
                break;

        }

    }

    // 敌人坦克击爆我方坦克
    public void hitPlayerTank() {
    
    
        // 遍历敌人的所有坦克
        for (int i = 0; i < enemyTanks.size(); i++) {
    
    
            // 取出敌人坦克
            EnemyTank enemyTank = enemyTanks.get(i);
            // 遍历enemyTank对象的所有子弹
            for (int j = 0; j < enemyTank.getEnemy_Shoots().size(); j++) {
    
    
                // 取出子弹
                Shot shot = enemyTank.getEnemy_Shoots().get(j);

                // 判断子弹是否击中我方坦克
                if (playerTank.isLive() && null != shot && shot.isLive()) {
    
    
                    hitTank(shot, playerTank);
                    if (playerTank.isLive() == false) {
    
    
                        new AePlayWave("src\\Explosion_03.wav").start();
                        Record.setX_player(playerTank.getX());
                        Record.setY_player(playerTank.getY());
                        Record.setDirection_player(playerTank.getDirection());
                        Record.saveRecordPlayer();
                        Record.minusPlayerTankCout();
                    }
                }

            }
        }
    }

    @Override
    public void keyTyped(KeyEvent keyEvent) {
    
    


    }

    // 键盘按下后触发
    @Override
    public void keyPressed(KeyEvent e) {
    
    
        if (Record.getAllPlayerTankCount() <= 0) {
    
    
            return;
        }

        if (e.getKeyCode() == KeyEvent.VK_UP) {
    
     // 坦克向上
            playerTank.setDirection(0);
            if (playerTank.getY() - 10 > 0) {
    
    
                playerTank.moveUp();
            }

        }

        if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
    
     // 坦克向右
            playerTank.setDirection(1);
            if ((int) (playerTank.getX() + 80 + 10) < 1000) {
    
    
                playerTank.moveRight();
            }
        }

        if (e.getKeyCode() == KeyEvent.VK_DOWN) {
    
     // 坦克向下
            playerTank.setDirection(2);
            if ((int) (playerTank.getY() + 80 + 10) < 750) {
    
    
                playerTank.moveDown();
            }
        }


        if (e.getKeyCode() == KeyEvent.VK_LEFT) {
    
     // 坦克向左
            playerTank.setDirection(3);
            if (playerTank.getX() - 10 > 0) {
    
    
                playerTank.moveLeft();
            }
        }

        if (e.getKeyCode() == KeyEvent.VK_SPACE) {
    
     // 坦克发射子弹
            // 播放音乐
            new AePlayWave("src\\Shoot_01.wav").start();
            System.out.println("用户坦克按下空格,开始射击");
            /** if (playerTank.getShot() == null){
             playerTank.shotEnemy();
             }
             这样写的话,只能打出一颗子弹,这个示例告诉我们,
             即使线程销毁了,对象是还存在的

             */

            // 子弹撞墙,或者子弹打死一个坦克才能发射第二发
            /**
             * if (playerTank.getShot() == null || playerTank.getShot().isLive() == false){
             *  playerTank.shotEnemy();
             }*/

            // 发射多颗子弹
            playerTank.shotEnemy();
        }

        if (e.getKeyCode() == KeyEvent.VK_1) {
    
     // 数字键1可以初始化(增加)敌人坦克
            initEnemyTank();
        }
        if (e.getKeyCode() == KeyEvent.VK_2) {
    
     // 数字键2可以初始化(增加)玩家坦克
            if (playerTank.isLive() == false) {
    
    
                loadPlayerTank();
                new AePlayWave("src\\Menu_Navigate_02.wav").start();
            } else {
    
    
                System.out.println("只有死亡时,才能初始化玩家坦克");
            }
        }

        // 让面板重新画一次
        this.repaint();

    }

    @Override
    public void keyReleased(KeyEvent keyEvent) {
    
    

    }

    @Override
    public void run() {
    
    
        while (true) {
    
    
            try {
    
    
                Thread.sleep(100);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            // 是否击中敌人的坦克
            hitEnemyAllTank();
            // 是否击中玩家坦克
            hitPlayerTank();
            this.repaint();
        }
    }
}

Tank parent class

package com.View;

/**
 * @author wty
 * @date 2022/10/20 23:57
 * 用于存放坦克模型
 */
public class Tank {
    
    
    private int x; // 坦克的横坐标
    private int y; // 坦克的纵坐标
    private int direction; // 坦克的方向 0上,1右,2下,3左
    private int speed;
    private boolean isLive = true;

    public boolean isLive() {
    
    
        return isLive;
    }

    public void setLive(boolean live) {
    
    
        isLive = live;
    }

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

    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 getDirection() {
    
    
        return direction;
    }

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

    // 坦克移动
    public void moveUp() {
    
    
        y -= speed;
    }

    public void moveRight() {
    
    
        x += speed;
    }

    public void moveDown() {
    
    
        y += speed;
    }

    public void moveLeft() {
    
    
        x -= speed;
    }
}

Enemy Tank Enemy Tank

package com.View;

import java.util.Vector;

/**
 * @author wty
 * @date 2022/10/21 15:23
 * <p>
 * 敌人的坦克
 */
public class EnemyTank extends Tank implements Runnable {
    
    
    //  使用Vector保存多个敌人的子弹
    private Vector<Shot> enemy_Shoots = new Vector<>();
    private int max_Shoots = 4;

    // 增加用于,EnemyTank可以得到敌人坦克的Vector成员
    private Vector<EnemyTank> enemyTanks = new Vector<>();

    public Vector<EnemyTank> getEnemyTanks() {
    
    
        return enemyTanks;
    }

    public void setEnemyTanks(Vector<EnemyTank> enemyTanks) {
    
    
        this.enemyTanks = enemyTanks;
    }

    public EnemyTank(int x, int y) {
    
    
        super(x, y);
    }

    private boolean isLive = true;

    public Vector<Shot> getEnemy_Shoots() {
    
    
        return enemy_Shoots;
    }

    public void setEnemy_Shoots(Vector<Shot> enemy_Shoots) {
    
    
        this.enemy_Shoots = enemy_Shoots;
    }

    public boolean isLive() {
    
    
        return isLive;
    }

    public void setLive(boolean live) {
    
    
        isLive = live;
    }

    @Override
    public void run() {
    
    
        while (true) {
    
    
            // 给敌人的坦克绘制子弹
            if (isLive == true && enemy_Shoots.size() < max_Shoots) {
    
    
                Shot s = null;
                // 判断坦克的方向,创建对应子弹
                switch (this.getDirection()) {
    
    
                    case 0:
                        s = new Shot(this.getX() + 37, this.getY(), this.getDirection());
                        break;
                    case 1:
                        s = new Shot(this.getX() + 80, this.getY() + 40, this.getDirection());
                        break;
                    case 2:
                        s = new Shot(this.getX() + 37, this.getY() + 70, this.getDirection());
                        break;
                    case 3:
                        s = new Shot(this.getX() + 10, this.getY() + 37, this.getDirection());
                        break;
                }
                enemy_Shoots.add(s);
                // 启动敌人开枪线程
                new Thread(s).start();
            } else {
    
    
                // 这里清空集合有疑问,待定
                enemy_Shoots.clear();
            }


            // 根据坦克方向调动
            if (isTouchEnemyTank()) {
    
     // 如果碰撞了就直接调正方向
                // random 是[0, 1)
                setDirection((int) (Math.random() * 4));
            } else {
    
    
                adjustDirection();
                // random 是[0, 1)
                setDirection((int) (Math.random() * 4));
            }

            // 多线程要考虑什么时候结束
            if (isLive == false || Record.getAllPlayerTankCount() <= 0) {
    
    
                break;
            }

        }
    }

    // 坦克调整方向
    public void adjustDirection() {
    
    
        switch (this.getDirection()) {
    
    
            case 0: // 向上
                for (int i = 1; i <= 30; i++) {
    
    
                    // 让坦克保持一个方向走一会儿
                    try {
    
    
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                    if (this.getY() - 10 > 0 && !isTouchEnemyTank()) {
    
    
                        moveUp();
                    } else {
    
    
                        return;
                    }
                }
                break;
            case 1: // 向右
                for (int i = 1; i <= 30; i++) {
    
    
                    try {
    
    
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                    if ((int) (this.getX() + 80 + 10) < 1000 && !isTouchEnemyTank()) {
    
    
                        moveRight();
                    } else {
    
    
                        return;
                    }
                }
                break;
            case 2: // 向下
                for (int i = 1; i <= 30; i++) {
    
    
                    try {
    
    
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                    if ((int) (this.getY() + 80 + 10) < 750 && !isTouchEnemyTank()) {
    
    
                        moveDown();
                    } else {
    
    
                        return;
                    }
                }
                break;
            case 3: // 向左
                for (int i = 1; i <= 30; i++) {
    
    
                    try {
    
    
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                    if (this.getX() - 10 > 0 && !isTouchEnemyTank()) {
    
    
                        moveLeft();
                    } else {
    
    
                        return;
                    }
                }
                break;
        }
    }

    // 编写方法,判断敌人坦克和其它敌人坦克是否碰撞 碰撞返回 true 没碰撞返回 false
    public boolean isTouchEnemyTank() {
    
    
        switch (this.getDirection()) {
    
    
            case 0: // 当前坦克向上
                for (int i = 0; i < enemyTanks.size(); i++) {
    
    
                    EnemyTank enemyTank = enemyTanks.get(i);

                    // 取出敌人坦克,然后每一辆坦克和除了自己以外的坦克进行比较是否碰撞
                    if (enemyTank != this) {
    
    

                        // x范围 [enemyTank.getX(),enemyTank.getX() + 80]
                        // y范围 [enemyTank.getY() -10,enemyTank.getY() + 80]
                        if (enemyTank.getDirection() == 0) {
    
    // 其它敌人坦克在朝上
                            // 当前坦克左上角坐标 [this.getX(),this.getY() - 10]
                            if (this.getX() >= enemyTank.getX()
                                    && this.getX() <= enemyTank.getX() + 80
                                    && this.getY() - 10 >= enemyTank.getY() - 10
                                    && this.getY() - 10 <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                            // 当前坦克右上角坐标 [this.getX() + 80,this.getY() - 10]
                            if (this.getX() + 80 >= enemyTank.getX()
                                    && this.getX() + 80 <= enemyTank.getX() + 80
                                    && this.getY() - 10 >= enemyTank.getY() - 10
                                    && this.getY() - 10 <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                        }

                        // x范围 [enemyTank.getX(),enemyTank.getX() + 80]
                        // y范围 [enemyTank.getY(),enemyTank.getY() + 80 + 10]
                        if (enemyTank.getDirection() == 2) {
    
    // 其它敌人坦克在朝下
                            // 当前坦克左上角坐标 [this.getX(),this.getY() - 10]
                            if (this.getX() >= enemyTank.getX()
                                    && this.getX() <= enemyTank.getX() + 80
                                    && this.getY() - 10 >= enemyTank.getY()
                                    && this.getY() - 10 <= enemyTank.getY() + 80 + 10) {
    
    
                                return true;
                            }
                            // 当前坦克右上角坐标 [this.getX() + 80,this.getY() - 10]
                            if (this.getX() + 80 >= enemyTank.getX()
                                    && this.getX() + 80 <= enemyTank.getX() + 80
                                    && this.getY() - 10 >= enemyTank.getY()
                                    && this.getY() - 10 <= enemyTank.getY() + 80 + 10) {
    
    
                                return true;
                            }
                        }

                        // x范围 [enemyTank.getX(),enemyTank.getX() + 80 + 10]
                        // y范围 [enemyTank.getY(),enemyTank.getY() + 80]
                        if (enemyTank.getDirection() == 1) {
    
    // 其它敌人坦克在朝右
                            // 当前坦克左上角坐标 [this.getX(),this.getY() - 10]
                            if (this.getX() >= enemyTank.getX()
                                    && this.getX() <= enemyTank.getX() + 80 + 10
                                    && this.getY() - 10 >= enemyTank.getY()
                                    && this.getY() - 10 <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                            // 当前坦克右上角坐标 [this.getX() + 80,this.getY() - 10]
                            if (this.getX() + 80 >= enemyTank.getX()
                                    && this.getX() + 80 <= enemyTank.getX() + 80 + 10
                                    && this.getY() - 10 >= enemyTank.getY()
                                    && this.getY() - 10 <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                        }


                        // x范围 [enemyTank.getX() - 10,enemyTank.getX() + 80]
                        // y范围 [enemyTank.getY(),enemyTank.getY() + 80]
                        if (enemyTank.getDirection() == 3) {
    
    // 其它敌人坦克在朝左
                            // 当前坦克左上角坐标 [this.getX(),this.getY() - 10]
                            if (this.getX() >= enemyTank.getX() - 10
                                    && this.getX() <= enemyTank.getX() + 80
                                    && this.getY() - 10 >= enemyTank.getY()
                                    && this.getY() - 10 <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }

                            // 当前坦克右上角坐标 [this.getX() + 80,this.getY() - 10]
                            if (this.getX() + 80 >= enemyTank.getX() - 10
                                    && this.getX() + 80 <= enemyTank.getX() + 80
                                    && this.getY() - 10 >= enemyTank.getY()
                                    && this.getY() - 10 <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                        }
                    } // enemyTank != this
                }
                break;
            case 1: // 当前坦克向右
                for (int i = 0; i < enemyTanks.size(); i++) {
    
    
                    EnemyTank enemyTank = enemyTanks.get(i);
                    // 取出敌人坦克,然后每一辆坦克和除了自己以外的坦克进行比较是否碰撞
                    if (enemyTank != this) {
    
    
                        // x范围 [enemyTank.getX(),enemyTank.getX() + 80]
                        // y范围 [enemyTank.getY() -10,enemyTank.getY() + 80]
                        if (enemyTank.getDirection() == 0) {
    
    // 其它敌人坦克在朝上
                            // 当前坦克左上角坐标 [this.getX(),this.getY()]
                            if (this.getX() >= enemyTank.getX()
                                    && this.getX() <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY() - 10
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                            // 当前坦克右上角坐标 [this.getX() + 80 + 10,this.getY()]
                            if (this.getX() + 80 + 10 >= enemyTank.getX()
                                    && this.getX() + 80 + 10 <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY() - 10
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                        }

                        // x范围 [enemyTank.getX(),enemyTank.getX() + 80]
                        // y范围 [enemyTank.getY(),enemyTank.getY() + 80 + 10]
                        if (enemyTank.getDirection() == 2) {
    
    // 其它敌人坦克在朝下
                            // 当前坦克左上角坐标 [this.getX(),this.getY()]
                            if (this.getX() >= enemyTank.getX()
                                    && this.getX() <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80 + 10) {
    
    
                                return true;
                            }
                            // 当前坦克右上角坐标 [this.getX() + 80 + 10,this.getY()]
                            if (this.getX() + 80 + 10 >= enemyTank.getX()
                                    && this.getX() + 80 + 10 <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80 + 10) {
    
    
                                return true;
                            }
                        }

                        // x范围 [enemyTank.getX(),enemyTank.getX() + 80 + 10]
                        // y范围 [enemyTank.getY(),enemyTank.getY() + 80]
                        if (enemyTank.getDirection() == 1) {
    
    // 其它敌人坦克在朝右
                            // 当前坦克左上角坐标 [this.getX(),this.getY()]
                            if (this.getX() >= enemyTank.getX()
                                    && this.getX() <= enemyTank.getX() + 80 + 10
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                            // 当前坦克右上角坐标 [this.getX() + 80 + 10,this.getY()]
                            if (this.getX() + 80 + 10 >= enemyTank.getX()
                                    && this.getX() + 80 + 10 <= enemyTank.getX() + 80 + 10
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                        }

                        // x范围 [enemyTank.getX() - 10,enemyTank.getX() + 80]
                        // y范围 [enemyTank.getY(),enemyTank.getY() + 80]
                        if (enemyTank.getDirection() == 3) {
    
    // 其它敌人坦克在朝左
                            // 当前坦克左上角坐标 [this.getX(),this.getY()]
                            if (this.getX() >= enemyTank.getX() - 10
                                    && this.getX() <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                            // 当前坦克右上角坐标 [this.getX() + 80 + 10,this.getY()]
                            if (this.getX() + 80 + 10 >= enemyTank.getX() - 10
                                    && this.getX() + 80 + 10 <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                        }

                    }// enemyTank != this

                } // for
                break;
            case 2: // 当前坦克向下
                for (int i = 0; i < enemyTanks.size(); i++) {
    
    
                    EnemyTank enemyTank = enemyTanks.get(i);

                    // 取出敌人坦克,然后每一辆坦克和除了自己以外的坦克进行比较是否碰撞
                    if (enemyTank != this) {
    
    
                        // x范围 [enemyTank.getX(),enemyTank.getX() + 80]
                        // y范围 [enemyTank.getY() -10,enemyTank.getY() + 80]
                        if (enemyTank.getDirection() == 0) {
    
    // 其它敌人坦克在朝上
                            // 当前坦克左上角坐标 [this.getX(),this.getY()]
                            if (this.getX() >= enemyTank.getX()
                                    && this.getX() <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY() - 10
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                            // 当前坦克右上角坐标 [this.getX() + 80,this.getY()]
                            if (this.getX() + 80 >= enemyTank.getX()
                                    && this.getX() + 80 <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY() - 10
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                        }

                        // x范围 [enemyTank.getX(),enemyTank.getX() + 80]
                        // y范围 [enemyTank.getY(),enemyTank.getY() + 80 + 10]
                        if (enemyTank.getDirection() == 2) {
    
    // 其它敌人坦克在朝下
                            // 当前坦克左上角坐标 [this.getX(),this.getY()]
                            if (this.getX() >= enemyTank.getX()
                                    && this.getX() <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80 + 10) {
    
    
                                return true;
                            }
                            // 当前坦克右上角坐标 [this.getX() + 80,this.getY()]
                            if (this.getX() + 80 >= enemyTank.getX()
                                    && this.getX() + 80 <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80 + 10) {
    
    
                                return true;
                            }

                        }

                        // x范围 [enemyTank.getX(),enemyTank.getX() + 80 + 10]
                        // y范围 [enemyTank.getY(),enemyTank.getY() + 80]
                        if (enemyTank.getDirection() == 1) {
    
    // 其它敌人坦克在朝右
                            // 当前坦克左上角坐标 [this.getX(),this.getY()]
                            if (this.getX() >= enemyTank.getX()
                                    && this.getX() <= enemyTank.getX() + 80 + 10
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                            // 当前坦克右上角坐标 [this.getX() + 80,this.getY()]
                            if (this.getX() + 80 >= enemyTank.getX()
                                    && this.getX() + 80 <= enemyTank.getX() + 80 + 10
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                        }


                        // x范围 [enemyTank.getX() - 10,enemyTank.getX() + 80]
                        // y范围 [enemyTank.getY(),enemyTank.getY() + 80]
                        if (enemyTank.getDirection() == 3) {
    
    // 其它敌人坦克在朝左
                            // 当前坦克左上角坐标 [this.getX(),this.getY()]
                            if (this.getX() >= enemyTank.getX() - 10
                                    && this.getX() <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                            // 当前坦克右上角坐标 [this.getX() + 80,this.getY()]
                            if (this.getX() + 80 >= enemyTank.getX() - 10
                                    && this.getX() + 80 <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                        }
                    } // enemyTank != this
                }// for
                break;
            case 3: // 当前坦克向左
                for (int i = 0; i < enemyTanks.size(); i++) {
    
    
                    EnemyTank enemyTank = enemyTanks.get(i);

                    // 取出敌人坦克,然后每一辆坦克和除了自己以外的坦克进行比较是否碰撞
                    if (enemyTank != this) {
    
    
                        // x范围 [enemyTank.getX(),enemyTank.getX() + 80]
                        // y范围 [enemyTank.getY() -10,enemyTank.getY() + 80]
                        if (enemyTank.getDirection() == 0) {
    
    // 其它敌人坦克在朝上
                            // 当前坦克左上角坐标 [this.getX() - 10,this.getY()]
                            if (this.getX() - 10 >= enemyTank.getX()
                                    && this.getX() - 10 <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY() - 10
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                            // 当前坦克右上角坐标 [this.getX() + 80,this.getY()]
                            if (this.getX() + 80 >= enemyTank.getX()
                                    && this.getX() + 80 <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY() - 10
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                        }

                        // x范围 [enemyTank.getX(),enemyTank.getX() + 80]
                        // y范围 [enemyTank.getY(),enemyTank.getY() + 80 + 10]
                        if (enemyTank.getDirection() == 2) {
    
    // 其它敌人坦克在朝下
                            // 当前坦克左上角坐标 [this.getX() - 10,this.getY()]
                            if (this.getX() - 10 >= enemyTank.getX()
                                    && this.getX() - 10 <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80 + 10) {
    
    
                                return true;
                            }
                            // 当前坦克右上角坐标 [this.getX() + 80,this.getY()]
                            if (this.getX() + 80 >= enemyTank.getX()
                                    && this.getX() + 80 <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80 + 10) {
    
    
                                return true;
                            }
                        }

                        // x范围 [enemyTank.getX(),enemyTank.getX() + 80 + 10]
                        // y范围 [enemyTank.getY(),enemyTank.getY() + 80]
                        if (enemyTank.getDirection() == 1) {
    
    // 其它敌人坦克在朝右
                            // 当前坦克左上角坐标 [this.getX() - 10,this.getY()]
                            if (this.getX() - 10 >= enemyTank.getX()
                                    && this.getX() - 10 <= enemyTank.getX() + 80 + 10
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                            // 当前坦克右上角坐标 [this.getX() + 80,this.getY()]
                            if (this.getX() + 80 >= enemyTank.getX()
                                    && this.getX() + 80 <= enemyTank.getX() + 80 + 10
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                        }


                        // x范围 [enemyTank.getX() - 10,enemyTank.getX() + 80]
                        // y范围 [enemyTank.getY(),enemyTank.getY() + 80]
                        if (enemyTank.getDirection() == 3) {
    
    // 其它敌人坦克在朝左
                            // 当前坦克左上角坐标 [this.getX() - 10,this.getY()]
                            if (this.getX() - 10 >= enemyTank.getX() - 10
                                    && this.getX() - 10 <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                            // 当前坦克右上角坐标 [this.getX() + 80,this.getY()]
                            if (this.getX() + 80 >= enemyTank.getX() - 10
                                    && this.getX() + 80 <= enemyTank.getX() + 80
                                    && this.getY() >= enemyTank.getY()
                                    && this.getY() <= enemyTank.getY() + 80) {
    
    
                                return true;
                            }
                        }

                    } // enemyTank != this
                } // for
                break;
        }
        return false;
    }
}

Player Tank PlayerTank

package com.View;

import java.util.Vector;

/**
 * @author wty
 * @date 2022/10/21 0:00
 * 玩家的坦克
 */
public class PlayerTank extends Tank{
    
    
    private  Shot shot = null;
    private Vector<Shot> manyShoots = new Vector<>();
    private int max_Shoots = 4;

    public PlayerTank(int x, int y) {
    
    
        super(x, y);
    }

    public Shot getShot() {
    
    
        return shot;
    }

    public void setShot(Shot shot) {
    
    
        this.shot = shot;
    }

    public Vector<Shot> getManyShoots() {
    
    
        return manyShoots;
    }

    public void setManyShoots(Vector<Shot> manyShoots) {
    
    
        this.manyShoots = manyShoots;
    }

    // 玩家坦克的射击行为
    public void shotEnemy(){
    
    
        // 控制己方坦克最大导弹量
        if (manyShoots.size() >= max_Shoots){
    
    
            return;
        }

        // 要根据当前坦克的位置创建子弹对象
        switch (this.getDirection()){
    
    
            case 0:
                shot = new Shot(this.getX() + 37,this.getY() - 10,0);
                break;
            case 1:
                shot = new Shot(this.getX() + 80,this.getY() + 37,1);
                break;
            case 2:
                shot = new Shot(this.getX() + 37,this.getY() + 70,2);
                break;
            case 3:
                shot = new Shot(this.getX() - 10,this.getY() + 37,3);
                break;
        }
        manyShoots.add(shot);
        // 启动线程
        new Thread(shot).start();
    }
}

Music player AePlayWave

The code written by Mr. Han

package com.View;

import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;

/**
 * @author hsp
 * @date 2022/10/21 0:01
 * 播放音乐
 */
public class AePlayWave extends Thread {
    
    
    private String filename;

    public AePlayWave(String wavfile) {
    
     //构造器 , 指定文件
        filename = wavfile;

    }

    public void run() {
    
    

        File soundFile = new File(filename);

        AudioInputStream audioInputStream = null;
        try {
    
    
            audioInputStream = AudioSystem.getAudioInputStream(soundFile);
        } catch (Exception e1) {
    
    
            e1.printStackTrace();
            return;
        }

        AudioFormat format = audioInputStream.getFormat();
        SourceDataLine auline = null;
        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

        try {
    
    
            auline = (SourceDataLine) AudioSystem.getLine(info);
            auline.open(format);
        } catch (Exception e) {
    
    
            e.printStackTrace();
            return;
        }

        auline.start();
        int nBytesRead = 0;
        //这是缓冲
        byte[] abData = new byte[512];

        try {
    
    
            while (nBytesRead != -1) {
    
    
                nBytesRead = audioInputStream.read(abData, 0, abData.length);
                if (nBytesRead >= 0)
                    auline.write(abData, 0, nBytesRead);
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
            return;
        } finally {
    
    
            auline.drain();
            auline.close();
        }

    }
}

Tank Explosion Boom

package com.View;

/**
 * @author wty
 * @date 2022/10/21 18:38
 *
 * 爆炸效果
 */
public class Boom {
    
    
    private int x;
    private int y;
    private int life = 9; // 坦克的生命,三条命
    private boolean isLive = true;

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

    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 getLife() {
    
    
        return life;
    }

    public void setLife(int life) {
    
    
        this.life = life;
    }

    public boolean isLive() {
    
    
        return isLive;
    }

    public void setLive(boolean live) {
    
    
        isLive = live;
    }

    // 减少生命值
    public void lifeKill(){
    
    
        if (life > 0){
    
    
            life --;
        }else {
    
    
            isLive = false;
        }
    }
}

Game over EndGame

package com.View;

import javax.swing.*;
import java.awt.*;

/**
 * @author wty
 * @date 2022/10/22 22:51
 */
public class EndGame extends JDialog {
    
    
    public EndGame(){
    
    
        setVisible(true);
        setBounds(100,100,200,200);
        //setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 弹出窗口自带关闭

        Container container = getContentPane();
        container.setLayout(null);

        JLabel jLabel = new JLabel("玩家坦克被击毁,游戏结束!");
        jLabel.setSize(200,100);
        container.add(jLabel);
    }
}

Enemy tank coordinates Node

package com.View;

/**
 * @author wty
 * @date 2022/10/22 18:28
 * <p>
 * 一个Node对象:表示一个敌人坦克的坐标和信息
 */
public class Node {
    
    
    private int x;
    private int y;
    private int direction;

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

    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 getDirection() {
    
    
        return direction;
    }

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

Game data Record on the right

package com.View;

import java.io.*;
import java.util.Vector;

/**
 * @author wty
 * @date 2022/10/22 16:47
 * 该类用于记录游戏信息,和文件交互,用到IO流
 */
@SuppressWarnings({
    
    "all"})
public class Record {
    
    
    private static int allEnemyTankCount = 0; // 击毁敌方坦克数
    private static int allPlayerTankCount = 3; // 玩家坦克生命

    // 输出流
    private static BufferedWriter bufferedWriter = null; // 文件处理流
    private static FileWriter fileWriter = null; // 文件节点流
    private static String recordFile = "src\\EnemyRecord.txt";

    // 用于存储玩家坦克的坐标
    private static BufferedWriter bufferedWriterPlay = null; // 文件处理流
    private static FileWriter fileWriterPlay = null; // 文件节点流
    private static String recordFilePlay = "src\\PlayerRecord.txt";

    // 输入流
    private static BufferedReader bufferedReader = null; // 文件处理流
    private static FileReader fileReader = null; // 文件节点流

    // 读取玩家坐标
    private static BufferedReader bufferedReaderPlayer = null; // 文件处理流
    private static FileReader fileReaderPlayer = null; // 文件节点流

    // 定义Vector集合,指向MyPanel对象的敌人坦克
    private static Vector<EnemyTank> enemyTanks = null;

    // 定义一个Vector类型的Node用于存放敌方信息
    private static Vector<Node> nodes = new Vector<>();

    private  static int x_player;
    private  static int y_player;
    private  static int direction_player;

    public static String getRecordFile() {
    
    
        return recordFile;
    }

    public static void setRecordFile(String recordFile) {
    
    
        Record.recordFile = recordFile;
    }

    public static String getRecordFilePlay() {
    
    
        return recordFilePlay;
    }

    public static void setRecordFilePlay(String recordFilePlay) {
    
    
        Record.recordFilePlay = recordFilePlay;
    }

    public static int getX_player() {
    
    
        return x_player;
    }

    public static void setX_player(int x_player) {
    
    
        Record.x_player = x_player;
    }

    public static int getY_player() {
    
    
        return y_player;
    }

    public static void setY_player(int y_player) {
    
    
        Record.y_player = y_player;
    }

    public static int getDirection_player() {
    
    
        return direction_player;
    }

    public static void setDirection_player(int direction_player) {
    
    
        Record.direction_player = direction_player;
    }

    public static void setEnemyTanks(Vector<EnemyTank> enemyTanks) {
    
    
        Record.enemyTanks = enemyTanks;
    }


    public static int getAllEnemyTankCount() {
    
    
        return allEnemyTankCount;
    }

    public static void setAllEnemyTankCount(int allEnemyTankCount) {
    
    
        Record.allEnemyTankCount = allEnemyTankCount;
    }

    public static int getAllPlayerTankCount() {
    
    
        return allPlayerTankCount;
    }

    public static void setAllPlayerTankCount(int allPlayerTankCount) {
    
    
        Record.allPlayerTankCount = allPlayerTankCount;
    }

    // 读取文件恢复敌人相关信息
    public static Vector<Node> getNodesandCountEnemy() {
    
    
        try {
    
    
            // 先判断文件是否存在
            File file = new File(recordFile);
            if (null != file && 0 != file.length() && file.exists()){
    
    
                bufferedReader = new BufferedReader(new FileReader(recordFile));
                allEnemyTankCount = Integer.parseInt(bufferedReader.readLine());
                //allPlayerTankCount = Integer.parseInt(bufferedReader.readLine());

                // 生成Node集合
                String str_cont = "";
                while((str_cont = bufferedReader.readLine()) != null) {
    
    
                    String[] s = str_cont.split(" ");
                    Node node = new Node(Integer.parseInt(s[0]), Integer.parseInt(s[1]), Integer.parseInt(s[2]));
                    nodes.add(node); // 把坐标存入Node集合(Vector)中
                }
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
                if (bufferedReader != null){
    
    
                    bufferedReader.close();
                }
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
        return nodes;
    }
    // 读取文件恢复敌人相关信息
    public static void getNodesandCountPlayer() {
    
    
        try {
    
    
            // 先判断文件是否存在
            File file = new File(recordFilePlay);
            if (null != file && 0 != file.length() && file.exists()){
    
    
                bufferedReaderPlayer = new BufferedReader(new FileReader(recordFilePlay));
                allPlayerTankCount = Integer.parseInt(bufferedReaderPlayer.readLine());
                x_player = Integer.parseInt(bufferedReaderPlayer.readLine());
                y_player = Integer.parseInt(bufferedReaderPlayer.readLine());
                direction_player = Integer.parseInt(bufferedReaderPlayer.readLine());
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
                if (bufferedReader != null){
    
    
                    bufferedReader.close();
                }
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
        return;
    }


    // 当玩家击毁一辆敌方坦克
    public static void addTankCout() {
    
    
        // 静态对象,可以类名.变量名
        Record.allEnemyTankCount++;
    }

    // 当玩家坦克被敌方击毁时
    public static void minusPlayerTankCout() {
    
    
        // 静态对象,可以类名.变量名
        Record.allPlayerTankCount--;

        if (allPlayerTankCount <= 0){
    
    
            System.out.println("玩家坦克被击毁,游戏结束!");
            new EndGame();
        }
    }

    // 增加一个方法保存击败坦克数量等游戏信息
    // 保存敌方坦克的坐标和方向
    public static void saveRecordEnemy() {
    
    
        try {
    
    
            bufferedWriter = new BufferedWriter(new FileWriter(recordFile));
            bufferedWriter.write(allEnemyTankCount + "\r\n"); // 换行
            //bufferedWriter.write(allPlayerTankCount + "\r\n"); // 换行
            System.out.println("写入allPlayerTankCount:" + allPlayerTankCount);
            //bufferedWriter.newLine();

            // 遍历敌人坦克的集合Vector然后看情况保存
            for (int i = 0; i < enemyTanks.size(); i++) {
    
    
                // 取出坦克
                EnemyTank enemyTank = enemyTanks.get(i);
                if (enemyTank != null && enemyTank.isLive()) {
    
    
                    // 保存该enemyTank信息
                    String record = enemyTank.getX() + " " + enemyTank.getY() + " " + enemyTank.getDirection();
                    bufferedWriter.write(record + "\r\n");
                }

            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
                bufferedWriter.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
    }
    // 保存玩家坦克的坐标和方向
    public static void saveRecordPlayer() {
    
    
        try {
    
    
            bufferedWriterPlay = new BufferedWriter(new FileWriter(recordFilePlay));
            bufferedWriterPlay.write(allPlayerTankCount + "\r\n"); // 换行
            System.out.println("写入allPlayerTankCount:" + allPlayerTankCount);
            //bufferedWriter.newLine();
            bufferedWriterPlay.write(x_player + "\r\n");
            bufferedWriterPlay.write(y_player + "\r\n");
            bufferedWriterPlay.write(direction_player + "\r\n");
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
                bufferedWriterPlay.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

shooting shot

package com.View;

/**
 * @author wty
 * @date 2022/10/21 15:51
 * <p>
 * 这个类用来记录子弹
 */
public class Shot implements Runnable {
    
    
    private int x; // 子弹横坐标
    private int y;// 子弹纵坐标
    private int direct = 0; // 子弹方向
    private int speed = 16; // 子弹速度
    private boolean isLive = true; // 子弹是否存活

    // 子弹的设计行为
    @Override
    public void run() {
    
    
        while (true) {
    
    
            try {
    
    
                // 休眠
                Thread.sleep(80); // 子弹刷新频率
            } catch (Exception e) {
    
    
                e.printStackTrace();
            }

            // 根据方向改变子弹的横纵坐标
            switch (direct) {
    
    
                case 0: // 子弹向上
                    y -= speed;
                    break;
                case 1:// 子弹向右
                    x += speed;
                    break;
                case 2:// 子弹向下
                    y += speed;
                    break;
                case 3:// 子弹向左
                    x -= speed;
                    break;
            }
            // 调试方便输出x,y的坐标
            //System.out.println("x = " + x + ",y = " + y);


            // 子弹撞墙了就销毁(超出边界就销毁)
            // 当子弹碰到敌人坦克的时候也应该结束线程
            if (!(x > 0 && x < 1000 && y > 0 && y < 750 && isLive) || Record.getAllPlayerTankCount() <= 0) {
    
    
                System.out.println("子弹线程退出");
                isLive = false;
                break;
            }
        }

    }

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

    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 getDirect() {
    
    
        return direct;
    }

    public void setDirect(int direct) {
    
    
        this.direct = direct;
    }

    public int getSpeed() {
    
    
        return speed;
    }

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

    public boolean isLive() {
    
    
        return isLive;
    }

    public void setLive(boolean live) {
    
    
        isLive = live;
    }
}

Guess you like

Origin blog.csdn.net/sinat_38316216/article/details/127473383