Labels, Menus, and Options in Cocos2d-iPhone
In my previous post I indicated that I was using the Cocoa Touch framework to do my menus and was having that interact with the Cocos2D-iPhone framework that I was doing to implement the actual game. This was a big mistake. After trying to get it all to interact correctly, I realized that I was “doing it wrong”. I ended up with a solution that added a blank UIView to the window, and then had to load up the other views. It was a mess and I still had the problem of the UIView overlay screwing up the touch events in Cocos2D-iPhone.
After decided there had to be a better way, I looked into the menu API in Cocos2D-iPhone. Turns out it is much easier, but to get good looking menu’s I’d need some more art. There are a few ways to make a menu with the API. First you can just use text and specify the menu name with a string. This is okay, but it really should look better for a game. Secondly, and the route I chose, is you can use images to display menu options. First I created some the images in Inkscape:
The first image is the default display, second the image to display when selected (i.e. touched) and finally when the menu item is disabled. Here’s how to create a simple menu with these images:
/* Utility method to create a menu item assuming a naming convention */
- (MenuItemImage *)createMenuItem:(NSString *)prefix selector:(SEL)selector
{
NSString *normal = [prefix stringByAppendingString:@"_n.png"];
NSString *selected = [prefix stringByAppendingString:@"_s.png"];
NSString *disabled = [prefix stringByAppendingString:@"_d.png"];
MenuItemImage *result = [MenuItemImage itemFromNormalImage:normal
selectedImage:selected
disabledImage:disabled target:self selector:selector];
return result;
}
// event handler...
-(void)showOptions:(id)sender
{
[[Director sharedDirector] pushScene:[OptionsMenuScene node]];
}
- (id) init {
self = [super init];
if (self != nil) {
MenuItemImage *options = [self createMenuItem:@"options"
selector:@selector(showOptions:)];
Menu *menu = [Menu menuWithItems:optionsItem, nil];
[menu alignItemsVertically];
[self addChild:menu];
}
}
It’s just that easy. I create a MenuItemImage using the three images, add it to a menu, and then add the menu to my scene. This example also takes advantage of the Menu class’s built-in layout facility. The event handler simply pushes another menu scene onto the scene stack. The documentation suggests that you avoid using the scene stack to save on memory, but I simply use it for the menus and it never gets more than 3 deep.
I also replaced the score display with a simple label:
scoreLabel_ = [Label labelWithString:@"Score: " dimensions:CGSizeMake(150,30)
alignment:UITextAlignmentLeft fontName:@"Helvetica"
fontSize:20.0];
[scoreLabel_ setRGB:0 :0 :0];
[scoreLabel_ setPosition:ccp(80, 300)];
[layer addChild:scoreLabel_];
// Then later to set the score:
[scoreLabel_ setString:[NSString stringWithFormat:@"Score: %d", score]];
The only thing interesting here is that I specify the width of the label, and make it left justified so that it renders how I need it to.
The last thing I did this weekend was to load and save game options. I used the built-in NSUserDefaults class to store and load the preferences. There are tons of examples out there, so I won’t bother repeating it here. I only have 7 more items on the list before I’m ready to release. Mostly it’s just some game mechanics and hooking up some more menus. I’m pumped.

