Box2D碰撞检测

时间:2013-08-01 11:36:59

标签: ios ios6 box2d-iphone

我在碰撞检测方面遇到了一些问题。事情是碰撞被发现得太晚,当碰撞的两个物体相互重叠时。只有一个物体在移动,其他物体是静止的。身体用SetTransform()函数移动并复制精灵的移动。这是来自scheduledUpdate方法和ContactListener类的代码

- (void)update:(ccTime)deltaTime {
std::vector<b2Body *>toDestroy;
std::vector<MyContact>::iterator pos;
for (pos=_contactListener->_contacts.begin();
     pos != _contactListener->_contacts.end(); ++pos) {
    MyContact contact = *pos;
    b2Body *bodyA = contact.fixtureA->GetBody();
    b2Body *bodyB = contact.fixtureB->GetBody();
    if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL) {
        CCSprite *spriteA = (CCSprite *) bodyA->GetUserData();
        CCSprite *spriteB = (CCSprite *) bodyB->GetUserData();
        // Contact detected between spriteA and spriteB
    }
}
} 

ContactListener.h

#import "Box2D.h"
#import <vector>
#import <algorithm>

struct MyContact {
b2Fixture *fixtureA;
b2Fixture *fixtureB;
bool operator==(const MyContact& other) const
{
    return (fixtureA == other.fixtureA) && (fixtureB == other.fixtureB);
}
};

class MyContactListener : public b2ContactListener {

public:
    std::vector<MyContact>_contacts;

    MyContactListener();
    ~MyContactListener();

    virtual void BeginContact(b2Contact* contact);
    virtual void EndContact(b2Contact* contact);
    virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);
    virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse);

};

ContactListener.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) {
}

2 个答案:

答案 0 :(得分:1)

我不建议使用setTransform来移动身体。为了使一切正常,身体应该通过对它们应用forces/impulses来移动。如果你“手动”改变你的身体位置,就会发生奇怪的事情。

也就是说,很难在不实际尝试代码的情况下知道发生了什么,但假设代码没问题(并且setTransform没有任何关系),问题可能在于身体本身;我开始检查你的所有体形都是convex polygons

答案 1 :(得分:1)

是的,你不应该使用setTransform移动身体,而是像ssantos所说的那样使用力量和冲动。在夹具重叠之后检测到碰撞碰撞的两个动态体的情况下也会发生什么。为了避免这种情况,你可以将机身设置为“子弹”,它可以打开CCD,连续碰撞检测。这是更昂贵的,因为不断地评估该物体的碰撞,而不仅仅是当两个AABB重叠时。