《Java小游戏实现》:坦克大战(续四)
相关博文:
《Java小游戏实现》:坦克大战http://blog.csdn.net/u010412719/article/details/51712663
《Java小游戏实现》:坦克大战(续一):http://blog.csdn.net/u010412719/article/details/51723570
《Java小游戏实现》:坦克大战(续二):http://blog.csdn.net/u010412719/article/details/51729655
《Java小游戏实现》:坦克大战(续三):http://blog.csdn.net/u010412719/article/details/51735013
博文《Java小游戏实现》:坦克大战(续三)中已经实现到了坦克大战的基本对战功能。这篇博文在此基础上继续实现更多的功能,例如:为游戏添加围墙。
完成功能:为游戏添加围墙
本项目为围墙单独建立一个类:Wall。
我们利用面向对象的思想,可以考虑Wall类应该有什么属性和方法。
根据我们将这个游戏开发到目前这个阶段的经验,可以很容易的想到,Wall这个类,应该有如下:
1、位置属性:x,y,width,height
2、有一个大管家TankClient的引用
3、构造方法
4、draw方法
5、由于会涉及到和墙的碰撞检测,因此也需要一个getRect()方法
具体内容如下:
public class Wall {
//位置属性
private int x;
private int y;
private int width;
private int height;
private TankClient tc;
public Wall(int x, int y, int width, int height, TankClient tc) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.tc = tc;
}
public void draw(Graphics g){
Color c = g.getColor();
g.setColor(Color.BLACK);
g.fillRect(x, y, width, height);
g.setColor(c);
}
public Rectangle getRect(){
return new Rectangle(x,y,width,height);
}
}
测试这个类是否在我们的游戏界面中显示出来。
在TankClient类new两个Wall对象并在draw显示出来即可。
具体如下:
private Wall w1 = new Wall(200, 200, 200, 10, this);
private Wall w2 = new Wall(100, 100, 10, 300, this);
@Override
public void paint(Graphics g) {
//画墙
w1.draw(g);
w2.draw(g);
//....其它的一些代码省略
}
测试结果如下:
以上就添加了一个简单的墙,但是目前还存在一些问题
1、子弹可以穿透墙
2、坦克也可以穿透墙
本项目中处理上面两个问题的方法如下:
1、而本来子弹是不可以穿透墙的,当子弹击中墙时,子弹应该消失。
2、坦克也应该不可以穿透墙的,当坦克碰到墙时,应该换其它的方向运动。
下面我们一个一个的来解决上面提到的两个问题。
完成的功能:处理子弹和墙的碰撞
本项目处理这种情况的方法为:当子弹和墙碰撞时,子弹消失。
子弹和墙碰撞的处理方式与之前子弹和坦克碰撞的处理方式一样。
而之前子弹和坦克碰撞的处理方式为:在Missile类添加了如下的两种方法:
public boolean hitTank(Tank t){...}
public boolean hitTanks(List<Tank> tanks){...}
基于此,我们处理子弹和墙的碰撞,同样也是在Missile添加两个函数,具体如下:
/*
* 函数的功能:判断子弹是否击中了墙
* */
public boolean hitWall(Wall w){
if(!this.live){
return false;
}
if(this.live&&this.getRect().intersects(w.getRect())){
this.live = false;
return true;
}
else{
return false;
}
}
/*
* 函数的功能:判断子弹是否击中了一系列的墙
* */
public boolean hitWalls(List<Wall> walls){
for(int i=0;i<walls.size();i++){
if(this.hitWall(walls.get(i))){
return true;
}
}
return false;
}
然后在TankClient类中的draw方法调用子弹的这两个方法,即ms.hitWall(w1);
。
如下:
@Override
public void paint(Graphics g) {
//画墙
w1.draw(g);
w2.draw(g);
//画子弹
for(int i=0;i<missiles.size();i++){
Missile ms = missiles.get(i);
//判断子弹是否还存活在,如果不是存活的,则移除
if(!ms.isLive()){
missiles.remove(ms);
}
else{
ms.hitTanks(enemyTanks);
ms.draw(g);
//将自己的坦克也加入到子弹可以攻击的范围
ms.hitTank(tk);
//子弹打墙
ms.hitWall(w1);
ms.hitWall(w2);
}
}
}
接下来,处理坦克撞墙的情况
本项目处理坦克撞墙的方法为:当坦克撞墙后,回到上一次的位置。
//坦克前一个时刻的位置
private int oldX;
private int oldY;
//坦克撞一个墙
public boolean tankHitWall(Wall w){
if(!this.live){
return false;
}
if(this.getRect().intersects(w.getRect())){
this.x = oldX;
this.y = oldY;
return true;
}
else{
return false;
}
}
//坦克撞一系列的墙
public boolean tankHitWalls(List<Wall> walls){
for(int i=0;i<walls.size();i++){
if(tankHitWall(walls.get(i))){
return true;
}
}
return false;
}
这样在TankClient 中每个坦克都调用tankHitWall和tankHitWalls方法即可进行测试,发现是可以完成其功能的。
到这里位置基本上功能就差不多完成了。由于时间的关系,和教研室项目的原因,不能花太多时间鼓捣自己的东西。这个小游戏就到此结束了!
整个游戏的代码可以在这里提取:https://github.com/wojiushimogui/Tank_2.3
待完成的功能
以后继续完善的地方有:
1、为我方坦克加入生命值
2、加入血块
3、加入超级技能,例如:连发,大炮弹等。