~~~~我的生活,我的点点滴滴!!
在Box2D中,经常会遇到物体之间的碰撞问题,当一个碰撞发生时,就是利用定制器(fixtures)用来做碰撞检测的。碰撞可以以很多
方式进行,我们可以在碰撞过程中获取大量信息用在游戏逻辑中。
1、碰撞信息获取
b2Contact对象包含了碰撞的信息。从对象中可以得知哪两个定制器发生了碰撞,以及碰撞的位置和碰撞之后的反作用方向。在Box2D中
有两个方法可以获取b2Contact对象,一个是遍历接触(contacts)链表每一个物体,另外一种方法是用接触监听器(contact listener)。
下面先让我们快速浏览一下接下来要讨论的两种方法。
1.1、查看接触链表
你可以在任何时候,通过查看世界接触链表来获取当前所有接触:
for (b2Contact* contact = world->GetContactList(); contact; contact = contact->GetNext())
{
contact->... //do something with the contact
}
或者通过某个物体查看它的接触:
for (b2ContactEdge* edge = body->GetContactList(); edge; edge = edge->next)
{
edge->contact->... //do something with the contact
}
如果你使用这种方法,有一点非常重要的地方就是,即便链表中存在接触(contact)也并不代表着两个定制器之间正在发生接触-这仅仅代表
了两个物体的AABB框发生了接触而已。如果你想知道定制器自身是否真正发生了碰撞,需要通过判断IsTouching()方法来检测。
1.2、接触监听器
使用接触链表进行碰撞检测,对于需要进行大量快速的碰撞信息获取来说,显得就很低效。设置接触监听器可以让Box2D告诉你你所感兴趣的
事情什么时候会发生,比起你只是为了得知碰撞的开始和结束而兴师动众的完成所有重量级工作(例如不停的遍历接触链表)来说,显得非常
高效。接触监听器是一个包括四个方法的类(b2ContactListener),这些方法可以根据你的需要进行重写。
void BeginContact(b2Contact* contact);
void EndContact(b2Contact* contact);
void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);
void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse);
具体的事件内容取决于当前正在发生什么,一些事件只是给我们传递了b2Contact对象。世界中的Step方法执行过程中,当Box2D检测到某个事
件发生时,就会回调这些方法,你就会知道到底发生了什么事情。实际当中的应用会在“碰撞回调”中讨论,这里我们只是关注碰撞的什么时
候发生。
通常我比较建议使用接触监听器这种方法来做碰撞检测。乍看起来它好像有点烦杂笨重,但是从长远来看,这种方法更加高效和有用。
2、拆解碰撞
我利用AABB框来看下效果,AABB框可以在testbed的选项上勾选,我们就从定制器的AABB框尚未重叠的那一刻开始。