Cocos2d – Part 4: Menus and Transitions

Menus

OK, let’s talk menus. Because some people might have a preconceived idea of what a menu is, let’s define it in this context as a collection of visual items that can be tapped on to make a choice. This includes main menu screens of games as well as settings or options menus and even things like level choosers. Menus are very often lists of text items, but could also include icons or larger images as items.

Let’s take a simple example of a main menu. It might have various options such as “Play”, “Settings”, and “About”. If you’ve been following along, you’ll probably be getting the idea that this menu would reside in a menu screen, and that choosing one of these options would take you to a play scene, a settings scene, or an about scene. So start a new project as described in Part 1 of this series, and create four new classes: MenuScene, PlayScene, SettingsScene, and AboutScene. In each one, import the Scene.h file, and have each class extend Scene.

First let’s create the three target scenes. I grabbed three different 480×320 images to serve as different backgrounds and added them to my project. Each of these classes is almost identical, so I’m just going to show you the PlayScene and you should be able to figure out the rest.

[c]#import “PlayScene.h”
#import “Label.h”
#import “cocos2d.h”
#import “MenuScene.h”
#import “Sprite.h”

@implementation PlayScene

– (id) init
{
self = [super init];
if (self != nil) {
Sprite *bg = [Sprite spriteWithFile:@”background.png”];
bg.position = ccp(240, 160);
[self addChild:bg];

Label *label = [Label labelWithString:@”play scene” fontName:@”Arial” fontSize:20];
label.position = ccp(240, 160);
[self addChild:label];

[self schedule:@selector(onEnd:) interval:5];
}
return self;
}

– (void)onEnd:(ccTime)dt
{
[[Director sharedDirector] replaceScene:[MenuScene node]];
}

@end
[/c]

Here you can see we are creating, positioning and adding the background. No rocket science there. Then creating a label and adding that. We haven’t covered labels, but what you see there is pretty straightforward. Finally, we fake a game over by starting a schedule job that will fire after 5 seconds. This just tells the Director to replace this scene with the MainMenu scene.

The settings and about scenes are nearly identical. Just use a different background and change the label string.

Now, onto the menu scene. This also obviously extends Scene as well. Nothing else interesting is in the interface, so we’ll move onto the implementation:

[c]#import “MenuScene.h”
#import “MenuItem.h”
#import “Menu.h”
#import “PlayScene.h”
#import “SettingsScene.h”
#import “AboutScene.h”
#import “cocos2d.h”

@implementation MenuScene

– (id) init
{
self = [super init];
if (self != nil) {
MenuItem *menuItem1 = [MenuItemFont itemFromString:@”Play” target:self selector:@selector(onPlay:)];
MenuItem *menuItem2 = [MenuItemFont itemFromString:@”Settings” target:self selector:@selector(onSettings:)];
MenuItem *menuItem3 = [MenuItemFont itemFromString:@”About” target:self selector:@selector(onAbout:)];

Menu *menu = [Menu menuWithItems:menuItem1, menuItem2, menuItem3, nil];
[menu alignItemsVertically];
[self addChild:menu];
}
return self;
}

– (void)onPlay:(id)sender
{
NSLog(@”on play”);
[[Director sharedDirector] replaceScene:[PlayScene node]];
}

– (void)onSettings:(id)sender
{
NSLog(@”on settings”);
[[Director sharedDirector] replaceScene:[SettingsScene node]];
}

– (void)onAbout:(id)sender
{
NSLog(@”on about”);
[[Director sharedDirector] replaceScene:[AboutScene node]];
}

@end[/c]

The first thing we do in init is to create a few MenuItems. These will be text menu items, so these are created with the MenuItemFont’s itemFromString:target:selector method. You simply pass in the text you want to display, and the target (self) and selector you want to have called when the item is tapped.

Each selector simply tells the Director to replace the MenuScene with the newly chosen scene.

Finally, we create the menu itself with these three items, using Menu’s menuWithItems static method. This takes a nil terminated list of MenuItems. We tell it to align these vertically, and add the menu to the scene.

All that’s left is to tell the Director to run with the MenuScene. This would be done in the main app delegate’s applicationDidFinishLaunching method. I’m hoping that you have learned enough so far to not need explicit instructions on how to do this.

When you are done, you should have a nice menu like this:

menu

So that’s a start to menus. Note that there is a lot more you can do with them. Don’t like the default font? Change it with this line:

[MenuItemFont setFontName:@”Arial”];

And in addition to MenuItemFont, there is MenuItemAtlasFont, MenuItemImage, MenuItemLabel, and MenuItemToggle. As for layout, you can arrange items vertically, horizontally, with or without padding, or in columns or rows. There’s probably lots more you can do with them, allowing all kinds of customization.

Transitions

OK, now that we are moving between scene, let’s polish things up a bit and add some nice transitions. So far, we have been replacing scenes like this:

[[Director sharedDirector] replaceScene:[PlayScene node]];

Kind of jarring. Fortunately, cocos2d comes with a whole slew of cheesy transitions. πŸ™‚ OK, they’re not all cheesy, but I advise a conservative viewpoint when choosing amongst them. That said, let’s throw caution to the wind and get all ostentatious with our transitions. Hell, this is only a tutorial.

