引言
最近在与好友聊天的过程中,好友问我如何实现类似这样的游戏。它主要想知道,如何检测旋转过后的物体与其他物体之间的碰撞。
我们知道,在没有旋转的情况下,对于这样的方块,比较规则的物体,我们完全可以使用AABB(Axie-Align Bonding Box)来进行交叉检测,cocos2d-x内置的交叉检测函数也支持这样的功能。但是,在cocos2d-x中,并没有对旋转过后的物体支持进行检测。好友说,它发现经过旋转过后的AABB盒变的比原图要大,的确是这样的。在旋转之后,cocos2d-x内部会重新计算新的AABB盒。而我们知道AABB盒是和坐标轴平行的盒,所以它自然而然变大。(如果读者不知道为什么会变大了,不必深究,这并不是本文的重点)。
想要解决这样的问题,我第一个想到的方案就是使用OBB(Orient Bounding Box)碰撞检测算法来实现。下面就来像大家讲述下,如何在2D空间中实现这样的算法,并且在后面给出大家一个使用cocos2d-x来演示的Demo。
OBB包围盒
OBB,全称是Oriented Bounding Box,也就是带有方向的包围盒。实际上,它和AABB盒一样,也是一个矩形,只不过它具有任意的方向。对OBB进行结构表示,有很多种方法,我在下面的Demo中是使用矩形的四个顶点来定义OBB的。
好了,我们知道了OBB的具体表现形式之后,我们就需要判断两个OBB是否相互碰撞,也就是是否有相互重叠的部分???这里有两种不同的方法来进行。
第一种,我们通过判断OBB包围盒的四个顶点,是否都在另一个OBB盒的四条边定义的正半空间内,这样的方法很简单,感兴趣的同学可以自己去实现下。
另外一种,也是本文将要介绍的方法,称为Seperating Axie Theorem(分离定理),简称为SAT,这是一种一般性的判断基本几何体是否分离的算法。也就是说,对于凸变形,我们都可以使用SAT来判断两个凸多边形是否发生重叠。对于做游戏开发的我们,很有必要掌握这样的理论。
SAT理论解释
对于两个凸多边形,如果他们之间没有发生重叠,那么就是说,存在一个平面能够将这两个物体进行分离。读者可以看下图:
上面的灰线条就表示一个可以将这两个OBB盒分离的平面(读者可以将这条灰线想象成向屏幕里面深入的平面)。
在看下图:
这个图中的白色线条,它垂直于黑色的平面,我们将这个白色的线条称之为分离轴(Seperating Axie)。
在有了分离轴之后,我们需要确定这两个物体是否会发生重叠,也就是说这条潜在的分离轴(注意,这里的分离轴表示的是可能成为这两个OBB之间的分离轴,他们之间是否发生分离,我们需要通过潜在的分离轴来判断是否发生了分离)能够给我们判断两个OBB盒是否分离带来一些便利。
如何通过这条潜在的分离轴来判断这两个OBB盒是否发生了分离了???我们需要将物体在这条分离轴上的投影的起点和终点计算出来,也就是下图中在白色线条上的红线和蓝色线条的起点和终点计算出来:
看到上图,也就是我们需要将A,B,C,D这四个点计算出来。当然,读者需要注意,我这里说的点是在白色直线这条轴上的点&