Java学习-第一部分-第二阶段-项目实战:坦克大战【3】

坦克大战【3】

笔记目录:(https://www.cnblogs.com/wenjie2000/p/16378441.html)

坦克大战0.6版

√增加功能

  1. 防止敌人坦克重叠运动

    image

  2. 记录玩家的成绩(累积击毁敌方坦克数),存盘退出【io流】

  3. 记录当时的敌人坦克坐标与方向,存盘退出【io流】

    image

  4. 玩游戏时,可以选择是开新游戏还是继续上局游戏

代码

Tank

package tankgame06;

//坦克
public class Tank {
    //坦克左上角坐标
    private int x;
    private int y;
    private int direct;//坦克方向 0上 1右 2下 3左
    boolean isLive = true;//是否存活

    public int getSpeed() {
        return speed;
    }

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

    private int speed = 2;//坦克速度

    //上右下左移动方法
    public void moveUp() {
        if (y - speed > 0) {
            y -= speed;
        }
    }

    public void moveDown() {
        if (y + 60 + speed < 750) {
            y += speed;
        }
    }

    public void moveLeft() {
        if (x - 10 - speed > 0) {
            x -= speed;
        }
    }

    public void moveRight() {
        if (x - 10 + 60 + speed < 1000) {
            x += speed;
        }
    }

    public int getDirect() {
        return direct;
    }

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

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

Hero

package tankgame06;

import java.util.Vector;

//玩家坦克
public class Hero extends Tank {
    Shot shot = null;//射击行为
    //发射多个子弹
    Vector<Shot> shots = new Vector<>();

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

    //射击
    public void shotEnemyTank() {

        //发多颗子弹怎么办,控制在我们的面板上,最多只有5颗
        if (shots.size()==5){
            return;
        }
        switch (getDirect()) {
            case 0://上
                shot = new Shot(getX() + 20, getY(), 0);
                break;
            case 1://右边
                shot = new Shot(getX() + 50, getY() + 30, 1);
                break;
            case 2:
                shot = new Shot(getX() + 20, getY() + 60, 2);
                break;
            case 3:
                shot = new Shot(getX() - 10, getY() + 30, 3);
                break;
        }
        //把新创建的shot放入到shots
        shots.add(shot);
        //启动我们的Shot线程
        new Thread(shot).start();
    }
}

EnemyTank

package tankgame06;

import java.util.Vector;

//敌方坦克
public class EnemyTank extends Tank implements Runnable {
    //在敌人坦克类,使用Vector保存多个Shot
    Vector<Shot> shots = new Vector<>();
    static Vector<EnemyTank> enemyTanks = new Vector<>();//存放所有敌人坦克信息


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

    //编写方法,判断当前的这个敌人坦克,是否和 enemyTanks 中的其他坦克发生的重叠或者碰撞
    public boolean isTouchEnemyTank() {
        switch (this.getDirect()) {
            case 0:
                //让当前敌人坦克和其它所有的敌人坦克比较
                for (int i = 0; i < enemyTanks.size(); i++) {
                    //从vector中取出一个敌人坦克
                    EnemyTank enemyTank = enemyTanks.get(i);
                    //不和自己比较
                    if (enemyTank == this) {
                        continue;
                    }
                    //1.如果敌人坦克是上/下x的范围[enemyTank.getX(),enemyTank.getX() +40]
                    //                  y的范围 [enemyTank.getY(),enemyTank.getY() +60]
                    if (enemyTank.getDirect() == 0 || enemyTank.getDirect() == 2) {
                        //2。当前坦克左上角的坐标[this.getX(),this.getY()]
                        if (this.getX() >= enemyTank.getX() && this.getX() <= enemyTank.getX() + 40 && this.getY() >= enemyTank.getY() && this.getY() <= enemyTank.getY() + 60) {
                            return true;
                        }
                        //3.当前坦克右上角的坐标[this.getX() +40, this.getY()]
                        if (this.getX() + 40 >= enemyTank.getX() && this.getX() + 40 <= enemyTank.getX() + 40 && this.getY() >= enemyTank.getY() && this.getY() <= enemyTank.getY() + 60) {
                            return true;
                        }

                    }
                    //如果敌人坦克是 右/左
                    if (enemyTank.getDirect() == 1 || enemyTank.getDirect() == 3) {
                        //2。当前坦克左上角的坐标[this.getX(),this.getY()]
                        if (this.getX() >= enemyTank.getX() - 10 && this.getX() <= enemyTank.getX() + 50 && this.getY() >= enemyTank.getY() + 10 && this.getY() <= enemyTank.getY() + 50) {
                            return true;
                        }
                        //3.当前坦克右上角的坐标[this.getX() +40, this.getY()]
                        if (this.getX() + 40 >= enemyTank.getX() - 10 && this.getX() + 40 <= enemyTank.getX() + 50 && this.getY() >= enemyTank.getY() + 10 && this.getY() <= enemyTank.getY() + 50) {
                            return true;
                        }
                    }
                }
                break;
            case 1:
                //让当前敌人坦克和其它所有的敌人坦克比较
                for (int i = 0; i < enemyTanks.size(); i++) {
                    //从vector中取出一个敌人坦克
                    EnemyTank enemyTank = enemyTanks.get(i);
                    //不和自己比较
                    if (enemyTank == this) {
                        continue;
                    }
                    //1.如果敌人坦克是上/下
                    if (enemyTank.getDirect() == 0 || enemyTank.getDirect() == 2) {
                        //2。当前坦克右上角的坐标[this.getX()+50,this.getY()+10]
                        if (this.getX()+50 >= enemyTank.getX() && this.getX()+50 <= enemyTank.getX() + 40 && this.getY()+10 >= enemyTank.getY() && this.getY()+10 <= enemyTank.getY() + 60) {
                            return true;
                        }
                        //3.当前坦克右下角的坐标[this.getX() +50, this.getY()+50]
                        if (this.getX() + 50 >= enemyTank.getX() && this.getX() + 50 <= enemyTank.getX() + 40 && this.getY()+50 >= enemyTank.getY() && this.getY()+50 <= enemyTank.getY() + 60) {
                            return true;
                        }

                    }
                    //如果敌人坦克是 右/左
                    if (enemyTank.getDirect() == 1 || enemyTank.getDirect() == 3) {
                        //2。当前坦克右上角的坐标[this.getX()+50,this.getY()+10]
                        if (this.getX()+50 >= enemyTank.getX() - 10 && this.getX()+50 <= enemyTank.getX() + 50 && this.getY()+10 >= enemyTank.getY() + 10 && this.getY()+10 <= enemyTank.getY() + 50) {
                            return true;
                        }
                        //3.当前坦克右下角的坐标[this.getX() +50, this.getY()+50]
                        if (this.getX() + 50 >= enemyTank.getX() - 10 && this.getX() + 50 <= enemyTank.getX() + 50 && this.getY()+50 >= enemyTank.getY() + 10 && this.getY()+50 <= enemyTank.getY() + 50) {
                            return true;
                        }
                    }
                }
                break;
            case 2:
                //让当前敌人坦克和其它所有的敌人坦克比较
                for (int i = 0; i < enemyTanks.size(); i++) {
                    //从vector中取出一个敌人坦克
                    EnemyTank enemyTank = enemyTanks.get(i);
                    //不和自己比较
                    if (enemyTank == this) {
                        continue;
                    }
                    if (enemyTank.getDirect() == 0 || enemyTank.getDirect() == 2) {
                        //2。当前坦克左下角的坐标[this.getX(),this.getY()+60]
                        if (this.getX() >= enemyTank.getX() && this.getX() <= enemyTank.getX() + 40 && this.getY()+60 >= enemyTank.getY() && this.getY()+60 <= enemyTank.getY() + 60) {
                            return true;
                        }
                        //3.当前坦克右下角的坐标[this.getX() +40, this.getY()+60]
                        if (this.getX() + 40 >= enemyTank.getX() && this.getX() + 40 <= enemyTank.getX() + 40 && this.getY()+60 >= enemyTank.getY() && this.getY()+60 <= enemyTank.getY() + 60) {
                            return true;
                        }

                    }
                    //如果敌人坦克是 右/左
                    if (enemyTank.getDirect() == 1 || enemyTank.getDirect() == 3) {
                        //2。当前坦克左下角的坐标[this.getX(),this.getY()+60]
                        if (this.getX() >= enemyTank.getX() - 10 && this.getX() <= enemyTank.getX() + 50 && this.getY()+60 >= enemyTank.getY() + 10 && this.getY()+60 <= enemyTank.getY() + 50) {
                            return true;
                        }
                        //3.当前坦克右下角的坐标[this.getX() +40, this.getY()+60]
                        if (this.getX() + 40 >= enemyTank.getX() - 10 && this.getX() + 40 <= enemyTank.getX() + 50 && this.getY()+60 >= enemyTank.getY() + 10 && this.getY()+60 <= enemyTank.getY() + 50) {
                            return true;
                        }
                    }
                }
                break;
            case 3:
                //让当前敌人坦克和其它所有的敌人坦克比较
                for (int i = 0; i < enemyTanks.size(); i++) {
                    //从vector中取出一个敌人坦克
                    EnemyTank enemyTank = enemyTanks.get(i);
                    //不和自己比较
                    if (enemyTank == this) {
                        continue;
                    }
                    //1.如果敌人坦克是上/下
                    if (enemyTank.getDirect() == 0 || enemyTank.getDirect() == 2) {
                        //2。当前坦克左上角的坐标[this.getX()-10,this.getY()+10]
                        if (this.getX()-10 >= enemyTank.getX() && this.getX()-10 <= enemyTank.getX() + 40 && this.getY()+10 >= enemyTank.getY() && this.getY()+10 <= enemyTank.getY() + 60) {
                            return true;
                        }
                        //3.当前坦克左下角的坐标[this.getX()-10, this.getY()+50]
                        if (this.getX() -10 >= enemyTank.getX() && this.getX() -10 <= enemyTank.getX() + 40 && this.getY()+50 >= enemyTank.getY() && this.getY()+50 <= enemyTank.getY() + 60) {
                            return true;
                        }

                    }
                    //如果敌人坦克是 右/左
                    if (enemyTank.getDirect() == 1 || enemyTank.getDirect() == 3) {
                        //2。当前坦克左上角的坐标[this.getX()-10,this.getY()+10]
                        if (this.getX()-10 >= enemyTank.getX() - 10 && this.getX()-10 <= enemyTank.getX() + 50 && this.getY()+10 >= enemyTank.getY() + 10 && this.getY()+10 <= enemyTank.getY() + 50) {
                            return true;
                        }
                        //3.当前坦克左下角的坐标[this.getX()-10, this.getY()+50]
                        if (this.getX() -10 >= enemyTank.getX() - 10 && this.getX() -10 <= enemyTank.getX() + 50 && this.getY()+50 >= enemyTank.getY() + 10 && this.getY()+50 <= enemyTank.getY() + 50) {
                            return true;
                        }
                    }
                }
                break;
        }
        return false;
    }

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

    @Override
    public void run() {
        while (true) {

            //这里我们判断如果shots size() =0,创建一颗子弹,放入到
            //shots集合,并启动
            if (isLive && shots.size() <= 5) {//敌人同时只能存在五个子弹
                Shot s = null;
                switch (getDirect()) {
                    case 0://上
                        s = new Shot(getX() + 20, getY(), 0);
                        break;
                    case 1://右边
                        s = new Shot(getX() + 50, getY() + 30, 1);
                        break;
                    case 2:
                        s = new Shot(getX() + 20, getY() + 60, 2);
                        break;
                    case 3:
                        s = new Shot(getX() - 10, getY() + 30, 3);
                        break;
                }
                shots.add(s);
                new Thread(s).start();
            }

            //根据坦克方向继续移动
            for (int i = 0; i < 30; i++) {
                if (isTouchEnemyTank()){//如果有碰撞
                    continue;
                }
                    switch (getDirect()) {
                        case 0://向上
                            //让坦克保持一个方向,走30步
                            moveUp();
                            break;
                        case 1://向右
                            moveRight();
                            break;
                        case 2://向下
                            moveDown();
                            break;
                        case 3://向左
                            moveLeft();
                            break;
                    }

                //休眠50毫秒
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //然后随机的改变坦克方向 0-3
            setDirect((int) (Math.random() * 4));
            if (!isLive) {
                break;
            }
        }
    }
}

Shot

package tankgame06;
//射击事件
public class Shot implements Runnable {
    private int x;
    private int y;
    private int direct;//方向 0上 1右 2下 3左
    private int speed = 10;//子弹速度
    boolean isAlive = true;

    public Shot(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;
    }

    @Override
    public void run() {
        while (true) {
            //休眠
            try {
                Thread.sleep(100);
            } catch (InterruptedException 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;
            }
//            System.out.println("子弹坐标(" + x + "," + y + ")");
            //当子弹移动到面板的边界时,就应该销毁(把启动的子弹的线程销毁)
            // 当子弹碰到敌人坦克时,也应该结束线程
            if (x < 0 || x >= 1000 || y < 0 || y >= 750 || isAlive == false) {
//                System.out.println("子弹线程退出");
                isAlive = false;
                break;
            }
        }
    }
}

Bomb

package tankgame06;
//爆炸事件

public class Bomb {
    int x, y;//炸弹的坐标
    int life = 9;//炸弹的生命周期
    boolean isLive = true;//是否还存活

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

    //减少爆炸效果的生命值
    public void lifeDown() {//配合出现图片的爆炸效果
        if (life > 0) {
            life--;
        } else {
            isLive = false;
        }
    }
}

Record

package tankgame06;
//记录信息,与文件交互

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

public class Recorder {
    //定义变量,记录我方击毁敌人坦克数
    private static int allEnemyTankNum = 0;//定义IO对象,准备写数据到文件中
    //    private static BufferedWriter bw = null;
    private static String recordFile = "d:\\myRecord.txt";

    //保存游戏数据
    //对keepRecord进行升级,保存敌人坦克的坐标和方向
    public static void keepRecord() {
        BufferedWriter bw = null;
        try {
            bw = new BufferedWriter(new FileWriter(recordFile));
            bw.write(allEnemyTankNum + "\n");
            Vector<EnemyTank> enemyTanks = EnemyTank.enemyTanks;
            for (int i = 0; i < enemyTanks.size(); i++) {
                EnemyTank enemyTank = enemyTanks.get(i);
                if (enemyTank.isLive) {
                    String record = enemyTank.getX() + " " + enemyTank.getY() + " " + enemyTank.getDirect();
                    bw.write(record + "\n");
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bw != null) {
                    bw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //读取文件数据
    public static void loadRecord() {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(recordFile));
            allEnemyTankNum = Integer.parseInt(br.readLine());
            String line = null;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
                String[] s = line.split(" ");
                EnemyTank enemyTank = new EnemyTank(Integer.parseInt(s[0]), Integer.parseInt(s[1]));
                enemyTank.setDirect(Integer.parseInt(s[2]));
                EnemyTank.enemyTanks.add(enemyTank);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static int getAllEnemyTankNum() {
        return allEnemyTankNum;
    }

    public static void setAllEnemyTankNum(int allEnemyTankNum) {
        Recorder.allEnemyTankNum = allEnemyTankNum;
    }

    //当我方坦克击毁一个敌人坦克,就应当allEnemyTankNum++
    public static void addAllEnemyTankNum() {
        Recorder.allEnemyTankNum++;
    }
}

MyPanel

package tankgame06;
//面板

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

////为了监听键盘事件,实现KeyListener
//为了让Panel不停的重绘子弹,需要将MyPanel实现Runnable ,当做一个线程使用
public class MyPanel extends JPanel implements KeyListener, Runnable {
    Hero hero = null;//定义我的坦克
    Vector<EnemyTank> enemyTanks = new Vector<>();//定义敌人坦克
    //定义一个Vector ,用于存放多个爆炸效果
    //说明,当子弹击中坦克时,加入一个Bomb对象到bombs
    Vector<Bomb> bombs = new Vector<>();
    int enemyTankSize = 5;//敌方坦克数量

    //定义三张炸弹图片,用于显示爆炸效果
    Image image1 = null;
    Image image2 = null;
    Image image3 = null;

    public MyPanel(int key) {
        hero = new Hero(800, 100);//初始化自己的坦克位置
        switch (key){
            case 1:
                Recorder.loadRecord();
                enemyTanks = EnemyTank.enemyTanks;
                for (int i = 0; i < enemyTanks.size(); i++) {//初始化敌人的坦克位置
                    EnemyTank enemyTank = enemyTanks.get(i);
                    //启动敌人坦克线程,让他们动起来
                    new Thread(enemyTank).start();
                }
                break;
            case 2:
                for (int i = 0; i < enemyTankSize; i++) {//初始化敌人的坦克位置
                    EnemyTank enemyTank = new EnemyTank(100 * (i + 1), 0);
                    enemyTank.setDirect(2);//设置坦克方向
                    //启动敌人坦克线程,让他们动起来
                    new Thread(enemyTank).start();
                    enemyTanks.add(enemyTank);//加入敌方坦克集合
                }
                EnemyTank.setEnemyTanks(enemyTanks);//将enemyTanks 设置给enemyTank !!!
                break;
        }
//        hero.setSpeed(5);
        image1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/(1).png"));
        image2 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/(2).png"));
        image3 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/(3).png"));

        //图片在被第一次使用时才真正加载
        // 所以会出现第一次爆炸的图程序找不到还没加载好图片导致这次爆炸效果缺失的情况。
        //因此要提前自定义爆炸一次
//        bombs.add(new Bomb(-100,-100));
    }

    public void showInfo(Graphics g) {
        g.setColor(Color.BLACK);
        Font font = new Font("宋体", Font.BOLD, 25);
        g.setFont(font);
        g.drawString("累积击毁坦克", 1020, 30);

        drawTank(1020, 60, g, 0, 1);

        g.setColor(Color.BLACK);
        g.drawString(Recorder.getAllEnemyTankNum() + "", 1080, 100);

    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);

        g.fillRect(0, 0, 1000, 750);//黑色背景
        showInfo(g);
        if (hero != null && hero.isLive) {//画出hero坦克
            drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 0);
        }

        //画出hero发出的子弹
//        if (hero.shot != null && hero.shot.isAlive == true) {
//            g.fill3DRect(hero.shot.getX() - 1, hero.shot.getY() - 1, 3, 3, false);
//        }
        //将hero的子弹集合shots ,遍历取出绘制
        for (int i = 0; i < hero.shots.size(); i++) {
            Shot shot = hero.shots.get(i);
            if (shot != null && shot.isAlive) {
                g.fill3DRect(shot.getX() - 1, shot.getY() - 1, 3, 3, false);
            } else {//如果该shot对象已经无效,就从shots集合中拿掉
                hero.shots.remove(shot);
            }
        }

        for (int i = 0; i < bombs.size(); i++) {
            //取出炸弹
            Bomb bomb = bombs.get(i);
            //根据当前这个bomb对象的life值去画出对应的图片
            if (bomb.life > 6) {
                g.drawImage(image1, bomb.x, bomb.y, 60, 60, this);
            } else if (bomb.life > 3) {
                g.drawImage(image2, bomb.x, bomb.y, 60, 60, this);
            } else {
                g.drawImage(image3, bomb.x, bomb.y, 60, 60, this);
            }
            //让这个炸弹的生命值减少
            bomb.lifeDown();
            //如果bomb life为0,就从bombs 的集合中删除
            if (bomb.life <= 0) {
                bombs.remove(bomb);
            }
        }

        //画出敌人坦克
        for (int i = 0; i < enemyTanks.size(); i++) {
            //取出坦克
            EnemyTank enemyTank = enemyTanks.get(i);
            if (enemyTank.isLive) {//判断敌方坦克是否存活
                drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 1);
                //画出 enemyTank所有子弹
                for (int j = 0; j < enemyTank.shots.size(); j++) {
                    //取出子弹
                    Shot shot = enemyTank.shots.get(j);//绘制
                    if (shot.isAlive) { //isAlive = true
                        g.draw3DRect(shot.getX() - 1, shot.getY() - 1, 3, 3, false);
                    } else {
                        //从Vector移除
                        enemyTank.shots.remove(shot);
                    }
                }
            }
        }
    }

    /**
     * @param x      坦克左上角x坐标
     * @param y      坦克左上角y坐标
     * @param g      画笔
     * @param direct 坦克方向(上下左右)
     * @param type   坦克类型
     */
    public void drawTank(int x, int y, Graphics g, int direct, int type) {

        switch (type) {
            case 0://我们的坦克
                g.setColor(Color.cyan);
                break;
            case 1://敌人的坦克
                g.setColor(Color.yellow);
                break;
        }
        //根据坦克方向,绘制坦克
        switch (direct) {
            case 0://向上
                g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子
                g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子
                g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克盖子
                g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子
                g.drawLine(x + 20, y + 30, x + 20, y);//画出炮筒
                break;
            case 1://右
                g.fill3DRect(x - 10, y + 10, 60, 10, false);//画出坦克左边轮子
                g.fill3DRect(x - 10, y + 40, 60, 10, false);//画出坦克右边轮子
                g.fill3DRect(x, y + 20, 40, 20, false);//画出坦克盖子
                g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子
                g.drawLine(x + 20, y + 30, x + 50, y + 30);//画出炮筒
                break;
            case 2://下
                g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子
                g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子
                g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克盖子
                g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子
                g.drawLine(x + 20, y + 30, x + 20, y + 60);//画出炮筒
                break;
            case 3://左
                g.fill3DRect(x - 10, y + 10, 60, 10, false);//画出坦克左边轮子
                g.fill3DRect(x - 10, y + 40, 60, 10, false);//画出坦克右边轮子
                g.fill3DRect(x, y + 20, 40, 20, false);//画出坦克盖子
                g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子
                g.drawLine(x + 20, y + 30, x - 10, y + 30);//画出炮筒
                break;
        }

    }

    //如果我们的坦克可以发射多个子弹
    //在判断我方子弹是否击中敌人坦克时,就需要把我们的子弹集合中
    //所有的子弹,都取出和敌人的所有坦克,进行判断
    public void hitEnemyTank() {
        //遍历我们的子弹
        for (int j = 0; j < hero.shots.size(); j++) {
            Shot shot = hero.shots.get(j);
            if (shot != null && shot.isAlive) {
                //遍历敌人所有坦克,实时判断坦克是否被击中
                for (int i = 0; i < enemyTanks.size(); i++) {
                    EnemyTank enemyTank = enemyTanks.get(i);
                    hitTank(shot, enemyTank);
                }
            }
        }
    }

    //编写方法,判断我子弹是否击中对方坦克
    //什么时候判断我方的子弹是否击中对方坦克 ?run方法
    //enemyTank可以是Hero,可以是EnemyTank
    public void hitTank(Shot s, Tank enemyTank) {
        switch (enemyTank.getDirect()) {
            case 0://上
            case 2://下
                if (s.getX() > enemyTank.getX() && s.getX() < enemyTank.getX() + 40 &&
                        s.getY() > enemyTank.getY() && s.getY() < enemyTank.getY() + 60) {
                    s.isAlive = false;//设置子弹为死亡状态
                    enemyTank.isLive = false;//设置该坦克为死亡状态
                    //创建Bomb对象,加入到bombs集合
                    Bomb bomb = new Bomb(enemyTank.getX() - 10, enemyTank.getY());
                    bombs.add(bomb);
                    //当我的子弹击中敌人坦克后,将enemyTank 从lector拿掉
                    enemyTanks.remove(enemyTank);//移除该坦克

                    if (enemyTank instanceof EnemyTank) {
                        Recorder.addAllEnemyTankNum();//增加摧毁坦克数量
                    }
                }
                break;
            case 1:
            case 3:
                if (s.getX() > enemyTank.getX() - 10 && s.getX() < enemyTank.getX() + 50 &&
                        s.getY() > enemyTank.getY() + 10 && s.getY() < enemyTank.getY() + 50) {
                    s.isAlive = false;
                    enemyTank.isLive = false;
                    //创建Bomb对象,加入到bombs集合
                    Bomb bomb = new Bomb(enemyTank.getX() - 10, enemyTank.getY());
                    bombs.add(bomb);
                    //当我的子弹击中敌人坦克后,将enemyTank 从lector拿掉
                    enemyTanks.remove(enemyTank);//移除该坦克

                    if (enemyTank instanceof EnemyTank) {
                        Recorder.addAllEnemyTankNum();//增加摧毁坦克数量
                    }
                }
                break;
        }
    }

    //判断敌方的子弹是否击中我方坦克
    public void hitHeroTank() {
        //遍历敌方子弹
        for (int i = 0; i < enemyTanks.size(); i++) {
            EnemyTank enemyTank = enemyTanks.get(i);
            for (int j = 0; j < enemyTank.shots.size(); j++) {
                Shot shot = enemyTank.shots.get(j);
                hitTank(shot, hero);
            }
        }
    }


    @Override
    public void keyTyped(KeyEvent e) {
    }

    //处理WDSA键按下情况
    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_W) {
            //改变坦克方向
            hero.setDirect(0);
            //修改坦克坐标
            hero.moveUp();
        } else if (e.getKeyCode() == KeyEvent.VK_D) {
            hero.setDirect(1);
            hero.moveRight();
        } else if (e.getKeyCode() == KeyEvent.VK_S) {
            hero.setDirect(2);
            hero.moveDown();
        } else if (e.getKeyCode() == KeyEvent.VK_A) {
            hero.setDirect(3);
            hero.moveLeft();
        }

        if (e.getKeyCode() == KeyEvent.VK_J) {
            //判断hero的子弹是否销毁,发射一颗子弹
//            if (hero.shot == null || !hero.shot.isAlive) {
//                hero.shotEnemyTank();
//            }
            //发射多颗子弹
            hero.shotEnemyTank();
        }
//        this.repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(100);//每停0.1s执行一次
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            hitEnemyTank();//检测子弹是否打中坦克
            hitHeroTank();
            this.repaint();//刷新面板

        }
    }
}

HspTankGame06

package tankgame06;
//窗体

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

public class HspTankGame06 extends JFrame {
    MyPanel mp=null;
    public static void main(String[] args) {
        new HspTankGame06();
    }

    public HspTankGame06() {
        Scanner in = new Scanner(System.in);
        int key;
        while (true){
            System.out.println("是否继续游戏?(1.是 2.否)");
            String s = in.next();
            key = Integer.parseInt(s);
            if (key==1||key==2){
                break;
            }
        }
        mp=new MyPanel(key);
        new Thread(mp).start();//另外开一线程一直刷新面板内容和面板中一些需要同时执行的程序
        this.add(mp);
        this.setSize(1200,789);
        this.addKeyListener(mp);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);

        //在JFrame中增加相应关闭窗口的处理
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                Recorder.keepRecord();
            }
        });
    }
}

