17 February 2010

How To Create Buttons in Cocos2D: Simple, Radio, and Toggle

If you're new here, you may want to subscribe to my RSS feed or follow me on Twitter. Thanks for visiting!

 

Buttons Tutorial Screenshot

Buttons Tutorial Screenshot

When you are making a game in Cocos2D, likely one of the first things you’ll find yourself needing is buttons. This tutorial will show you how to create buttons in Cocos2D step by step, starting with simple buttons and then covering toggle and radio buttons too. This tutorial assumes that you’ve already gone through the tutorial on how to create a simple game with Cocos2D, or have equivalent knowledge.

When I first started trying to add a button with Cocos2D, I thought the best way to was to just create a sprite representing the button and check for when the button was tapped. Although this is definitely possible, there’s a much easier way to create buttons in Cocos2D – by using the Cocos2D menu system.

The Cocos2D menu system consists of a menu that has a number of menu items inside it. Menu items can be either text or images, and the menu system contains logic for arranging menu items, highlighting items when they are tapped, toggling items, and more. So let’s give it a shot and try to create a simple button the Cocos2D way!

Creating A Simple Button

Create a new project in XCode using the cocos2d Application template, and name your project “CCButtons.” Next you need some images of buttons to work with – you can either use your own, or download some button images I have created. Once you have the images, drag them into your resources folder and make sure “Copy items into destination group’s folder (if needed)” is checked.

Open up HelloWorldScene.h under Classes and add a member variable to the HelloWorld class, we’ll need this in a bit:

CCLabelTTF *_label;

Then before we forget go to HelloWorldScene.m and add the cleanup code to the dealloc method:

[_label release];
_label = nil;

Ok now for the good stuff. In the same file (HelloWorldScene.m), replace the init method with the following code:

-(id) init
{
  if( (self=[super init] )) {
 
    CGSize winSize = [[CCDirector sharedDirector] winSize];
 
    // Create a label for display purposes
    _label = [[CCLabelTTF labelWithString:@"Last button: None" 
      dimensions:CGSizeMake(320, 50) alignment:UITextAlignmentCenter 
      fontName:@"Arial" fontSize:32.0] retain];
    _label.position = ccp(winSize.width/2, 
      winSize.height-(_label.contentSize.height/2));
    [self addChild:_label];
 
    // Standard method to create a button
    CCMenuItem *starMenuItem = [CCMenuItemImage 
      itemFromNormalImage:@"ButtonStar.png" selectedImage:@"ButtonStarSel.png" 
      target:self selector:@selector(starButtonTapped:)];
    starMenuItem.position = ccp(60, 60);
    CCMenu *starMenu = [CCMenu menuWithItems:starMenuItem, nil];
    starMenu.position = CGPointZero;
    [self addChild:starMenu];
 
  }
  return self;
}

First we create a label for debugging purposes. This should look pretty familiar – we did this in the last tutorial. However you’ll notice we’re using a new constructor this time that allows us to specify the dimensions of the label and the alignment. This way we specify the label size to be as wide as the window, and that the text should be centered. This is a handy technique to know, especially when you want to left or right justify text.

Next is the code where we create the button. We first create a menu item of class CCMenuItemImage and specify a selected and unselected image for the button. When we create the menu item, we specify a callback function to be called when the button is tapped (we’ll write this in a second). The last step is to create a menu to contain the button (or buttons).

Note that we create the menu at CGPointZero (a shortcut for 0,0). This is actually specifying where the center of the menu is. However, we also specify that the menu item is at offset (60, 60) relative to the center of the menu – so our button’s center is at (60, 60) on the screen.

Ok, one last bit of code to add. Underneath init add the callback function that will be called when the button is tapped:

- (void)starButtonTapped:(id)sender {
    [_label setString:@"Last button: *"];
}

Give it a compile and run, and if all goes well you should see the following:

Simple Button Screenshot

Toggle Buttons

Another common type of button you’ll need in an iPhone game is a toggle button. This is a button that has one image on it, until you tap it and it switches to another image. This could be used to toggle visibility of a control panel to make the best use of the limited screen real estate on the iPhone.

Luckily, Cocos2D comes with a special menu item class called CCMenuItemToggle that makes this easy. Let’s give this a shot! First add two more member variables to HelloWorldScene.h:

