乐趣区

关于java:我所知道坦克大战单机版之解决坦克出界问题添加机器坦克将机器坦克击毙

本章目标

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

一、解决坦克出界问题


咱们发现当初以后版本,如果管制这个坦克始终往左或者往右的话是会移出边界的

那么怎么解决这个问题呢?其实与子弹有殊途同归之处

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;}
    }
    
    // 省略其余关键性代码.......
}

这时咱们的坦克则无奈再跑到里面了

然而咱们发现以后这个版本只有咱们一个坦克,那么咱们能不能加点坦克进来玩呢?

二、增加机器坦克


个别咱们玩坦克大战都会有一个营垒的标识符辨别是好是坏的坦克


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

这时机器坦克就进去了,如果你感觉不好辨别色彩,能够在绘制办法里辨别


public class Tank {
    
    // 增加办法实现坦克的绘画
    public void draw(Graphics g) {
        // 省略其余关键性代码.......
        if(camp){
            // 将营垒好的坦克色彩为红色
            g.setColor(Color.red);
        }else{
            // 将营垒坏的坦克色彩为蓝色
            g.setColor(Color.blue);
        }
    }
    // 省略其余关键性代码.......
}

步骤总结

  • ✧退出区别敌我的变量 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);
        }
        // 省略其余关键性代码.......
    }
}

咱们发现子弹与坦克产生碰撞后,坦克是隐没了然而打中坦克的子弹没有隐没

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

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;
    }
    // 省略其余关键性代码.......
}

这时咱们打中坦克则实现了子弹移出、沦亡成果

步骤总结

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

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

判断这两个方框是否相交来判断证实是否击中,击中后进行相干解决

参考资料


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

退出移动版