您的位置:首页 > 其它

学习 Box2D 个人笔记(十)碰撞检测

2013-01-04 01:08 330 查看
首先,碰撞检测的前提是有两个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游戏  这篇文章挺好的推荐像我这样的新手学习
.
    
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: