Whitepaper: Introduction to Cocos2d iPhone

Please note that this tutorial is targeting the 0.7.2 release of cocos2d-iphone. We usually update within a week of new versions, but using either a newer or older version of cocos2d-iphone with this tutorial will likely not work, as the API is in flux until the 1.0 release.

Recently Monocle Studios LLC released its first product, touchDefense, which is an iPhone game. We feel pretty strongly that the game wouldn't have made it all the way to the AppStore if it hadn't been for Cocos2d iPhone, and we want to give back to the project which has done so much for us. This whitepaper is our first first step in doing so.

Let's get started with Cocos2d iPhone.

You can download the finished XCode project for this tutorial here.

Join the iPhone Development Program.

The very first step to becoming an iPhone developers is to register as an iPhone Developer with Apple. It's free to develop (although you'll have to pay $99 for a developer's certificate before you can deploy your applications to actual devices), and is a lot quicker than the alternatives (because there aren't any).

Afterwards you'll need to download the iPhone SDK which is a somewhat massive download (upwards of one gig), so you'll really want to download it on a fast connection.

Getting Started in XCode.

Next we need to setup a standard iPhone project in XCode. Go to File->New Project. Then click on Application under the iPhone OS header. Finally, choose the Window-Based Application and then click the Choose... button.

Creating an iPhone application in XCode.

Then name the project (we named ours SimpleGame, and it may be less confusing to name yours the same way), and save it somewhere appropriate. Afterwards a fresh new project will open up, looking like this:

Creating an iPhone application in XCode.

Now is a great time to setup version control for your project! We like to use Git, which makes creating a new repository for the project very quick:

cd SimpleGame
git init
git commit -a -m "Initial commit."

You might prefer Mercurial or SVN, that's good too, just use something!

Before we move on, go ahead and click the Build and Go button just to see the iPhone simulator launch and load a white screen (the humble beginnings of SimpleGame).

Removing the window and nib.

For Cocos2d iPhone projects we don't actually want to use any nibs or standard UI components, so we need to make a few modifications to the default project that XCode generated for us (unfortunately, none of the default projects really fit perfectly with using Cocos2d iPhone).

First, go ahead and delete MainWindow.xib from the project.

Second, in Info.plist remove the Main nib file base name key.

Editing Info.plist in XCode.

Next we'll also need to make a few modifications to the source files. Start by replacing the contents of main.m with this code:

#import <UIKit/UIKit.h>

int main(int argc, char *argv[]) {
    
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  int retVal = UIApplicationMain(argc, argv, nil,
                                 @"SimpleGameAppDelegate");
  [pool release];
  return retVal;
}

Fourth, modify SimpleGameAppDelegate.h to look like this:

#import <UIKit/UIKit.h>

@interface SimpleGameAppDelegate : NSObject <UIApplicationDelegate> {

}

@end

Finally, modify SimpleGameAppDelegate.m to look like this:

#import "SimpleGameAppDelegate.h"

@implementation SimpleGameAppDelegate

- (void)applicationDidFinishLaunching:(UIApplication *)app {    

}

@end

Those changes feel a bit like magic, but fortunately you'll only need to make them once and can forget them afterwards until you start a new project. (Better yet, you can make a Cocos2d iPhone project template and just reuse that, then you'll never have to revisit them.)

Integrating Cocos2d iPhone.

Our next step is to grab the Cocos2d iPhone library from Google Code. Head over to the Cocos2d iPhone download page, and grab the 0.7.2 version. Then untar the download.

tar -xvf cocos2d-iphone-0.7.2.tar

Next in your project go to Project->Add to Project.. and navigate to the unzipped directory, then from within that directory add the External directory to your project. Be sure to have a checkmark in the box next to Copy items into destination group's folder (if needed), and then click the Add button.

Adding resources to an XCode project.

