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

Bogdan Vladu

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

Learn how to create a game like Jetpack Joyride with latest LevelHelper and SpriteHelper!

Learn how to create a game like Jetpack Joyride with latest LevelHelper and SpriteHelper!

In this tutorial series, we will create a game similar to Jetpack Joyride using latest Cocos2D and Box2D. (Prefer Corona? Check out the Corona version of this tutorial!)

If you haven’t played Jetpack Joyride yet, you should check it out – it’s an incredibly polished and fun game, and best of all it’s free! :]

You could make this game with Cocos2D alone, but it would take a lot of time. To make things simpler, we’re going to use two tools written by yours truly – LevelHelper and SpriteHelper.

If you aren’t familiar with these tools, here’s a quick synopsis:

  • LevelHelper is a tool that makes creating levels much easier. You literally drag and drop sprites onto the scene!
  • SpriteHelper is a tool that creates the sprite sheets, physics shapes and animations for your games quickly and easily.

This is going to be a complex game, and we have a lot to do, so this series will be spread over four parts. In this first part, we’ll first spend some time setting up LevelHelper. Then we’ll create a basic level with a continuous scrolling parallax, and learn how to use SpriteHelper to add and modify our art.

By the end of this series, not only will you have earned valuable experience with these tools – you will have an exciting, sophisticated game to play!

This tutorial assumes you have some basic familiarity with Cocos2D and Box2D. If you are new to either of these game frameworks, you should check out our Cocos2D and Box2D tutorials first.

Getting Started

To get started, you just need to download several things:

Note: LevelHelper supports all versions of Cocos2D. As a general rule, it is better that you first go through the official step by step guide of LevelHelper which can be found under the Documentation section of www.gamedevhelper.com.

Installing Cocos2d Templates


After downloading Cocos2d 2.1 beta 4, unzip the archive. Open “Terminal” app and drag “install-templates.sh” file over the “Terminal” window.
Press Enter.
If you get an error saying that the templates are already installed, repeat the process again but add “-f” at the end of the terminal command before pressing Enter.

w00t you’ve installed the template! Now let’s try it out.

Creating Our Xcode Project

Open Xcode and choose File\New\New Project from the main menu.

Select the iOS\Cocos2d v2.x\Cocos2d iOS with Box2D template, and click Next.

In the next dialog, name your product “RocketMouse” (no spaces) and if you want, give an identifier or leave the default one. Click Next when ready.

Compile and run the project to test that everything is working:

Nice – soon you will see how easy it is to integrate LevelHelper and load some levels! :]

Cleaning Up What We Don’t Need

We could extend the template code from here, but to give you the best understanding of how everything works we’re going to start from scratch.

So let’s clean up everything we don’t need from the template code.

Keep reading to clean this up yourself, but if you’re feeling particularly lazy, you can download the cleaned up project and just skim over these steps :P

Inside Xcode, navigate and click on HelloWorldLayer.h and delete the Box2D PTM_RATIO define and the spriteTexture_ variable.

With the header file cleaned, navigate and click on HelloWorldLayer.mm file. Clean the source as pointed in the next images.

Note: When working with Box2D, all source files must have a “.mm” extension in order to tell Xcode to compile using the Objective C++ compiler since Box2D is a C++ library. If the extension is “.m”, Xcode will compile that file with the Objective-C compiler and Box2D will give lots of errors.

Preparing for LevelHelper

Let’s create two folders in the Resource folder of our Xcode project. While we don’t really need to do this, keeping our project organized will make our work easier!

In Finder, navigate to your Xcode project, open its Resources folder, and create two sub folders named “Images” and “Levels”. Important: Create these in Finder, not Xcode!

You should end up with something like this:

Creating a LevelHelper Project

Now that the project set up is complete, we can finally start creating our level with LevelHelper!

LevelHelper will keep things organized in projects. This means level files are part of the project and its mandatory that you save them inside a subfolder of the project.

So let’s create a new project with LevelHelper. Open it up and go to File\New Project:

A new window will appear. In the Project Name field, enter “RocketMouse,” the name of our project and press Next.

