Box2D ContactListener 未检测到碰撞

Box2D ContactListener Not Detecting Collision

我正在尝试使用 b2ContactListener class 检测静态 body 和运动学 body 之间的碰撞,但我的代码没有检测到我的两个固定装置之间的碰撞。我在我的运动 body 顶部放置了一个 EdgeShape,并将其作为一个夹具来检测与我的静态 body 夹具的碰撞。我正在使用 SFML 绘制到屏幕并检测键盘事件。

这是我的主要功能:

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;
    }

这是我的 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;
        }
    }
}

Box2D 不会对静态物体直接与其他静态或运动物体进行碰撞处理。它们在理论上都是无限质量的,因此运动定律似乎不再有意义(至少对我来说在碰撞方面没有意义)。

可能最简单的方法是将运动体改为动态体。

您也可以用动态物体包围其中一个物体,让接触监听器启动。不能使动态物体驱动它所包围的运动学或静态物体,但是在子步骤阶段,我认为它值得付出更多的努力。

希望这个回答对您有所帮助!