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.
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 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.
I'm making a top down tile based game (think old Pokemon and Zelda games on GameBoy). I'm having problems with the character moving smoothly. I think the problem is the delay between finishing an action and starting a new one.
Here's what the code looks like:
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
CGPoint touchCoor = [self coordinateForTouch:touch];
// If the character was touched, open their dialogue
if (CGPointEqualToPoint(touchCoor, ebplayer.coordinate)) {
[[CCDirector sharedDirector] replaceScene:
[CCTransitionMoveInR transitionWithDuration:1.0 scene:[HelloWorldLayer scene]]];
}
else // otherwise, move the character
{
activeTouch = [self directionForPoint:[touch locationInView:[touch view]]];
[self movePlayer:nil inDirection:activeTouch];
}
return YES;
}
// given in screen dimension points
// is the base movement function for all movements
- (void)movePlayer:(NSString*)pid toPosition:(CGPoint)position{
CGPoint playerCoordinate = [self coordinateForPositionPoint:position];
// if we're not already moving, and we can move, then move
if(!isAnimating && [self coordinateIsOnMap:playerCoordinate] && [self isPassable:playerCoordinate]){
id doneAction = [CCCallFuncN actionWithTarget:self selector:#selector(finishedAnimating)];
id moveAction = [CCMoveTo actionWithDuration:WALK_DURATION position:position];
id animAction = [CCAnimate actionWithAnimation: [ebplayer animateDirection:activeTouch withDuration:WALK_DURATION]];
id walkAndMove = [CCSpawn actionOne:moveAction two:animAction];
id action = [CCSequence actions: walkAndMove, doneAction, nil];
isAnimating = YES;
[player runAction:action];
ebplayer.coordinate = playerCoordinate;
[self setViewpointCenter:position Animated:YES];
}
// if it's not passable, just run the animation
if(!isAnimating){
id doneAction = [CCCallFuncN actionWithTarget:self selector:#selector(finishedAnimating)];
id animAction = [CCAnimate actionWithAnimation: [ebplayer animateDirection:activeTouch withDuration:WALK_DURATION]];
id action = [CCSequence actions: animAction, doneAction, nil];
isAnimating = YES;
[player runAction: action];
}
}
Then when that action is finished, try and start it up again:
(void)finishedAnimating{
isAnimating = NO;
[self movePlayer:nil inDirection:activeTouch];
}
You will always end up with a 1-frame delay when sequencing multiple CCMove* actions.
What happens is the following:
frame 0-100: move action runs, sprite is moving
frame 101: move action ended, CCCallFunc runs
frame 102: new move action begins
This one-frame delay is one of the main problems of sequencing move actions, and the reason why I wouldn't recommend using move actions for gameplay purposes.
The alternative is to move objects manually in a scheduled update method by modifying their position. You can use the CCMove* action code as basis.
all, I am making a game in which a sprite is move from one position to another through a jerk of 19 pixel, basically I want to make a game just like stacker online. in the app store, in this game the box is move through a jerk of 19 piexel , and the object is moving is in the grid , i have following code but I not give me the jerk motion
-(void)actionLayer
{
isRunning = 0;
addPixedlValue += 19;
id actionMove = [CCMoveTo actionWithDuration:6 position:ccp( 50,109)]; //300,100
id actionMoveDone = [CCCallFuncN actionWithTarget:self selector:#selector(LayerAction:)];
animateAction = [CCSequence actions:actionMove, actionMoveDone, nil];
NSLog(#"pixel value %d",addPixedlValue);
[boxSprite runAction:animateAction];
}
-(void)LayerAction:(id)sender
{
addPixedlValue +=19;
id actionMove = [CCMoveTo actionWithDuration:6 position:ccp( 270,109)]; //300,100
id actionMoveDone = [CCCallFuncN actionWithTarget:self selector:#selector(actionLayer)];
animateAction = [CCSequence actions:actionMove, actionMoveDone, nil];
[boxSprite runAction:animateAction];
}
I think your problem can be sort out By scheduling a selector for a time interval say 0.1 and you can update the position according to your self.
-(void)moveSprite
{
sprite.position = ccp ( sprite.position.x + 5 , sprite.position.y);
}
And unshedule the selector whenever needed to stop the sprite.
For Scheduling a selector
[self schedule : #selector ( moveSprite ) interval : 0.1];
For unscheduling
[self unschedule : #selector ( moveSprite )];
This help you in make jerking movement.
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.