Creating a simple menu with scene transition in cocos2d

cocos2d

cocos2d for iPhone is a fast, free, flexible, community-supported and easy to use framework for making iPhone games.

In this first tutorial, we'll discuss how to create a main menu scene with transition to a second scene using cocos2d.

What you'll need:

  • A Mac with Xcode 3.0 or higher installed.
  • A recent version of the cocos2d framework installed. You can find it and installation instructions here.

Create a new cocos2d project

In Xcode, choose File -> New Project and select cocos2d Application from your list of templates.

Create new cocos2d application

Click "Choose", name the project "BestGameEver", and click "Save". If this is your first time using cocos2d, you might want to build and run the default HelloWorld application in the simulator. We won't be needing the HelloWorldScene, so let's just delete both the HelloWorldScene.h and HelloWorldScene.m file.

Next, open up the BestGameEverAppDelegate.m file and look for this line in the applicationDidFinishLaunching: method:

  1. [[CCDirector sharedDirector] runWithScene: [HelloWorld scene]];

This is the scene that will load when your app launches. Change HelloWorld to MainMenuScene, which we're about to create:

  1. [[CCDirector sharedDirector] runWithScene: [MainMenuScene scene]];

At the top of the file, change the HelloWorld import statement to import our MainMenuScene instead:

  1. #import "MainMenuScene.h"

Create the new scenes

What we will be need are scenes for our main menu and for our game, so let's create those now. From the Xcode menu, click File -> New File… In the templates menu select Cocoa Touch Class and double-click Objective-C class.

Add new class files

Name the file MainMenuScene and be sure that "Also create MainMenuScene.h" is also checked. Repeat this process to create your GameScene.h and GameScene.m files.

Let's deal with the MainMenuScene first. Open up the MainMenuScene.h interface file and replace whatever is in it with the following:

  1. #import "cocos2d.h"
  2.  
  3. @interface MainMenuScene : CCLayer
  4. {
  5. }
  6.  
  7. +(id) scene;
  8.  
  9. @end

This is the standard structure of scenes in cocos2d. First, we're importing the cocos2d class files. Next, we're setting up our interface section and declaring our MainMenuScene which will be a child of the cocos2d class CCLayer. Finally, we declare the class method that will return our scene.

Next up, the MainMenuScene.m implementation file. Select it, delete its contents, and replace with the following:

  1. #import "MainMenuScene.h"
  2.  
  3. @implementation MainMenuScene
  4.  
  5. +(id) scene
  6. {
  7. CCScene *scene = [CCScene node];
  8.  
  9. MainMenuScene *layer = [MainMenuScene node];
  10.  
  11. [scene addChild: layer];
  12.  
  13. return scene;
  14. }
  15.  
  16. -(id) init
  17. {
  18.  
  19. if( (self=[super init] )) {
  20.  
  21. }
  22. return self;
  23. }
  24.  
  25. - (void) dealloc
  26. {
  27.  
  28. [super dealloc];
  29. }
  30. @end

Again, very similar to the HelloWorldScene.m. First, we're creating our scene which will contain all of our main menu's content. Then we're creating a MainMenuScene layer where we'll put our text, buttons, etc.

There is a bit of confusion between scenes and layers, so let me try to simplify it through an example. Think of scenes are containers for different views or screens in a game. You put your content on layers, and add these layers to the scene. For example, you might have a MainMenuScene, a LevelSelectScene, a GameScene, a GameOverScene, etc. In the GameScene you might add a background layer, a score layer, and a sprites layer.

The init method contains all the things you want to happen when the scene is loaded. For example, here you might want to add your buttons and title. Put everything between the:

  1. if( (self=[super init] )) {
  2.  
  3. }
  4. return self;

The dealloc method is for memory management stuff we won't need to worry about for this tutorial.

Add a title to our scene

