本章目标
- 解决坦克出界问题
- 让坦克发射多发炮弹问题
一、解决坦克出界问题
咱们发现当初以后版本,如果管制这个坦克始终往左或者往右的话是会移出边界的
那么怎么解决这个问题呢?其实与子弹有殊途同归之处
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类生成的方框包装起来
判断这两个方框是否相交来判断证实是否击中,击中后进行相干解决
参考资料
尚学堂:坦克大战(马士兵老师)