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