J2ME游戏中的碰撞检测

我们在游戏开发中总会遇到这样那样的碰撞,并且会很频繁的去处理这些行为.这也是游戏开发的一种基本的算法.2D的相对3D的要简单的多了,最简单的就是矩形碰撞\圆形碰撞,像素碰撞。矩形碰撞用的最多

我就简单总结一点我的认识,对于矩形碰撞.

我们就把游戏中的角色统称为一个一个的Actor,并且把每个 Actor框成一个与角色大小相等的矩形框,那么在游戏中每次的循环检查就是围绕每个Actor的矩形框之间是否发生了交错。为了简单起见,我们就拿一个主角与一个Actor来分析,其它的可以类似。

一个主角与一个Actor的碰撞其实就成了两个矩形的检测,是否发生了交集。

第一种方法:

我们可以通过检测一个矩形的4个顶点是否在另外一个矩形的内部来完成。代码如下:

我们简单的设定一个Actor类:

public class Actor {

int x,y,w,h;

public int getX() {

return x;

}

public int getY() {

return y;

}

public int getActorWidth() {

return w;

}

public int getActorHeight() {

return h;

}

}



检测的处理为:

public boolean isCollidingWith (int px ,int py){

if(px > getX() && px < getX() + getActorWidth()

&& px > getY() && px < getY() + getActorHeight())

return true;

return false;

}



public boolean isCollidingWith(Actor another) {

if(isCollidingWith(another.getX(),another.getY())

||isCollidingWith(another.getX()+ another.getActorWidth(),another.getY())

||isCollidingWith(another.getX(),another.getY()+another.getActorHeight())

||isCollidingWith(another.getX()+ another.getActorWidth(),another.getY()+another.getActorHeight())

)

return true;

return false;

}

以上处理运行应该是没有什么问题的,但是没有考虑不到运行速度,而游戏中需要大量的碰撞检测工作,所以要求碰撞检测要尽量的快。



第二种方法:

我们从相反的角度考虑,以前是想什么时候相交,现在我们处理什么时候不会相交,可以处理4条边,


a b

左边a矩形的右边界在b矩形的左边界以外,同理,a的上边界需要在b的下边界以外,四边都判断,则可以知道a是否与b相交,代码:

/**

* ax a矩形左上角x坐标

* ay--a矩形左上角y坐标

* aw -- a矩形宽度

* ah -- a矩形高度

*

* bx --b矩形左上角x坐标

* by --b矩形左上角y坐标

* bw-- b矩形宽度

* bh -- b矩形高度

* *

*/

public boolean isColliding(int ax,int ay,int aw,int ah,

int bx, int by, int bw, int bh){

if(ay > by + bh || by > ay + ah

|| ax > bx + bw || bx > ax + aw)

return false;

return true;

}

此方法比第一种简单且运行快。







第三种方法:

这种方法其实可以说是第二种的一个变异,我们可以保存两个矩形的左上和右下两个坐标的坐标值,然后对两个坐标的一个对比就可以得出两个矩形是否相交。这应该比第二种更优越一点。

/*

* rect1[0]: 矩形1左上角x坐标

* rect1[1]: 矩形1左上角y坐标

* rect1[2]: 矩形1右下角x坐标

* rect1[3]: 矩形1右上角y坐标

*

* rect2[0]: 矩形2左上角x坐标

* rect2[1]: 矩形2左上角y坐标

* rect2[2]: 矩形2右下角x坐标

* rect2[3]: 矩形2右上角y坐标

*/

static boolean IsRectCrossing (int rect1[], int rect2[])

{

if (rect1[0] > rect2[2]) return false;

if (rect1[2] < rect2[0]) return false;

if (rect1[1] > rect2[3]) return false;

if (rect1[3] < rect2[1]) return false;

return true;

}

这种速度应该很快的了,推荐使用这种。



第四种方法:(类似于圆形与圆形)

现在介绍一种测试两个对象边界是否重叠。可以通过比较两个对象间的距离和两个对象半径的和的大小,很快实现这种检测。如果它们之间的距离小于半径的和,就说明产生了碰撞。

为了计算半径,就可以简单的取高度或者宽度的一半作为半径的值。

代码如下:

public static boolean isColliding ( int ax,int ay,int aw, int ah,

int bx, int by, int bw, int bh){



int r1 = (Math.max(aw, ah)/2 + 1);

int r2 = (Math.max(bw, bh)/2 + 1);

int rSquard = r1 * r1;

int anrSquard = r2* r2;

int disX = ax - bx;

int disY = ay - by;



if((disX * disX) + (disY * disY) < (rSquard + anrSquard))

return true;

else

return false;

}

这种方法类似于圆形碰撞检测。处理两个圆的碰撞处理就可以用这种。



以上只是总结了几种简单的方法,当然其实在游戏中熟练的运用才是最好的,在J2ME中差不多以上几种算够了,它不需要太精密的算法,当然可能有些需要比以上更复杂,例如如果一个对象速度足够快的,可能只经历一步就穿越了一个本该和它发生碰撞的对象,如果要考虑这种的话就要根据它的运动路径来处理。还有可能碰到不同的边界发生不同的行为,这就要具体的对碰撞行为进行解剖,然后具体处理。

总之,可能游戏中遇到的碰撞行为会更复杂,还需要更进一步的学习。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值