坦克大战0.7版

增加功能

  1. 游戏开始时,播放经典的坦克大战音乐(AePlayWave.java此类可直接使用成品,不自己写)(需要准备wav格式音乐文件)

  2. 修正下文件存储位置(保存到src目录下)

  3. 处理文件相关异常=》提升程序健壮性(处理读取游戏信息文件不存在出现的异常)

代码

Tank

package tankgame07;

//坦克
public class Tank {
    //坦克左上角坐标
    private int x;
    private int y;
    private int direct;//坦克方向 0上 1右 2下 3左
    boolean isLive = true;//是否存活

    public int getSpeed() {
        return speed;
    }

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

    private int speed = 2;//坦克速度

    //上右下左移动方法
    public void moveUp() {
        if (y - speed > 0) {
            y -= speed;
        }
    }

    public void moveDown() {
        if (y + 60 + speed < 750) {
            y += speed;
        }
    }

    public void moveLeft() {
        if (x - 10 - speed > 0) {
            x -= speed;
        }
    }

    public void moveRight() {
        if (x - 10 + 60 + speed < 1000) {
            x += speed;
        }
    }

    public int getDirect() {
        return direct;
    }

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

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

Hero

package tankgame07;

import java.util.Vector;

//玩家坦克
public class Hero extends Tank {
    Shot shot = null;//射击行为
    //发射多个子弹
    Vector<Shot> shots = new Vector<>();

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