In the project settings window choose “Universal” and Landscape orientation. (default settings) and press Next.

Note: When you want to create a game for all models of iPhone and iPad, you generally want to choose Universal with Landscape or Portrait orientation. LevelHelper will automatically use image.png on iPhone2G/3G/3GS, image-hd.png on iPhone 4/4S/5,iPad1/iPad2,iPad Mini and image-ipadhd.png on iPad3/4.

The final step is to save the project file. Choose the topmost folder of your project. The folder where the Xcode project file is located.

LevelHelper will use this folder as the main project folder. Everything you save and edit with LevelHelper must be located somewhere inside this folder. The Mac App Store version of LevelHelper will have sandbox access to this folder. Trying to open something outside this project folder will be restricted by sandbox and will give an error.

Now the LevelHelper window should look something like this:

But we have no image, no nothing! Time to start adding our art.

Adding Art to Our LevelHelper Project

To add our art, we need to use SpriteHelper, so go ahead and open it up.

Now navigate to where you saved the art pack for this tutorial. Select the art inside the “objects” folder and drag it inside SpriteHelper.

SpriteHelper can contain multiple sheets per document so lets go ahead and rename this sheet to “objects” by changing the “Sheet Name” property.
Press enter so the change will take effect.
The resulting scene should look similar to this (sprites may be packed differently)

You might see that some sprites are trimmed and/or rotated so that the packing takes the smallest amount of space possible.

Note: Crop: means the empty space around the sprites will be removed entirely. This should not be used with sprites part of an animations as the position of a particular sprite in a frame may be changed.

Trim: means the empty space around the sprites will be removed but added back when the sprite is loaded in the game engine. This is useful for animations as the position of the frame is not changed.

Save the scene inside the Images folder that we created earlier in the Resource folder. Go to File\Save As.

Give a name to the SpriteHelper document and choose “Universal” since we are creating a universal project.

If you look inside Images folder you will see that SpriteHelper has created 3 images. One for each type of device.

The name of the image files has the following format:

[SpriteHelper Document Name]_[Sheet Name][device suffix].[extension];

So in our case, we named the SpriteHelper Document “RocketMouseAssets”
The sheet was named “objects”
And we used “png” file as the extension.

This will result in:
RocketMouseAssets_objects.png – to be used by iPhone 2G/3G/3GS
RocketMouseAssets_objects-hd.png – to be used by iPhone4/4S/5, iPad1/2,Mini
RocketMouseAssets_objects-ipadhd.png – to be used by iPad3/4

If you look inside the LevelHelper window now, you’ll see that the art has automatically been added for you.

LevelHelper keeps track of all the changes inside the project folder. Every time you add, remove or modify a file inside this folder, LevelHelper will automatically update its content.

Note: If you do not see the art in LevelHelper, click the refresh button (marked by a red circle in the image above).

Creating a Basic Level

Let’s start by creating a level with a scrolling floor and wallpaper background.

We first want to create a continuous scrolling parallax that will move from right to left. To do this, let’s decide how big our parallax will be. You can make it as big as you want.

Let’s make our game world the size of 8 screen sizes. Click the Game World Size button.

In the Width field, enter 3840. This is 480 (the width of the iPhone screen) multiplied by 8.

Now let’s create the background. Drag the bg sprite on to the level, and place it right at the beginning of the first screen. The first screen should be on the left side, and is denoted by a red border.

Now drag a bg_window sprite right next to that so they are next to each other, creating a seamless wall with a window.

Now we’re going to duplicate these sprites so that they cover all of our screens. With the two background sprites selected, set the clone direction via the relevant UI control on the left sidebar as shown in the image below. Select the right center segment so that the cloning will create new copies of the objects to the right of the current objects.

Then click the + button (marked in the image below). This is the clone button. (Alternatively, you could press Command+D). Continue pressing this button until the background sprites cover all sections of all eight screens. Do not go any further.

Note: You can scroll the level in LevelHelper by holding control as you drag the level, by dragging with the right mouse button pressed, or by swiping with two fingers over the trackpad. You can zoom in and out by holding the option key as you scroll the mouse wheel or by pinching the trackpad.

