I am making a game using cocos2d. By using the following code,I have added an animation.How do I send the CCSprite reference?
if(sprite != monkey)
{
[self scheduleOnce:#selector(animate_sprite:) delay:0.1f];
}
-(void)animate_sprite:(ccTime) dt
{
id s2 = [CCScaleTo actionWithDuration:0.5 scaleX:2.0 scaleY:2.0];
id fun = [CCCallFuncN actionWithTarget:self selector:#selector(spriteDone:)];
[sprite runAction:[CCSequence actions:s2,fun,nil]];
}
How to get the sprite reference in animate_sprite method?
You can use performSelector:withObject:afterDelay this will do the same thing.
if(sprite != monkey)
{
[self performSelector:#selector(animate_sprite:) withObject:sprite afterDelay:0.1f];
}
-(void)animate_sprite:(CCSprite *)sprite
{
id s2 = [CCScaleTo actionWithDuration:0.5 scaleX:2.0 scaleY:2.0];
id fun = [CCCallFuncN actionWithTarget:self selector:#selector(spriteDone:)];
[sprite runAction:[CCSequence actions:s2,fun,nil]];
}
So just edit your method to use the sprite and not the ccTime object since you are not using it at all.
Related
How to stop all actions in game after some time?
in below code i am calling runaction on a sprite.
id actionMove = [CCMoveTo actionWithDuration:actualDuration*2.5 position:ccp(winSize.width + (target.contentSize.width/2), actualY)];
id actionMoveDone = [CCCallFuncN actionWithTarget:self selector:#selector(spriteMoveFinished:)];
id sequece = [CCSequence actions:delayTime1, calFun1, delayTime2, calFun2,actionMove, actionMoveDone, nil];
id repeate = [CCRepeatForever actionWithAction:sequece];
[target runAction:repeate];
In this code a sprite is continuously moving. how to stop the above action after some time or after some condition ?
In runAction call Function and stop action for sprite.
[CCCallFuncN actionWithTarget:self selector:#selector(setInvisible:)];
- (void)setInvisiblestone:(CCNode *)node
{
[target stopAllActions];
}
All action stop in method.
-(void)gameover
{
[self unscheduleAllSelectors];
}
I have total 20 images in NSMutableArray of ccspirit objects, and I want to show them on screen moving moving upward, I add them to as [self addChild:p] as below
-(void) callMethod {
static int x = 50;
if (x>=0) {
Paddle *p = [paddlesFruits objectAtIndex:x];
p.position = CGPointMake(40,0);
[self addChild:p];
[self moveMethod1: p];
[p release];
x--;
}else {
x=50;
}
}
and the method which will move it upside is
-(void) moveMethod1 : (id) sender {
id actionMove2 = [CCMoveTo actionWithDuration:6 position:ccp(40, 520)];
id actionMoveDone2 = [CCCallFuncN actionWithTarget:self selector:#selector(spriteMoveFinished:)];
[sender runAction:[CCSequence actions:actionMove2, actionMoveDone2, nil]];
}
-(void)spriteMoveFinished:(id)sender {
//NOTHING HERE
}
but after using addChild again and again, it will make it heavier, so what should I do,
I am thinking to addChild and remove after certain time, I will removeChild, but is it possible to to add a ccspirit again after using removeChild for same ccspirit object?
I have three actions that are triggered in the CCSequence. The way I want it to be fired is that first the sprite should move in the center of the screen and then the scale action is fired. But for some reason the sprite moves to the center of the screen correctly but when the scale is fired it uses the old sprite position.
id actionRotate = [CCRotateBy actionWithDuration:0.6 angle:360];
id disappear = [CCFadeTo actionWithDuration:.5 opacity:0];
id actionMoveDone = [CCCallFuncN actionWithTarget:self selector:#selector(removeAlphabetToFindFromView:)];
id actionScale = [CCScaleBy actionWithDuration:0.6 scaleX:10 scaleY:10];
id moveTo = [CCMoveTo actionWithDuration:0.6 position:ccp(windowSize.width/2, windowSize.height/2)];
//[self removeAlphabetToFindFromView2:alphabetToFind];
[alphabetToFind runAction:[CCSequence actions:moveTo,actionScale,disappear,actionMoveDone, nil]];
UPDATE 1:
Maybe the startAnimation method has something to do with this. I have public x and y variables which is used as x and y positions for 4 different sprites:
-(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) finishedMoving:(id) sender
{
if(counter == randomAlphabets.count)
{
counter = 0;
}
CCSprite *sprite = [randomAlphabets objectAtIndex:counter];
[self generateRandomCoordinates];
[self startAnimation:sprite];
counter +=1;
}
UPDATE 2:
As expected the x and y used in the startAnimation method (getRandomCoordinates) were causing the problem. So, I removed all the actions before firing the sequence and now it works fine.
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!