Animate CCSprite - cocos2d-iphone

I am newer to cocos2d and preparing my demo game. I am moving a sprite from right to left using just a single image like a bird image moving from left to right. But I want to animate that sprite through various images so that it may look like a flying bird. I don't know how to accomplish that.
Here is my code:
CCSprite *target = [CCSprite spriteWithFile:#"Target.png" rect:CGRectMake(0, 0, 27, 40)]
id actionMove = [CCMoveTo actionWithDuration:actualDuration position:ccp(-target.contentSize.width/2, actualY)];
id actionMoveDone = [CCCallFuncN actionWithTarget:self selector:#selector(spriteMoveFinished:)];
[target runAction:[CCSequence actions:actionMove, actionMoveDone, nil]];

For Animating particular sprite You would require sprite-sheet to be there in your Resource. You can create the Sprite-sheet from eitherTexture Packer OR Zwoptex Tools which I normally use.
Next you can implement the Below Code
CCSpriteBatchNode *sheet = [CCSpriteBatchNode batchNodeWithFile:#"drawing1-i3.png"]; // Png File Name
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"drawing1-i3.plist"]; // Plist File Name
[self addChild:sheet];
//Generating the Animation
NSMutableArray *arr_anim =[NSMutableArray array];
for(int i=1; i<30; i++) // i< number of frames in the plist File Name
{
NSString *str_fileNm = [NSString stringWithFormat:#"drawing1%d.png",i];
CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache]spriteFrameByName:str_fileNm];
[arr_anim addObject:frame];
}
CCSprite *startAnim = [CCSprite spriteWithSpriteFrameName:#"drawing11.png"];
[startAnim setPosition:ccp(150,150)];
[self addChild:startAnim];
//Starting the Animation
CCAnimation *animation = [CCAnimation animationWithFrames:arr_anim delay:0.15f];
// id action =[CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:animation restoreOriginalFrame:YES]];
id action =[CCAnimate actionWithAnimation:animation restoreOriginalFrame:NO];
[startAnim runAction:action];
I think it would help you for creating the Animations.

Use the CCAnimation class.
In particular, use methods like animationWithFrames: and supply your images as an array.

Related

Move a whole animation sprite sheet

I have some sprite-sheet that i have to animate forever , and i would like to add it as a CCLayer
to my scene .
Later on , i have to move this whole animation sprite on the screen.
So, for example, i have some animation of a dog walking, from sprite sheet, this one is running forever. than i want to be able to move this dog on screen while animating.
What is the best way to do this ? (or the right way)
This is how i animate the frames :
CCSprite *boom;
boom = [CCSprite spriteWithSpriteFrameName:[NSString stringWithFormat:#"%#_00000.png",file]];
boom.position=touch;
[self addChild:boom];
NSMutableArray *animFrames = [NSMutableArray array];
for(int i = 0; i < 5; i++)
{
CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:
#"%#_0000%i.png",file,i]];
[animFrames addObject:frame];
}
CCAnimation* boxAnimation = [CCAnimation animationWithSpriteFrames:animFrames delay:0.075f];
CCAnimate * boxAction = [CCAnimate actionWithAnimation:boxAnimation];
CCAction *call=[CCCallBlock actionWithBlock:^{[self removeFromParentAndCleanup:YES];}];
CCAction * sequence=[CCSequence actions:boxAction,[CCHide action],call,nil];
[boom runAction:sequence];
return self;
How would you move this whole thing ?
There are a few ways to do this. If you are not preocupied with collision detection, then one way would be to :
CGPoint egressPosition = ccp(0,0); // figure this out in your app
float moveDuration = 1.5f ; // whatever time you compute for desired speed and distance
id move = [CCMoveTo actionWithDuration:moveDuration position:egressPosition];
id spawn = [CCSpawn actions:sequence,move,nil];
[boom runAction:spawn];
otherwise, using your code as is
[self schedule:#selector(moveBox:)]; // optional, you could do this in update method
[boom runAction:sequence];
-(void) moveBoom:(CCTime) dt {
CGPoint newPosition;
delta = ccp(dt*speedX,dt*speedY); // crude , just to get the idea
newPosition = ccpAdd(boom.position,delta);
// here you can figure out collisions at newPosition before the collision
// and do whatever seems appropriate
boom.position = newPosition;
}

textures that are bigger than 4096 x 4096?

Using iPad 2 simulator , after i have created a sprite sheet, its size was ±8000 pixels, i got warning that is bigger than the supported 4096 x 4096 .
The Animation is made of images in the size of half iPad screen, and each animation has 10 frames .
So , how can i create a sprite sheet to run the animation ? do i need 2 sprite sheets? and if yes , is there a way to run them in sequence ?
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:plist];
hotGirl= [CCSprite spriteWithSpriteFrameName:pngFirst];
hotGirl.position=ccp(winSize.width/2,winSize.height/1.335);
[self addChild:hotGirl];
NSMutableArray *animFrames = [NSMutableArray array];
for(int i = 1; i < num+1; i++)
{
CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"%#%i.png",file,i]];
[animFrames addObject:frame];
}
CCAnimation* Animation = [CCAnimation animationWithSpriteFrames:animFrames delay:0.1f];
CCAnimate * pAction = [CCAnimate actionWithAnimation:Animation];
id call=[CCCallFunc actionWithTarget:self selector:#selector(done:)];
id seq=[CCSequence actions:pAction,call, nil];
[hotGirl runAction:seq];
Thanks .
Its openGLES Texture memory limitation.
int maxTexSize;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
printf("Max = %d\n",maxTexSize);
You can't load image that is larger than GL_MAX_TEXTURE_SIZE. It depends on device.

CCAnimation, how to set frame rate for individual frames

Let's say I have an animation consisting of five frames.
How would I set frames 1-4 to play for 0.5 seconds each, then the 5th frame for 0.1 seconds?
I have not tried this yet, (new in cocos 2.x), but :
CCAnimation *anim = [CCAnimation animation];
NSMutableArray *frames = [NSMutableArray array];
CCSpriteFrame *sfr1 = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:#"name1"];
CCAnimationFrame *af1 = [[[CCAnimationFrame alloc] initWithSpriteFrame:sfr1 delayUnits:5 userInfo:nil] autorelease];
[frames addObject:af1];
// tru sfr4 and finally
CCSpriteFrame *sfr5 = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:#"name5"];
CCAnimationFrame *af5 = [[[CCAnimationFrame alloc] initWithSpriteFrame:sfr5 delayUnits:1 userInfo:nil] autorelease];
[frames addObject:af5];
anim = [CCAnimation animationWithAnimationFrames:frames delayPerUnit:.1 loops:1];
This should give you the effect you are looking for.
ps : userInfo is an NSDictionary. When the animation is played you can register for a notification named CCAnimationFrameDisplayedNotification, and receive the userInfo, frame by frame.
// not tested , yet //
By playing the animation manually. Schedule a selector, use its delta time to see if you need to switch to the next frame. Use setDisplayFrame: to change the sprite's frame.
Use two separate animation, one with 0.5 second and one with 0.2second.

Cocos2d move animation on a path

Is it possible in Cocos2d to create a move animation that would go on a specific path?
For example, how should I do if I need an object to move on an arc or full circle?
Regards!
Sure you can do this using :
ccBezierConfig bezier;
bezier.controlPoint_1 = ccp(320,0); // control point 1
bezier.controlPoint_2 =ccp(0,0); // control point 2
bezier.endPosition = ccp(endPoint.x,endPoint.y) ;
id bezierForward = [CCBezierTo actionWithDuration:3 bezier:bezier];
[ball runAction:bezierForward];
you can use ccBezier to move any node in curves :
Now Animation Part :
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"eggAnimation.plist"];
spriteSheet = [CCSpriteBatchNode batchNodeWithFile:#"eggAnimation.png"];
[gameBackgroundLayer addChild:spriteSheet];
eggAnimFrames = [NSMutableArray array];
for ( int i = 1; i <= 10; i++ )
{
[eggAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"%d.png", i]]];
}
rotateAnim = [CCAnimation animationWithFrames:eggAnimFrames delay:0.05f];
ball = [CCSprite spriteWithSpriteFrameName:#"1.png"];
ball.position=ccp(160,80);
rotateAction =[CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:rotateAnim restoreOriginalFrame:YES]];
[spriteSheet addChild:ball];
Reference Links : http://www.raywenderlich.com/1271/how-to-use-animations-and-sprite-sheets-in-cocos2d
http://www.math.ubc.ca/~cass/gfx/bezier.html

how to remove shape and body after a delay in collision callback (cocos2d-chipmunk)

can anyone help me to remove shape and body after a delay in collision callback.
By using cpSpaceAddPostStepCallback(sapce, (cpPostStepFunc)postStepRemove, blockShape, NULL);
i could safely remove the shape .
But i need some delay before i call the function.
I play an animation once the collision in detected.
At the end of the code i need to remove the shape.
Can anyone please help me with some sample code.
The code that i have written is as follows.
int collisionSapusBlock(cpArbiter *arb, struct cpSpace *sapce, void *data)
{
cpShape *sapusShape, *blockShape;
cpArbiterGetShapes(arb, &sapusShape, &blockShape);
cpBody *BlockBody = blockShape->body;
cpBody *sapusBody = sapusShape->body;
CCNode *parent = (CCNode*)data;
if (cpvlength(sapusBody->v) > 45)
{
NSLog(#"Collision2 called %f",cpvlength(sapusBody->v));
CCSprite *sprite = blockShape->data;
[parent removeChild:sprite cleanup:YES];
///////
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"Block2.plist"];
CCSpriteBatchNode *sheet1 = [CCSpriteBatchNode batchNodeWithFile:#"Block2.png" capacity:2];
[parent addChild:sheet1];
CCSpriteFrameCache *cache = [CCSpriteFrameCache sharedSpriteFrameCache];
CCSprite *sapusSprite1 = [[CCSprite alloc] initWithSpriteFrameName:#"Block2001.png"];
CCAnimation *sapusAnim = [[CCAnimation alloc] initWithName:#"select" delay:0.15f];
[sapusAnim addFrame:[cache spriteFrameByName:#"Block2001.png"]];
[sapusAnim addFrame:[cache spriteFrameByName:#"Block2002.png"]];
[sapusAnim addFrame:[cache spriteFrameByName:#"Block2003.png"]];
[sapusAnim addFrame:[cache spriteFrameByName:#"Block2004.png"]];
[sapusAnim addFrame:[cache spriteFrameByName:#"Block2005.png"]];
[sapusAnim addFrame:[cache spriteFrameByName:#"Block2006.png"]];
[sapusSprite1 addAnimation: sapusAnim];
[sheet1 addChild:sapusSprite1];
CCAnimate *animate = [CCAnimate actionWithAnimation: sapusAnim restoreOriginalFrame:NO];
[sapusSprite1 runAction:animate];
blockShape->data = sapusSprite1;
/////here after playing the animation i need to delete the blockShape. Help plzzz
}
return 1;
}
Can anyone please help me with some sample code.
Thanks
I haven't tried this, but it should work. In the collision handler, kick off the animation as part of a sequence and then execute the postStepCallback as the last item in the sequence:
CCSequence *finalSeq = [CCSequence actions:[CCAnimate actionWithAnimation:sapusAnim restoreOriginalFrame:NO],
[CCCallFunc actionWithTarget:self selector:#selector(removeCpShapeAndBody)], nil];
[sapusSprite1 runAction:finalSeq];
Then you'd create a method called removeCPShapeAndBody which would call cpSpaceAddPostStepCallback. Ideally you'd have all of this in an object that would hold reference to the shape and body (e.g. a subclass of CCSprite) so you don't have to pass those around.