    //射击
    public void shotEnemyTank() {

        //发多颗子弹怎么办,控制在我们的面板上,最多只有5颗
        if (shots.size()==5){
            return;
        }
        switch (getDirect()) {
            case 0://上
                shot = new Shot(getX() + 20, getY(), 0);
                break;
            case 1://右边
                shot = new Shot(getX() + 50, getY() + 30, 1);
                break;
            case 2:
                shot = new Shot(getX() + 20, getY() + 60, 2);
                break;
            case 3:
                shot = new Shot(getX() - 10, getY() + 30, 3);
                break;
        }
        //把新创建的shot放入到shots
        shots.add(shot);
        //启动我们的Shot线程
        new Thread(shot).start();
    }
}

EnemyTank

package tankgame07;

import java.util.Vector;

//敌方坦克
public class EnemyTank extends Tank implements Runnable {
    //在敌人坦克类,使用Vector保存多个Shot
    Vector<Shot> shots = new Vector<>();
    static Vector<EnemyTank> enemyTanks = new Vector<>();//存放所有敌人坦克信息


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

    //编写方法,判断当前的这个敌人坦克,是否和 enemyTanks 中的其他坦克发生的重叠或者碰撞
    public boolean isTouchEnemyTank() {
        switch (this.getDirect()) {
            case 0:
                //让当前敌人坦克和其它所有的敌人坦克比较
                for (int i = 0; i < enemyTanks.size(); i++) {
                    //从vector中取出一个敌人坦克
                    EnemyTank enemyTank = enemyTanks.get(i);
                    //不和自己比较
                    if (enemyTank == this) {
                        continue;
                    }
                    //1.如果敌人坦克是上/下x的范围[enemyTank.getX(),enemyTank.getX() +40]
                    //                  y的范围 [enemyTank.getY(),enemyTank.getY() +60]
                    if (enemyTank.getDirect() == 0 || enemyTank.getDirect() == 2) {
                        //2。当前坦克左上角的坐标[this.getX(),this.getY()]
                        if (this.getX() >= enemyTank.getX() && this.getX() <= enemyTank.getX() + 40 && this.getY() >= enemyTank.getY() && this.getY() <= enemyTank.getY() + 60) {
                            return true;
                        }
                        //3.当前坦克右上角的坐标[this.getX() +40, this.getY()]
                        if (this.getX() + 40 >= enemyTank.getX() && this.getX() + 40 <= enemyTank.getX() + 40 && this.getY() >= enemyTank.getY() && this.getY() <= enemyTank.getY() + 60) {
                            return true;
                        }

                    }
                    //如果敌人坦克是 右/左
                    if (enemyTank.getDirect() == 1 || enemyTank.getDirect() == 3) {
                        //2。当前坦克左上角的坐标[this.getX(),this.getY()]
                        if (this.getX() >= enemyTank.getX() - 10 && this.getX() <= enemyTank.getX() + 50 && this.getY() >= enemyTank.getY() + 10 && this.getY() <= enemyTank.getY() + 50) {
                            return true;
                        }
                        //3.当前坦克右上角的坐标[this.getX() +40, this.getY()]
                        if (this.getX() + 40 >= enemyTank.getX() - 10 && this.getX() + 40 <= enemyTank.getX() + 50 && this.getY() >= enemyTank.getY() + 10 && this.getY() <= enemyTank.getY() + 50) {
                            return true;
                        }
                    }
                }
                break;
            case 1:
                //让当前敌人坦克和其它所有的敌人坦克比较
                for (int i = 0; i < enemyTanks.size(); i++) {
                    //从vector中取出一个敌人坦克
                    EnemyTank enemyTank = enemyTanks.get(i);
                    //不和自己比较
                    if (enemyTank == this) {
                        continue;
                    }
                    //1.如果敌人坦克是上/下
                    if (enemyTank.getDirect() == 0 || enemyTank.getDirect() == 2) {
                        //2。当前坦克右上角的坐标[this.getX()+50,this.getY()+10]
                        if (this.getX()+50 >= enemyTank.getX() && this.getX()+50 <= enemyTank.getX() + 40 && this.getY()+10 >= enemyTank.getY() && this.getY()+10 <= enemyTank.getY() + 60) {
                            return true;
                        }
                        //3.当前坦克右下角的坐标[this.getX() +50, this.getY()+50]
                        if (this.getX() + 50 >= enemyTank.getX() && this.getX() + 50 <= enemyTank.getX() + 40 && this.getY()+50 >= enemyTank.getY() && this.getY()+50 <= enemyTank.getY() + 60) {
                            return true;
                        }

                    }
                    //如果敌人坦克是 右/左
                    if (enemyTank.getDirect() == 1 || enemyTank.getDirect() == 3) {
                        //2。当前坦克右上角的坐标[this.getX()+50,this.getY()+10]
                        if (this.getX()+50 >= enemyTank.getX() - 10 && this.getX()+50 <= enemyTank.getX() + 50 && this.getY()+10 >= enemyTank.getY() + 10 && this.getY()+10 <= enemyTank.getY() + 50) {
                            return true;
                        }
                        //3.当前坦克右下角的坐标[this.getX() +50, this.getY()+50]
                        if (this.getX() + 50 >= enemyTank.getX() - 10 && this.getX() + 50 <= enemyTank.getX() + 50 && this.getY()+50 >= enemyTank.getY() + 10 && this.getY()+50 <= enemyTank.getY() + 50) {
                            return true;
                        }
                    }
                }
                break;
            case 2:
                //让当前敌人坦克和其它所有的敌人坦克比较
                for (int i = 0; i < enemyTanks.size(); i++) {
                    //从vector中取出一个敌人坦克
                    EnemyTank enemyTank = enemyTanks.get(i);
                    //不和自己比较
                    if (enemyTank == this) {
                        continue;
                    }
                    if (enemyTank.getDirect() == 0 || enemyTank.getDirect() == 2) {
                        //2。当前坦克左下角的坐标[this.getX(),this.getY()+60]
                        if (this.getX() >= enemyTank.getX() && this.getX() <= enemyTank.getX() + 40 && this.getY()+60 >= enemyTank.getY() && this.getY()+60 <= enemyTank.getY() + 60) {
                            return true;
                        }
                        //3.当前坦克右下角的坐标[this.getX() +40, this.getY()+60]
                        if (this.getX() + 40 >= enemyTank.getX() && this.getX() + 40 <= enemyTank.getX() + 40 && this.getY()+60 >= enemyTank.getY() && this.getY()+60 <= enemyTank.getY() + 60) {
                            return true;
                        }

                    }
                    //如果敌人坦克是 右/左
                    if (enemyTank.getDirect() == 1 || enemyTank.getDirect() == 3) {
                        //2。当前坦克左下角的坐标[this.getX(),this.getY()+60]
                        if (this.getX() >= enemyTank.getX() - 10 && this.getX() <= enemyTank.getX() + 50 && this.getY()+60 >= enemyTank.getY() + 10 && this.getY()+60 <= enemyTank.getY() + 50) {
                            return true;
                        }
                        //3.当前坦克右下角的坐标[this.getX() +40, this.getY()+60]
                        if (this.getX() + 40 >= enemyTank.getX() - 10 && this.getX() + 40 <= enemyTank.getX() + 50 && this.getY()+60 >= enemyTank.getY() + 10 && this.getY()+60 <= enemyTank.getY() + 50) {
                            return true;
                        }
                    }
                }
                break;
            case 3:
                //让当前敌人坦克和其它所有的敌人坦克比较
                for (int i = 0; i < enemyTanks.size(); i++) {
                    //从vector中取出一个敌人坦克
                    EnemyTank enemyTank = enemyTanks.get(i);
                    //不和自己比较
                    if (enemyTank == this) {
                        continue;
                    }
                    //1.如果敌人坦克是上/下
                    if (enemyTank.getDirect() == 0 || enemyTank.getDirect() == 2) {
                        //2。当前坦克左上角的坐标[this.getX()-10,this.getY()+10]
                        if (this.getX()-10 >= enemyTank.getX() && this.getX()-10 <= enemyTank.getX() + 40 && this.getY()+10 >= enemyTank.getY() && this.getY()+10 <= enemyTank.getY() + 60) {
                            return true;
                        }
                        //3.当前坦克左下角的坐标[this.getX()-10, this.getY()+50]
                        if (this.getX() -10 >= enemyTank.getX() && this.getX() -10 <= enemyTank.getX() + 40 && this.getY()+50 >= enemyTank.getY() && this.getY()+50 <= enemyTank.getY() + 60) {
                            return true;
                        }

                    }
                    //如果敌人坦克是 右/左
                    if (enemyTank.getDirect() == 1 || enemyTank.getDirect() == 3) {
                        //2。当前坦克左上角的坐标[this.getX()-10,this.getY()+10]
                        if (this.getX()-10 >= enemyTank.getX() - 10 && this.getX()-10 <= enemyTank.getX() + 50 && this.getY()+10 >= enemyTank.getY() + 10 && this.getY()+10 <= enemyTank.getY() + 50) {
                            return true;
                        }
                        //3.当前坦克左下角的坐标[this.getX()-10, this.getY()+50]
                        if (this.getX() -10 >= enemyTank.getX() - 10 && this.getX() -10 <= enemyTank.getX() + 50 && this.getY()+50 >= enemyTank.getY() + 10 && this.getY()+50 <= enemyTank.getY() + 50) {
                            return true;
                        }
                    }
                }
                break;
        }
        return false;
    }

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

