190 likes | 362 Vues
This guide covers the implementation of collision handling in Box2D using C++. By subclassing `b2ContactListener`, you can receive collision callbacks through `BeginContact` and `EndContact`, allowing you to implement game logic, sounds, and more. The guide explains how to obtain references to the colliding sprites, manage contact listener objects, and appropriately color sprites upon collision. It also discusses methods for tagging and identifying colliding bodies, enabling you to execute specific actions based on collision events.
E N D
Collision handling • If you want to receive collision callbacks, you need to subclass b2ContactListener (in C++, rename implementation file to .mm) • BeginContact and EndContact will be called automatically; they are a good place to implement game logic, sounds, .. • Note: you cannot create or destroy Box2D entities inside these methods
Collision handling # import “Box2D.h” class ContactListener : public b2ContactListener { // … }; // do not forget ; here
Collision ! (BeginContact) • When a collision between 2 bodies is detected, BeginContact is called • void BeginContact( b2Contact *contact); • Override it if you want to execute some code at that time
Collision ! (BeginContact) • In ContactListener.mm void ContactListener::BeginContact( b2Contact *contact ) { // update sprites, game logic, play sound, … }
Collision ! (BeginContact) • The class b2Contact encapsulates a contact between 2 (and only 2) entities, A and B • GetFixtureA( ) and GetFixtureB( ) will give you references to the 2 fixtures • Then you can call GetBody( ) to have references to the 2 bodies • Then you can call GetUserData( ) to get references to the 2 sprites
Sprites that collided b2Body *bodyA = contact -> GetFixtureA( ) -> GetBody( ); b2Body *bodyB = contact -> GetFixtureB( ) -> GetBody( ); CCSprite *spriteA = (CCSprite *) bodyA -> GetUserData( ); CCSprite *spriteB = (CCSprite *) bodyB -> GetUserData( );
Sprites that collided if( spriteA != NULL && spriteB != NULL ) { // color sprites in red spriteA.color = ccMAGENTA; spriteB.color = ccMAGENTA; }
Sprites that collided • What if we want to know which sprite is what? • One could be a bullet, the other could be an enemy can tag the sprites and check the tag property for that
End of collision (EndContact) • When a collision between 2 bodies ends, EndContact is called • void EndContact( b2Contact *contact); • Override it if you want to execute some code at that time
Using ContactListener • We need to do 2 things in the layer class • Instantiate a ContactListener object • Set the contact listener of the world to be that object
Using ContactListener • In .h file #import “ContactListener” // ContactListener instance variable ContactListener *contactListener;
Using ContactListener • In .mm file contactListener = new ContactListener( ); world->SetContactListener( contactListener ); • And inside dealloc delete contactListener;
Collision ! (BeginContact) • We could also play a sound when 2 sprites collide • We could also have a state variable so that we play a sound on the first collision between 2 sprites, but not the secondary collisions • Since we can get the bodies, we could retrieve the linear velocity, and depending on its value, adjust the intensity of the sound
Collision ! A vs B • Does A (or B ) have a dynamic or static body? int typeOfBodyA = bodyA -> GetFixtureList( )->GetType( ); • // 1 static body • // 2 dynamic body
Collision ! A vs B • If A and B both have a dynamic body, then what are they? Spider? Ship? Bullet? Player? … • We can retrieve the sprite based on the body • If the sprite has been tagged earlier, we can retrieve the tag, that can identify the type of sprite
Collision ! A vs B • We will tag the blocks to identify them • 4 blocks: A, B, C, D • 4 different tags
Collision ! A vs B • Convert idx idy binary to decimal • int tag = 2 * idx + idy; • 0, 1, 2, or 3
Collision ! A vs B CCSprite * spriteA = ( CCSprite *) bodyA -> GetUserData( ); // could be null if the body is static if( spriteA != NULL ) int tagOfA = spriteA.tag; • Now we can decide what to do baed on the tag value