How to Make a Game Like Jetpack Joyride using LevelHelper, SpriteHelper [Cocos2D 2.X edition] – Part 4

Welcome to the fourth and final instalment of the tutorial series. You’ll continue where you left off by devising a system to track the player’s score as well as adding cute bunnies for bonus points. By .

Leave a rating/review
Save for later
Share

Contents

Hide contents

How to Make a Game Like Jetpack Joyride using LevelHelper, SpriteHelper [Cocos2D 2.X edition] – Part 4

15 mins

This is a post by special contributor Bogdan Vladu, an iOS application developer and aspiring game developer living in Bucharest, Romania.

Hello again, and welcome to the fourth and final instalment of the tutorial series on LevelHelper and SpriteHelper. I said that by the end of this series you would have an exciting game to play, and you’re almost there!

Last time, in Part Three, you came close to completing your game. You fully implemented collisions between the player and the other game elements, enabling the player to die and score points. You also made the player fly and added some nice sounds and animations.

But there are still a few improvements you can make. For one thing, you need a way to keep track of the score, and while you’re at it, you might as well add some cute moving bunnies that will be worth bonus points.

And wouldn’t it be interesting if you made some of your lasers rotate? Keep reading to do all that and complete the game!

Getting Started: Rotating Lasers

You pick up the project where you left off at the end of Part Three. You can download that version of the project here.

You can’t have your game be too easy, can you? So, the first thing you’ll do is make your lasers rotate.

Open your project in LevelHelper, and make sure you have the latest version of your level open. Then go to Define Tags and define a new tag named ROTATING_LASERS.

Don’t forget to regenerate the supporting code since you added a new tag.

You will use this new tag to reference the lasers you select to rotate (not all of them… you’re not that evil, are you?) when you implement the rotation via code.

Now select a couple of the lasers in the level – make sure the lasers you select have room to rotate. Assign the ROTATING_LASERS tag to the selected lasers.

Once you’re done tagging the lasers, save the level and open your Xcode project. Navigate to HelloWorldLayer.h and add the following instance variable:

NSArray* rotatingLasers;

Then add the following code at the end of retrieveRequiredObjects in HelloWorldLayer.mm:

rotatingLasers = [loader spritesWithTag:ROTATING_LASERS];
[rotatingLasers retain];

Here you get references to all the sprites that have the ROTATING_LASERS tag. Because the array returned by this method is autoreleased, you retain it. So that you won’t forget to release this retained array later, go to dealloc and add the following at the top of the method:

[rotatingLasers release];

Now that you’ve grabbed the lasers that you want, time to make them rotate! Add the following to the end of update::

for(LHSprite* laser in rotatingLasers) {
    [laser transformRotation:[laser rotation]+1];
}

If you run the game now, the chosen lasers will rotate, but the player won’t die when he makes contact with them. This is because the rotating lasers are no longer tagged as LASER. You need to register a collision event for the ROTATING_LASERS tag. To do that, add the following to the end of setupCollisionHandling:

    [loader registerPreCollisionCallbackBetweenTagA:PLAYER
                                            andTagB:ROTATING_LASERS
                                         idListener:self
                                        selListener:@selector(mouseLaserCollision:)];

Running the game now, the lasers will rotate and kill the player just as the non-rotating lasers do.

Congrats, you have just added another layer of difficulty to your game! That said, you may want to play-test the game some more at this point to make sure the player can still get through the level!

Moving Bunnies

Running and flying over sleeping cats and dogs and dodging rotating lasers is all fun, but let’s add another reward component to the game to give it more complexity.

I have just the ticket: bunnies. Cute, helpless bunnies that our player can kill for points.

Open the Animations.pshs SpriteHelper document. Then open Finder and navigate to the ArtPack folder (download it from Part One if you don’t have it), select the bunnies images and drag them on to the SpriteHelper window.

Now do the following:

  1. Select the “bunny_1” sprite in the list and switch over to the Physics tab.
  2. Create 2 fixtures on the bunny using “Create New Circle Shape”. Rename the two fixtures as “bunnyFixBody” and “bunnyFixHead”. Use the “Edit shape” button and “Radius” property” to resize the two shapes and place them correctly on the sprite.
  3. Check “Is Sensor” for both the shapes.
  4. Set the body type to “Static”.

Note: While I also have “Fix Rotation” checked (in the image below), this is not mandatory since the body is static. This property only has effect when the body is dynamic.

Next, create the following two animations using the bunny frames:

  • Animation Name: BunnyRun
  • Speed: 0.400 (default)
  • StartAtLaunch: YES (default)
  • LoopForever: YES
  • Frames: bunny_1, bunny2

  • Animation Name: BunnyDie
  • Speed: 0.400 (default)
  • StartAtLaunch: YES (default)
  • LoopForever: NO (default)
  • Frames: bunny_die_1, bunny_die_2