Let’s add these images to a continuous scrolling parallax. Navigate to the Parallax tab (the one that says “P”) and press the New Parallax button.

With the parallax selected, check the Continuous Scrolling option, “Right to Left” direction and enter a speed of about 150.

Now select all the background sprites in the level by going to the Level Navigator and click the Add Selected Scene Sprite(s) button in the parallax section.

There are still some adjustments to make to our continuous scrolling parallax.

Select all the sprites in the parallax list and set the Movement Ratio to “1”. This ratio and the speed determine the rate at which the sprites will move through the parallax.

In this case, the sprites will move at the rate of 1*150 (ratio*speed). If we want other sprites to move at a different rate, we can modify the ratio accordingly (e.g. 0.4*150).

If you run Scene Tester right now you will see the continuous parallax in action!

How to install Scene Tester:

  1. Press the “Scene Tester” button.
  2. Choose YES in order to go to the download page.
  3. On the web page press on the “Download Scene Tester” link.
  4. Unzip the LHSceneTester.zip file once downloaded.
  5. Run the LHSceneTester.app directly at least once.
  6. If on Lion or Mountain Lion choose Open when asked.
  7. Close Scene Tester.
  8. Inside LevelHelper tap on the “Scene Tester” button again.
  9. Choose Browse and point to “LHSceneTester.app” file.

Now the installation is complete. You only need to do this once.

If a line appears along the point where two sprites meet, this is a common issue in games caused by the movement of the objects that are pixel perfect next to each other. To fix this, select all the sprites and give a 1.02 (or an appropriate value) to the Scale X property (this will make the sprites be just a little bit on top of each other). (Remember, the Scale X property is on the Properties Navigator and you might currently be on the Parallax Navigator – so switch tabs :])

Let’s save this level and run it as an Xcode project. Inside LevelHelper, go to File\Save Level As.

In the dialog box, enter “level01″ and click Save. (You might need to make sure that the destination folder is correctly set to the Levels folder that you created earlier …)

By saving the level, we caused LevelHelper to update the Levels section. Switch to the Project Navigator and then go to the Levels to see the level file. By double clicking on a level, you can open that level inside LevelHelper.

Now let’s move back to Xcode. Open your RocketMouse Xcode project if it’s not open already. Right click or Control-click on the Resources folder inside Xcode, and select Add Files To “RocketMouse.”

A new window will appear. Navigate to the Resources folder on your hard drive and select both the Images and the Levels folders. Then press the Add button to copy them to the Resources folder in Xcode.

Your Resources folder in Xcode should now look like this:

Back in LevelHelper, navigate to the “Supporting Code” tab. Choose Cocos2d with Box2D, choose the 1.4.9 branch and latest code revision (You might need to tap the triangle next to the Branch header to expand the list of revisions). After that, press on the “Update Supporting Code to Selected Revision” button.

This will download the latest LevelHelper API code to your machine. Check back here regularly in order to stay up-to-date. Read the logs to see what was fixed or added in the API.

Now you can generate the supporting code for your project. Choose File/Generate Code/Cocos2d With Box2D(Objective C++)

In the new window navigate to your project. Choose the folder where you want the API to be generated (usually where HelloWorldLayer.mm file is located). Choose “Manually add supporting code in your Xcode project”:

With the code generated, go back to Xcode and add the new files by Control+clicking on the “HelloWorldLayer.mm” file and choosing “Add Files to Rocket Mouse”. Select the “LevelHelper” folder and click “Add”:

Now that we have all the necessary files in the Xcode project, lets use the LevelHelper API.

Navigate to HelloWorldLayer.h and add the following import statement:

#import "LevelHelperLoader.h"

Also add a variable of type LevelHelperLoader that we will use to load the level file:

    LevelHelperLoader* loader;

Switch to HelloWorldLayer.mm and add the following code to init just after the [self initPhysics]; line:

        loader = [[LevelHelperLoader alloc] initWithContentOfFile:@"level01"];
        [loader addObjectsToWorld:world cocos2dLayer:self];

It is important that you load the level after the Box2D world is created.