CCMenuItem *_plusItem; 
CCMenuItem *_minusItem;

And add the following cleanup code in your dealloc method:

[_plusItem release];
_plusItem = nil;
[_minusItem release];
_minusItem = nil;

Then add the following code in your init method right after you add the startMenu to the scene:

_plusItem = [[CCMenuItemImage itemFromNormalImage:@"ButtonPlus.png" 
  selectedImage:@"ButtonPlusSel.png" target:nil selector:nil] retain];
_minusItem = [[CCMenuItemImage itemFromNormalImage:@"ButtonMinus.png" 
  selectedImage:@"ButtonMinusSel.png" target:nil selector:nil] retain];
CCMenuItemToggle *toggleItem = [CCMenuItemToggle itemWithTarget:self 
  selector:@selector(plusMinusButtonTapped:) items:_plusItem, _minusItem, nil];
CCMenu *toggleMenu = [CCMenu menuWithItems:toggleItem, nil];
toggleMenu.position = ccp(60, 120);
[self addChild:toggleMenu];

First we create two CCMenuItemImages, just like we did in our previous example. Then comes the twist – we add both of those into a CCMenuItemToggle. This class keeps toggles between the elements inside, and keeps track of which is currently visible.

Note that we set the callbacks to nil when we created the CCMenuItemImages, but set it on the CCMenuItemToggle. This is to make it clear that any selectors on the CCMenuItemImages will not be called when they are inside a CCMenuItemToggle – only the CCMenuItemToggle’s selector will be called. Luckily, we can easily tell which of the menu items is visible in the callback.

Let’s see how by writing the callback! Add the following after your init method:

- (void)plusMinusButtonTapped:(id)sender {  
  CCMenuItemToggle *toggleItem = (CCMenuItemToggle *)sender;
  if (toggleItem.selectedItem == _plusItem) {
    [_label setString:@"Visible button: +"];    
  } else if (toggleItem.selectedItem == _minusItem) {
    [_label setString:@"Visible button: -"];
  }  
}

So as you can see, the CCMenuItemToggle has a selectedItem property that can show us which of the sub-items is currently visible (note it means visible, not which was tapped!)

So give it a compile and run, and if all goes well you should see the following:

Toggle Button Screenshot

Radio Buttons

A third common type of button that you might need in your iPhone projects are radio buttons. I found I needed some radio buttons for a game I was working on, but didn’t see an implementation for radio buttons in the Cocos2D source, so wrote an implementation of my own. While I was writing this article I came across two other guys who wrote implementations for radio button support in Cocos2D as well – so it looks like this will find its way into the Cocos2D source soon.

But it’s not in there yet, so in the meantime feel free to use the implementation I wrote or the ones I referenced above. For the purpose of this tutorial, let’s implement radio buttons using the implementation I wrote. First, download CCRadioMenu.h and CCRadioMenu.m and drag them to the Classes directory of your project (making sure “Copy items into destination group’s folder (if needed)” is checked). Then add the following import to the top of HelloWorldScene.m:

#import "CCRadioMenu.h"

And the following to your init method after you add the toggle menu to the scene:

CCMenuItem *menuItem1 = [CCMenuItemImage itemFromNormalImage:@"Button1.png" 
  selectedImage:@"Button1Sel.png" target:self selector:@selector(button1Tapped:)];
CCMenuItem *menuItem2 = [CCMenuItemImage itemFromNormalImage:@"Button2.png" 
  selectedImage:@"Button2Sel.png" target:self selector:@selector(button2Tapped:)];
CCMenuItem *menuItem3 = [CCMenuItemImage itemFromNormalImage:@"Button3.png" 
  selectedImage:@"Button3Sel.png" target:self selector:@selector(button3Tapped:)];
CCRadioMenu *radioMenu = 
  [CCRadioMenu menuWithItems:menuItem1, menuItem2, menuItem3, nil];
radioMenu.position = ccp(120, 180);
[radioMenu alignItemsHorizontally];
radioMenu.selectedItem = menuItem1;
[menuItem1 selected];
[self addChild:radioMenu];

We create the CCMenuItemImages like usual, but instead of adding them to a CCMenu we add them to the new CCRadioMenu class. This class makes sure only one is selected at a time. We also set the first item to be selected by default at start.

