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