0
votes

I've got some problems with collision detection. The thing is the collision is detected too late, when the two bodies which collide are overlapping each other. Only one body is moving, the other ones are static.The body is moved with SetTransform() function and copying the movements of a sprite. Here is my code from scheduledUpdate method and the ContactListener class

- (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

2 Answers

1
votes

I wouldn't recommend using setTransform for moving bodies. In order for everything to work ok, bodies are supposed to move by applying forces/impulses to them. Weird things can happen if you "manually" change your bodies positions.

That said, it's hard to know what's happening without actually trying your code, but assuming the code is ok (and that setTransform has nothing to do), the problem could be in the bodies themselves; I'd start checking that all your body shapes are convex polygons.

1
votes

Yes you shouldn't use setTransform for moving the bodies, instead use forces and impulses like ssantos said. What also can happen is in case of the two dynamic bodies colliding the collision is detected after the fixtures overlap. To avoid that you can set the body to be a "bullet" which switches on CCD, Continuous Collision Detection. This is more expensive as the collision is evaluated for that body constantly and not only when two AABB's overlap.