Because the above code allocates memory, we must also release it. Find dealloc and add the following lines at the very top:

[loader release];
loader = nil;

It is very important that you release the LevelHelperLoader object before deleting the Box2D world or else you will have a crash when you replace the scene.

That’s all it takes to run your level – pretty cool eh?
You can download the project as it stands up to this point from here.

Creating the Full Level

Let’s go back to LevelHelper and add the remaining art so that we have a final level to play with.

Drag the small bookshelf onto the main screen. Drag it around until you are satisfied with its placement relative to the background sprite.

With the bookshelf sprite selected in the level, click the Clone Tool button in order to make multiple clones of this sprite.

Set the number of clones to 7, and set offset X to 500 and offset Y to 0.

You should see a series of outlines indicating how the sprites will be set in the level. Click the “Make Clones” button when you are satisfied.

Note: Right clicking on any stepper button will reset the associated field to the default value.

Now let’s repeat the process to add the rest of the art.

Add in the big bookshelf, the cat, the dog and the window sprites and place them according to your preferences.

I’ve opted to put the dog under each window, because dogs like to look out the window. I’ve placed the cat next to each mouse hole, for obvious reasons. And I’ve placed the bookshelves randomly in the level.

My final level looks like this:

If you enable the Show Polygon Shapes option inside LevelHelper, you’ll see that the sprites have no physic shapes on them.

If your sprites have “Handled by SpriteHelper” selected, each time you do a change in the corresponding SpriteHelper document, the change will be immediately visible in the level.

Fortunately “Handled By SpriteHelper” is the default setting, so you shouldn’t need to do anything to enable it. Now open the SpriteHelper document and modify the settings for the sprites. You could do this by opening SpriteHelper and then opening that document, but there’s an easier way: simply click the “Edit” button.

Note: The Physice Properties section with the “Edit” button might not be visible if you are at the top of the Properties Navigator. The Properties Navigator has a lot of sections – so scroll down a bit to get to the Physics Properties section.

This will open the needed scene in SpriteHelper, where you can select the sprite you want to modify the physics properties for.

With the dog sprite selected, go to the Physics tab. Press on the “Create New Auto Traced Shape”. Select Static as the body type. Double click on the fixture name to rename it and further optimize the shape by moving the “Optimize Fixture” slider.

That’s all there is to it. Isn’t that cool?

Repeat the process for the cat sprite.

Save the scene when you’re done. (press “Command-S”)

Now if you go back to LevelHelper, you’ll see that the level has been updated and the cat and dog sprites have physics shapes. Save the level as a new level by pressing Command-Shift-S. Name it “level02.”

If you run Scene Tester now (press “Test Level” button), you’ll see that only the background sprite will move.

Let’s add the other sprites to the parallax. To do this, first select all sprites except the background sprites that have already been added to the parallax.

Now go to the Parallax tab, select your parallax and add the selected sprites.

Select the sprites from the list of sprites in the parallax, and set the Movement Ratio to 1.

If you run Scene Tester now, all the sprites in the scene should move at the same speed continuously.

Lets create a background sheet inside the SpriteHelper document. Each sheet represent a batch node so this will make it easier for you to sort sprites by z order. You will understand more in a minute.

With your SpriteHelper document open, click on the + button to create a new sheet and drag all images from the “background” folder on to it.

Rename the new sheet to “background” and then save it (Command-S).

If you now look in LevelHelper, you will see that your SpriteHelper document has 2 sheets. (Reload the document if you don’t see the two sheets.)

Drag the “window_background” sprite on to your scene and place it somewhere above the other sprites. Set its z order to -1

Drag the “window_foreground” sprite on top of the “window_background” sprite. Leave the z order at 0.

With both the new sprites selected, clone them until the end of the 8 screens.

Add all the new sprites to the parallax. Set the ratio to 0.4 for the “background” sprites and 0.7 for the “foreground” sprites.

Now select all the new sprites and drag them on top of the windows. As you can see all the new sprites are above the other sprites:

But we need them to be behind the existing sprites. So, select the “background” batch node from the Level Navigator and change its z order to -1.