So our MainMenuScene looks like a menu page, let's give it a title and position it near the top of the screen:

  1. CCLabel *title = [CCLabel labelWithString:@"Main Menu" fontName:@"Courier" fontSize:64];
  2. title.position = ccp(240, 240);
  3. [self addChild: title];

Create a new menu layer

In this simple tutorial we really don't need another layer, but let's make one anyway to help illustrate their purpose. First, we'll declare a new layer for our menu and add it as a child of our scene:

  1. CCLayer *menuLayer = [[CCLayer alloc] init];
  2. [self addChild:menuLayer];

This layer will contain all (one!) of our menu items. Next, we'll add a button/link to start our game using CCMenuItemImage. When the user touches the button, it will change to the selected image and when released, launch the game scene. We'll use some images for the button, so add these two images to your Resources group in Xcode:

  1. CCMenuItemImage *startButton = [CCMenuItemImage
  2. itemFromNormalImage:@"startButton.png"
  3. selectedImage:@"startButtonSelected.png"
  4. target:self
  5. selector:@selector(startGame:)];

Note the startGame: method. We'll create this later.

Create and add the menu

Now, let's actually create the menu and add our startButton to it. Note that we're adding the menu to the menuLayer we just created.

  1. CCMenu *menu = [CCMenu menuWithItems: startButton, nil];
  2. [menuLayer addChild: menu];

Create the startGame: method

Everything looks good so far, but we'll need to define where to go when the startButton is pressed. To do that, add the following method below your init method, but before the @end statement of your MainMenuScene.m file:

  1. - (void) startGame: (id) sender
  2. {
  3. [[CCDirector sharedDirector] replaceScene:[GameScene scene]];
  4. }

As you can see, we're replacing the current scene with our GameScene. We'll need to import our GameScene.h file now, so add an import statement to the top of the MainMenuScene.m file:

  1. #import "GameScene.h"

Great, but our GameScene is blank so let's add some content to it.

Add GameScene content

Just so we don't launch to a black screen and you think this whole tutorial is a big lie, add the following to your GameScene.h file:

  1. #import "cocos2d.h"
  2.  
  3. @interface GameScene : CCLayer
  4. {
  5. }
  6.  
  7. +(id) scene;
  8.  
  9. @end

And add the following to your GameScene.m file:

  1. #import "GameScene.h"
  2.  
  3. @implementation GameScene
  4.  
  5. +(id) scene
  6. {
  7. CCScene *scene = [CCScene node];
  8.  
  9. GameScene *layer = [GameScene node];
  10.  
  11. [scene addChild: layer];
  12.  
  13. return scene;
  14. }
  15.  
  16. -(id) init
  17. {
  18.  
  19. if( (self=[super init] )) {
  20.  
  21. CCLabel *message = [CCLabel labelWithString:@"Greetings" fontName:@"Courier" fontSize:64];
  22. message.position = ccp(240, 160);
  23. [self addChild: message];
  24. }
  25. return self;
  26. }
  27.  
  28. - (void) dealloc
  29. {
  30.  
  31. [super dealloc];
  32. }
  33. @end

Build and run the application. First, your MainMenuScene should load. Clicking the startButton will replace it with the GameScene.
MainMenuSimulator

GameSceneSimulator

Ok, maybe BestGameEver is a bit of an overstatement, but it's a start! Next time, I'll explain how to import a spritesheet, and add a sprite to the game scene.

If you're interested in cocos2d, I'd also suggest checking out Ray Wenderlich's fantastic cocos2d and iPhone tutorials.

