How To Build a Monkey Jump Game Using Cocos2d 2.X, PhysicsEditor & TexturePacker – Part 1

Learn how to make a fun 2D physics game called Monkey Jump in this 3-part tutorial series covering Physics Editor, Texture Packer, and Cocos2D. By .

Leave a rating/review
Save for later
You are currently viewing page 5 of 7 of this article. Click here to view the first page.

Basic Setup in Xcode

The goals for this section of the tutorial are to set up the basic game layers and backgrounds, and to set up the physics engine.

If you’ve followed along the tutorial so far you should have the same setup as in the 1-ReadyToCode folder.

Before you dive into the code, there’s one more thing to do: add the resources you created to XCode. Remember these?

  • background.plist
  • background.pvr.ccz
  • background-hd.plist
  • background-hd.pvr.ccz
  • background-568h@2x.plist
  • background-568h@2x.pvr.ccz
  • frame.plist
  • frame.pvr.ccz
  • jungle.plist
  • jungle.pvr.ccz
  • jungle-hd.plist
  • jungle-hd.pvr.ccz
  • shapes.plist

Add the above files to the Resources folder in your Xcode project by Control-clicking on the Resources folder inside Xcode, selecting Add Files To “MonekyJump” and then selecting the files listed above from the project Resources folder.

Now for the code. First, you need to create a “Floor” class to represent the floor for the game. Add Floor.h and files to your project by creating a new file with the iOS\Cocoa Touch\Objective-C class template. Name the class Floor, and make it a subclass of GB2Sprite. And don’t forget to change the extension for Floor.m to .mm once it has been created.

Floor.h should simply contain this:

#pragma once

#import "cocos2d.h"
#import "GB2Sprite.h"

@interface Floor : GB2Sprite

+(Floor*) floorSprite;


And this:

#import "Floor.h"
@implementation Floor

+(Floor*) floorSprite
    return [[[self alloc] initWithStaticBody:@"grassfront" spriteFrameName:@"floor/grassfront.png"] autorelease];


The only remarkable line of code here is the call to the initWithStaticBody selector. This makes your object a static object – one that isn’t moved by the physics engine. It initializes the body’s shape using a shape from the shapes.plist file with the name grassfront.

It also uses a sprite image with the name floor/grassfront.png that is taken from jungle.plist.

Why did you derive this class from GB2Sprite instead of simply using a GB2Sprite directly? The answer is GBox2D’s collision handling, which uses the name of the class to call appropriate selectors on the colliding objects. Since you want to know when something collides with the floor, the class name for the floor object must be distinguishable from other GB2Sprite objects.

The next thing to do is update the GameLayer. Add some instance variables to hold the required objects in GameLayer.h:

@interface GameLayer : CCLayer
    CCSprite *background;                   //!< weak reference
    CCSprite *floorBackground;              //!< weak reference 
    CCSpriteBatchNode* objectLayer;         //!< weak reference

    CCSprite *leftFrame;                    //!< weak reference
    CCSprite *rightFrame;                   //!< weak reference

You will store the objects as weak references – that is, without increasing the retain count for each object.

You do not need to worry about the CCSprites being deleted. They will be added as children of the CCLayer and thus have a retain count of at least 1. This is done because otherwise you will be caught in a retain cycle and not able to free the memory allocated by these objects.

Now fill's init selector with content. First, load the jungle sprite sheet:

[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"jungle.plist"];

For the background you have to check if the game runs on iPhone 5 and load the appropriate sheet. One way to detect this is to use the window size. The advantage of using the size is that if some other device with the same width or height comes out, the game might still adapt to that one too.

The director delivers the size in points - which is 1 pixel in on a non-retina display and 2 pixels on a retina display. Thus checking for the size has to be done by checking against 568 (1136/2).

You also need to check against height and width because the orientation changes after startup phase and width and height are swapped.
This is also a good point to calculate the offset from the center of the screen you have to take into account for iPhone 5. The distance is (1136-960)/2 in pixels or (568-480)/2 in points. The offset for non-iPhone 5 devices is 0.

To center the game screen on the device simply set the offset value for the x coordinate.

CGSize winSize = [CCDirector sharedDirector].winSize;
bool is5 = (winSize.height == 568) || (winSize.width == 568);
CGFloat centerOffsetX = is5 ? ((568-480)/2) : 0;
self.position = ccp(centerOffsetX,0);

Now load the background depending on the device:

    // load the extended background from iPhone5
    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"background-568h@2x.plist"];
    // load the standard background
    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"background.plist"];

Next, load the physics shapes into the GB2ShapeCache:

[[GB2ShapeCache sharedShapeCache] addShapesWithFile:@"shapes.plist"];

Then, set up the layers. You'll divide the game into the following layers:

  • Background layer: The jungle image
  • Floor background: A single sprite with the tall grass
  • Object layer: Contains all the items and the monkey
  • Borders: (iPhone 5 only) Restrict the playfield
  • Debug draw layer: Activated as needed
  • Hud layer: Has the score and life energy indicators (to be added later)

The background layer is a child of the playfield and would now leave a gap of 44 points to the left on iPhone 5. You have to move it back to the left by the centerOffsetX to center it again.
On other devices centerOffsetX is 0 - so everything is fine here.

Add the code to create the basic background and floor background layers to init.

// Setup background layer
background = [CCSprite spriteWithSpriteFrameName:@"jungle.png"];
[self addChild:background z:0];
background.anchorPoint = ccp(0,0);
background.position = ccp(-centerOffsetX,0);

// Setup floor background
floorBackground = [CCSprite spriteWithSpriteFrameName:@"floor/grassbehind.png"];
[self addChild:floorBackground z:1];
floorBackground.anchorPoint = ccp(0,0);
floorBackground.position = ccp(0,0);

Then, add the object layer. This will be a sprite batch node to speed up rendering of the objects:

objectLayer = [CCSpriteBatchNode batchNodeWithFile:@"jungle.pvr.ccz" capacity:150];
[self addChild:objectLayer z:10];

And finally, the debug draw layer:

// add the debug draw layer, uncomment this if something strange happens ;)
[self addChild:[[GB2DebugDrawLayer alloc] init] z:30];

If you want to disable the debug drawing, simply comment out the second line. If enabled, the physics shapes will be drawn over the sprites, allowing you to see where collisions happen and if all shapes are properly aligned.

Next, add the floor object as the child of the object layer. Include Floor.h at the top of

#import "Floor.h"

Then add the floor object at the end of init:

[objectLayer addChild:[[Floor floorSprite] ccNode] z:20];

There isn't anything more you have to do to add the objects to the physics world – everything else is covered inside Gbox2D!

One final step is required for iPhone 5: Loading and adding the left and right frame objects. They have to be placed outside of the play field:

    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"frame.plist"];

    leftFrame = [CCSprite spriteWithSpriteFrameName:@"left.png"];
    [self addChild:leftFrame z:20];
    leftFrame.anchorPoint = ccp(0,0);
    leftFrame.position = ccp(-44,0);

    rightFrame = [CCSprite spriteWithSpriteFrameName:@"right.png"];
    [self addChild:rightFrame z:20];
    rightFrame.anchorPoint = ccp(1.0,0);
    rightFrame.position = ccp(568-44,0);

Build and run the project in the iPhone Retina 4-inch simulator. You should see something similar to this:

Nice – now let's add some action to the game!