敌方坦克相互不能碰撞

Enemy类中添加isTouch()方法判断自己坦克运动方向是否碰撞到别的坦克,碰到则返回true

public boolean isTouch() {//判断是否碰撞
    switch (this.getDirect()) {
        case 0:
            for (int i = 0; i < enemies.size(); i++) {
                Enemy enemy = enemies.get(i);
                if (this != enemy) {
                    if (this.getX() >= enemy.getX() &&
                            this.getX() <= enemy.getX() + 40 &&
                            this.getY() >= enemy.getY() &&
                            this.getY() <= enemy.getY() + 40) {
                        return true;
                    }
                    if (this.getX() + 40 >= enemy.getX() &&
                            this.getX() + 40 <= enemy.getX() + 40 &&
                            this.getY() >= enemy.getY() &&
                            this.getY() <= enemy.getY() + 40) {
                        return true;
                    }
                }
            }
            break;
        case 1:
            for (int i = 0; i < enemies.size(); i++) {
                Enemy enemy = enemies.get(i);
                if (this != enemy) {
                    if (this.getX() + 40 >= enemy.getX() &&
                            this.getX() + 40 <= enemy.getX() + 40 &&
                            this.getY() >= enemy.getY() &&
                            this.getY() <= enemy.getY() + 40) {
                        return true;
                    }
                    if (this.getX() + 40 >= enemy.getX() &&
                            this.getX() + 40 <= enemy.getX() + 40 &&
                            this.getY() + 40 >= enemy.getY() &&
                            this.getY() + 40 <= enemy.getY() + 40) {
                        return true;
                    }
                }
            }
            break;
        case 2:
            for (int i = 0; i < enemies.size(); i++) {
                Enemy enemy = enemies.get(i);
                if (this != enemy) {
                    if (this.getX() >= enemy.getX() &&
                            this.getX() <= enemy.getX() + 40 &&
                            this.getY() + 40 >= enemy.getY() &&
                            this.getY() + 40 <= enemy.getY() + 40) {
                        return true;
                    }
                    if (this.getX() + 40 >= enemy.getX() &&
                            this.getX() + 40 <= enemy.getX() + 40 &&
                            this.getY() + 40 >= enemy.getY() &&
                            this.getY() + 40 <= enemy.getY() + 40) {
                        return true;
                    }
                }
            }
            break;
        case 3:
            for (int i = 0; i < enemies.size(); i++) {
                Enemy enemy = enemies.get(i);
                if (this != enemy) {
                    if (this.getX() >= enemy.getX() &&
                            this.getX() <= enemy.getX() + 40 &&
                            this.getY() >= enemy.getY() &&
                            this.getY() <= enemy.getY() + 40) {
                        return true;
                    }
                    if (this.getX() >= enemy.getX() &&
                            this.getX() <= enemy.getX() + 40 &&
                            this.getY() + 40 >= enemy.getY() &&
                            this.getY() + 40 <= enemy.getY() + 40) {
                        return true;
                    }
                }
            }
            break;
    }
    return false;
}

Enemy类run( )中运动前添加判断条件

