Skip to content

ContactListener for Collision Event

CleftObsidian edited this page Oct 11, 2021 · 10 revisions

개요

ContactListener는 PhysicsBody 간의 충돌 시에 호출되는 메소드*를 포함하는 클래스이다.

각 메소드는 조건에 따라 충돌 발생 시 자동으로 호출된다.

Client는 ContactListener를 상속하는 클래스를 만들어 PhysicsWorld에 새로운 Contact Listener로 설정할 수 있다.

메소드를 수정하여 충돌 시 원하는 기능을 수행하게 만들 수 있다.

*BeginContact, EndContact, PreSolve, PostSolve

class ContactListener : public b2ContactListener
{
public:
    void BeginContact(b2Contact* contact)
    { /* handle begin event */ }
 
    void EndContact(b2Contact* contact)
    { /* handle end event */ }
 
    void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
    { /* handle pre-solve event */ }
 
    void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse)
    { /* handle post-solve event */ }
};

기본 메소드

  • BeginContact: PhysicsBody들의 Fixture가 겹치는 순간에 호출되는 메소드

    void BeginContact(b2Contact* contact)
    { /* handle begin event */ }
  • EndContact: PhysicsBody들의 Fixture가 겹치는 것을 멈추는 순간에 호출되는 메소드

    void EndContact(b2Contact* contact)
    { /* handle end event */ }
  • PreSolve: 충돌을 감지한 후, 충돌을 처리하기 전에 호출되는 메소드

    void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
    { /* handle pre-solve event */ }
  • PostSolve: 충돌 처리 이후에 호출되는 메소드

    void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse)
    { /* handle post-solve event */ }

메소드 수정 예시

  • 올라갈 때만 통과 가능한 일방적 플랫폼 구현 시

    void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) override
    {
        ContactListener::PreSolve(contact, oldManifold);
    
        b2Fixture* fixtureA = contact->GetFixtureA();
        b2Fixture* fixtureB = contact->GetFixtureB();
    
        if (fixtureA != m_platform && fixtureA != m_character)
        {
            return;
        }
    
        if (fixtureB != m_platform && fixtureB != m_character)
        {
            return;
        }
    
        b2Vec2 position = m_character->GetBody()->GetPosition();
    
        if (position.y < m_top + m_radius - 3.0f * b2_linearSlop)
        {
            contact->SetEnabled(false);
        }
    }
  • 충돌 속도 감지와 이벤트 구현 시

    void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
    {
        b2WorldManifold worldManifold;
        contact->GetWorldManifold(&worldManifold);
    
        b2PointState state1[2], state2[2];
        b2GetPointStates(state1, state2, oldManifold, contact->GetManifold());
    
        if (state2[0] == b2_addState)
        {
            const b2Body* bodyA = contact->GetFixtureA()->GetBody();
            const b2Body* bodyB = contact->GetFixtureB()->GetBody();
            b2Vec2 point = worldManifold.points[0];
            b2Vec2 vA = bodyA->GetLinearVelocityFromWorldPoint(point);
            b2Vec2 vB = bodyB->GetLinearVelocityFromWorldPoint(point);
    
            float approachVelocity = b2Dot(vB -- vA, worldManifold.normal);
    
            if (approachVelocity > 1.0f)
            {
                MyPlayCollisionSound();
            }
        }
    }
Clone this wiki locally