    @Override
    public void run() {
        while (true) {

            //这里我们判断如果shots size() =0,创建一颗子弹,放入到
            //shots集合,并启动
            if (isLive && shots.size() <= 5) {//敌人同时只能存在五个子弹
                Shot s = null;
                switch (getDirect()) {
                    case 0://上
                        s = new Shot(getX() + 20, getY(), 0);
                        break;
                    case 1://右边
                        s = new Shot(getX() + 50, getY() + 30, 1);
                        break;
                    case 2:
                        s = new Shot(getX() + 20, getY() + 60, 2);
                        break;
                    case 3:
                        s = new Shot(getX() - 10, getY() + 30, 3);
                        break;
                }
                shots.add(s);
                new Thread(s).start();
            }

            //根据坦克方向继续移动
            for (int i = 0; i < 30; i++) {
                if (isTouchEnemyTank()){//如果有碰撞
                    continue;
                }
                    switch (getDirect()) {
                        case 0://向上
                            //让坦克保持一个方向,走30步
                            moveUp();
                            break;
                        case 1://向右
                            moveRight();
                            break;
                        case 2://向下
                            moveDown();
                            break;
                        case 3://向左
                            moveLeft();
                            break;
                    }

                //休眠50毫秒
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //然后随机的改变坦克方向 0-3
            setDirect((int) (Math.random() * 4));
            if (!isLive) {
                break;
            }
        }
    }
}

Shot

package tankgame07;
//射击事件
public class Shot implements Runnable {
    private int x;
    private int y;
    private int direct;//方向 0上 1右 2下 3左
    private int speed = 10;//子弹速度
    boolean isAlive = true;

