首先,碰撞检测的前提是有两个body 了 . 我还是把两个body 定义为bodyA 和bodyB ,并且 类里边有他们的Fixture成员。 这是个前提。
然后 我们需要在这两个body碰撞的时候,CCLOG(“BOOM!”);
那么我们要做的是:
1、建一个类,这个类继承b2ContactListener,x-code里注意建object-c class 的时候改掉后缀名 m 改成mm 这样就可以用C++混编。(后边这句是人云亦云)
接下用下面的代码替换掉 MyContactListener.h里面的内容:
#import"Box2D.h"
#import<vector>
#import<algorithm>
struct MyContact {
b2Fixture *fixtureA;
b2Fixture *fixtureB;
booloperator==(const MyContact& other) const
{
return (fixtureA == other.fixtureA) && (fixtureB == other.fixtureB);
}
};
class MyContactListener : public b2ContactListener {
public:
std::vector<MyContact>_contacts;
MyContactListener();
~MyContactListener();
virtualvoid BeginContact(b2Contact* contact);
virtualvoid EndContact(b2Contact* contact);
virtualvoid PreSolve(b2Contact* contact, const b2Manifold* oldManifold);
virtualvoid PostSolve(b2Contact* contact, const b2ContactImpulse* impulse);
};
这里,我们定义了一个数据结构,当碰撞通知到达的时候,用来保存碰撞点信息。再说一遍,我们需要存储其拷贝,因为它们会被重用,所以不能保存指针。注意,我们这里一定要重载=号,因为,我们将使用find算法来查找vector中的一个特定的元素,而这个标准算法find必须要求其查找的元素是可比较相等的。
在我们申明完contact listener类之后,我们只需要声明一些我们感兴趣的方法来实现就可以了。这里的vector用来缓存碰撞点信息。
现在,用下面的内容替换掉MyContactListener.mm:
#import"MyContactListener.h"
MyContactListener::MyContactListener() : _contacts() {
}
MyContactListener::~MyContactListener() {
}
void MyContactListener::BeginContact(b2Contact* contact) {
// We need to copy out the data because the b2Contact passed in
// is reused.
MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() };
_contacts.push_back(myContact);
}
void MyContactListener::EndContact(b2Contact* contact) {
MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() };
std::vector<MyContact>::iterator pos;
pos = std::find(_contacts.begin(), _contacts.end(), myContact);
if (pos != _contacts.end()) {
_contacts.erase(pos);
}
}
void MyContactListener::PreSolve(b2Contact* contact,
const b2Manifold* oldManifold) {
}
void MyContactListener::PostSolve(b2Contact* contact,
const b2ContactImpulse* impulse) {
}
我们在构造函数中初使化vector。然后,我们只需要实现BeginContact和EndContact方法就可以了。这两个方法,一个是碰撞开始的时候world对象会回调,另一个就是碰撞结束的时候被回调。在BeginContact方法中,我们复制了刚刚发生碰撞的fixture的一份拷贝,并把它存储在vector中。在EndContact方法中,我们检查一下碰撞点是否在我们的vector中,如果在的话,就移除它!
好了,现在可以使用它吧。打开HelloWorldScene.h,然后做下面的修改:
// Add to top of file
#import"MyContactListener.h"
// Add inside @interface
MyContactListener *_contactListener;
然后在init 方法里加上:
// Create contact listener
_contactListener =new MyContactListener();
_world->SetContactListener(_contactListener);
这里,我们创建了contact listener对象,然后调用world对象把它设置为world的contact listener。
接下来,再我们忘记之前先做一些清理内存的操作:
delete _contactListener;
接下来万事俱备,只欠东风了。
写一个每秒调用n次的那个方法,这个都会吧。然后在里面加入:
std::vector<MyContact>::iterator pos;
for(pos = mycontactlistener->_contacts.begin();
pos != mycontactlistener->_contacts.end(); ++pos)
{
MyContact contact =*pos;
if ((contact.fixtureA == bodyAFixture && contact.fixtureB == bodyBFixture) ||
(contact.fixtureA == bodyBFixture && contact.fixtureB == bodyAFixture))
{
CCLog("BOOM!!");
// world->DestroyBody(bodyB);
// bodyB = NULL;
// break;
}
}
这样就ok了 .
总结一下 ,用到了vector这玩意,我原来都没见过,现充的电。
std::vector介绍 和 vector与iterator
最后 .这篇笔记严重借鉴 如何使用cocos2d和box2d制作一个简单的breakout游戏 这篇文章挺好的推荐像我这样的新手学习 .