28 Comments

  1. Luise | July 6th, 2010

    Thanks, that was a great help!!!

  2. Sola | October 18th, 2010

    Thanks I have been searching for this. Ran into a problem though.

    While compiling, it gives me the following error: ld: duplicate symbol _OBJC_METACLASS_$_MainMenuScene in /Users/akoredenitan/Desktop/MainMenuScene/build/Debug-iphonesimulator/libcocos2d libraries.a(MainMenuScene.o) and /Users/akoredenitan/Desktop/MainMenuScene/build/MainMenuScene.build/Debug-iphonesimulator/MainMenuScene.build/Objects-normal/i386/MainMenuScene.o”

    Not sure why that is however.

    Thanks again.

  3. Stephen Stephen Ceresia | October 19th, 2010

    @Sola Are you able to build and run the cocos2d “Hello World” sample project ok? If so, did you import your MainMenuScene.h in your implementation file? Also, if you want to post your code I can take a look.

  4. Sola | October 20th, 2010

    By import do u mean I add the main menu into the class folder. If so I did that.
    Sorry I am a newbie in this so basically still finding my way around.

  5. Sola | October 20th, 2010

    I have managed to create the menu. I followed your instructions but rather than replace the HelloWorldScene, I made it my default Scene, I removed the label that was there initially and replaced with a background of my choosing so I think its okay. Also managed to add sound to it though I would love to be able to control the sound because it starts playing immediately the scene loads (I want it to wait a few seconds after scene loads before the sound is initialized.)

    Thank you for the response earlier forgot to thank you for the quick response. I would also like to know if you have other similar tutorials available.

  6. Richard Grove | November 17th, 2010

    Having a scope problem I was hoping you’d see right through :)

    I want to separate the adding of the Layer into a function.

    In my init function I have:

    CCLayer *gameControlsLayer = [[CCLayer alloc] init];
    [self addChild:gameControlsLayer];
    [self addDataDisplays];

    and in addDataDisplays I have:

    CCLabel *altitudeDisplayLabel = [CCLabel labelWithString:@"Altitude:" fontName:@"Futura" fontSize:10];
    altitudeDisplayLabel.position = ccp(405, 315);
    altitudeDisplayLabel.color = ccc3(120,120,120);
    [gameControlsLayer addChild: altitudeDisplayLabel];

    This doesn’t work. It will work if I put it all into the init function. But that seems rather messy. Seems like a scope problem, but I can’t seem to get around it. Any thoughts much appreciated. Thank you for the excellent tutorial.

  7. Stephen Stephen Ceresia | November 18th, 2010

    @Richard:

    One way to get around this would be to make a separate GameLayer class, and then create an instance variable for it in your scene above. For example, your GameLayer class .h file might look like:

    // GameLayer.h

    #import “CCLayer.h”

    @interface GameLayer : CCLayer
    {

    }

    @end

    and your GameLayer class .m file:

    // GameLayer.m

    #import “GameLayer.h”

    -(id) init
    {

    if( (self=[super init] ))
    {
    }

    return self;
    }

    - (void) dealloc
    {
    [super dealloc];
    }

    Then, in your scene you can create an instance of this new class and reference it anywhere in the scene:

    // GameScene.h

    #import “cocos2d.h”
    #import “GameLayer.h”

    @interface GameScene : CCLayer
    {

    GameLayer *gameLayer;

    }

    +(id) scene;

    @end

    // GameScene.m

    -(id) init
    {


    gameLayer = [GameLayer alloc] init];
    [self addChild: gameLayer];

    }

    @end

  8. dav | December 18th, 2010

    hi i’m new on this…i need some help hope someone can help me im creating a menu but in this case:
    -(id) init
    {

    if( (self=[super init] )) {

    CCLabel *message = [CCLabel labelWithString:@"Greetings" fontName:@"Courier" fontSize:64];
    message.position = ccp(240, 160);
    [self addChild: message];
    }
    return self;
    }

    - (void) dealloc
    {

    [super dealloc];
    }
    @end

    i want to add some sprites and background instead of showing the CClabel of “greetings”

    thanks!!

    its a greatul post, it helped me a lot!!!

  9. Zoran Em | February 14th, 2011

    Awesome, i’m using Ray’s tutorials to build my first iPhone game and it’s super cool, i can’t wait to try adding this menu in tonite! thanks for the tut

  10. Tommy säfström | March 6th, 2011

    Hi,

    GREAT tutorial but it seems that “CCLabel” has been replaced with three other classes in cocos2d v0.99.5
    and CCLabelTTF seems to do the trick.

    The specification is here:
    http://www.cocos2d-iphone.org/wiki/doku.php/release_notes:0_99_5

    Once again, thanks for the straightforward and useful tut!

    Sincerely,
    Tommy

  11. Gaurav | June 27th, 2011

    Thanks , finally understood what is scene and layers and how to use it . can u tell how to load hd and non hd images from Plist , any link to some site would also be great.

  12. Gaurav | June 27th, 2011

    Hi , after the transition on my second scene i have placed the label but its not appearing what can i do? thanks

  13. Greg | July 4th, 2011

    THANK YOU THANK YOU THANK YOU THANK YOU THANK YOU

    This is the ONLY tutorial I’ve found that is:

    1 – complete
    2 – ACTUALLY WORKS

    Thank you so much!!! I’ve literally spent ALL day going through tutorials that don’t work for menus, and this is the ONLY complete and accurate one on the internet. This just made my day!!! You’re the best!!!

    I’ve looked through tons of books too, and none of them teach menus in Cocos2D, so HELLA props to you for creating this tutorial.

  14. Greg | July 4th, 2011

    THANK YOU THANK YOU THANK YOU THANK YOU THANK YOU

    This is the ONLY tutorial I’ve found that is:

    1 – complete
    2 – ACTUALLY WORKS

    Thank you so much!!! I’ve literally spent ALL day going through tutorials that don’t work for menus, and this is the ONLY complete and accurate one on the internet. This just made my day!!! You’re the best!!!

    I’ve looked through tons of books too, and none of them teach menus in Cocos2D, so HELLA props to you for creating this tutorial.

  15. Bengamen | August 6th, 2011

    Thx alot,
    this will help me out !

  16. Wesley Bastos | August 6th, 2011

    Very good tutorial!

  17. Paul | August 18th, 2011

    Could you show me what should be in each file? I got a lot of errors. Was I supposed to create another file named GameScene?

  18. C Tutorial | October 19th, 2011

    Thank you for sharing this tricks. It helps a lot. I also want to share some downloadable tutorial on graphic http://docsheets.info/docs/C_Graphic_Tutorial.html

  19. Naveed | February 2nd, 2012

    The simplest and THE BEST tutorial ever seen on cocos2d

    A BIG THANKS!!!!!!!

  20. Hendrik | February 2nd, 2012

    A great tutorial, thank you very much!

    The code works for me, but once i call my Box2D Game Scene, I get more that 200 compile errors, which all revolve around stuff that is expected to be implemented. Both parts work fine independently. Does anybody know how to glue them together ;)?!

  21. Hendrik | February 3rd, 2012

    I figured out what the problem was. I was using another tutorial, which implemented the ContactListener of Box2D in Objective-c++. After renaming MainMenuScene.m to MainMenuScene.mm, the errors disappeared!

  22. Seanie323 | February 28th, 2012

    After entering all the code. i can build and run the project but it keeps crashing before i run it

  23. Grateful | May 20th, 2012

    Brilliant!! Thank you so much for this excellent tutorial. :)

  24. Andy | May 27th, 2012

    Thank You. SImple. Concise. Accurate. Well Done. Become a teacher.

  25. Fifi | July 18th, 2012

    Thank you very much, I am a noob and this guide help me a lot

  26. Quentin | July 19th, 2012

    Great tutorial! Out of all the scene transition tutorials yours was the only one that worked, and not giving the error: Linking failed. Thanks! Should make more of these!

  27. Pingback: cocos2dの入門・サンプルサイト まとめ (iPhoneゲーム開発) | ER Game Design

  28. Darell | February 20th, 2013

    The Tutorial is great and it is helping me as a programmer, but after I followed everything, I recieved this error saying: Assigning to CCdirectorIOS * from incompatible type ‘void’. The error is coming from AppDelegate.m . Can someone give my any advice how to fix this please ? Thank You

Post a Comment