When you’re done creating the animations, save the scene.

Going back to LevelHelper, you should see the bunny animations inside the Animations section. (If you don’t, use the reload button or failing that, close and relaunch LevelHelper.)

Select the “bunny_1” sprite and drag it on to your level. Then assign the “BunnyRun” animation to the new sprite.

You now have a bunny in the level, but it will not be visible because you need to move it with the parallax.

To add the bunny to the parallax, go to the Parallax tab, select your parallax node and add the bunny sprite to it. Set the x component of the movement ratio to 1 so that the bunny moves at the same speed as your level.

Running the level in Scene Tester, you should see the bunny moving with the parallax, but the bunny appears to be moving in place. You want the bunny to move from right to left and from left to right. To do this, you have to make it move on a path.

Open the Bezier tool and click “Start Bezier Creation” to create a new bezier path that will describe the path taken by the bunny. Click in the level twice to create a path from the first click point to the second click point.

When you’re done, click on the “Finish Bezier” button.

With the bezier selected (use the Level Navigator if the path is not selected), navigate to “Bezier Properties” and select “Is Line” and “Is Path”.

You now have a path, but the bunny sprite doesn’t know that it should move on that path. Let’s make the bunny aware of this.

Select the bunny, then in the “Path Movement” section, select the bezier name from the “Path Name:” property.

In the Path Movement section, make the motion cyclic by selecting “Cyclic Motion.”

Set the amount of time you want the bunny to take to move from one end of the bezier to the other (or, leave it at the default value). Then select “Flip Sprite X At Ends” so that the bunny is always facing in the direction it is moving. Otherwise, it will appear to be moving backwards half the time.

If you now test the level in Scene Tester, the bunny should move along the path and also move with the parallax. This is cool, eh? LevelHelper is the only editor that lets you move sprites on a path and with a continuos scrolling parallax at the same time.

The last step in LevelHelper is to define a new tag called “BUNNY” and assign it to the bunny sprite. Once you’ve done this, save the level. (Don’t forget to regenerate the code after you have added the BUNNY tag.)

Time to move back to your Xcode project and write some code that will make the bunny die when the player collides with it.

Add the following to the end of setupCollisionHandling:

    [loader registerBeginOrEndCollisionCallbackBetweenTagA:PLAYER
                                                   andTagB:BUNNY
                                                idListener:self
                                               selListener:@selector(mouseBunnyCollision:)];

This registers the collision callback, but you also need to define the method for the callback. Add it as follows:

-(void)mouseBunnyCollision:(LHContactInfo*)contact {
    if(playerIsDead)
        return;
    LHSprite* bunny = [contact spriteB];
    
    if (nil != bunny) {
        if ([[bunny animationName] isEqualToString:@"BunnyRun"]) {
            [self scoreHitAtPosition:[bunny position] withPoints:500];
            [[SimpleAudioEngine sharedEngine] playEffect:@"bunnyHit.wav"];
        }
        [bunny prepareAnimationNamed:@"BunnyDie" fromSHScene:@"Animations"];
        [bunny playAnimation];
        [bunny pausePathMovement];
    }
}

The above code tests for a dead player and does nothing if that’s the case. It then takes the bunny sprite from the contact and tests if it’s valid and whether it’s running the “bunnyRun” animation.

If the bunny sprite meets both conditions, the player is given 500 points and the bunny hit sound is played (part of the sound pack downloaded in Part Three of this series). You then start the bunnyDie animation on the bunny sprite and stop the sprite’s movement along the path.

If you run the game now, you’ll see that the bunny dies when he collides with the mouse. But if you loop through the entire level, you’ll see that the bunny you killed doesn’t reappear in the level – it stays dead! So let’s do the same thing you did with the coins in Part Three and reset the bunny.

Find spriteInParallaxHasReset: in HelloWorldLayer.mm and modify it to look like this:

-(void)spriteInParallaxHasReset:(LHSprite*)sprite {
    if(COIN == [sprite tag]){
        [sprite setVisible:YES];
    }
    else if(BUNNY == [sprite tag]){
        [sprite prepareAnimationNamed:@"BunnyRun" fromSHScene:@"Animations"];
        [sprite playAnimation];
        [sprite startPathMovement];
    }
}

Above, you simply check for the BUNNY tag, and when you find a sprite that is a bunny, you set its animation to bunnyRun and start its path movement.

Because sometimes the player (mouse) Box2D body goes to sleep – the collision between the player (mouse) and the bunny may not get triggered. To fix this, open the Animations.pshs SpriteHelper document and uncheck “Can Sleep” on “rocketmouse_1_run” and on “bunny_1”

The complete project up to this point is available here.