How to Make a Game Like Jetpack Joyride using LevelHelper, SpriteHelper [Cocos2D 2.X edition] – Part 3
In this part of the series, you’ll make your game fully capable of handling collisions. In other words, by the end of this part you’ll be able to reward and kill the mouse! By .
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
How to Make a Game Like Jetpack Joyride using LevelHelper, SpriteHelper [Cocos2D 2.X edition] – Part 3
25 mins
Implementing Collisions: Lasers
The next step is to handle the collision between the lasers and the mouse.
Add the following at the end of setupCollisionHandling in HelloWorldLayer.mm:
[loader registerPreCollisionCallbackBetweenTagA:PLAYER
andTagB:LASER
idListener:self
selListener:@selector(mouseLaserCollision:)];
The above code registers a pre-collision callback for collisions between the player and the lasers. Since the laser sprites are not sensors, you want to receive notifications about this type of collision on every frame in order to kill the mouse when the laser does become active.
Add the mouseLaserCollision: method:
-(void)mouseLaserCollision:(LHContactInfo*)contact {
LHSprite* laser = [contact spriteB];
int frame = [laser currentFrame];
// If we make the laser a sensor, the callback will be called only once - at first collision.
// This is not good as we want to kill the player when the laser changes to active.
// So we disable the contact so that the player and laser don't collide, but trigger a collision.
// Disabling the contact is only active for one frame,
// so on the next frame the contact will be active again, triggering the collision.
b2Contact* box2dContact = [contact contact];
box2dContact->SetEnabled(false);
if(playerIsDead)
return;
if(frame != 0) {
[self killPlayer];
}
}
The above code gets sprite B from the contact info. In this case sprite B is the laser. Then the code takes the current frame from the sprite, because it needs to test if the laser is active so that the player can be killed if it is.
Then the code takes the Box2D contact information from the LevelHelper contact object and disables the contact so that no collision behavior will occur during the current frame. It then checks whether the player is dead. If so, nothing further is done.
Finally, the code tests if the frame number is not 0. If it is 0, then the laser is not on and the player is safe. If it’s not 0, it means that the mouse struck a live laser and so, the player has to be killed.
The above code has two elements that have not been defined yet: the killPlayer method and the playerIsDead variable. So let’s define them.
Switch to HelloWorldLayer.h and add the following instance variable:
bool playerIsDead;
Then add the killPlayer implementation to HelloWorldLayer.mm:
-(void)killPlayer {
playerVelocity = 0.0;
playerShouldFly = false;
playerIsDead = true;
playerWasFlying = false;
[rocketFlame setVisible:NO];
[player prepareAnimationNamed:@"mouseDie" fromSHScene:@"Animations"];
[player playAnimation];
[paralaxNode setSpeed:0];
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCLabelTTF *label = [CCLabelTTF labelWithString:@"Game Over"
fontName:@"Marker Felt"
fontSize:64];
label.color = ccRED;
label.position = ccp(winSize.width*0.5, winSize.height*0.75);
[self addChild:label];
CCMenuItem *item = [CCMenuItemFont itemWithString:@"Restart"
target:self
selector:@selector(restartGame)];
CCMenu *menu = [CCMenu menuWithItems:item, nil];
[menu alignItemsVertically];
[self addChild:menu];
}
This is what the above code does:
- Set the velocity of the player to 0. If the player was flying, he will now fall to the ground.
- Set the playerIsDead variable to TRUE so we know the player is dead in the methods where this information is a factor.
- Hide the rocket flame.
- Start the death animation on the player sprite by using a LevelHelper method that will take as arguments the animation’s unique name and the sprite on which the animation should be performed.
- Stop the parallax from moving by setting its speed to 0.
Note: For more details on using animations with LevelHelper, check out the LevelHelper API via the Documentation tab in LevelHelper.
Note: For more details on using animations with LevelHelper, check out the LevelHelper API via the Documentation tab in LevelHelper.
Now you need to create a Cocos2d menu so that you can restart the game if the player dies. Define the necessary method method as follows:
-(void)restartGame {
[[CCDirector sharedDirector] replaceScene:[HelloWorldLayer scene]];
}
Compile and run. Your mouse can now die if he collides with a laser!
Note: If a collision does not work as it should, check to make sure that you have the correct tags set on the sprites.
Note: If a collision does not work as it should, check to make sure that you have the correct tags set on the sprites.
Gratuitous Sound Effects
If you’ve read game tutorials on this blog before, you know we’d never leave you hanging without some gratuitous (and awesome) sound effects! :]
Navigate to your Xcode Resources folder in Finder. Then, open a new Finder window and navigate to where you saved the sounds pack that you downloaded at the beginning of this tutorial.
Inside the Resources folder, create a new folder called Music, and drag all the sound files from the sound pack into this new folder.
Now go back to Xcode and add the music assets to the project by right-clicking (or Control-clicking) on the Resources folder and choosing “Add Files to RocketMouse.”
From the new dialog, navigate to your Resources folder, select the Music folder, and click the Add button.
Your new Resources folder in Xcode should look something like this:
Now that you’ve added the sound files to your project, let’s add some code to make some noise!
At the top of HelloWorldLayer.mm import the audio engine:
#import "SimpleAudioEngine.h"
Now add a new method that will load the sounds:
-(void) setupAudio {
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"backgroundMusic.m4a"];
[[SimpleAudioEngine sharedEngine] preloadEffect:@"coin.wav"];
[[SimpleAudioEngine sharedEngine] preloadEffect:@"fly.wav"];
[[SimpleAudioEngine sharedEngine] preloadEffect:@"ground.wav"];
[[SimpleAudioEngine sharedEngine] preloadEffect:@"hitObject.wav"];
[[SimpleAudioEngine sharedEngine] preloadEffect:@"laser.wav"];
[[SimpleAudioEngine sharedEngine] preloadEffect:@"lose.wav"];
[[SimpleAudioEngine sharedEngine] preloadEffect:@"bunnyHit.wav"];
}
Next, add the following line to init (right before the call to scheduleUpdate):
[self setupAudio];
This loads all the sounds in the pack – backgroundMusic.m4a is loaded as a music asset and the rest of the files are preloaded as effects. Now we have to match the sound effects to the events that will generate them.
Add the following to the end of mouseCoinCollision::
[[SimpleAudioEngine sharedEngine] playEffect:@"coin.wav"];
In mouseLaserCollision: add the following inside the if(frame != 0) block:
[[SimpleAudioEngine sharedEngine] playEffect:@"laser.wav"];
Let’s also add a flying sound. Inside update:, add the following inside the if (playerShouldFly) block:
[[SimpleAudioEngine sharedEngine] playEffect:@"fly.wav"];
Compile and run. Enjoy the new music and sound effects! :]
The complete project up to this point can be downloaded from here.