我所知道坦克大战(单机版)之添加多个机器坦克、让机器坦克动起来、让坦克智能起来

本章目的

  • 添加多个机器坦克
  • 让机器坦克动起来
  • 让坦克智能起来

一、添加多个机器坦克


目前我的坏阵营的坦克只有一个,是我们手动创建出来的

但是我们现在想要玩的过瘾,杀的痛快就要创建多个坦克,也需要使用一个容器管理起来

public class TankClient extends Frame {
    
    //管理多个坏坦克容器
    List tanklist = new ArrayList();
    
    @Override
    public void paint(Graphics g) {
        //省略其他关键性代码....
        //画出容器里的坦克
        for ( int i = 0; i < tanklist.size();i++){
            Tank tank = tanklist.get(i);
            tank.draw(g);
        }
        //画出 好的 坦克
        mytank.draw(g);
    }
    
    //定义窗口方法
    public void lauchFrame() {
        //省略其他关键性代码....
        //游戏窗口界面创建多个坦克
        //画出容器里的爆炸效果
        for ( int i = 0; i < 10;i++){
           tanklist.add(new Tank(50 + 40 * (i+1),50,this,false));
        }
    }
    //省略其他关键性代码....
}

这时我们就有十个敌方阵营的坦克了

image.png

但是我们还是要思考一个问题:我们发射的子弹怎么打中这些容器里的坦克呢?

class Missle{

    public boolean hitTank(List tankList){
        for(Tank tank:tankList){
            if(hitTank(tank)){
                return true;
            }
        }
        return false;
    }
     //省略其他关键性代码....
}

我们在子弹的类里添加对装放坦克集合类的处理,那么我们调用也要进行优化

public class TankClient extends Frame {
    
    //管理多个坏坦克容器
    List tanklist = new ArrayList();
    
    @Override
    public void paint(Graphics g) {
        //画出容器里的子弹
        for ( int i = 0; i < missles.size();i++){
            Missle m = missles.get(i);
            //由原先敌方坦克的处理
            //修改为对装放一堆坦克的容器处理
            m.hitTank(tanklist);
            m.draw(g);
        }
        //省略其他关键性代码....
    }
    //省略其他关键性代码....
}

这时我们就可以对十个敌方坦克一顿乱杀了,完成痛苦的体验

image.png

当我们击毙敌方坦克时,是不是同样也要与子弹、爆炸效果一样,需要移出容器里?

class Tank{

    //省略其他关键性代码....
    //添加方法完成坦克的绘画
    public void draw(Graphics g) {

        //死掉的坦克不用绘制
        if(!live){
            //如果是坏阵营的坦克则移出容器里
            if(!camp){tc.tanklist.remove(this);}
            return;
        }
        //省略其他关键性代码....
    }
}

步骤总结

  • ✧用容器来装敌人的Tank
  • ✧向容器中装入多辆敌人Tank
  • ✧游戏窗口将容器里的坦克画出来
  • ✧添加hitTanks方法处理打掉容器里的一系列Tank
  • ✧TankClient里面每发子弹都对坦克容器进行处理

二、让机器坦克动起来


我们发现这个敌方坦克虽然是出来了,但是他并没有动起来,只是被我们打而已

那么我们先考虑一下:怎么让这些敌方坦克动起来呢?

我们知道坦克是不是都有方向?

假如我们初始时不给予STOP方向,而给定其他方向,它能动起来吗?

class Tank{

    //省略其他关键性代码....
    //添加初始坦克时方向的给予
    public Tank(int x, int y, TankClient tc, boolean camp, Direction dir) {
        this.x = x;
        this.y = y;
        this.tc = tc;
        this.camp = camp;
        this.dir = dir;
    }
}

我们在TankClint中给予不同的初始方向看看,是否能动起来

public class TankClient extends Frame {
    
    //阵营:好的坦克初始方向不动
    Tank mytank = new Tank(50,50,this,true,Tank.Direction.STOP);
    
    //定义窗口方法
    public void lauchFrame() {
        //阵营坏的坦克初始方向为:下
        for ( int i = 0; i < 10;i++){
           tanklist.add(new Tank(50 + 40 * (i+1),50,this,false,Tank.Direction.D));
        }
        //省略其他关键性代码....
    }
    //省略其他关键性代码....
}

动起来了,但是我们发现敌方坦克的初始方向为:下后,则一直都是往下

image.png

那么我们能不能让他随机产生一些方向并进行移动呢?答案:随机数

class Tank{

    //随机数
    private static Random random = new Random();

    void move() {
        
        //针对于坏的坦克我们进行随机方向移动
        if(!camp){
            //将方向枚举转为数组
            Direction[] dirarr = Direction.values();
            //根据八个方向产生一个随机方向出来
            int rn = random.nextInt(dirarr.length);
            dir = dirarr[rn];
        }
        //省略其他关键性代码....
    }
    
    //省略其他关键性代码....
}

这时我们运行起游戏窗口就可以发现,敌方坦克已经可以根据随机方向动起来了

image.png

步骤总结

  • ✧让敌军坦克动起来:构造函数中可以指定方向
  • ✧游戏窗口new敌军坦克的时候指定敌军坦克的方向
  • ✧让敌军坦克向随机方向移动
  • ✧(Tank)类添加静态的随机数产生器java.util.Random
  • ✧将方向枚举转为数组Direction. values()
  • ✧在move完成后如果是敌军坦克的,随机产生一个数来设定坦克下一个方向

坦克是已经动起来了,但是我们需要思考一下:怎么让它动的更加智能?

三、让坦克智能起来


