Individual buttons in cocos2d - cocos2d-iphone

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;
}

Related

Cocos2d - Alternative for CCNode userData

I am using CCNode userData property to define whether a touched sprite has had a node built upon it (using Ray Wenderlich's - Tower Defence Tutorial).
The problem I am having is that for every new sprite position I touch and build upon, the previous ones are not retained in the sense that I am unable to sell the building built on it using my sell method.
What is the best way to save data to an individual CCSprite that is selected by touch, and defined by a property through a for loop?
I have read that subclassing CCSprite is an option, or creating a struct for userData etc. I have tried to implement these strategies but have been unsuccessful getting them to work.
touch method with sprite property:
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
for(UITouch *touch in touches){
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
for(CCSprite *tb in self.BuildPositions){
//BuildPositions contains CCSprites from a class defining build positions and contained in a mutable array.
if(CGRectContainsPoint([tb textureRect],[tb convertToNodeSpace:location ])){
_selectedBuildPosition = tb;
[self buildMenuTapped];
}
}
}
}
build menu method:
-(void)buildMenuTapped{
[self removeChild:_buildSelectMenu cleanup:YES];
[self removeChild:_sellBuildingMenu cleanup:YES];
if (_selectedBuildPosition.userData == nil) {
CCMenuItem *buildOption = [CCMenuItemImage itemWithNormalImage:#"building.png" selectedImage:#"building.png" target:self selector: #selector(buildOption)];
buildOption.position = ccpAdd(_selectedBuildPosition.position,ccp(0,40));
_buildSelectMenu = [CCMenu menuWithItems:BuildOption, nil];
_buildSelectMenu.position = CGPointZero;
[self addChild:_buildSelectMenu z:100];
}else{
[self sellBuildingMenu];
}
}
build upon method:
-(void)buildOption{
if([self canBuyBuilding] && !_selectedBuildPosition.userData){
_playerEssence -= kBUILD_COST;
_lvl1BuildNodeInstance = [lvl1BuildNode nodeWithTheGame:self location:_selectedBuildPosition.position];
//method as seen in RW tutorial. Generates a lvl1BuildNode class node within the HelloWorldLayer.
_selectedBuildPosition.userData = (__bridge void*)(_lvl1BuildNodeInstance);
}
}
sell menu method:
-(void)sellBuildingMenu{
[self removeChild:_buildSelectMenu cleanup:YES];
[self removeChild:_sellBuildingMenu cleanup:YES];
CCMenuItem *buildingSell = [CCMenuItemImage itemWithNormalImage:#"sell.png" selectedImage:#"sell.png" target:self selector:#selector(sellBuilding)];
buildingSell.position = ccpAdd(_selectedBuildPosition.position,ccp(40,0));
_sellBuildingMenu = [CCMenu menuWithItems:buildingSell, nil];
_sellBuildingMenu.position = CGPointZero;
[self addChild:_sellBuildingMenu z:100];
}
sell method:
-(void)sellBuilding{
if (_selectedBuildPosition.userData == (__bridge void*)(_lvl1BuildNodeInstance)){
[self removeChild:_lvl1GemNodeInstance cleanup:YES];
[_buildings removeObject:_lvl1BuildNodeInstance];
_playerEssence += kBUILD_COST;
_selectedBuildPosition.userData = nil;
}else{
}
}
Thank you for your time.

Slide In and Slide Out animation like keyboard in cocos2d

I want to create a toolbar (initially hidden) with items that can be dragged. If a button is tapped, the toolbar will appear buttom-up (just like the animation of keyboard). I just like to ask how to do it in cocos2d.
Thanks for the response!
I used this code for drawer open and close.
-(void)showMyCocos2DDrawer
{
CGSize s = [[CCDirector sharedDirector] winSize];
self.position = ccp(-s.width,0.0f); //do this in ur init method :)
CGPoint pos =ccp(0.0f, 0.0f );
id moveTo = [CCMoveTo actionWithDuration:0.5f position:pos];
id calFun = [CCCallFunc actionWithTarget:self selector:#selector(animDone)];
id seq = [CCSequence actions:moveTo, calFun, nil];
[self runAction:seq];
}
-(void)hideCocos2DDrawer
{
CGSize s = [[CCDirector sharedDirector] winSize];
CGPoint pos =ccp(-s.width, 0.0f);
id moveTo = [CCMoveTo actionWithDuration:0.3f position:pos];
id calFun = [CCCallFunc actionWithTarget:self selector:#selector(goBack)];
id seq = [CCSequence actions:moveTo, calFun, nil];
[self runAction:seq];
}
-(void) animDone
{
//write in code here..
}
-(void)goBack
{
//write out code here..
}

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).