The other new thing here is we call alignItemsHorizontally on the menu to take advantage of the neat auto-layout capability in Cocos2D. Note that the items will be laid out with respect to the center of the menu. Therefore, we can no longer center the menu at position (0, 0) – we have to move the center up and to the right a bit where we want the items to display.

One last thing to add – the callback methods as usual:

- (void)button1Tapped:(id)sender {
  [_label setString:@"Last button: 1"];
}
 
- (void)button2Tapped:(id)sender {
  [_label setString:@"Last button: 2"];
}
 
- (void)button3Tapped:(id)sender {
  [_label setString:@"Last button: 3"];
}

Once you compile and run this you should see something like the following:

Radio Buttons Creenshot

Behind The Scenes

If you look at how the menu system is implemented, you will note that menu items are CCNodes, but a Menu is a CCLayer. According to the Cocos2D best practices, you shouldn’t create a big hierarchy of layers, and should keep the count as low as you can.

So this means you probably should combine as many menu items into a single menu layer as you can. Also since a Menu derives from CCLayer you can’t make it run actions such as MoveTo, etc. I only mention this because I tried to move a whole menu of items when I was first starting and was wondering why it didn’t work :] Update: Eric from the comments below pointed out that CCLayer derives from CCNode, so you can run actions on it if you need to. Something else must have been going on when I was playing with it earlier, thanks Eric! :]

And That’s A Wrap!

Here’s a project with all of the code from the above tutorial.

Hope this was of use, and if you have any other cool tips about Buttons in Cocos2D please let me know!


Category: iPhone

Tags: , , ,