我们目前的坦克虽然动起来了,但是移动的范围比较小,像个蚂蚁转来转去

那么我们可以让它先朝一个方向移动一段距离再修改方向会不会好点呢?

class Tank{

    //定义变量随意移动的步数
    //最小值移动三步,最大值移动14步
    private int randowStep = random.nextInt(12) + 3;

    void move() {
        //针对于坏的坦克我们进行随机方向移动
        if(!camp){
            //将方向枚举转为数组
            Direction[] dirarr = Direction.values();
            //当移动距离完后重新调整方向继续移动
            if (randowStep == 0){
                randowStep = random.nextInt(12 ) + 3;
                //根据八个方向产生一个随机方向出来
                int rn = random.nextInt(dirarr.length);
                dir = dirarr[rn];
            }
            //不断的移动距离
            randowStep --;
        }
        //省略其他关键性代码....
    }
    //省略其他关键性代码....
}

这时我们在运行起来就发现,敌方坦克移动的范围更加的大了

image.png

现在敌方坦克是会动了,但是还不会发射炮弹,那么我们怎么让他发射炮弹呢?

这时可能有小伙伴就会说,那我直接fire开火不就行了吗?实践一起看看

class Tank{

    void move() {
        
        //针对于坏的坦克我们进行随机方向移动
        if(!camp){
            //省略其他关键性代码....
            //实现开火
            this.fire();
        }
        //省略其他关键性代码....
    }
    //省略其他关键性代码....
}

运气来我们就会发现,这时敌方坦克发射炮弹就碰撞到自己造成灭亡了

image.png

所以我们需要对子弹也要做一个阵营的区分

class Missle{

    //区分子弹的阵营
    private boolean camp = true;
    
    //坦克发射子弹的时候添加阵营身份
    public Missle(int x, int y, Tank.Direction dir, TankClient tc, boolean camp) {
        this.x = x;
        this.y = y;
        this.dir = dir;
        this.tc = tc;
        this.camp = camp;
    }
}

当坦克发射子弹时携带阵营标识,并且碰撞的处理为对异阵营进行处理

class Tank{

    //坦克发射子弹.....
    public Missle fire(){
        //省略其他关键性代码....
        //坦克发射炮弹的时候,携带自己的阵营标识
        Missle missle =new Missle(x,y,ptdir,tc,camp);
        tc.missles.add(missle);
        return missle;
    }
    //省略其他关键性代码....
}
class Missle{

    public boolean hitTank(Tank t){
        if(t.isLive() && this.getRect().intersects(t.getRect()) && this.camp != t.isCamp()){
            t.setLive(false);
            this.live = false;
            //爆炸效果产生在与子弹发生碰撞的地方
            Explode e = new Explode(x,y,tc);
            tc.explods.add(e);
            return true;
        }
        return false;
    }
     //省略其他关键性代码....
}

这时我们运行游戏窗口,就不会对同阵营造成伤害了

image.png

但是这时我们的敌方阵营的子弹太猛了,我们有没有什么方法减少一点?答案是:随机数

class Tank{

    //坦克发射子弹.....
    void move() {
        
        //针对于坏的坦克我们进行随机方向移动
        if(!camp){
            //省略其他关键性代码....
            //如果生成的随机大于38 才发射子弹
            if(random.nextInt(40) > 38 ){
                //实现开火
                this.fire();
            }
        }
    }
    //省略其他关键性代码....
}

这时敌方坦克的子弹就没有这么猛烈了,但是有个问题:我们怎么是无敌状态?

image.png

我们怎么让敌方阵营打到我们,然后打中后怎么也跟着消亡呢?

public class TankClient extends Frame {
    
    @Override
    public void paint(Graphics g) {
        g.drawString("missiles count:" + missles.size()+"",10,50);
        //画出容器里的子弹
        for ( int i = 0; i < missles.size();i++){
            Missle m = missles.get(i);
            //将阵营坏的坦克放进来进行碰撞
            m.hitTank(tanklist);
            //将我们自己的坦克也放进来进行碰撞
            m.hitTank(mytank);
            m.draw(g);
        }
        //省略其他关键性代码....
    }
    
    //省略其他关键性代码....
}

这时当敌方坦克击中我们的时候,我们也跟着进行消亡了

image.png

同时当我们的坦克消亡后,就不必进行发生爆炸效果与发射子弹了

class Tank{

    //坦克发射子弹.....
    public Missle fire(){
        
        //如果坦克消亡了不必发射子弹
        if(!live){return null;}
        
        //省略其他关键性代码....
    }
    //省略其他关键性代码....
}
class Missle{

    public boolean hitTank(Tank t){
        
        //要求:目标坦克是活的、不同阵营的、子弹与坦克碰撞一块
        if(t.isLive() && t.isLive() && this.getRect().intersects(t.getRect()) && this.camp != t.isCamp()){
            t.setLive(false);
            this.live = false;
            //爆炸效果产生在与子弹发生碰撞的地方
            Explode e = new Explode(x,y,tc);
            tc.explods.add(e);
            return true;
        }
        return false;
    }
     //省略其他关键性代码....
}

步骤总结

让敌军坦克发射炮弹:
  • ✧本军炮弹不打本军
  • ✧炮弹添加好坏bGood,根据好坏画不同颜色
  • ✧修改炮弹的构造方法
  • ✧修改Tank的fire方法
  • ✧修改hitTank方法,好不能打好,坏不能打坏
  • ✧敌军炮火不能太猛烈

参考资料


尚学堂:坦克大战(马士兵老师)

你可能感兴趣的