    public Shot(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;
    }

    @Override
    public void run() {
        while (true) {
            //休眠
            try {
                Thread.sleep(100);
            } catch (InterruptedException 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;
            }
//            System.out.println("子弹坐标(" + x + "," + y + ")");
            //当子弹移动到面板的边界时,就应该销毁(把启动的子弹的线程销毁)
            // 当子弹碰到敌人坦克时,也应该结束线程
            if (x < 0 || x >= 1000 || y < 0 || y >= 750 || isAlive == false) {
//                System.out.println("子弹线程退出");
                isAlive = false;
                break;
            }
        }
    }
}

Bomb

package tankgame07;
//爆炸事件

public class Bomb {
    int x, y;//炸弹的坐标
    int life = 9;//炸弹的生命周期
    boolean isLive = true;//是否还存活

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

    //减少爆炸效果的生命值
    public void lifeDown() {//配合出现图片的爆炸效果
        if (life > 0) {
            life--;
        } else {
            isLive = false;
        }
    }
}

Recorder

package tankgame07;
//记录信息,与文件交互

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

public class Recorder {
    //定义变量,记录我方击毁敌人坦克数
    private static int allEnemyTankNum = 0;//定义IO对象,准备写数据到文件中
    //    private static BufferedWriter bw = null;
    private static String recordFile = "src\\myRecord.txt";

