• 190 likes • 343 Views
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, ..
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