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:
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.
Wow you’ve added so much on this already, thanks for sharing all of this great information.
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?
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!
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?
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?
Thanks a lot for the cool tuts.
Cocos2d seems to be reaaally easy, and a lot of fun too.
Hi, I was wondering, how do I change de font color in my menus?!
thanks
Great series, Keith!
Very helpful for the Cocos2d beginner (like me) to get a handle on the framework. Really looking forward to some more!
Thanks for all your help Keith.
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.
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
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 π
Your tutorial is good… can you teach how to add more tutorials on how making character moving?
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??
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
Great articles Keith.. Very very helpful for a beginner.. Cheesy indeed.. Waiting for more..
Thanks for all dude
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.
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!!!!!!!!!
Very good tutorial!
Great tutorial!
It solved my problems quickly.
Thank you very much.
Jonas, dont forget to #import the scene in the menu scene.
#import “gamePlay.h”