Save the level! If you run Scene Tester now you will see that the outside sprites move at a slower rate, giving a feeling of depth.

Now let’s try it out in your app! Switch back to Xcode, control-click on your Resources\Levels folder, select Add Files to RocketMouse. Add the new level file “level02.plhs”.

Also right-click on the Resource\Images folder and add the new sheet images.

Your new Resource folder should look something like this:

Change the level loader code to set “level02″ as the argument.

lh = [[LevelHelperLoader alloc] initWithContentOfFile:@"level02"];

Compile and run. Your level is looking a lot more interesting!

Basic scrolling level made with LevelHelper

Update physics

In order for the physic shapes to be synchronized with the sprites, replace the current update: implementation in HelloWorldLayer.mm with this:

-(void) update:(ccTime)dt {
	//It is recommended that a fixed time step is used with Box2D for stability
	//of the simulation, however, we are using a variable time step here.
	//You need to make an informed choice, the following URL is useful
	//http://gafferongames.com/game-physics/fix-your-timestep/
 
	int32 velocityIterations = 8;
	int32 positionIterations = 1;
 
	// Instruct the world to perform a single step of simulation. It is
	// generally best to keep the time step and iterations fixed.
	world->Step(dt, velocityIterations, positionIterations);
 
    //Iterate over the bodies in the physics world
    for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
    {
        if (b->GetUserData() != NULL)
        {
            //Synchronize the AtlasSprites position and rotation with the corresponding body
            LHSprite *myActor = (LHSprite*)b->GetUserData();
 
            if(myActor != 0)
            {
                //THIS IS VERY IMPORTANT - GETTING THE POSITION FROM BOX2D TO COCOS2D
                myActor.position = [LevelHelperLoader metersToPoints:b->GetPosition()];
                myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
            }
 
        }
    }
}

Where to Go From Here?

So now we have our basic level! But most significantly – we’ve learned a great deal about navigating within and between LevelHelper and SpriteHelper, and adding and modifying that all-important art.

You can download the entire project up to this point here.

In Part Two, we’ll learn how to add and work with animations and sensors. We’ll also create our player, and begin working with tags – the first step in implementing collisions between sprites. In other words, the action begins!

Things will get even more interesting in the third and fourth parts. Besides fully implementing collisions, we’ll animate takeoffs and landings, learn how to kill the player and restart the game, create and display a scoring system, and add plenty of other cool features.

In other words, you definitely want to continue with this series :] Getting through the basics is always challenging, so if you’ve made it this far, congratulations! In the meantime, I look forward to reading and responding to your questions, comments and suggestions in the LevelHelper forum and in the forum below.


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

User Comments

16 Comments

[ 1 , 2 ]
  • Hello Bogdan,
    this tutorial is really great and detailed but I`m missing something cause I`ve a crash. I repeated your tutorial twice but still have the same message: 2014-01-20 11:13:39.147 CrazySki[1604:a0b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid level file. Please add the LevelHelper scene file to Resource folder. Please do not add extension in the given string.' What`s wrong? I followed your instructions and it seems that I have all the files.
    MyBigBang
[ 1 , 2 ]

Other Items of Interest

Ray's Monthly Newsletter

Sign up to receive a monthly newsletter with my favorite dev links, and receive a free epic-length tutorial as a bonus!

Advertise with Us!

Vote for Our Next Tutorial!

Every week, we alternate between Gaming and Non-Gaming tutorial votes. This week: Gaming!

    Loading ... Loading ...

Last week's winner: Porting your Apps to iPhone 6 and iPhone 6 Plus.

Suggest a Tutorial - Past Results

Hang Out With Us!

Every month, we have a free live Tech Talk - come hang out with us!


Coming up in October: Xcode 6 Tips and Tricks!

Sign Up - October

Our Books

Our Team

Tutorial Team

  • Kirill Muzykov

... 52 total!

Update Team

  • Riccardo D'Antoni

... 14 total!

Editorial Team

  • John Clem

... 22 total!

Code Team

  • Orta Therox

... 3 total!

Subject Matter Experts

  • Richard Casey

... 4 total!