CheetahBongos
CheetahBongos

Reputation: 197

Box2D ContactListener Not Detecting Collision

I am trying to detect a collision between a static body and a kinematic body using the b2ContactListener class but my code is not detecting a collision between my two fixtures. I placed an EdgeShape at the top of my kinematic body and made it a fixture to detect a collision with my static body fixture. I am using SFML to draw to the screen and detect keyboard events.

Here is my main function:

int main()
{
    Vector2f resolution;
    resolution.x = VideoMode::getDesktopMode().width;
    resolution.y = VideoMode::getDesktopMode().height;

    RenderWindow window(VideoMode(resolution.x, resolution.y),
        "Box2D Test", Style::Fullscreen);

    Vector2f staticRectSize(100.0f, 20.0f);
    Vector2f kinematicRectSize(40.0f, 20.0f);

    Event keyBoardEvent;

    b2Vec2 gravity(0.0f, 0.0f);

    b2World world(gravity);

    // Creating static body and fixture
    b2BodyDef groundBodyDef;
    groundBodyDef.position.Set(100.0f, 150.0f);

    b2Body* groundBody = world.CreateBody(&groundBodyDef);

    b2PolygonShape groundBox;

    groundBox.SetAsBox(50.0f, 10.0f);

    groundBody->CreateFixture(&groundBox, 0.0f);

    // Creating kinematic body and fixture
    b2BodyDef bodyDef;
    bodyDef.type = b2_kinematicBody;
    bodyDef.position.Set(125.0f, 700.0f);
    b2Body* body = world.CreateBody(&bodyDef);

    b2PolygonShape kinematicBox;
    kinematicBox.SetAsBox(20.0f, 10.0f);

    b2FixtureDef fixtureDef;
    fixtureDef.shape = &kinematicBox;

    fixtureDef.density = 1.0f;

    fixtureDef.friction = 0.3f;

    body->CreateFixture(&fixtureDef);

    // world.Step inputs
    float32 timeStep = 1.0f / 60.0f;
    int32 velocityIterations = 6;
    int32 positionIterations = 2;

    RectangleShape staticRect(staticRectSize);
    RectangleShape dynamicRect(kinematicRectSize);

    b2Vec2 staticPosition = groundBody->GetPosition();
    staticRect.setPosition(staticPosition.x, staticPosition.y);

    b2Vec2 dynamicPosition = body->GetPosition();

    // Creating EdgeShape
    b2EdgeShape top;
    top.Set(b2Vec2(dynamicPosition.x, dynamicPosition.y), b2Vec2(dynamicPosition.x + 40.0, dynamicPosition.y));
    fixtureDef.shape = ⊤
    fixtureDef.isSensor = true;
    body->CreateFixture(&fixtureDef)->SetUserData("top collision");

    // Creating an instance of myContactListener class
    myContactListener contactListener;
    world.SetContactListener(&contactListener);

    while (window.isOpen())
    {
        world.Step(timeStep, velocityIterations, positionIterations);

        dynamicPosition = body->GetPosition();

        dynamicRect.setPosition(dynamicPosition.x, dynamicPosition.y);

        while (window.pollEvent(keyBoardEvent))
        {
            if (keyBoardEvent.type == Event::KeyPressed)
            {
                if (keyBoardEvent.key.code == Keyboard::W)
                {
                    body->SetLinearVelocity(b2Vec2(0, -10));
                }
    ...

            window.clear();
            window.draw(staticRect);
            window.draw(dynamicRect);
            window.draw(line);
            window.display();

            if (Keyboard::isKeyPressed(Keyboard::Escape))
            {
                break;
            }
        }
        return 0;
    }

And here is my MyContactListiner.cpp:

void myContactListener::BeginContact(b2Contact* contact)
{
    b2Fixture *fa = contact->GetFixtureA();
    b2Fixture *fb = contact->GetFixtureB();

    if (fa == NULL || fb == NULL) { return; }

    while (1)
    {
        printf("Collision occurred");

        if (Keyboard::isKeyPressed(Keyboard::Escape))
        {
            break;
        }
    }
}

Upvotes: 0

Views: 409

Answers (1)

Louis Langholtz
Louis Langholtz

Reputation: 3123

Box2D doesn't do collision handling for static bodies directly against other static or kinematic bodies. They're both theoretically of infinite mass for which laws of motion don't seem to make much sense anymore (at least not to me in terms of collisions).

Probably easiest to make the kinematic body a dynamic one instead.

You could alternatively surround one of the bodies with dynamic ones to get the contact listener to fire up. The dynamic bodies can't be made to drive the kinematic or static one it surrounds however in the substep phases without more effort than I think it'd be worth.

Hope this answer helps!

Upvotes: 2

Related Questions