Then, and this is an important step, delete both the Demo directory and CMakeLists.txt in External\Chipmunk by right-clicking on each and choosing delete. (You'll want to delete the files, not just the references.) Deleting these means Xcode won't get confused about whether its building your project or the Chipmunk demos. You'll also want to delete Tremors from the External directory, as the current release does not build as shipped. Afterwards, it's a good idea to try compiling your project to make sure that nothing has gone haywire (it's always best to catch odd compilation issues earlier than later).

Now, go back to Project->Add to Project.. and add the cocos2d-iphone-0.7.2/cocos2d folder to your project as well.

You can optionally repeat that last step to add the cocos2d-iphone-0.7.2/cocoslive folder to your project. We're going to exclude adding the experimental folder, as it is both optional and has caused compilation issues in the past.

The last file to add to your project is cocos2d-iphone-0.7.2/cocos2d/Resources/images/fps_images.png. Put it into your Resources group.

We're almost done with setup, but our project won't quite compile yet. In the outline view for the project go down to Targets, then within it open SimpleGame, and finally select Link Binary With Libraries. Right click on it, and in the popup menu go to Add->Add Existing Frameworks... like in the screenshot below.

Add existing framework to an XCode project.

In the screen that opens up, click on the plus sign in the bottom left corner (beneath the list named Linked Libraries). After clicking on the plus sign, a list of frameworks will open up, and from it you will need to add two frameworks: OpenGLES.framework and QuartzCore.framework.

Add linked libraries for Cocos2d iPhone.

After you've added the two frameworks, your linked libraries should look like this:

Linked libraries settings for Cocos2d iPhone.

Now when you build the project, it will actually build. Sure, it isn't actually doing anything yet, but it's not actively failing anymore, which is a nice improvement.

Cleaning up the project.

Let's take a quick intermission to clean up the project groups. Right now it's difficult to get a hold of the SimpleGameAppDelegate class because it's at the base level of the project.

Let's make two new groups: Support and Classes.

Adding a new group in XCode.

First, let's move Chipmunk and cocos2d into the Support group. Then look through the base SimpleGame group and move SimpleGameAppDelegate.h and SimpleGameAppDelegate.m into the Classes group. Afterwards your project layout should look something like this:

Appearance of XCode project after cleanup.

None of this rearrangement is strictly necessary, but keeping groups organized has a direct correlation with maintaining your sanity as your project grows more complex.

Creating a main menu.

Now we're going to finally get started with Cocos2d iPhone. However, before any code we'll take a few moments for an overview of the classes we'll be using.

In Cocos2d iPhone you'll be dealing with the Scene and Layer classes frequently. A Scene is what the players can see at a given time, and is composed of one or more Layers. To display a specific Scene, you tell the Director (which is a singleton) to play it.

Right now we're going to create MenuScene, which is a subclass of Scene, and will also create MenuLayer, which will contain the details of our menu.

Finally, we'll need to hook up the applicationDidFinishLaunching method in our application delegate to tell the Director to run MenuScene.


We also need to add an image to our project. Download this image and add it to the project. We're going to use it as a background for our menu layer.


Now to start writing some code.

Right click on the Classes group and select Add->New File.... From Cocoa Touch Classes create an NSObject subclass file named MenuScene.m (leave the option to create a corresponding .h file checked).

Adding a new file in XCode.

Now open up the MenuScene.h file, and update it to look like this:

#import <UIKit/UIKit.h>
#import "cocos2d.h"

@interface MenuScene : Scene {}
@end

@interface MenuLayer : Layer {}
-(void)startGame: (id)sender;
-(void)help: (id)sender;
@end

Next we need to flesh out MenuScene.m to implement the MenuScene and MenuLayer classes.

#import "MenuScene.h"
@implementation MenuScene
- (id) init {
    self = [super init];
    if (self != nil) {
        Sprite * bg = [Sprite spriteWithFile:@"menu.png"];
        [bg setPosition:ccp(240, 160)];
        [self addChild:bg z:0];
        [self addChild:[MenuLayer node] z:1];
    }
    return self;
}
@end

@implementation MenuLayer
- (id) init {
    self = [super init];
    if (self != nil) {
        [MenuItemFont setFontSize:20];
        [MenuItemFont setFontName:@"Helvetica"];
        MenuItem *start = [MenuItemFont itemFromString:@"Start Game"
                                        target:self
                                      selector:@selector(startGame:)];
        MenuItem *help = [MenuItemFont itemFromString:@"Help"
                                       target:self
                                       selector:@selector(help:)];
        Menu *menu = [Menu menuWithItems:start, help, nil];
        [menu alignItemsVertically];
        [self addChild:menu];
    }
    return self;
}
-(void)startGame: (id)sender {
    NSLog(@"start game");
}
-(void)help: (id)sender {
    NSLog(@"help");
}
@end

For the time, being we're going to leave the startGame and help methods as stubs. We'll come back and update them a bit later.

Now we have our menu implemented, we just need to open up the two (.h and .m) SimpleGameAppDelegate files so we can tell the Director to load MenuScene when the application launches.

In SimpleGameAppDelegate.h at the top add an import for cocos2d and MenuScene:

#import <UIKit/UIKit.h>
#import "cocos2d.h"
#import "MenuScene.h"

Next, open up the SimpleGameAppDelegate.m file and add this code:

#import "SimpleGameAppDelegate.h"
@implementation SimpleGameAppDelegate
- (void)applicationDidFinishLaunching:(UIApplication *)application {
    UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    [window setUserInteractionEnabled:YES];
    [window setMultipleTouchEnabled:YES];
    [[Director sharedDirector] setLandscape: YES];
    [[Director sharedDirector] attachInWindow:window];

    [window makeKeyAndVisible];

    MenuScene * ms = [MenuScene node];

    [[Director sharedDirector] runWithScene:ms];
}
@end

Now you can go ahead and Build and Go the project, and there is finally something--albeit something incredibly ugly--to see.

Picture of the main menu of SimpleGame.

Fortunately we're out of the forest now, and it'll be much simpler from here.

Adding a game scene.

Next we're going to create a simple game scene to display after clicking the Start Game option in the menu. Let's begin by adding another background to the project to make it clear which scene we are in.


Add this image to the project. It'll be the game scene's background.


Then create the GameScene.h and GameScene.m files and put them in the Classes group.
In the GameScene.h file add this code:

#import <UIKit/UIKit.h>
#import "cocos2d.h"

@interface GameScene : Scene {}
@end

@interface GameLayer : Layer {}
@end

And fill in GameScene.m with this code:

#import "GameScene.h"
#import "MenuScene.h"

@implementation GameScene
- (id) init {
    self = [super init];
    if (self != nil) {
        Sprite * bg = [Sprite spriteWithFile:@"game.png"];
        [bg setPosition:ccp(240, 160)];
        [self addChild:bg z:0];
        [self addChild:[GameLayer node] z:1];
    }
    return self;
}
@end

@implementation GameLayer
- (id) init {
    self = [super init];
    if (self != nil) {
        isTouchEnabled = YES;
    }
    return self;
}
- (BOOL)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    MenuScene * ms = [MenuScene node];
    [[Director sharedDirector] replaceScene:ms];
    return kEventHandled;
}
@end

Finally, we need to update the startGame: method in the MenuLayer class to look like this:

-(void)startGame: (id)sender {
    GameScene * gs = [GameScene node];
    [[Director sharedDirector] replaceScene:gs];
}

One last edit to the code is required to get a working project. Go back to MenuScene.m and add #import "GameScene.h" to the top of the file.

Go ahead and build the project and play around with it for a couple of seconds. The best part about Cocos2d iPhone is that it all gets easier from here: the hard part's over.

You'll notice in our screenshots that the iPhone status bar has been disabled. To do the same for your project, simply open up Info.plist from the Resources folder and add a new boolean key to the file--UIStatusBarHidden and mark the checkbox.

And that's all we wrote.

You can download the project we developed in this tutorial right here.

We hope that this has been a helpful introduction to getting started with Cocos2d iPhone, and that you'll spend some of your time getting to know this great project.

Thanks for reading, and please send any comments, corrections or complaints to support@monoclestudios.com. If you have any suggestions for future topics, let us know by filling out our suggestion form. Also, don't forget to check out the game we built, touchDefense.

Special thanks to Jeffrey Vanneste for sending in a list of changes to get everything up-to-date with cocos2d-iphone 0.7.2.