Removing animation sprite frames from layer? - iphone

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

Related

CCSprite doesn't go invisible -iphone

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

Cocos2D random sprite movement

As a very beginner in Cocos2D i´m trying to make an iPhone game where some cows move randomly around the screen. I used the code for moving the sprites from here: highoncoding.com/.../. I´m adding the sprites in the init method wia an addAnimal method:
-(void) addAnimal {
animal = [CCSprite spriteWithFile:#"cow.png"];
animal.position = [self generateRandomCoordinates];
[self addChild:animal];
[self startAnimation:animal];
}
My problem:
When i add more than one cow to my game, they move from that random spawn position to another random position and then the first cow stops and the other cow goes on correctly. The startAnimation command in the finishedMoving method goes always to the last sprite. That means i need better control over my sprites but how to da that right?
You can try to implement animal class, that will contain your sprite and incapsulate random movement. Smth like
#implementation Cow
- (id) init
{
self = [super init];
if( self != nil )
{
CCSprite* cowSprite = [CCSprite spriteWithFile:#"cow.png"];
[self addChild: cowSprite];
}
return self;
}
- (void) onEnter
{
[super onEnter];
[self makeRandomMovement];
}
- (void) makeRandomMovement
{
id randomMoveAction = // create your random move action here
id moveEndCallback = [CCCallFunc actionWithTarget: self selector: #selector(makeRandomMovement)];
id sequence = [CCSequence actionOne: randomMoveAction two: moveEndCallback];
[self runAction: sequence];
}
#end
In such way after ending random movement part, method makeRandomMovement will be called again to generate and start new random movement part.
then remake your addAnimal method to smth like
- (void) addAnimal
{
Cow* newCow = [Cow node];
[newCow setPosition: [self generateRandomPosition]];
[self addChild: newCow];
}

cocos2d-iphone popScene: Incomplete Events

So I'm developing an iPhone game using cocos2d.
I'm using pushScene to transition from my gameplay scene to a main menu scene because I want the player to be able to resume gameplay from the main menu if they choose. If they do choose to resume, I use popScene.
The trouble seems to be that if events are "incomplete" at the time when the gameplay scene is pushed, when the scene is popped, those events do not complete. What's worse, they leave artifacts on the scene that don't clear by themselves.
Examples: particle explosion effect (particles get "frozen" and don't dissipate as designed), sprite fade-out effect (sprite remains visible at a certain level of transparency).
I guess I would have expected popScene to resume the scene exactly as it was when the scene was pushed, but it seems to be "abandoning" currently-running actions.
How can I achieve my goal?
I suggest you to add both game play layer and main menu layer to the same CCScene as children rather than using pushScene and popScene. When you need to show the menu, change the visibility of the layers and pause all the contents in your game play layer. You can try these methods to recursively pause/resume activities of your game layer:
- (void)pauseSchedulerAndActionsRecursive:(CCNode *)node {
[node pauseSchedulerAndActions];
for (CCNode *child in [node children]) {
[self pauseSchedulerAndActionsRecursive:child];
}
}
- (void)resumeSchedulerAndActionsRecursive:(CCNode *)node {
[node resumeSchedulerAndActions];
for (CCNode *child in [node children]) {
[self resumeSchedulerAndActionsRecursive:child];
}
}
call something like:
[self pauseSchedulerAndActionsRecursive:gamePlayLayer];
I used Hailei's code but created a category that works OK for me.
CCNode+additions.h
#import "CCNode.h"
#interface CCNode (additions)
-(void)pauseSchedulerAndActionsRecursive;
-(void)resumeSchedulerAndActionsRecursive;
#end
CCNode+additions.m
#import "CCNode+additions.h"
#implementation CCNode (additions)
-(void)pauseSchedulerAndActionsRecursive {
[self pauseSchedulerAndActions];
for (CCNode *child in [self children]) {
[child pauseSchedulerAndActionsRecursive];
}
}
-(void)resumeSchedulerAndActionsRecursive {
[self resumeSchedulerAndActions];
for (CCNode *child in [self children]) {
[child resumeSchedulerAndActionsRecursive];
}
}
#end
So when pausing, call pauseSchedulerAndActionsRecursive on your game node before you add a "pause menu node" to the game node (else the pause node will be paused too and thus unusable).

Replacing Scene and Stop All Animations and Sounds

I have a home button on my scene which when pressed goes to the home menu. I use replaceScene to replace the current scene (Game Scene) with the HomeMenu Scene. For some reason the actions and sounds which are happening in the game scene are not stopped when I replace the scene. I have tried the following code but still when I am in the home menu I can hear the actions and sounds of the game scene playing.
// fired when the home menu is
clicked!
-(void) homeMenuClicked:(CCMenuItem *) item { NSLog(#"home menu clicked!");
CCScene *scene = [[CCDirector
sharedDirector] runningScene]; [scene
stopAllActions];
[self.layer stopAllActions];
[self unloadSoundEffects];
[[CCDirector sharedDirector]
replaceScene:[CCSlideInLTransition
transitionWithDuration:1.0
scene:[HomeScene scene]] ];
}
I must also add that the game layer also has a timer (NSTimer) object which starts in 2 seconds or something.
UPDATE 2:
Let me post some code! I think the problem is that when the player guess the correct answer the following method is invoked:
[self updateForCorrectAnswer];
Inside updateForCorrectAnswer I have a performSelector which is scheduled to fire in 6-7 seconds. I believe that performSelector is the culprit. If somehow can I stop that from being firing then the I think I will be fine.
[self performSelector:#selector(refreshScore) withObject:nil afterDelay:7.0];
You should not use NSTimer as cocos2d documents.
/* call scheduleUpdate in initializing */
[self scheduleUpdate];
It schedules update: method to be called every frame when this node is on the stage.
- (void)update:(ccTime)dt
{
/* This method is automatically called every frame. */
}
scheduleUpdateWithPriority:, schedule:interval: are also available.
And why don't you use like this instead of performSelector:withObject:afterDelay.
[self runAction:[CCSequence actions:[CCDelayTime actionWithDuration:7], [CCCallFunc actionWithTarget:self selector:#selector(refreshScore)], nil]];
If you use this method "[self performSelector:withObject:afterDelay:]", cocos2d will not manage it in this run loop. You should use it instead of the previous one:
[self schedule:interval:];
Then in your "homeMenuClicked:" method, just call this:
[self.layer unschedule:#selector(refreshScore)];
I haven't tried it but I think it'll be better.
For more information you can see the documentation here.

scaling a CCMenuItem in Cocos2d (Objective-C)

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.