CCMenu child of child selector not firing - cocos2d-iphone

I have a ccmenu with a ccmenuitemsprite in a ccmenuitemsprite which has the selector.
I wish for the child of child to be a play button that fires a selector but its not firing.
CCMenu *menu [CCMenu menuWithItems: nil];
CCMenuItem *bg = [CCMenuItemSprite itemFromNormalSprite:[CCSprite spriteWithFile:#"sprite_sheet.png" rect:CGRectMake(0,50,100,100)]
selectedSprite:nil
disabledSprite:nil
target:self
selector:nil];
CCMenuItem *playBtn = [CCMenuItemSprite itemFromNormalSprite:[CCSprite spriteWithFile:#"sprite_sheet.png" rect:CGRectMake(0,0,50,50)]
selectedSprite:[CCSprite spriteWithFile:#"sprite_sheet.png" rect:CGRectMake(50,0,50,50)]
disabledSprite:[CCSprite spriteWithFile:#"sprite_sheet.png" rect:CGRectMake(100,0,50,50)]
target:self
selector:#selector(onPlay:)];
[bg addChild:playBtn];
[menu addChild:bg];
[self addChild:menu];

If you want to pass the name of your images as arguments, please use the following code:
CCMenuItem *playBtn = [CCMenuItemImage itemFromNormalImage:#"image.png"
selectedImage:#"image_selected.png"
disabledImage:#"image_disabled.png"
target:self
selector:#selector(onPlay:)];
The constructor you are using is expecting a CCSprite, not an NSString.
OK, after you edited the answer, I looked more closely, and you have the playBtn as a child of bg. You can't do that. Only the direct children of CCMenu are able to send callbacks:
[menu addChild:playBtn];
I would suggest you do this actually:
CCMenuItem *playBtn = [CCMenuItemSprite itemFromNormalSprite:[CCSprite spriteWithFile:#"sprite_sheet.png" rect:CGRectMake(0,0,50,50)]
selectedSprite:[CCSprite spriteWithFile:#"sprite_sheet.png" rect:CGRectMake(50,0,50,50)]
disabledSprite:[CCSprite spriteWithFile:#"sprite_sheet.png" rect:CGRectMake(100,0,50,50)]
target:self
selector:#selector(onPlay:)];
CCMenu* menu = [CCMenu menuWithItems:playBtn, nil];
CCSprite* bg = [CCSprite spriteWithFile:#"sprite_sheet.png" rect:CGRectMake(0,50,100,100)];
[self addChild:bg];
[self addChild:menu];

Related

How do I pause all actions while fading cclayer then resume gameplay in cocos2d?

I have this:
-(void)fadeBackground
{
ccColor4B color = {0,0,0,255};
CCLayerColor *fadeLayer = [CCLayerColor layerWithColor:color];
[self addChild:fadeLayer z:7];
fadeLayer.opacity = 0;
id fade = [CCFadeTo actionWithDuration:1.0f opacity:200];//200 for light blur
id calBlk = [CCCallBlock actionWithBlock:^{
//show pause screen buttons here
//[self showPauseMenu];
}];
id fadeBack = [CCFadeTo actionWithDuration:2.0f opacity:0];
id sequen = [CCSequence actions:fade, calBlk, fadeBack, nil];
[fadeLayer runAction:sequen];
}
How do I stop the actions while the fadein occurs and resume them when the fadeBack occurs?
[[CCDirector sharedDirector] pause]; & [[CCDirector sharedDirector] resume]; will pause and resume the schedulers and actions throughout all the Sprites/Layers or any other cocos2d Nodes.
If you want to pause/resume a particular CCLayer along with children its containing,
////for pausing
[myLayer pauseSchedulerAndActions];
for(CCNode *child in myLayer.children){
[child pauseSchedulerAndActions];
}
///for resuming
[myLayer resumeSchedulerAndActions];
for(CCNode *child in myLayer.children){
[child resumeSchedulerAndActions];
}
To pause, you can use this call, need to call same for each menu in game.
[self pauseSchedulerAndActions];
[menu pauseSchedulerAndActions];
To resume:
[self resumeSchedulerAndActions];
[menu pauseSchedulerAndActions];

Individual buttons in cocos2d

Most talk about buttons for cocos2d seems to be directed to CCMenu, where CCMenu AFAIK is meant for having a row or column in center of screen.
I need to place buttons randomly on screen and have yet to find a simple out of the box solution for this. I did try CCControlButton but didn't get it to work (CCScale9Sprite spriteWithSpriteFrameName loads incorrectly from sprite atlas).
For now I try to use this. It uses only one button in each CCMenu. So my screen will have lots of CCMenu instances, one for each button.
+(CCMenu*)button:(NSString*)spriteframename at:(const CGPoint)POINT block:(void(^)(id sender))block {
CCSprite* sprite1 = [CCSprite spriteWithSpriteFrameName:spriteframename];
CCSprite* sprite2 = [CCSprite spriteWithSpriteFrameName:spriteframename];
CCMenuItem* menuitem = [CCMenuItemImage itemWithNormalSprite:sprite1 selectedSprite:sprite2 block:block];
CCMenu* menu = [CCMenu menuWithItems:menuitem, nil];
menu.contentSize = sprite1.contentSize;
menu.position = POINT;
return menu;
}
This is a better way which I changed to.
Put this in like init:
CCMenuItem* menuitemRetry = [[self class] buttonWithSpriteframenameOff:#"retry_off.png" on:#"retry_on.png" at:ccp(198, 184) block:^(id sender) {
// Do something
}];
CCMenuItem* menuitemMenu = [[self class] buttonWithSpriteframenameOff:#"menu_off.png" on:#"menu_on.png" at:ccp(362, 184) block:^(id sender) {
// Do something else
}];
CCMenu* menuLow = [CCMenu menuWithItems:menuitemMenu, menuitemRetry, nil];
menuLow.position = CGPointZero;
[self addChild:menuLow];
This also needed
+(CCMenuItem*)buttonWithSpriteframenameOff:(NSString*)spriteframenameOff on:(NSString*)spriteframeOn at:(const CGPoint)POINT block:(void(^)(id sender))block {
CCMenuItem* menuitem = [CCMenuItemImage itemWithNormalSprite:[CCSprite spriteWithSpriteFrameName:spriteframenameOff] selectedSprite:[CCSprite spriteWithSpriteFrameName:spriteframeOn] block:block];
menuitem.position = POINT;
return menuitem;
}

How do you place a ccmenuitem with a cclabel underneath it?

In cocos2d-iphone, I would like to use a sprite for the menu button item and I'd like to place a label underneath it describing the button.
However, I am not sure how to do this.
If I attempt to make more buttons/labels and then use
[menu alignItemsHorizontallyWithPadding:1.5f];
The position of the items is wrong.
Anyway, here is my code;
// Button
CCSprite *panel = [CCSprite spriteWithFile:#"panel.png"];
// Menu
CCMenu *menu = [CCMenu menuWithItems:nil];
CCLabelBMFont *lblFont = [CCLabelBMFont labelWithString:#"Some text" fntFile:#"arial16.fnt"];
CCMenuItemLabel *mnuLabel = [CCMenuItemLabel itemWithLabel:lblFont];
CCMenuItemSprite *mnuSprite = [CCMenuItemSprite itemFromNormalSprite:panel selectedSprite:nil disabledSprite:nil target:nil selector:nil];
[menu addChild:mnuSprite];
[menu addChild:mnuLabel];
[menu setPosition:ccp(winSize.width/2, winSize.height/2)];
[self addChild:menu z:1];
Are you sure, you need label UNDERNEATH your sprite? If I understand right, you can just create CCMenuItemSprite instance, then add label to it as a child. smth like:
CCMenuItemSprite *mnuSprite = [CCMenuItemSprite itemFromNormalSprite:panel selectedSprite:nil disabledSprite:nil target:nil selector:nil];
CCLabelBMFont *lblFont = [CCLabelBMFont labelWithString:#"Some text" fntFile:#"arial16.fnt"];
[lblFont setAnchorPoint: ccp(0.f, 0.f)];
[mnuSprite addChild: lblFont];

how to do a function for a sprite or menu in cocos2d?

I created two CCLayers, one is gamelayer, another is howlayer. The code of gamelayer.m is
-(id)init{
if (self = [super init]) {
CCSprite *gamebg = [CCSprite spriteWithFile:#"bg.png"];
gamebg.anchorPoint = CGPointZero;
[self addChild:gamebg z:0 tag:1];
HowLayer *howLayer = [HowLayer node];
[self addChild:howLayer];
[self schedule:#selector(showthegamecontent:) interval:0.4];
}
return self;
}
the code of howlayer is
-(id)init{
if (self=[super init]) {
CCSprite *howbg = [CCSprite spriteWithFile:#"translucentbg.png"];
howbg.anchorPoint = CGPointZero;
[self addChild:howbg z:5 tag:1];
CCMenuItem *howmenu = [CCMenuItemImage itemFromNormalImage:#"how.png"
selectedImage:#"how.png"
target:self
selector:#selector(startgame:)];
CCMenu *ccMenuhowmenu = [CCMenu menuWithItems:howmenu, nil];
ccMenuhowmenu.position=ccp(517,384);
[self addChild:ccMenuhowmenu z:5 tag:2];
}
return self;
}
-(void)startgame:(id)sender{
[self removeAllChildrenWithCleanup:YES];
}
I want to do function like this:
When I click the menu on howlayer, the Howlayer will be removed (I have done), and then the game starts, calls the selector 'showthegamecontent', so how should I do?
Simple hack in your howlayer:
-(void)startgame:(id)sender{
gameLayer* parent = (gameLayer*) self.parent;
[parent showthegamecontent];
}
but it may leave you with a warning.. But it works..
The implementation without warning is that you have to store a reference to the parent with you init. Which i feel its unnecessary as you only need to reference it once.

Cocos2d Displaying a Layer Issue

I'm trying to display a pause game layer from the applicationDidEnterBackground: method and for some reason it does call the method but nothing happens.
Delegate
- (void)applicationDidEnterBackground:(UIApplication*)application {
ship = [[Ship alloc] init];
[ship pause];
Pause Method
- (void)pause
{
BOOL isPaused = [[CCDirector sharedDirector] isPaused];
if(!isPaused)
{
//Pause the game
ccColor4B c = {100,100,0,100};
PauseLayer *pauseLayer = [[[PauseLayer alloc] initWithColor:c] autorelease];
[self.leftMenuItem setIsEnabled:NO];
[self.rightMenuItem setIsEnabled:NO];
[self.fireMenuItem setIsEnabled:NO];
[self addChild:pauseLayer z:10 tag:100];
[[CCDirector sharedDirector] pause];
}
}
PauseLayer
+ (id)scene
{
CCScene *scene = [CCScene node];
PauseLayer *layer = [PauseLayer node];
[scene addChild:layer];
return scene;
}
- (id)initWithColor:(ccColor4B)color
{
if((self = [super initWithColor:color]))
{
self.isTouchEnabled = YES;
[CCMenuItemFont setFontName:#"Marker Felt"];
[CCMenuItemFont setFontSize:40];
CCMenuItemFont *resumeGameItem = [CCMenuItemFont itemFromString:#"Resume" target:self selector:#selector(resumeGame)];
CCMenuItemFont *menuGameItem = [CCMenuItemFont itemFromString:#"Menu" target:self selector:#selector(goToGameMenu)];
CCMenu *menu = [CCMenu menuWithItems:resumeGameItem,menuGameItem,nil];
[menu alignItemsVerticallyWithPadding:40.00];
[self addChild:menu];
}
return self;
}
Thanks!
If you init the ship in the delegate, it isn't added to any cocos layer that I can see. you would have to get a reference to the current scene and add the ship to it (assuming ship is a sub-class of Cocos node).