我所知道坦克大战(单机版)之解决坦克出界问题、添加机器坦克、将机器坦克击毙

本章目的

  • 解决坦克出界问题
  • 让坦克发射多发炮弹问题

一、解决坦克出界问题


我们发现现在当前版本,如果控制这个坦克一直往左或者往右的话是会移出边界的

我所知道坦克大战(单机版)之解决坦克出界问题、添加机器坦克、将机器坦克击毙_第1张图片

那么怎么解决这个问题呢?其实与子弹有异曲同工之处

我所知道坦克大战(单机版)之解决坦克出界问题、添加机器坦克、将机器坦克击毙_第2张图片

public class Tank {
    
    void move() {
    
        //省略其他关键性代码.......
        
        if (x < 0){ x = 0;}//若坦克x小于0则等于0
        
        //小于30 是因为要考虑标题的宽度
        if (y < 30){ y = 30;}//若坦克y小于30则等于30

        //当坦克的x坐标加上坦克的宽度大于游戏窗口的宽度
        if (x + Tank.WIDTH > TankClient.GAME_WINDTH ) {
            x = TankClient.GAME_WINDTH - Tank.WIDTH;
        }
        //当坦克的y坐标加上坦克的高度大于游戏窗口的高度
        if (y + Tank.HEIGHT > TankClient.GAME_HEIGHT ) {
            y = TankClient.GAME_HEIGHT - Tank.HEIGHT;
        }
    }
    
    //省略其他关键性代码.......
}

这时我们的坦克则无法再跑到外面了

我所知道坦克大战(单机版)之解决坦克出界问题、添加机器坦克、将机器坦克击毙_第3张图片

但是我们发现当前这个版本只有我们一个坦克,那么我们能不能加点坦克进来玩呢?

二、添加机器坦克


一般我们玩坦克大战都会有一个阵营的标识符区分是好是坏的坦克


public class Tank {
    
    //区分阵营好坏
    private boolean camp = false;

    public Tank(int x, int y, TankClient tc, boolean camp) {
        this.x = x;
        this.y = y;
        this.tc = tc;
        this.camp = camp;
    }
    //省略其他关键性代码.......
}

这时我们修改一下方法,并且创建多一个坦克

public class TankClient extends Frame {
    
    //阵营:好的坦克
    Tank mytank = new Tank(50,50,this,true);

    //阵营:坏的坦克
    Tank enemytank = new Tank(100,100,this,false);
    
    //省略其他关键性代码.......
    
    @Override
    public void paint(Graphics g) {
        //省略其他关键性代码.......
        //画出 好的 坦克
        mytank.draw(g);
        //画出 坏的 坦克
        enemytank.draw(g);
    }
}

我所知道坦克大战(单机版)之解决坦克出界问题、添加机器坦克、将机器坦克击毙_第4张图片

这时机器坦克就出来了,如果你觉得不好区分颜色,可以在绘制方法里区分


public class Tank {
    
    //添加方法完成坦克的绘画
    public void draw(Graphics g) {
        //省略其他关键性代码.......
        if(camp){
            //将阵营好的坦克颜色为红色
            g.setColor(Color.red);
        }else{
            //将阵营坏的坦克颜色为蓝色
            g.setColor(Color.blue);
        }
    }
    //省略其他关键性代码.......
}

我所知道坦克大战(单机版)之解决坦克出界问题、添加机器坦克、将机器坦克击毙_第5张图片

步骤总结

  • ✧加入区别敌我的变量camp
  • ✧根据敌我的不同设置不同的颜色
  • ✧更新Tank的构造函数,加入camp
  • ✧TankClient中new 出敌人的坦克并画出

这时我们就有一个新的想法出来了:怎么将这个坦克给干掉呢?

三、击毙机器坦克


在我们发射炮弹的时候,那么如何检测到是否击中坦克呢?我们称为碰撞检测

游戏中的碰撞检测方式有很多,不同的算法之间主要是在精度和速度之间权衡

我们这里介绍一个类:Rectangle,它指的是坐标空间中的一块区域,通过坐标空间中Rectangle对象左上方的点 (x,y)、宽度和高度可以定义这个区域

下面是其比较常用的几个方法:

//-->判定点(x,y)是否包含在指定区域内
boolean contains(int x,int y)

