Archive

Posts Tagged ‘Labels’

Labels, Menus, and Options in Cocos2d-iPhone

June 1st, 2009 beardo No comments

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:

options_n

options_s

options disabled



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.