public void run() {//重写run方法
    
    //子弹
    while (true) {
        if (shots.size() < 2) {//设置敌方子弹个数为2
            switch (getDirect()) {
                case 0:
                    shot = new Shot(getX() + 20, getY(), 0);
                    break;
                case 1:
                    shot = new Shot(getX() + 60, getY() + 20, 1);
                    break;
                case 2:
                    shot = new Shot(getX() + 20, getY() + 60, 2);
                    break;
                case 3:
                    shot = new Shot(getX(), getY() + 20, 3);
                    break;
            }
            new Thread(shot).start();//启动子弹线程
            shots.add(shot);//添加进子弹集合
        }
        
        //坦克运动
        int random = (int) (Math.random() * 60);//获取随机移动距离
        switch (getDirect()) {//获取方向
            case 0://上
                for (int i = 0; i < random; i++) {
                    if (!isTouch())//判断是否碰撞,未碰撞运动
                        moveUp();//向上移动random步
                    try {
                        Thread.sleep(50);//休眠50ms
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                break;
            case 1://右
                for (int i = 0; i < random; i++) {
                    if (!isTouch())
                        moveRight();//向右移动random步
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                break;
            case 2://下
                for (int i = 0; i < random; i++) {
                    if (!isTouch())
                        moveDown();//向下移动random步
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                break;
            case 3://左
                for (int i = 0; i < random; i++) {
                    if (!isTouch())
                        moveLeft();//向左移动random步
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                break;
        }
        setDirect((int) (Math.random() * 4));//设置随机方向
    }
}

验证结果

击中坦克添加爆炸效果

bomb_1.gif 图片.png bomb_2.gif 图片.png bomb_3.gif 图片.png 爆炸特效本质上就是图片的快速切换,这里我们用3张图片的快速切换达到爆照效果

添加Bomb类,给其相应的属性及get方法

/**
 * @author 谢阳
 * @version 1.8.0_131
 */
public class Bomb {
    private int x;//x坐标
    private int y;//y坐标
    private int live = 12;//生命周期

    public Bomb(int x, int y) {//构造器
        this.x = x;
        this.y = y;
    }

    public void lifeDown() {
        if (live > 0) {
            live--;
        }
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int getLive() {
        return live;
    }
}

在项目下添加所需要的图片 图片.png MyPanel类中添加爆炸属性集合和3个图片属性,并在构造器中初始化图片属性

public class MyPanel extends JPanel implements KeyListener, Runnable {
    Vector<Hero> heroes = new Vector<>();//创建我方坦克集合
    int enemyNum = 10;//创建敌方坦克数量
    Vector<Enemy> enemies = new Vector<>();//创建敌方坦克集合
    Vector<Bomb> bombs = new Vector<>();//创建爆炸集合
    Image image1 = null;//新建3个图片属性
    Image image2 = null;
    Image image3 = null;

    public MyPanel() {//创建无参构造器

        //初始化我方坦克
        Hero hero = new Hero(550, 500, 0);
        hero.setSpeed(5);//设置我方移动速度
        heroes.add(hero);//添加我方坦克集合

        //初始化敌方坦克
        for (int i = 0; i < enemyNum; i++) {
            Enemy enemy = new Enemy(100 * (i + 0), 0, 2);
            enemy.setSpeed(2);//设置敌人移动速度
            enemies.add(enemy);//添加至敌人坦克集合
            new Thread(enemy).start();//启动敌人坦克线程
            enemy.setEnemies(enemies);
        }

      //初始化爆炸图片属性
      image1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_1.gif"));
      image2 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_2.gif"));
      image3 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_3.gif"));

    }

MyPanel类的hit()方法中击中时新建bomb对象,并添加进bombs集合中

public void hit(Shot shot, Tank tank) {//hit方法,判断是否击中坦克
    int x = tank.getX();
    int y = tank.getY();
    if (shot.getX() > x && shot.getX() < x + 40 && shot.getY() > y && shot.getY() < y + 40) {
        tank.isLive = false;//击中坦克,坦克不存活
        shot.setIsLive(false);//击中坦克,子弹不存活
        if (tank instanceof Enemy) {//判断是否为敌方坦克
            enemies.remove(tank);//是敌方tank就从集合中移除
        }
        if (tank instanceof Hero) {//是我方坦克移除
            heroes.remove(tank);
        }
        Bomb bomb = new Bomb(x, y);//新建bomb对象
        bombs.add(bomb);//加入bombs集合中
    }
}

MyPanel类的paint()方法中画出爆炸效果

@Override
public void paint(Graphics g) {
    super.paint(g);
    g.fill3DRect(0, 0, 1000, 750, false);//设置背景大小

    //我方坦克
    for (int i = 0; i < heroes.size(); i++) {//如果坦克数量为零则不画出
        Hero hero = heroes.get(i);
        drawTank(hero.getX(), hero.getY(), hero.getDirect(), 0, g);//画出我方坦克
        for (int j = 0; j < hero.shots.size(); j++) {//当子弹不为空时画出子弹
            Shot shot = hero.shots.get(j);
            if (shot.getIsLive()) {//判断子弹是否超界,未超界画出
                g.fill3DRect(shot.getX() - 1, shot.getY() - 1, 3, 3, false);
            } else {
                hero.shots.remove(shot);//超界移除
            }
        }
    }

    //敌方坦克
    for (int i = 0; i < enemies.size(); i++) {//遍历画出敌方坦克
        Enemy enemy = enemies.get(i);
        if (enemy.isLive) {//判断存活才画出坦克
            drawTank(enemy.getX(), enemy.getY(), enemy.getDirect(), 1, g);
        }
        for (int j = 0; j < enemy.shots.size(); j++) {//当子弹不为空时画出子弹
            Shot shot = enemy.shots.get(j);
            if (shot.getIsLive()) {//判断子弹是否超界,未超界画出
                g.fill3DRect(shot.getX() - 1, shot.getY() - 1, 3, 3, false);
            } else {
                enemy.shots.remove(shot);//超界移除
            }
        }
    }

    showInfo(g);//调用方法显示游戏信息

    //显示爆炸信息
    for (int i = 0; i < bombs.size(); i++) {//有爆炸对象画出
        Bomb bomb = bombs.get(i);
        int x = bomb.getX();
        int y = bomb.getY();
        int live = bomb.getLive();
        if (live > 6) {
            g.drawImage(image1, x, y, 40, 40, this);//bomb_1.gif
        } else if (live > 3) {
            g.drawImage(image2, x, y, 40, 40, this);//bomb_2.gif
        }else {
            g.drawImage(image3, x, y, 40, 40, this);//bomb_3.gif
        }
        bomb.lifeDown();
        if (live == 0){//完成后移除
            bombs.remove(bomb);
        }
    }
}

演示效果 图片.png

保存游戏数据

添加Recorder类,给其相应属性及方法

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

/**
 * @author 谢阳
 * @version 1.8.0_131
 */
public class Recorder {
    private static int killCount;//击毁敌方坦克数属性
    private static String path = "src\\myRecord.txt";//保存路径
    private static BufferedWriter bw = null;//写入路径文件
    private static Vector<Enemy> enemies = null;//敌人坦克集合

    public static void setEnemies(Vector<Enemy> enemies) {//获取敌人坦克集合
        Recorder.enemies = enemies;
    }

    //保存数据方法
    public static void keepRecord() {
        if (enemies.size() != 0) {//如果敌人数量不为零则创建文件并保存数据,否则删除文件
            try {//捕获异常
                bw = new BufferedWriter(new FileWriter(path));//添加写入文件的路径
                bw.write(killCount + "\r\n");//保存击毁敌人坦克数,并换行(注:数据类型为字符型)
                for (int i = 0; i < enemies.size(); i++) { //遍历敌人
                    Enemy enemy = enemies.get(i);
                    if (enemy.isLive) {//判断是否存活
                        String info = enemy.getX() + " " + enemy.getY() + " " + enemy.getDirect();//敌人信息
                        bw.write(info + "\r\n");//写入敌人信息
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (bw != null) {
                    try {//捕获异常
                        bw.close();//br不为空则关闭(注:关闭才能写入数据)
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        } else {//没有坦克则获胜,不需要记录游戏信息
            File file = new File(path);
            file.delete();//删除游戏信息
        }
    }
    
    public static int getKillCount() {//获取击毁敌人坦克信息
        return killCount;
    }

    public static void addKillCount() {//击毁坦克时调用
        killCount++;
    }

}

MyPanel类构造器中为Recorder类传入敌人坦克数据

public MyPanel() {//创建无参构造器

    //初始化我方坦克
    Hero hero = new Hero(550, 500, 0);
    hero.setSpeed(5);//设置我方移动速度
    heroes.add(hero);//添加我方坦克集合

    //初始化敌方坦克
    for (int i = 0; i < enemyNum; i++) {
        Enemy enemy = new Enemy(100 * (i + 0), 0, 2);
        enemy.setSpeed(2);//设置敌人移动速度
        enemies.add(enemy);//添加至敌人坦克集合
        new Thread(enemy).start();//启动敌人坦克线程
        enemy.setEnemies(enemies);//传入enemies判断是否碰撞
        Recorder.setEnemies(enemies);//传入enemies记录游戏信息
    }

    //初始化爆炸图片属性
    image1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_1.gif"));
    image2 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_2.gif"));
    image3 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_3.gif"));

}

MyPanel类hit()方法中当击毁敌人坦克时调用相应方法

public void hit(Shot shot, Tank tank) {//hit方法,判断是否击中坦克
    int x = tank.getX();
    int y = tank.getY();
    if (shot.getX() > x && shot.getX() < x + 40 && shot.getY() > y && shot.getY() < y + 40) {
        tank.isLive = false;//击中坦克,坦克不存活
        shot.setIsLive(false);//击中坦克,子弹不存活
        if (tank instanceof Enemy) {//判断是否为敌方坦克
            enemies.remove(tank);//是敌方tank就从集合中移除
            Recorder.addKillCount();//调用方法记录击毁坦克数
        }
        if (tank instanceof Hero) {//是我方坦克移除
            heroes.remove(tank);
        }
        Bomb bomb = new Bomb(x, y);//新建bomb对象
        bombs.add(bomb);//加入bombs集合中
    }
}

MyPanel类showInfo()方法中修改获取信息方式

public void showInfo(Graphics g) {//显示游戏信息
    g.setColor(Color.BLACK);
    Font font = new Font("宋体", Font.BOLD, 25);
    g.setFont(font);
    g.drawString("累计击毁敌方坦克", 1050, 30);
    g.drawString(Recorder.getKillCount() + "", 1110, 80);//直接从Recorder中获取信息
    drawTank(1050, 50, 0, 1, g);

    if (enemies.size() == 0) {//胜利信息
        g.setColor(Color.red);
        Font font1 = new Font("宋体", Font.BOLD, 80);
        g.setFont(font1);
        g.drawString("YOU WIN", 350, 350);
    }

    if (heroes.size() == 0) {//失败信息
        g.setColor(Color.red);
        Font font2 = new Font("宋体", Font.BOLD, 80);
        g.setFont(font2);
        g.drawString("Game Over", 350, 350);
    }
}

在TankGame类的构造器中添加监听

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

/**
 * @author 谢阳
 * @version 1.8.0_131
 */
public class TankGame extends JFrame {
    MyPanel mp = null;

    public TankGame() {//重写构造器
        mp = new MyPanel();//初始化属性
        new Thread(mp).start();//启动Mypanel的线程
        this.setSize(1300, 800);//设置界面大小
        this.add(mp);//添加mp
        this.setVisible(true);//设置可见
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭窗口结束程序
        this.addKeyListener(mp);//监听键盘输入
        
        this.addWindowListener(new WindowAdapter() {//监听窗口事件
            @Override
            public void windowClosing(WindowEvent e) {//重写方法
                Recorder.keepRecord();//当窗口关闭时(点击X时)保存游戏信息
                System.exit(0);//退出
            }
        });
    }

    public static void main(String[] args) {
        TankGame tankGame = new TankGame();//启动游戏入口
    }
}

验证结果 图片.png

可以继续上局游戏

添加Node类记录敌人坦克坐标信息,并给其相应属性和方法

/**
 * @author 谢阳
 * @version 1.8.0_131
 */
public class Node {
    private int x;//x坐标
    private int y;//y坐标
    private int direct;//方向

    public Node(int x, int y, int direct) {//构造器传参
        this.x = x;
        this.y = y;
        this.direct = direct;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int getDirect() {
        return direct;
    }

}

Recorder类中添加getLastInfo()方法和相应属性

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

/**
 * @author 谢阳
 * @version 1.8.0_131
 */
public class Recorder {
    private static int killCount;//击毁敌方坦克数属性
    private static String path = "src\\myRecord.txt";//保存路径
    private static BufferedWriter bw = null;//写入路径文件
    private static BufferedReader br = null;//读取路径文件
    private static Vector<Enemy> enemies = null;//敌人坦克集合
    private static Vector<Node> nodes = new Vector<>();//添加node集合

    public static void setEnemies(Vector<Enemy> enemies) {//获取敌人坦克集合
        Recorder.enemies = enemies;
    }

    //保存数据方法
    public static void keepRecord() {
        if (enemies.size() != 0) {//如果敌人数量不为零则创建文件并保存数据,否则删除文件
            try {//捕获异常
                bw = new BufferedWriter(new FileWriter(path));//添加写入文件的路径
                bw.write(killCount + "\r\n");//保存击毁敌人坦克数,并换行(注:数据类型为字符型)
                for (int i = 0; i < enemies.size(); i++) { //遍历敌人
                    Enemy enemy = enemies.get(i);
                    if (enemy.isLive) {//判断是否存活
                       String info = enemy.getX() + " " + enemy.getY() + " " + enemy.getDirect();//敌人信息以空格隔开
                       bw.write(info + "\r\n");//写入敌人信息
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (bw != null) {
                    try {//捕获异常
                        bw.close();//br不为空则关闭(注:关闭才能写入数据)
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        } else {//没有坦克则获胜,不需要记录游戏信息
            File file = new File(path);
            file.delete();//删除游戏信息
        }
    }

    //获取上局游戏信息方法
    public static Vector<Node> getLastInfo() {//记录信息,调用时返回坦克信息集合
        try {
            br = new BufferedReader(new FileReader(path));//添加读取文件路径
            killCount = Integer.parseInt(br.readLine());//读取一行并转为Integer赋值给killCount
            String line;
            while ((line = br.readLine()) != null) {//当读取不为空是继续
                String[] s = line.split(" ");//以空格为标识符String数组
                //创建Node坦克数据并初始化
                Node node = new Node(Integer.parseInt(s[0]), Integer.parseInt(s[1]), Integer.parseInt(s[2]));
                nodes.add(node);//添加进入nodes坦克信息集合
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();//不为空时关闭
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return nodes;//返回nodes信息
    }


    public static int getKillCount() {//获取击毁敌人坦克信息
        return killCount;
    }

    public static void addKillCount() {//击毁坦克时调用
        killCount++;
    }

    public static String getPath() {//获取路径信息
        return path;
    }

}

TankGame类中写入是否继续游戏的判断

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

/**
 * @author 谢阳
 * @version 1.8.0_131
 */
public class TankGame extends JFrame {
    MyPanel mp = null;
    Scanner scanner = new Scanner(System.in);

    public TankGame() {//重写构造器

        String key;
        File file = new File(Recorder.getPath());//写入文件路径
        if(!file.exists()){//如该文件不存在直接开始新游戏
            key = "N";
        }else {
            System.out.println("是否继续上局游戏(Y/N):");
            while (true) {//用户只能输入Y和N来进行游戏,否则一直循环
                key = scanner.next().toUpperCase();
                if (key.compareTo("Y") == 0 || key.compareTo("N") == 0) {
                    break;//满足要求跳出循环
                }
                System.out.println("输入有误,请重新输入");
            }
        }

        mp = new MyPanel(key);//初始化属性,传入key
        new Thread(mp).start();//启动Mypanel的线程
        this.setSize(1300, 800);//设置界面大小
        this.add(mp);//添加mp
        this.setVisible(true);//设置可见
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭窗口结束程序
        this.addKeyListener(mp);//监听键盘输入
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                Recorder.keepRecord();
                System.exit(0);
            }
        });
    }

    public static void main(String[] args) {
        TankGame tankGame = new TankGame();//启动游戏入口
    }
}

MyPanel类中添加信息集合属性,并改写构造器为有参,初始化敌人时判断是否继续游戏

public class MyPanel extends JPanel implements KeyListener, Runnable {
    Vector<Hero> heroes = new Vector<>();//创建我方坦克集合
    int enemyNum = 10;//创建敌方坦克数量
    Vector<Enemy> enemies = new Vector<>();//创建敌方坦克集合
    Vector<Bomb> bombs = new Vector<>();//创建爆炸集合
    Image image1 = null;//新建3个图片属性
    Image image2 = null;
    Image image3 = null;
    Vector<Node> nodes = new Vector<>();//创建信息集合

    public MyPanel(String key) {//有参构造器

        //初始化我方坦克
        Hero hero = new Hero(550, 500, 0);
        hero.setSpeed(5);//设置我方移动速度
        heroes.add(hero);//添加我方坦克集合

        //初始化敌方坦克前,判断是否继续游戏
        switch (key){
            case "Y":
                nodes = Recorder.getLastInfo();//调用方法获取上局游戏的敌人信息
                for (int i = 0; i < nodes.size(); i++) {//遍历获取每个敌人信息
                    Node node = nodes.get(i);
                    Enemy enemy = new Enemy(node.getX(),node.getY(),node.getDirect());//赋值上局敌人位置
                    enemy.setSpeed(2);//设置敌人移动速度
                    enemies.add(enemy);//添加至敌人坦克集合
                    new Thread(enemy).start();//启动敌人坦克线程
                    enemy.setEnemies(enemies);//传入enemies判断是否碰撞
                    Recorder.setEnemies(enemies);//传入enemies记录游戏信息
                }
                break;
            case "N":
                for (int i = 0; i < enemyNum; i++) {
                    Enemy enemy = new Enemy(100 * (i + 0), 0, 2);
                    enemy.setSpeed(2);//设置敌人移动速度
                    enemies.add(enemy);//添加至敌人坦克集合
                    new Thread(enemy).start();//启动敌人坦克线程
                    enemy.setEnemies(enemies);//传入enemies判断是否碰撞
                    Recorder.setEnemies(enemies);//传入enemies记录游戏信息
                }
                break;
        }


        //初始化爆炸图片属性
        image1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_1.gif"));
        image2 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_2.gif"));
        image3 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_3.gif"));

    }

验证结果 图片.png 图片.png

添加音乐

这段代码我是直接用的老师的,也不是核心内容,直接用即可

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

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();
        }

    }
}

导入音频文件 图片.png Mypanel类的构造器中最后启动音频线程

public MyPanel(String key) {//有参构造器

    //初始化我方坦克
    Hero hero = new Hero(550, 500, 0);
    hero.setSpeed(5);//设置我方移动速度
    heroes.add(hero);//添加我方坦克集合

    //初始化敌方坦克前,判断是否继续游戏
    switch (key) {
        case "Y":
            nodes = Recorder.getLastInfo();//调用方法获取上局游戏的敌人信息
            for (int i = 0; i < nodes.size(); i++) {//遍历获取每个敌人信息
                Node node = nodes.get(i);
                Enemy enemy = new Enemy(node.getX(), node.getY(), node.getDirect());//赋值上局敌人位置
                enemy.setSpeed(2);//设置敌人移动速度
                enemies.add(enemy);//添加至敌人坦克集合
                new Thread(enemy).start();//启动敌人坦克线程
                enemy.setEnemies(enemies);//传入enemies判断是否碰撞
                Recorder.setEnemies(enemies);//传入enemies记录游戏信息
            }
            break;
        case "N":
            for (int i = 0; i < enemyNum; i++) {
                Enemy enemy = new Enemy(100 * (i + 0), 0, 2);
                enemy.setSpeed(2);//设置敌人移动速度
                enemies.add(enemy);//添加至敌人坦克集合
                new Thread(enemy).start();//启动敌人坦克线程
                enemy.setEnemies(enemies);//传入enemies判断是否碰撞
                Recorder.setEnemies(enemies);//传入enemies记录游戏信息
            }
            break;
    }

    //初始化爆炸图片属性
    image1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_1.gif"));
    image2 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_2.gif"));
    image3 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_3.gif"));

    //启动音频
    new AePlayWave("src\\111.wav").start();
}

资料:

【韩顺平讲Java】Java坦克项目 面向对象 多线程 集合 IO流 算法 坦克大战游戏源码