//-->判定指定区域是否在其指定区域内
boolean contains(int x,int y,int width,int height)

而我们只需要判断子弹与坦克之间是否碰撞到一块来确定是否击中

public class Tank {
    
    //创建子弹的坐标空间区域
    public Rectangle getRect(){
        return new Rectangle(x,y,WIDTH,HEIGHT);
    }
    //省略其他关键性代码.......
}
class Missle{

    //创建子弹的坐标空间区域
    public Rectangle getRect(){
        return new Rectangle(x,y,WIDTH,HEIGHT);
    }
    public boolean hitTank(Tank t){
        if(this.getRect().intersects(t.getRect())){
            return true;
        }
        return false;
    }
    //省略其他关键性代码.......
}

那么我们怎么让这个坦克消失呢?回想一下我们子弹是怎么消失的?

是不是有一个变量控制着存活状态呀?所以我们坦克也添加一个变量控制

public class Tank {
    
    //用于判断控制坦克存活变量
    private boolean live = true;

    public boolean isLive() {
        return live;
    }
    public void setLive(boolean live) {
        this.live = live;
    }
    
    //添加方法完成坦克的绘画
    public void draw(Graphics g) {

        //死掉的坦克不用绘制
        if(!live){
            return;
        }
        //省略其他关键性代码.......
    }
    //省略其他关键性代码.......
}

同时当我们的子弹与坦克进行碰撞时,则将它修改为false状态即可

class Missle{

    public boolean hitTank(Tank t){
        if(this.getRect().intersects(t.getRect())){
            t.setLive(false);
            return true;
        }
        return false;
    }
    //省略其他关键性代码.......
}

当我们运行起来的时候,还需要调用该方法完成碰撞检测

public class TankClient extends Frame {
    
    //省略其他关键性代码.......
    @Override
    public void paint(Graphics g) {
        //画出容器里的子弹
        for ( int i = 0; i < missles.size();i++){
            Missle m = missles.get(i);
            //将阵营坏的坦克放进来进行碰撞
            m.hitTank(enemytank);
            m.draw(g);
        }
        //省略其他关键性代码.......
    }
}

我所知道坦克大战(单机版)之解决坦克出界问题、添加机器坦克、将机器坦克击毙_第6张图片

我们发现子弹与坦克发生碰撞后,坦克是消失了但是打中坦克的子弹没有消失

这是因为我们没有对这颗子弹也进行消亡,移出

class Missle{

    public boolean hitTank(Tank t){
        if(this.getRect().intersects(t.getRect())){
            t.setLive(false);
            this.live = false;
            return true;
        }
        return false;
    }
    //添加方法完成子弹的绘画
    public void draw(Graphics g) {
        if(!live){
            //若消亡则进行移出
            tc.missles.remove(this);
        }
        //省略其他关键性代码.......
    }
    //省略其他关键性代码.......
}

但是为什么这时我们打一堆子弹出去,也会一并消亡呢?为什么?

因为我们在判断碰撞的时候,并没有将坦克的存活状态考虑进去

class Missle{
    
    public boolean hitTank(Tank t){
        if(this.getRect().intersects(t.getRect()) && t.isLive()){
            t.setLive(false);
            this.live = false;
            return true;
        }
        return false;
    }
    //省略其他关键性代码.......
}

这时我们打中坦克则完成了子弹移出、消亡效果

我所知道坦克大战(单机版)之解决坦克出界问题、添加机器坦克、将机器坦克击毙_第7张图片

步骤总结

  • ✧Missle中 加入hitTank(Tank)方法,返回布尔类型
  • ✧碰撞检测的辅助类Rectangle
  • ✧为Tank 和Missle都加入getRect方法
  • ✧当击中敌人坦克时,坦克被打死,子弹也死去
  • ✧增加控制Tank生死的量live
  • ✧如果坦克死去就不画了

我们这里的碰撞检测采用的是最简单的方式,将子弹与坦克用Rectangle类生成的方框包装起来

判断这两个方框是否相交来判断证明是否击中,击中后进行相关处理

参考资料


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

你可能感兴趣的:(我所知道坦克大战(单机版)之解决坦克出界问题、添加机器坦克、将机器坦克击毙)