I'm trying to make a CCMenuItem that has scaled images. For example, I tried:
CCSprite* normalSprite = [CCSprite spriteWithFile:#"button_play.png"];
CCSprite* selectedSprite = [CCSprite spriteWithFile:#"button_play.png"];
selectedSprite.scale = 1.2;
CCMenuItem menuItem = [CCMenuItemSprite
itemFromNormalSprite:normalSprite
selectedSprite:selectedSprite
target:self
selector:#selector(onPlay:)];
But it looks like CCMenuItemSprite ignores the scale of the underlying sprites. Is there a way to do this (aside from just creating scaled versions of the underlying images)? Thanks.
Thyrgle is correct about how CCMenuItem works.
However, there certainly is a way to do what you want. All you need to do is subclass CCMenuItem and override the selected and unselected methods to achieve what you want. In fact, I'm pretty sure you could just cut and paste the code from CCMenuItemLabel, because scaling the item to 1.2 is exactly what it does. (In fact, it does it better, since it animates the scale change.)
-(void) selected
{
// subclass to change the default action
if(isEnabled_) {
[super selected];
[self stopActionByTag:kZoomActionTag];
CCAction *zoomAction = [CCScaleTo actionWithDuration:0.1f scale:1.2f];
zoomAction.tag = kZoomActionTag;
[self runAction:zoomAction];
}
}
-(void) unselected
{
// subclass to change the default action
if(isEnabled_) {
[super unselected];
[self stopActionByTag:kZoomActionTag];
CCAction *zoomAction = [CCScaleTo actionWithDuration:0.1f scale:1.0f];
zoomAction.tag = kZoomActionTag;
[self runAction:zoomAction];
}
}
CCMenuItemImage Class is also available for displaying image with its scale in CCMenu.Please Check this link http://www.cocos2d-iphone.org/forum/topic/8310
[mainMenu alignItemsVerticallyWithPadding:15.0f];
No there is not another way. The thing is that menuItem is only acknowledging the files part of the sprites. It is not looking at other properties such as the scale property.
Related
in .h file
CCSprite *backwheels;
in .m file
backwheels = [CCSprite spriteWithFile:#"wheels_back.png"];
backwheels.position = ccp(400,120);
[self addChild:backwheels];
-(void) showGameOver {
backwheels.visible = false;
}
but when Game is Over backWheels still appears on scene..? !
any help ?!
NOTE:i have synthesized backWheels too,but still doesn't work for me.
I can give you a quick fix. This is not the best approach, the best one is to find out what exactly causes such a behavior, but i can't do that without seeing the rest of your code. Anyway this is how you can access backwheels sprite in showGameOver method. When you create the sprite make it this way:
backwheels = [CCSprite spriteWithFile:#"wheels_back.png"];
backwheels.position = ccp(400,120);
backwheels.tag = 100; // whatever integer value you wish
[self addChild:backwheels];
Then you retrieve it in showGameOver :
backwheels = [self getChildByTag:100];
backwheels.visible = false;
I believe it's gonna work.
You could always just change the opacity of the sprite i.e.
-(void) showGameOver {
backwheels.opacity = 0.0f;
}
And then when you want it to reappear change it to
backwheels.opacity = 1.0f;
Use Remove Child :
[self removeChild:backwheels cleanup:YES];
Let's say I have a character in a game and its class is like this.
#interface Player
{
CCSprite* stand;
CCAnimation* run;
}
-(void) playRunAction
{
// Create CCAnimate* object from CCAnimation object (run)
[self runAction:runAniate];
}
-(void) playStandAction
{
stand.visible = YES;
[self stopAllActions];
}
The player has ability to stand or run.
But one problem is, after playStandAction is called, stand animation is visible and running animation stopped, but one frame of running animation still there!
( Now you see 'stand sprite' AND 'one of running animation frame' together. )
How can I make running animation not visible?
P.s Can anyone throw me a better way of managing animation in one character? This is totally disaster as animations added.
-(void) playStandAction
{
//Make the animation object.visible = NO; here
stand.visible = YES;
[self stopAllActions];
}
and in
-(void) playRunAction
{
// Create CCAnimate* object from CCAnimation object (run)
//Make the animation object.visible = YES; here
stand.visible = NO;
[self runAction:runAniate];
}
Use method with parameter restoreOriginalFrame and pass it yes
I don't know which method you are calling for creating CCAnimate object...
Like this:
[CCAnimate actionWithAnimation:animation restoreOriginalFrame:YES]];
And don't call runAction on layer. I would prefer you to runAction on sprite itself...
You don't need to hide and show 2 different objects...
Hope this helps. :)
I have an existing game that I want to have a title screen with a button "play" to the app that loads the game.
EDIT: The interface was made in Level Helper
Here's how you can implement a menu that changes scenes with a transition. In your HelloWorldLayer.m file, add this:
-(id) init
{
if( (self=[super init])) {
CCMenuItemImage *menuImage = [CCMenuItemImage itemFromNormalImage:#"yourimage.png" selectedImage:#"Icon.png" target:self selector:#selector(changeScene:)];
CCMenu *menu;
menu = [CCMenu menuWithItems:menuImage, nil];
[self addChild:menu];
}
return self;
}
-(void) changeScene:(id)sender
{
[[CCDirector sharedDirector] replaceScene:[CCTransitionZoomFlipX transitionWithDuration:1 scene:[Scene1 node]]];
}
This creates a menu item image assigned to a selector, adds it to a menu, and then on click, transitions to a new scene, which I will show you how to do now. Create a new class called Scene1, and just to show that the transition worked, we will add a sprite in this new scene. In your init method:
-(id) init
{
if( (self=[super init])) {
sprite = [CCSprite spriteWithFile:#"yourimage.png"];
sprite.position = ccp(100,200);
[self addChild:sprite];
}
return self;
}
If you see this new sprite on the screen, it means that everything worked.
I'll assume by saying u have an existing game, that u have the source code of the game.
All u need is to make a new CCLayer with a CCMenu (containing the CCMenuButton u want) that all it does is load the CCLayer that loads as u start the game, and make ur CCLayer the one that gets loaded as u start the app.
create a menu using the following code:
// Intalize your menu item
CCMenuItem *menuItem = [CCMenuItemFont itemFromString:#"This is what you want your item to say" target:self selector:#selector(selectorToHandleYourSelection)];
// Define where you want your item to be
menuItem.position = ccp(100,100);
// Intalize a menu for your menu item
CCMenu *menu = [CCMenu menuWithItems:menuItem, nil];
// Add the 'menu' as a child to your layer
[self addChild:menu];
// If the item position isn't defined then you can align the items horizontally
[menu alignItemsHorizontally];
I have written a few games using Cocos2d iPhone. In all of my previous games I would change scenes when I setup a CCMenu and then leave that scene when I was finished. In my current project, I need the menu to exist in my current scene and be able to open and then close the menu many times. For some reason, I can't seem to understand, removeChild will not remove the menu. I have seen several examples online that show using removeChild, but it does not work for me. Below is my menu code, when the Start/CreateNewAccount button is pressed I want the current menu to be removed from the scene completely.
This is in my init method.
CCMenuItemImage *Start = [CCMenuItemImage itemFromNormalImage:#"MakeLemonade.png" selectedImage:#"MakeLemonadePressed.png"
target:self
selector:#selector(CreateNewAccount:)];
CCMenuItemImage *About = [CCMenuItemImage itemFromNormalImage:#"About.png" selectedImage:#"AboutPressed.png"
target:self
selector:#selector(About:)];
Start.position = ccp(-175, -90);
About.position = ccp(175, -90);
CCMenu *MainMenu = [CCMenu menuWithItems: Start, About, nil];
[Start runAction:[CCFadeIn actionWithDuration:1.0]];
[About runAction:[CCFadeIn actionWithDuration:1.0]];
[self addChild:MainMenu z:6];
}
return self;
}
-(void) BeginMenuLayer {
//this is not working
[self removeChild:MainMenu cleanup:YES];
}
In your init method you've declared MainMenu as a local variable. You're not setting it as a property, so you don't have a reference when you go to remove it later.
1) Make sure you have a property declared for it like this:
#property (nonatomic, retain) CCMenu *MainMenu;
2) Synthesize it at the top of your implementation:
#synthesize MainMenu;
3) Make sure you release it in your dealloc:
-(void)dealloc {
self.MainMenu = nil;
[super dealloc];
}
4) When you construct it, assign it to your property rather than a local variable:
self.MainMenu = [CCMenu menuWithItems: Start, About, nil];
Now you have a retained reference to the object, which you can pass later to removeChild:cleanup:.
I'm creating an universal application and my CCMenu appears just fine on both iPhone, iPhone 4 and iPad. However the buttons do nothing when touched on the iPad.
I have no specific iPad code other than modifying the contentScaling property so that the iPad uses the same images as the iPhone 4. This means that the same images work on iPhone 4 but not on the iPad.
I am using cocos2d 0.99.rc0 and the iOS 4.1 SDK. I don't even know where to start troubleshooting this.
The only oddity i noticed recently is that the iPad seems to draw the menu scene once, then quickly redraws it for some reason, moving everything one pixel or something. My menu class is very simple and has no "refreshing" code or anything that is supposed to move. This doesnt happen on either low or high res iPhones.
Here is my code, sloppy but yet very simple.
MainMenu.m:
CCMenuItemImage * playItem = [self makeMenuButtonWithSprite:#"Play.png" withSelector:#selector(play:)];
CCMenuItemImage * resumeItem = [self makeMenuButtonWithSprite:#"Resume.png" withSelector:#selector(resume:)];
CCMenuItemImage * optionsItem = [self makeMenuButtonWithSprite:#"Options.png" withSelector:#selector(options:)];
CCMenuItemImage * helpItem = [self makeMenuButtonWithSprite:#"Help.png" withSelector:#selector(help:)];
CCMenu *myMenu;
// Check if there is a valid savegame by comparing versions.
if ([[uD stringForKey:#"CFBundleVersion"] isEqualToString:[[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleVersion"]] ) {
myMenu = [CCMenu menuWithItems:playItem, resumeItem, optionsItem, helpItem, nil];
} else {
myMenu = [CCMenu menuWithItems:playItem, optionsItem, helpItem, nil];
}
// Arrange the menu items vertically
[myMenu alignItemsVerticallyWithPadding:0.0f];
myMenu.position = ccp(dB.wWidth/2,dB.wHeight/2);
// add the menu to your scene
[self addChild:myMenu z:100];
And the CCMenuItemImage factory:
- (CCMenuItemImage *)makeMenuButtonWithSprite:(NSString *)spriteFileName withSelector:(SEL)selector {
CCSprite *spriteForButton = [CCSprite spriteWithFile:spriteFileName];
spriteForButton.anchorPoint = ccp(0.5f,0.5f);
CCMenuItemImage * buttonImage =[CCMenuItemImage itemFromNormalImage:#"button.png"
selectedImage: #"button.png"
target:self
selector:selector];
[buttonImage addChild:spriteForButton z:100];
spriteForButton.position = ccp([buttonImage boundingBox].size.width/2,([buttonImage boundingBox].size.height/2)-5);
return buttonImage;
}
I don't think that any known bug exists for this issue. Not sure how to debug this without seeing any code, but, if it helps, here's some code of mine that successfully adds a menu using cocos2d 0.99.5, on iOS 4.0, 4.1 and 4.2 (no difference when I upgraded):
-(void) initBottomMenu {
CCMenuItem *aboutButton = [self gameButtonWithName:#"about" selector:#selector(onAbout:)];
CCMenuItem *settingsButton = [self gameButtonWithName:#"settings" selector:#selector(onSettings:)];
CCMenuItem *tutButton = [self gameButtonWithName:#"tutorial" selector:#selector(onTutorial:)];
CCMenu *menu = [CCMenu menuWithItems:aboutButton, settingsButton, tutButton, nil];
menu.position = ccp(xPos, yPos);
[menu alignItemsHorizontallyWithPadding:45.0];
[self addChild:menu];
}
The gameButtonWithName:selector: method looks like this:
-(CCMenuItem *) gameButtonWithName:(NSString *)name selector:(SEL)s {
NSString *iPadSuffix = #"IPad";
NSString *normal = [[NSString alloc] initWithFormat:#"%#Btn%#.png", name, iPadSuffix, nil] ;
NSString *selected = [[NSString alloc] initWithFormat:#"%#Btn%#.png", name, iPadSuffix, nil];
CCMenuItem *retButton = [CCMenuItemImage itemFromNormalImage:normal
selectedImage:selected
disabledImage:selected
target:self
selector:s];
[selected release];
[normal release];
return retButton;
}
sort of sloppy, but it works out well for adding a menu to my main scene.
Problem found. This was related to my custom hack to make the iPad load retina graphics. The problem was in my appDelegate where i set the contentScaleFactor which made ccDirector scale and UIScreen scale mismatch.
Problem boiled down to graphics being big but cocos2d thinking that coordinates are low res.