63 Comments

  1. Wayfarer (1 comments) says:

    Hey, I downloaded the code and tried to run it… it compiled successfully but wouldn’t install on the Simulator. I got an error -1, springboard failed to launch. I’m running it in 3.1.2 and xcode 3.2.1 64 bit.

  2. Eric (15 comments) says:

    Hi Ray,

    You can run actions on CCLayer, the runAction: method is part of CCNode class and CCLayer is a subclass of CCNode.

    In one of my project, I use a CCMoveTo action on a custom CCLayer subclass that contains a CCMenu and some other stuffs and it works nicely. I’ve also tried directly on the CCMenu and it’s ok too.

    For example on line 54 of HelloWordScene.m of your project, if you replace :
    toggleMenu.position = ccp(60, 120);
    [self addChild:toggleMenu];

    by something like :
    toggleMenu.position = ccp(-60, 120);
    [self addChild:toggleMenu];
    [toggleMenu runAction:[CCMoveTo actionWithDuration:0.5 position:ccp(60,120)]];

    the + button slides in from left.

    If you want to obtain the same effect for all your menus, it can be easier to have them on a separate CCLayer and run the action on that CCLayer.

    Hope it helps.

  3. Ray Wenderlich (874 comments) says:

    @Wayfarer: Hm I am not sure about that, I pulled down the code and tried it and it worked OK here.

    @Eric: Thanks!! I must have missed that when I was looking at it earlier. I’ve updated the post to clear that up.

  4. Jesse (3 comments) says:

    Very Simple and Useful.

  5. Eric (15 comments) says:

    You’re welcome Ray ! In fact, I should thank you too, after reading your first post on Cocos2D, I started again one of my projects of game which I had begun with this framework several weeks ago.

  6. Joakim (1 comments) says:

    Hey, I’ve played around a little with cocos2d and followed your tutorials, but I wonder how do I make the button do an action when pressed and not released?

  7. Ray Wenderlich (874 comments) says:

    @Joakim – One way to do that is to override CCMenu and make a menu that activates your button on ccTouchBegan rather than ccTouchEnded.

    If you open up CCMenu.m, you’ll see that in ccTouchEnded it calls [selectedItem activate] – this is what gets your selector to be called.

    So you could make a subclass of CCMenu and override the ccTouchBegan and ccTouchEnded methods. Copy and paste the code from CCMenu, except move the [selectedItem activate] call up into ccTouchBegan rather than ccTouchEnded.

    Hope this helps!

  8. geykel (4 comments) says:

    Hello, nice post! I got this issue, I would like to generate several menu items (they will act as radio buttons) let say a list of countries where you can only select one, the countries will be pulled from a database so I need to use labels instead of images for the menu items but I want to have the radio buttons looks like standard radio buttons, I mean, with the circle before the text, like this: () Italy, () China, (x) USA, so my question is: how can I do that using CCMenu? any ideas?

  9. Ray Wenderlich (874 comments) says:

    @geykel – Off the top of my head, here’s one solution I can think of. Remember that CCMenuItem derives from CCNode, so you can use CCMenuItemLabels for the text, and then add a CCSprite child image on each menu item to represent the dot, and then just use relative positioning to get it placed where you want.

    Best of luck!

  10. geykel (4 comments) says:

    Thanks Ray, I will try that…

  11. Saliom (16 comments) says:

    Hi Ray, i got a question for you, i hope you can help me :)

    i’m still doing my game for my internship, and i’m using some menus in a level editor, but i got a little problem when i place a sprite over a button from my menu, i can’t touch that button again, i was hoping you could have any idea on how i could have that button always on top??

    and also another question, how can i get a background for that menu?? by reading the comments here i thought by maybe adding a CCColorLayer to my scene and add the menu to that Layer?? would it be a good idea?? and working? :D

    thx again for your posts and your help :)

  12. Ray Wenderlich (874 comments) says:

    @Saliom: Have you tried using the z parameter when you use addChild to add the sprite? The higher the z value, the more toward the top a node is.

    For a background, one simple way of doing it would be to have a CCSprite for the background and just put it underneath where you’re putting the menu.

  13. Saliom (16 comments) says:

    huhu ok, i’ll try those, thx for your help :)

  14. Saliom (16 comments) says:

    ho by the way, i found a lil bug, when you got radio buttons, if you flood them at some point the buttons are blocked and you can’t chose another radio button… i don’t really know where does it come from, my colleague guess that it’s a thread concurrence or something

  15. Ray Wenderlich (874 comments) says:

    @Saliom – Hm thanks, hwill keep an eye out for that!

  16. Saliom (16 comments) says:

    Hi Ray, we took a look this morning with my colleague to see why it does block the button and it seems to come from the ccTouchEnded

    - (void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event {

    NSAssert(state == kMenuStateTrackingTouch, @”[Menu ccTouchEnded] — invalid state”);

    CCMenuItem *curSelection = [self itemForTouch:touch];
    if (curSelection != _curHighlighted && curSelection != nil) {
    [selectedItem selected];
    [_curHighlighted unselected];
    _curHighlighted = nil;
    //here is what we added
    state = kMenuStateWaiting;
    return;
    }

    selectedItem = _curHighlighted;
    if([_curHighlighted respondsToSelector:@selector(activate)])
    {
    [_curHighlighted activate];
    }
    _curHighlighted = nil;

    state = kMenuStateWaiting;

    }

    this is the code we have now and it seems to work fine and i couldn’t block it for now :p

    but we didn’t really understood what was done in the first if, maybe you could explain it to me? :)

    about the little bug, in fact the state should be on waiting at start of ccToucheBegin and on tracking at start of ccTouchEnded, but when we could block the buttons, the state was blocked on Tracking at the start of ccTouchBegin, and because of that the first if was returning NO; and then it was impossible to change the state again … i hope this help you ;) :)

  17. Ray Wenderlich (874 comments) says:

    Cool, thanks! Looks like I forgot to set the state variable in that if clause.

    The reason for that clause was to cover the case where the user taps down over a button, holds their finger down, moves to another button, and then moves their finger up. I wanted the buttons to highlight as the user moves their finger over the various buttons, but call selected on the final button once the user brings their finger up.

    I’ve updated the zip file on the tutorial to include the fix. Thanks again!

  18. Saliom (16 comments) says:

    no problem ;) glad it could help :) thx for the fix :D

  19. Matt (1 comments) says:

    Hi Ray,

    Great example. I was wanting to do an action while a button was pressed as well, so I was trying to do your suggestion of overriding CCMenu.m but still couldn’t get it to work. Would you by any chance have an example of this so I might be able to see what I am doing wrong?

    Thanks

  20. Ricardo (3 comments) says:

    Hi!

    I’m using your CCRadioMenu but it have some problems:

    -It seems you didn’t updated your zip file with post 16 modification

    -After doing that change, I still have the same problem, still blocks sometimes.

    -When compiling it in my XCODE, I receive this warning:
    warning: CCRadioMenu may not respond to – itemForTouch
    in 2nd line of ccTouchEnded

    Thanks a lot for your help.
    Ricardo.

  21. TD (1 comments) says:

    Nitpicking: Please don’t use Arial as font if there is Helvetica available.

  22. Ray Wenderlich (874 comments) says:

    @Ricardo: Ack, you’re right, guess I forgot to upload it! Uploaded it for real this time :] After doing the change, I have had no further problems – in fact I’m using the code in my most recent game. The warning is there because CCMenu doesn’t expose that method, if you want to remove the warning you could move the method declaration to the header file.

    @TD: Thanks! I’m a programmer not a designer so stuff like that is not obvious to me :]

  23. Dominique (2 comments) says:

    Hi Ray and thx for this.
    But one question : is it possible (maybe with some modifications in the cocos2d sources) to use this method for a action like “while push do” ?
    For example to move a sprite ?

    thx again.

  24. Pete (11 comments) says:

    Does anyone see “cocos2d: removeChildByTag: child not found!” in their debugger console after declaring and adding the toggleItems?

    It doesn’t affect the operation, but I was curious to see why I got this message/warning.

  25. Ray Wenderlich (874 comments) says:

    @Dominique: Yeah you could do that, one way to do it would be by making a custom CCMenu class with the ccTouchBegan/Ended/Cancelled methods overridden, scheduling a periodic callback in ccTouchBegan where you call [selectedItem activate], and stopping the callback in ccTouchEnded.

    @Pete: Hm, I didn’t see that warning in the sample project, but there is a warning for CCRadioMenu may not respond to itemForTouch, is that the one you mean…?

  26. Pete (11 comments) says:

    No, it’s actually outputted to the Debugger console.
    Every time I load that scene, the same message pops up:
    “cocos2d: removeChildByTag: child not found!” which I narrowed down to the toggleItem, by simply commenting it out.

  27. Ray Wenderlich (874 comments) says:

    @Pete: Ah, ok! I just checked it out, and it appears to be because when a CCMenuItemToggle is initialized, it calls setSelectedIndex to initialize the selected index to 0.

    This then removes any child from the node that is tagged with “current item”, but of course there is no such child yet because this is the first time setSelectedIndex has been called, so that warning prints out.

    So it’s no big deal and shouldn’t be any problem for your project. However if it annoys you, you could just modify CCMenuItem to only remove the current item child after the first iteration or some such :]

  28. Pete (11 comments) says:

    Cheers Ray, no longer annoying :]

  29. Dominique (2 comments) says:

    Thank you Ray, it works perfect ! ;)

  30. Abhilash Vijayakumar (4 comments) says:

    Hi Ray,
    When one button touch and hold, other buttons don’t seem to respond. How to enable multi touch ?

  31. Ray Wenderlich (874 comments) says:

    If you take a look at CCRadioButton.h/m, you’ll see the implementations of the ccTouchBegan/ended/etc methods. You can modify these to your desire to get any behavior you want.

  32. Abhilash Vijayakumar (4 comments) says:

    Thank you Ray

  33. elpuerco (16 comments) says:

    Hi Ray, could you explain the position property as I am a tad confused how this equates to a location on the screen?

    “Note that we create the menu at CGPointZero (a shortcut for 0,0). This is actually specifying where the center of the menu is. However, we also specify that the menu item is at offset (60, 60) relative to the center of the menu – so our button’s center is at (60, 60) on the screen.”

    (0,0) in openGL space is bottom left, correct? So you are positioning the menu’s centre there, so some of it is off screen?

    And then you place the button offset at 60,60?

    I have an image that is 1024 * 50 and I am trying to position it at the bottom of the screen, so this would be (0, 50)? But when I do that there is a gap at the bottom?

    If i do image.contentSize.height / 2 it looks OK???

    thanks

  34. Jim P. (16 comments) says:

    Hi Ray,

    I’m only a level 3 n00b iPhone app developer (yes, I have Level Me Up) and for some reason it’s giving me an error here:

    //This is in my init:
    CCMenuItem *menuItem1 = [CCMenuItemImage itemFromNormalImage:@"Button1.jpg" selectedImage:@"Button1Sel.jpg" target:self selector:@selector(button1Tapped:)];
    CCMenuItem *menuItem2 = [CCMenuItemImage itemFromNormalImage:@"Button2.jpg" selectedImage:@"Button2Sel.jpg" target:self selector:@selector(button2Tapped:)];
    CCMenuItem *menuItem3 = [CCMenuItemImage itemFromNormalImage:@"Button3.jpg" selectedImage:@"Button3Sel.jpg" target:self selector:@selector(button3Tapped:)];
    CCRadioMenu *radioMenu = [CCRadioMenu menuWithItems:menuItem1, menuItem2, menuItem3, nil];
    radioMenu.position = ccp(120,180);
    [radioMenu alignItemsHorizontally];
    radioMenu.selectedItem = menuItem1;
    [menuItem1 selected];
    [self addChild:radioMenu];

    //This is a method after:
    -(void)button1Tapped:(id)sender {
    [_label setString:@"Last button: 1"];

    //It says that “button1Tapped” is undeclared. Help!
    }

  35. forkon (8 comments) says:

    Hi, Ray. Hi, everyone.

    I want to implement a direction key to control my sprite’s movement (move up, down, right or left).

    This is the normal image of my direction button

    http://i531.photobucket.com/albums/dd360/forkon/normal.jpg

    one of the selected image(move up)

    http://i531.photobucket.com/albums/dd360/forkon/uppress.jpg

    I know there are many iphone games equipped direction button, but I don’t know how they implement usually.

    Thanks!

  36. Ric (2 comments) says:

    Jlim:
    Do you have:
    -(void)button1Tapped:(id)sender;
    in your header (.h) file?

  37. Jim P. (16 comments) says:

    @Ric:
    No, said method (or function, whatever floats your boat) is in HelloWorldScene.m. Is it supposed to be in the .h file?

  38. Ric (2 comments) says:

    @Jim: Of course!
    The common way to declare and implement a method in ObjectiveC is writting it in the header file AND .m file.
    Note that if you are using a delegate (protocol), you don’t need (or have) to declare it in your header file.

  39. Jim P. (16 comments) says:

    @Ric:
    I declared the method in the .h file, and it just gave me more problems.
    Then I moved the button1Tapped method to before the init and it said that button2Tapped was undeclared. I repeated this (moving all of my methods to before the init) until it said that dealloc was undeclared. What the heck?

    Is there any way for me to upload my entire code?

  40. Jim P. (16 comments) says:

    @Ric:
    Okay, THAT was weird. I put a close bracket ‘}’ after my init and everything fixed itself. How did I not see that? :O

  41. Ray Wenderlich (874 comments) says:

    @elpuerco: You’ve got it the idea. Except menus are just CCLayers, and most CCLayers have their position at 0,0 so that when you specify positions of objects their position will be the same as screen coordinates.

    So it’s not really that some of the menu is “off screen” since the menu is just a virtual plane that you can put things on top of, and you wouldn’t usually put things offscreen (with negative coordinates).

    Regarding the placement of your image, when you place any CCNode the position is relative to the node’s anchor point. The anchor point for a node is by default (0.5,0.5), which is the center of an object. So that’s why you had to use image.contentsize.height/2.

    Let me know if any of this is still unclear! Sometimes playing around with a sample project in Cocos2D helps a bit.

    @forkon: You may want to look into the SneakyInput cocos2d library.

    @Jim: Glad you got it working, and grats on level 3 hehe!

    @Ric: Thanks so much for helping out Jim!

  42. forkon (8 comments) says:

    Thanks Ray, I’m studying SneakyInput’s code.Very useful I think.

  43. Jiaren Wu (8 comments) says:

    Hi Ray,

    Thank you for your tutorial!

    I am combining your radio buttons to my project. But I have a quick question. Is it possible to retrieve the image of selected radio button? I couldn’t find any such property or could you please improve your class definition? Otherwise I may have to use switch case to get the chosen image.

    Thank you in advance.

  44. Ray Wenderlich (874 comments) says:

    @Jiaren: Well, you can get the selected item from the CCRadioMenu with the selectedItem property. You know that this is a CCMenuItemImage, which derives from CCMenuItemSprite. And CCMenuItemSprite has properties for normal/selected/disabledImage. Hope this helps!

  45. Ozgur (1 comments) says:

    Man it was a great tutorial but I have a question.
    You said =>
    “For a background, one simple way of doing it would be to have a CCSprite for the background and just put it underneath where your’e putting the menu”

    My question is not putting the background image to Menu, to Main Game screen. when i do that my fps goes down because i draw my other game components on the background image. Could you suggest me another way to put background?

    Thanks.
    özgür

  46. Jiaren Wu (8 comments) says:

    Thanks, Ray!

    I solved this problem by set tag to each radio button.

  47. Ray Wenderlich (874 comments) says:

    @Ozgur: Here’s a good link to a discussion on some Cocos2D performance tips:

    http://allseeing-i.com/Performance-tips-for-Cocos2d-for-iPhone

    @Jiaren: w00t glad you got it working!

  48. Luv (3 comments) says:

    @Everyone
    what if i want to call a function repeatedly when the menu item is in pressed state….?

  49. Luv (3 comments) says:

    @Dominique

    you have implemented “while push do ” action in cocos2d …. i want to implement the same …Any idea how to do that…..

  50. Ray Wenderlich (874 comments) says:

    @Luv: You can subclass the type of CCMenuItem you are using (such as CCMenuItemImage), and override the selected and unselected methods. If you want a method to be called periodically while the button is held down, you could schedule a method on “selected” and unschedule it on “unselected.”

  51. Mark W (7 comments) says:

    thanks for sharing that link to SneakyInput. very useful for most games :} the link got changed though to something else

  52. Ray Wenderlich (874 comments) says:

    @Mark: Thanks for catching that! I have updated the link.

  53. Jake Boxer (1 comments) says:

    Just a note for other people: compiling CCRadioMenu produces errors on cocos2d 0.99.5 because kMenuStateX has been renamed to kCCMenuStateX. So, replace kMenuStateWaiting with kCCMenuStateWaiting, and kMenuStateTrackingTouch with kCCMenuStateTrackingTouch, and you’ll be fine.

    Also, [CCMenu itemForTouch] was made private. It still works fine, but you’ll get compiler warnings.

  54. Ray Wenderlich (874 comments) says:

    @Jake: Thanks Jake for sharing for everyone else!

  55. griga (2 comments) says:

    Hi, Ray! I don’t understand releasing labels in dealloc. Aren’t they an autorelease objects? Can u clear this 2 me? thnx ))

  56. griga (2 comments) says:

    and why have u retained that labels?

  57. Stefan (1 comments) says:

    Hi Ray,

    thanks for this tutorial! I am using your CCRadioMenu Class and I am wondering wether it will be possible to have 2 Buttons selected at the same time?

    Thanks for your advice!

    BR,

    Stefan

  58. Ray Wenderlich (874 comments) says:

    @griga: There are two strategies for how to deal with member variables pointing to Cocos2D objects – either make them assign (since Cocos2D will keep a retain count on them as long as they’re in the scene) or to retain them yourself to be absolutely sure it’s still valid even if it’s been removed from the scene. For this tutorial, I chose option 2, but sometimes I use option 1 as well, so it depends.

    @Stefan: The radio button class is designed to select 1 at a time, but you could hack it to support different behavior if you’d like.

  59. Eric Colson (1 comments) says:

    Hi Ray,

    thank you very much for yours tutorials. I appreciate their simplicity and all the time necessary you need to elaborate them.
    I have just one question about the toggle button : why do you release it in the dealloc method ? This button isn’t alloc when you create it. Is it an error or there is a thing I don’t understand concerning memory allocation in Cocos2D ?

  60. Ray Wenderlich (874 comments) says:

    @Eric: Are you asking why the plus/minus buttons are released? That’s because they’re retained in the code, so they need to be released to decrement the ref count back down.

  61. Lowell (1 comments) says:

    This is a great tutorial ( Really nice blog Ray!). But being new to Cocos2d & Objective C, I’m wondering if someone can help me understand the right syntax for sending a variable along with the @selector method in the Cocos2d menu setup. For instance if I wanted to send the button number along with a generic method: @selector(buttonTapped:1)… Can the cocos2d menu support this? I’ve only encountered errors and was wondering what simple thing I might be missing?

    thanks,

    Lowell

  62. Ricardo (3 comments) says:

    Hello!

    It seems your current version does not work with cocos2d 0.99.5. Just change some var names, for instance rename state to state_, selectedItem to selectedItem_…

I'd love to hear your thoughts!