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

In part third and final part of the Monkey Jump tutorial series, you will add the HUD layer, some performance improvements, and yes – kill the monkey! :] By .

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

Final improvements

Your game is looking awesome! But you can still make a few improvements.

The game is a bit unfair right now: the monkey is on the scene and BAM! – a statue kills him instantly. It is a game that can be won more by chance than by skill.

To make the gameplay a bit more even, You're going to add a drop indicator. It will be a small red bar that shows the position of the next object drop.

Go to GameLayer.h and add the following variable for the drop indicator:

    CCLayerColor *objectHint; // weak reference  

Then, add the following initialization code to the very end of the init method of GameLayer.mm:

    // object Hint
    objectHint = [CCLayerColor layerWithColor:ccc4(255,0,0,128) 
                                        width:10.0f 
                                       height:10.0f];
    [self addChild:objectHint z:15000];
    objectHint.visible=NO;

You create a semi-transparent red box as the drop indicator and set the box dimensions to 10x10 pixels. You'll resize it later to match the dropping object's size.

Next, scroll down to just above section #8 in the update selector and add the following code:

    if(nextDrop < dropDelay*0.5)
    {
        // update object hint
        [objectHint setVisible:YES];
        
        // get object's width
        float w = nextObject.ccNode.contentSize.width;
        
        // and adjust the objectHint according to this
        [objectHint changeWidth:w];
        objectHint.position = ccp([nextObject physicsPosition].x * PTM_RATIO-w/2, 310);
    }
    else
    {
        [objectHint setVisible:NO];
    }

If the nextDrop is less than half of the dropDelay, you set the objectHint to visible and its width to the dropping object's width. you also set its position centered below the object's x coordinate.

Build and run, and check if the object hint appears below the position of the next drop.

One last addition – the theme music! Import SimpleAudioEngine.h at the beginning of GameLayer.mm, if you haven't done so already:

    #import "SimpleAudioEngine.h"

Add the following lines to the end of the init selector. The music resources have already been added to the project:

    // music
    [[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"tafi-maradi-loop.caf"];

Build and run. The current state is available as 6-CompleteGame.

contentprotection_1-1

iOS apps have one big disadvantage: It's easy to steal the contents from an app. You don't believe me?

Just open your user folder in finder and navigate to Music/iTunes/iTunes Media/Mobile Applications. There are all the .ipa files from the apps you own.

Now copy one and rename it from .ipa to .zip. Extract the files. Inside you find a folder payload containing the app itself. Right-click and select Show Package Contents. Bam! - there you are.

It is of course illegal to use this content without permission. But be realistic: What would happen if somebody uses your assets? Can you check all the zillions of apps in the store? And what would you do if you see your assets in another game? Sue somebody in a foreign country? Good luck!

TexturePacker 3.0.10 comes with a new feature called "ContentProtection". TexturePacker partially encrypts the data - using a variation of the xxtea algorithm with 128-bit keys - protecting your spritesheets. The algorithm is designed to deliver good protection while having close to no overhead in runtime and memory. This works with a variant of Cocos2d's pvr.ccz files.

All your need to do is three simple steps:

  1. Activate the encryption in TexturePacker
  2. Exchange 2 files in Cocos2d
  3. Set the key in your app

The encryption protects you against most of the people trying to steal your assets. It won't protect you from a professional hacker. But encrypting the complete file with AES or even RSA won't change that.

That's because in the end the assets must be converted to something iPhone can use - and thus the key and algorithm both have to be part of your game - and can be extracted by somebody. My guess is that most people would look for easier prey if they see that the files are protected.

Encrypting the assets

Open the jungle.tps file in TexturePacker and click on the Content protection icon. As already said - a 128-bit key is required. You can create a key by pressing the Create new key button. Save as global key allows you to save the key and to use it with other sheets by simply restoring it using Use global key.

TexturePacker's .pvr previewer also uses the global key to decrypt your images if you want to inspect them.

Now just press Publish.

Open background.tps and frame.tps, open ContentProtection, press Use global key and Publish.

Using the same key for all files should be fine - and it makes handling the assets way easier than applying an individual key to each file.

Adding decryption to Cocos2d

Simply replace ZipUtils.h and ZipUtils.m in libs/cocos2d/Support with the files from the ContentProtection folder in the MonkeyJump zip file.

Setting the key

The key must be set as four 32-bit values. It is separated in multiple steps to make it harder for a potential attacker to retrieve the key.

If your key is aaaaaaaabbbbbbbbccccccccdddddddd you have to split it into 4 parts, each consisting of 8 hex digits.
Make a call to caw_setkey_part with the index of the part and the value prefixed with 0x.

You can place this code as a block or as separate lines in different source code files. Just make sure that it gets executed before loading the first sprite sheet. The more it's distributed - the harder the key is to hack.

If you want to keep it simple, copy it in the init selector in GameLayer.mm:

caw_setkey_part(0, 0xaaaaaaaa);
caw_setkey_part(1, 0xbbbbbbbb);
caw_setkey_part(2, 0xcccccccc);
caw_setkey_part(3, 0xdddddddd);

Import the ZipUtils.h in the file(s) that set the key - it defines caw_setkey_part

#import "ZipUtils.h"

The implementation with the key from the screenshot would look like this, you could place it in the init selector of the GameLayer.mm

caw_setkey_part(0, 0x50e23559);
caw_setkey_part(1, 0x293f9940);
caw_setkey_part(2, 0x3a4fb526);
caw_setkey_part(3, 0x592e48b2);

The loader code warns you if you entered a wrong key in debug build. A release build does not contain this code to make it more difficult to attack.

The final version is available as 7-Final.

Where to Go From Here?

If you don't have it already, here is all of the source code for this tutorial series.

Congratulations – you finished the tutorial! Looking back, you've learned a ton of things:

  • Using TexturePacker to create your sprite sheets
  • Using PhysicsEditor to create your collision shapes
  • Building a physics-based game with collision detection and sound using Box2d
  • Handling different resolutions including iPhone 5
  • Building a HUD layer to display the health and score
  • Protecting your assets from being stolen

I hope you have enjoyed this tutorial! I'd love to hear what you think of the game and the products you used to make it, so keep the questions and comments coming.