    public static String getRecordFile() {
        return recordFile;
    }

    //保存游戏数据
    //对keepRecord进行升级,保存敌人坦克的坐标和方向
    public static void keepRecord() {
        BufferedWriter bw = null;
        try {
            bw = new BufferedWriter(new FileWriter(recordFile));
            bw.write(allEnemyTankNum + "\n");
            Vector<EnemyTank> enemyTanks = EnemyTank.enemyTanks;
            for (int i = 0; i < enemyTanks.size(); i++) {
                EnemyTank enemyTank = enemyTanks.get(i);
                if (enemyTank.isLive) {
                    String record = enemyTank.getX() + " " + enemyTank.getY() + " " + enemyTank.getDirect();
                    bw.write(record + "\n");
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bw != null) {
                    bw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //读取文件数据
    public static void loadRecord() {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(recordFile));
            allEnemyTankNum = Integer.parseInt(br.readLine());
            String line = null;
            while ((line = br.readLine()) != null) {
                String[] s = line.split(" ");
                EnemyTank enemyTank = new EnemyTank(Integer.parseInt(s[0]), Integer.parseInt(s[1]));
                enemyTank.setDirect(Integer.parseInt(s[2]));
                EnemyTank.enemyTanks.add(enemyTank);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static int getAllEnemyTankNum() {
        return allEnemyTankNum;
    }

    public static void setAllEnemyTankNum(int allEnemyTankNum) {
        Recorder.allEnemyTankNum = allEnemyTankNum;
    }

    //当我方坦克击毁一个敌人坦克,就应当allEnemyTankNum++
    public static void addAllEnemyTankNum() {
        Recorder.allEnemyTankNum++;
    }
}

MyPanel

package tankgame07;
//面板

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

////为了监听键盘事件,实现KeyListener
//为了让Panel不停的重绘子弹,需要将MyPanel实现Runnable ,当做一个线程使用
public class MyPanel extends JPanel implements KeyListener, Runnable {
    Hero hero = null;//定义我的坦克
    Vector<EnemyTank> enemyTanks = new Vector<>();//定义敌人坦克
    //定义一个Vector ,用于存放多个爆炸效果
    //说明,当子弹击中坦克时,加入一个Bomb对象到bombs
    Vector<Bomb> bombs = new Vector<>();
    int enemyTankSize = 5;//敌方最开始坦克数量

    //定义三张炸弹图片,用于显示爆炸效果
    Image image1 = null;
    Image image2 = null;
    Image image3 = null;

    public MyPanel(int key) {
        hero = new Hero(800, 100);//初始化自己的坦克位置

        //判断游戏信息文件是否存在
        File file = new File(Recorder.getRecordFile());
        if (!file.exists()) {
            System.out.println("文件不存在");
            key = 2;
        }
        switch (key) {
            case 1:
                Recorder.loadRecord();
                enemyTanks = EnemyTank.enemyTanks;
                for (int i = 0; i < enemyTanks.size(); i++) {//初始化敌人的坦克位置
                    EnemyTank enemyTank = enemyTanks.get(i);
                    //启动敌人坦克线程,让他们动起来
                    new Thread(enemyTank).start();
                }
                break;
            case 2:
                for (int i = 0; i < enemyTankSize; i++) {//初始化敌人的坦克位置
                    EnemyTank enemyTank = new EnemyTank(100 * (i + 1), 0);
                    enemyTank.setDirect(2);//设置坦克方向
                    //启动敌人坦克线程,让他们动起来
                    new Thread(enemyTank).start();
                    enemyTanks.add(enemyTank);//加入敌方坦克集合
                }
                EnemyTank.setEnemyTanks(enemyTanks);//将enemyTanks 设置给enemyTank !!!
                break;
        }
//        hero.setSpeed(5);
        image1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/(1).png"));
        image2 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/(2).png"));
        image3 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/(3).png"));

        //播放音乐
        new AePlayWave("src/坦克大战_BGM.wav").start();
    }

    public void showInfo(Graphics g) {
        g.setColor(Color.BLACK);
        Font font = new Font("宋体", Font.BOLD, 25);
        g.setFont(font);
        g.drawString("累积击毁坦克", 1020, 30);

        drawTank(1020, 60, g, 0, 1);

        g.setColor(Color.BLACK);
        g.drawString(Recorder.getAllEnemyTankNum() + "", 1080, 100);

    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);

        g.fillRect(0, 0, 1000, 750);//黑色背景
        showInfo(g);
        if (hero != null && hero.isLive) {//画出hero坦克
            drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 0);
        }

        //画出hero发出的子弹
//        if (hero.shot != null && hero.shot.isAlive == true) {
//            g.fill3DRect(hero.shot.getX() - 1, hero.shot.getY() - 1, 3, 3, false);
//        }
        //将hero的子弹集合shots ,遍历取出绘制
        for (int i = 0; i < hero.shots.size(); i++) {
            Shot shot = hero.shots.get(i);
            if (shot != null && shot.isAlive) {
                g.fill3DRect(shot.getX() - 1, shot.getY() - 1, 3, 3, false);
            } else {//如果该shot对象已经无效,就从shots集合中拿掉
                hero.shots.remove(shot);
            }
        }

        for (int i = 0; i < bombs.size(); i++) {
            //取出炸弹
            Bomb bomb = bombs.get(i);
            //根据当前这个bomb对象的life值去画出对应的图片
            if (bomb.life > 6) {
                g.drawImage(image1, bomb.x, bomb.y, 60, 60, this);
            } else if (bomb.life > 3) {
                g.drawImage(image2, bomb.x, bomb.y, 60, 60, this);
            } else {
                g.drawImage(image3, bomb.x, bomb.y, 60, 60, this);
            }
            //让这个炸弹的生命值减少
            bomb.lifeDown();
            //如果bomb life为0,就从bombs 的集合中删除
            if (bomb.life <= 0) {
                bombs.remove(bomb);
            }
        }

        //画出敌人坦克
        for (int i = 0; i < enemyTanks.size(); i++) {
            //取出坦克
            EnemyTank enemyTank = enemyTanks.get(i);
            if (enemyTank.isLive) {//判断敌方坦克是否存活
                drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 1);
                //画出 enemyTank所有子弹
                for (int j = 0; j < enemyTank.shots.size(); j++) {
                    //取出子弹
                    Shot shot = enemyTank.shots.get(j);//绘制
                    if (shot.isAlive) { //isAlive = true
                        g.draw3DRect(shot.getX() - 1, shot.getY() - 1, 3, 3, false);
                    } else {
                        //从Vector移除
                        enemyTank.shots.remove(shot);
                    }
                }
            }
        }
    }

    /**
     * @param x      坦克左上角x坐标
     * @param y      坦克左上角y坐标
     * @param g      画笔
     * @param direct 坦克方向(上下左右)
     * @param type   坦克类型
     */
    public void drawTank(int x, int y, Graphics g, int direct, int type) {

        switch (type) {
            case 0://我们的坦克
                g.setColor(Color.cyan);
                break;
            case 1://敌人的坦克
                g.setColor(Color.yellow);
                break;
        }
        //根据坦克方向,绘制坦克
        switch (direct) {
            case 0://向上
                g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子
                g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子
                g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克盖子
                g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子
                g.drawLine(x + 20, y + 30, x + 20, y);//画出炮筒
                break;
            case 1://右
                g.fill3DRect(x - 10, y + 10, 60, 10, false);//画出坦克左边轮子
                g.fill3DRect(x - 10, y + 40, 60, 10, false);//画出坦克右边轮子
                g.fill3DRect(x, y + 20, 40, 20, false);//画出坦克盖子
                g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子
                g.drawLine(x + 20, y + 30, x + 50, y + 30);//画出炮筒
                break;
            case 2://下
                g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子
                g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子
                g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克盖子
                g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子
                g.drawLine(x + 20, y + 30, x + 20, y + 60);//画出炮筒
                break;
            case 3://左
                g.fill3DRect(x - 10, y + 10, 60, 10, false);//画出坦克左边轮子
                g.fill3DRect(x - 10, y + 40, 60, 10, false);//画出坦克右边轮子
                g.fill3DRect(x, y + 20, 40, 20, false);//画出坦克盖子
                g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子
                g.drawLine(x + 20, y + 30, x - 10, y + 30);//画出炮筒
                break;
        }

    }

    //如果我们的坦克可以发射多个子弹
    //在判断我方子弹是否击中敌人坦克时,就需要把我们的子弹集合中
    //所有的子弹,都取出和敌人的所有坦克,进行判断
    public void hitEnemyTank() {
        //遍历我们的子弹
        for (int j = 0; j < hero.shots.size(); j++) {
            Shot shot = hero.shots.get(j);
            if (shot != null && shot.isAlive) {
                //遍历敌人所有坦克,实时判断坦克是否被击中
                for (int i = 0; i < enemyTanks.size(); i++) {
                    EnemyTank enemyTank = enemyTanks.get(i);
                    hitTank(shot, enemyTank);
                }
            }
        }
    }

    //编写方法,判断我子弹是否击中对方坦克
    //什么时候判断我方的子弹是否击中对方坦克 ?run方法
    //enemyTank可以是Hero,可以是EnemyTank
    public void hitTank(Shot s, Tank enemyTank) {
        switch (enemyTank.getDirect()) {
            case 0://上
            case 2://下
                if (s.getX() > enemyTank.getX() && s.getX() < enemyTank.getX() + 40 &&
                        s.getY() > enemyTank.getY() && s.getY() < enemyTank.getY() + 60) {
                    s.isAlive = false;//设置子弹为死亡状态
                    enemyTank.isLive = false;//设置该坦克为死亡状态
                    //创建Bomb对象,加入到bombs集合
                    Bomb bomb = new Bomb(enemyTank.getX() - 10, enemyTank.getY());
                    bombs.add(bomb);
                    //当我的子弹击中敌人坦克后,将enemyTank 从lector拿掉
                    enemyTanks.remove(enemyTank);//移除该坦克

                    if (enemyTank instanceof EnemyTank) {
                        Recorder.addAllEnemyTankNum();//增加摧毁坦克数量
                    }
                }
                break;
            case 1:
            case 3:
                if (s.getX() > enemyTank.getX() - 10 && s.getX() < enemyTank.getX() + 50 &&
                        s.getY() > enemyTank.getY() + 10 && s.getY() < enemyTank.getY() + 50) {
                    s.isAlive = false;
                    enemyTank.isLive = false;
                    //创建Bomb对象,加入到bombs集合
                    Bomb bomb = new Bomb(enemyTank.getX() - 10, enemyTank.getY());
                    bombs.add(bomb);
                    //当我的子弹击中敌人坦克后,将enemyTank 从lector拿掉
                    enemyTanks.remove(enemyTank);//移除该坦克

                    if (enemyTank instanceof EnemyTank) {
                        Recorder.addAllEnemyTankNum();//增加摧毁坦克数量
                    }
                }
                break;
        }
    }

    //判断敌方的子弹是否击中我方坦克
    public void hitHeroTank() {
        //遍历敌方子弹
        for (int i = 0; i < enemyTanks.size(); i++) {
            EnemyTank enemyTank = enemyTanks.get(i);
            for (int j = 0; j < enemyTank.shots.size(); j++) {
                Shot shot = enemyTank.shots.get(j);
                hitTank(shot, hero);
            }
        }
    }


    @Override
    public void keyTyped(KeyEvent e) {
    }

    //处理WDSA键按下情况
    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_W) {
            //改变坦克方向
            hero.setDirect(0);
            //修改坦克坐标
            hero.moveUp();
        } else if (e.getKeyCode() == KeyEvent.VK_D) {
            hero.setDirect(1);
            hero.moveRight();
        } else if (e.getKeyCode() == KeyEvent.VK_S) {
            hero.setDirect(2);
            hero.moveDown();
        } else if (e.getKeyCode() == KeyEvent.VK_A) {
            hero.setDirect(3);
            hero.moveLeft();
        }

        if (e.getKeyCode() == KeyEvent.VK_J) {
            //判断hero的子弹是否销毁,发射一颗子弹
//            if (hero.shot == null || !hero.shot.isAlive) {
//                hero.shotEnemyTank();
//            }
            //发射多颗子弹
            hero.shotEnemyTank();
        }
//        this.repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(100);//每停0.1s执行一次
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            hitEnemyTank();//检测子弹是否打中坦克
            hitHeroTank();
            this.repaint();//刷新面板

        }
    }
}

HspTankGame07

package tankgame07;
//窗体

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

public class HspTankGame07 extends JFrame {
    MyPanel mp=null;
    public static void main(String[] args) {
        new HspTankGame07();
    }

    public HspTankGame07() {
        Scanner in = new Scanner(System.in);
        int key;
        while (true){
            System.out.println("是否继续游戏?(1.是 2.否)");
            String s = in.next();
            key = Integer.parseInt(s);
            if (key==1||key==2){
                break;
            }
        }
        mp=new MyPanel(key);
        new Thread(mp).start();//另外开一线程一直刷新面板内容和面板中一些需要同时执行的程序
        this.add(mp);
        this.setSize(1200,789);
        this.addKeyListener(mp);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);

        //在JFrame中增加相应关闭窗口的处理
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                Recorder.keepRecord();
            }
        });
    }
}

AePlayWave

package tankgame07;

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();
        }
    }
}
posted @ 2022-09-06 02:18  文杰2000  阅读(120)  评论(0编辑  收藏  举报