You’ll find all the transitions listed in the Transitions.h file in the cocos2d folder. They are all used pretty much the same:

[TransitionClassName transitionWithDuration:(ccTime)t scene:(Scene *)s]

The interesting thing about calling this method is that it returns an instance of TransitionScene, which extends Scene and contains the scene you passed into it. So you can use this method directly in the call to Director’s replaceScene, or any other scene changing method. For example, in MenuScene, replace this line:

[c][[Director sharedDirector] replaceScene:[PlayScene node]];[/c]

with this:

[c][[Director sharedDirector] replaceScene:[RotoZoomTransition transitionWithDuration:1.0 scene:[PlayScene node]]];[/c]

And behold the lovely results when you hit the Play item! Who wouldn’t want their iPhone app to do that??? πŸ˜‰

OK, that’s it for this installment. Make some menus and make me proud.

This entry was posted in iPhone, Objective C. Bookmark the permalink.

22 Responses to Cocos2d – Part 4: Menus and Transitions

  1. John says:

    Wow you’ve added so much on this already, thanks for sharing all of this great information.

  2. Eric says:

    These are great!!! I have a project where I need to make a game and I was going to use Cocos 2D. Are you planning anything on accelerometer support or chipmunk physics?

  3. Dave S says:

    Awesome articles Keith.
    Can’t wait for making things move iPhone edition.

    I pretty much learnt physics style Actionscript stuff through the old bit-101 and have your books. I am off deep in Flex land for now, who knows how that happened? Anyhow, I got an iPhone a few weeks ago and Apps seem like an exciting thing to try. How did I know that once again, you would be an influence & great source.

    You are the man Keith!

  4. Signar says:

    Hello Keith! Got things moving, but I was just trying out using transitions both to the “sub” scenes and back to the menu scene. Having difficulties making the interval timer stop, found some cocos2d api that says that scheduled intervals are automatically paused when a node exits the current director scene. This is however not working for me. The onEnd-method gets fired constantly every 5 seconds even after the first 5 seconds has taken me back to the menuScene. Any ideas?

  5. thomas says:

    Hi

    I’ve just found your tutorials on cocos2d, and are loving them. Will you be adding more anytime soon πŸ™‚ Is there any place to find lots of tutorials on cocos2d or do i have to figure it out by looking in cocos2d code?

  6. bjoern says:

    Thanks a lot for the cool tuts.
    Cocos2d seems to be reaaally easy, and a lot of fun too.

  7. rafael says:

    Hi, I was wondering, how do I change de font color in my menus?!

    thanks

  8. Garry Seto says:

    Great series, Keith!

    Very helpful for the Cocos2d beginner (like me) to get a handle on the framework. Really looking forward to some more!

  9. Jack Cardinal says:

    Thanks for all your help Keith.

  10. Drahc says:

    The Best tutorial i’ve read so far. You inspired me to continue learning in programming games on iphone. Hope to see more from you. Thanks a lot.

  11. Andres says:

    Sorry, quick and stupid question, How would you do to add an text input box to any of the scenes? I mean, can’t find the correct import or anything… any ideas?

    Thanks

  12. Thomas says:

    I am new to iphone games development and these tutorials are amazing. Very easy to follow! I was wondering are you going to add anymore tutorials?

    cheers mate πŸ˜‰

  13. Ashraf says:

    Your tutorial is good… can you teach how to add more tutorials on how making character moving?

  14. Tim says:

    These tutorials are the most useful i’ve seen. Thanks so much. Can you do a tutorial on user input, and responding to touch events and Accelerometer events??

  15. riash says:

    thanks for posting the useful tutorial. can u add a another thing in this tutorial that is EXIT must among the buttons…expalin how to add this button.i added the scene “appDelegate.m”
    for EXIT button.is it right way to do it ? or not

  16. Neha says:

    Great articles Keith.. Very very helpful for a beginner.. Cheesy indeed.. Waiting for more..

  17. chuck says:

    Thanks for all dude

  18. Shane says:

    Very nice tutorial. Just thought I would add that:
    [[Director sharedDirector] replaceScene:[RotoZoomTransition transitionWithDuration:1.0 scene:[PlayScene node]]]; no longer works.

    “Director” is now “CCDirector” and all the transition classes were renamed.
    Old New
    CCXXXTransition CCTransitionXXX
    Example:
    Old New
    CCFadeTransition CCTransitionFade

    Just figure anyone new might now click to this at first. πŸ˜‰ Thanks again.

  19. Jonas BrΓΈske says:

    i keep getting a error on the scene after the menu. My scene after the menu is called gamePlay.
    I write:

    [[CCDirector sharedDirector] replaceScene:[gamePlay node]];

    But the error says: gamePlay undeclared (first use in this function)

    HEEEEEEEELP!!!!!!!!!

  20. Wesley Bastos says:

    Very good tutorial!

  21. Laban says:

    Great tutorial!
    It solved my problems quickly.
    Thank you very much.

  22. Oddyse says:

    Jonas, dont forget to #import the scene in the menu scene.

    #import “gamePlay.h”

Leave a Reply