Java简单游戏开发之碰撞检测 (一)

2014-11-24 11:03:55 · 作者: · 浏览: 0

前言
不久之前在论坛上有人发贴,使用java编写的超级马里奥如何实现碰撞检测,笔者自己以前

也做过Tank大战。里面同样涉及到碰撞检测,翻翻U盘里的东西还在,什么时候也给共享出来。

这篇文章就简单游戏中的碰撞检测做一个简单的总结。首先需声明的是这里只是2D的碰撞检测。

碰撞检测
对于形状之间如何来判断是否是碰撞的这要根据具体的形状来定。在新手练手的小游戏中,

物体形状一般可以设定为矩形区域,这类规则图形。它的碰撞检测可以通过java API中的

Rectangle类来实现碰撞的检测。

规则图形碰撞检测(Rectangle)
首先我们查看API关于Rectangle类的介绍:它就是指定坐标空间的一个区域,这个区域是通过

指定左上角x、y坐标和去高度和宽度来确定的。

接下来看起具体的方法public Rectangle intersection(Rectangle r),这个方法就是碰撞检测的

关键了,如果两个Rectangle对象有交集,那么他们就有碰撞了。而每个形状我们都可以得到他们

的Rectangle对象,这样图形的碰撞检测也就得以实现了。

\


看下具体实现源码


[java] /* 判断子弹是否击中障碍物 */
public boolean isHit(com.Alex.map.Map map) {
boolean flag = true;// 代表没有撞到
// 分类别的得到所有的障碍物
List stuffList = new Vector();
stuffList.addAll(map.getBricks());
stuffList.addAll(map.getIrons());
stuffList.addAll(map.getWaters());
for (int i = 0; i < stuffList.size(); i++) {
Stuff a = stuffList.get(i);
Rectangle tankRectangle = new Rectangle(bullet2.getRec());
Rectangle stuffRectangle = new Rectangle(a.getX(), a.getY(), 20, 20);
if (stuffRectangle.intersects(tankRectangle)) {
flag = false;// 撞到了
break;

}

}
return flag;
}

/* 判断子弹是否击中障碍物 */
public boolean isHit(com.Alex.map.Map map) {
boolean flag = true;// 代表没有撞到
// 分类别的得到所有的障碍物
List stuffList = new Vector();
stuffList.addAll(map.getBricks());
stuffList.addAll(map.getIrons());
stuffList.addAll(map.getWaters());
for (int i = 0; i < stuffList.size(); i++) {
Stuff a = stuffList.get(i);
Rectangle tankRectangle = new Rectangle(bullet2.getRec());
Rectangle stuffRectangle = new Rectangle(a.getX(), a.getY(), 20, 20);
if (stuffRectangle.intersects(tankRectangle)) {
flag = false;// 撞到了
break;

}

}
return flag;
}

上述这个例子就是判断Tank发出的子弹是否对地图中的障碍物有碰撞,如果有的话

就做相关的操作(子弹爆炸、障碍物消失)。上述代码中子弹对象有一个getRec()方法就是

得到子弹图形的Rectangle对象,具体实现就是根据其坐标和width、height来生成的。

采用此种方法进行碰撞检测需要注意,对于图片的实现处理应该尽量的去掉图标边角

的空白,不然实际效果可以产生肉眼可辨的误差。也就是说Rectangle尽量的包住图形

且Rectangle的区域尽量小。这种碰撞检测的方法被称之为多矩形碰撞。

\

一旦有一个矩形数组中的矩形与另外一个矩形数组的矩形发生碰撞就可认为发生了

多矩形碰撞。其中多圆形碰撞也是同样的道理,只是包裹的图形区域是圆形罢了。

不过仔细思考多矩形碰撞同样会有误差,虽然这种误差十分小。

\


像素级别的碰撞检测

像素级别的碰撞检测算得上是最精确的碰撞检测方法了。

首先遍历算出一张位图所有的像素点坐标,然后与另外一张位图上的所有点坐标进行对比,

一旦有一个像素点的坐标相同,就立刻取出这两个坐标相同的像素点,通过位运算取出这两个

像素点的最高位(透明度)进行对比,如果两个像素点都是非透明像素则判定这两张位图发生

碰撞。

介绍了像素碰撞之后可以得到两个结论:

1、像素碰撞很精确,不论位图之间是否带有透明像素,都可以精确判断;

2、正是因为像素碰撞的这种高精确判定,从而也会造成代码效率明显降低!

假设两张100×100 大小的位图利用像素级检测碰撞,仅是遍历两张位图的像素点就要循环

100×100×2=20000 句逻辑代码;况且还要对筛选出来的相同坐标的像素点进行遍历对比其

透明值!这种效率可想而知!

当然,这里的像素碰撞只是大致提供一种思路,肯定还可以进行代码优化;但是不论再优的
代码,使用像素级进行碰撞检测终会导致整个程序的