I´m new to Cocos2d. I´m trying to run two animations one after another.
The first one is:
CCAction *walkAction;
CCAnimation *walkAnim = [CCAnimation
animationWithFrames:walkAnimFrames delay:0.15f];
bear = [CCSprite spriteWithSpriteFrameName:#"normal1.png"];
walkAction = [CCAnimate actionWithAnimation:walkAnim restoreOriginalFrame:NO];
[bear runAction:walkAction];
[spriteSheet addChild:bear];
The second which I want to fire right after the first one is:
CCParticleSystem *killPigAnim = [CCParticleSystemPoint particleWithFile:#"killPigAnim.plist"];
[self addChild:killPigAnim];
How can I achive that when the second one is not an action but the CCParticleSystem object.
You can use the action CCCallFunc to either call the start method on the particle system or call a method in your class which starts the particle system.
i.e.
-(void) startParticles
{
//Start your particles
}
-(void) myOtherMethod
{
...
walkAction = [CCAnimate actionWithAnimation:walkAnim restoreOriginalFrame:NO];
CCCallFunc *callAction = [CCCallFunc actionWithTarget:self selector:#selector(startParticles)];
[bear runAction:[CCSequence actionWithActions:walkAction, callAction, nil];
...
}
Related
I've looked all over and i can't find any information on how to do this. I want to run an action animation then right after that animation is done i want it to run another action animation all on the same sprite. how is this possible?
[self.mainShip runAction:retractdoor];
[self.mainShip runAction:activatedoor];
this crashes me.
self.mainShip runAction: [CCSequence actions:retractdoor,activatedoor, nil];
gives me a yellow notification
incompatible pointer types sending Cc action to parameter of type ccfinite time action
CCAnimation *retractdoorAnimation = [CCAnimation
animationWithSpriteFrames:retractdoorframes delay:0.1f];
CCAnimation *activatedoorAnimation = [CCAnimation
animationWithSpriteFrames:activatedoorframes delay:0.1f];
self.retractdoorAction = [CCAnimate actionWithAnimation:retractdoorAnimation];
self.activatedoorAction = [CCAnimate actionWithAnimation:activatedoorAnimation];
you missed the nil termination.
[self.mainShip runAction: [CCSequence actions:retractdoor,activatedoor, nil]];
this should work, dont use the square brackets and dont miss the comma..
I want to start InFinite CCAction at particular time. I tried using CCSequence but it supports only finite time animation.
Any idea?
Best Regards,
Paras
Put the action that you want to repeat inside of a method. Then put this in your init method
[[CCScheduler sharedScheduler] scheduleSelector:#selector(myMethod) forTarget:self interval:10 paused:NO];
This will call myMethod after 10 seconds, however once inside myMethod you'll want to unschedule it. So my method should look something like this.
- (void) myMethod
{
[[CCScheduler sharedScheduler] unscheduleSelector:#selector(myMethod) forTarget:self];
CCMoveBy *move = [CCMoveBy actionWithDuration:3 position:ccp(75,0)];
CCRepeatForever *repeat = [CCRepeatForever actionWithAction:move];
[mySprite runAction:repeat];
}
The last two lines are what you need.
CCMoveBy* move = [CCMoveBy actionWithDuration:3 position:ccp(75,0)];
CCCallFuncO* shot = [CCCallFuncO actionWithTarget:self selector:#selector(shoot:) object:enemy];
CCSequence* sequ = [CCSequence actions:move,shot,nil];
CCRepeatForever* repeat = [CCRepeatForever actionWithAction:sequ];
[sprite runAction:repeat]; //sprite here
I play an animation like this:
- (CCSprite *)explodeWithBatchNode:(CCSpriteBatchNode *)batchNode andAnimation:(CCAnimation *)ani
{
CCSprite *explosionSprite = [CCSprite spriteWithTexture:batchNode.texture rect :CGRectMake(0, 0, 154,119)];
CCAction *goldenExplosionAction = [CCAnimate actionWithAnimation:ani];
[explosionSprite runAction:goldenExplosionAction];
return explosionSprite;
}
Everything works fine, the only problem is that the animation stops at the first frame instead of the last. How can I have it finish on the last one?, also, how can I know that the animation has finished?
+ (id) actionWithAnimation:CCAnimation *) a restoreOriginalFrame:(BOOL) b
it's a method of a CCAnimate action. Just put the second argument to NO
In your case
CCAction *goldenExplosionAction = [CCAnimate actionWithAnimation:ani restoreOriginalFrame:NO];
To understand the animation was finished create a callback, that will be called after animation like this:
id animation = [CCAnimate actionWithAnimation: someAnimation];
id callback = [CCCallfunc actionWithTarget: targetObject selector: #selector(mySelector)];
id sequence = [CCSequence actions: animation, callback, nil];
[mySprite runAction: sequence];
So after animation is finished targetObject's mySelector method will be called.
If you want to pass some data through a callback and/or a sender use CCCallFuncN or CCCallFuncND actions
I have an array randomAlphabets which contains CCSprite objects. I need to start animation on these objects. The randomAlphabets array (NSMutable) can contain max of 4 elements. I am running a loop and then starting the animation. Is this the correct way?
-(void) startAnimation:(CCSprite *) sprite
{
[self generateRandomCoordinates];
id actionMove = [CCMoveTo actionWithDuration:3.0 position:ccp(x,y)];
id actionRotate = [CCRotateBy actionWithDuration:0.0 angle:rotateBy];
id actionMoveDone = [CCCallFuncN actionWithTarget:self selector:#selector(finishedMoving:)];
[sprite runAction:[CCSequence actions:actionMove,actionRotate, actionMoveDone, nil]];
}
-(void) addAlphabetsOnScreen
{
for (int i=0; i<=randomAlphabets.count -1; i++) {
CCSprite *sprite = [randomAlphabets objectAtIndex:i];
[self generateRandomCoordinates];
sprite.position = ccp(x,y);
[self addChild:sprite];
[self startAnimation:sprite];
}
}
Sure, why not?
If have performance issues or sprites not starting their anims simultaneously, you might want to "prepare" the sequences for each sprite in one step (maybe after loading the level) and then just kick them all of in another step. 4 Sprites starting at the same time seems not too tough though.
Friends i am new to cocos2d programming and Mac in general!
I have noticed this EXC_BAD_ACCESS errors ruining most of my time... Take the following snippet of code from the Geek & Dad's tutorial...
-(void) AddEnemyAtX:(int)x Y:(int)y {
CCSprite *enemy1 = [CCSprite spriteWithFile:#"enemy1.png"];
enemy1.position = ccp(x,y);
[self addChild:enemy1];
[self animateEnemy:enemy1];
NSLog(#"%#", enemy1);
}
-(void) animateEnemy:(CCSprite *)enemy {
ccTime actualDuration = .5;
id actionMove = [CCMoveBy actionWithDuration:actualDuration
position:ccpMult(ccpNormalize(ccpSub(_player.position,enemy.position)), 10)];
id actionFinished = [CCCallFunc actionWithTarget:self
selector:#selector(animateEnemyFinished:)];
[enemy runAction:[CCSequence actions:actionMove,actionFinished,nil]];
}
-(void) animateEnemyFinished:(id)sender {
CCSprite *enemy = (CCSprite *)sender;
[self animateEnemy:enemy];
}
here _player is a global variable and accessible everywhere, I call AddEnemyAtX: Y: and pass some coordinates. My problem is the first time the loop runs fine... But again when the control is passed from animateEnemyFinished to animateEnemy then the app crashes mentioning "EXC_BAD_ACCESS"!
From what i figured out, the Sprite reference is not passed correctly! Help!
CCSprite *enemy1 = [CCSprite spriteWithFile:#"enemy1.png"];
gives you an autoreleased object. This means you should not call
[enemy1 release]
and 2nd after you set
enemy1=nil
you can't do
[self animateEnemy:enemy1];
because you give nil to animateEnemy:
Removing
[enemy1 release];
and
enemy1 = nil;
from your code should fix your problem.
Wow!!
Atlast figured it out...
A small mistake... just replacing the line
id actionFinished = [CCCallFunc actionWithTarget:self
selector:#selector(animateEnemyFinished:)];
with
id actionFinished = [CCCallFuncN actionWithTarget:self
selector:#selector(animateEnemyFinished:)];
did the trick! What i understood from this was that #selector() passes the id of the object which called upon it but at the same time when we use it along with CCCallFuncN it passes the id of the Node just parent to the object which called upon it!