CCAnimation, how to set frame rate for individual frames - cocos2d-iphone

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.

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.

Reduce frame rate

Is there any way to reduce the game framerate from 30 to 25 fps on the iPhone? I'm porting a Flash game created at 25 fps and exporting the sprites with this frame rate but animations are not shown as correctly as they should.
Any idea?
Try this instead, straight out of the box :
animation = [CCAnimation animationWithSpriteFrames:frames delay:.04];
with 40 ms delay, that should come real close to 25 fps (rendered animation) while the rest of the game is clocking full bore at 60 fps (if you don't have lag issues elsewhere)
I think that you can change your animation interval in your App Delegate with the following snippet in your didFinishLaunching method :
CCDirector *director = [CCDirector sharedDirector];
[director setAnimationInterval:1.0/25];
Hope this helps!
EDIT :
Could this link provide you more information about how to deal with that ?
http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:best_practices
Well, at last the solution is by another way.
Kept the framerate to 1.0/60.0
What you need to do for animating the spritesheet slowest is to add the frame more than once to the animation array.
NSMutableArray *walkAnimFrames = [NSMutableArray array];
for(int i = _spriteMetadata.spriteInitFrame; i <= _spriteMetadata.spriteEndFrame; ++i)
{
NSString *spriteFrameName = [NSString stringWithFormat:#"%#%#", _spriteMetadata.spriteBaseName, index];
for (int i=0; i<2; i++)
{
[walkAnimFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:spriteFrameName]];
}
}
It's not very orthodox but it works! :)
Thanks for your help Andy!

Animate CCSprite

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.

Cocos2d: Preloading animation causes a crash

I am trying to preload an animation in the init method of my layer. I then call the animation if the screen is touched. The app crashes with no error message as soon as I touch the screen and seems it is to do with calling the preloaded animation. I would like to do it this way as it seems expensive to create the animation every time the screen is touched - which does seems to work though. Any tips greatly appreciated.
Sample Code:
In my header:
#interface Test : CCLayer {
NSMutableArray *wake;
CCSprite* ani;
CCAnimate *animate;
}
#end
In my implementation:
-(id) init {
if( (self=[super init])) {
// enable touches
self.isTouchEnabled = YES;
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"ani.plist" texture:[[CCTexture2D alloc] initWithImage:[UIImage imageNamed:#"ani.png"]]];
ani = [CCSprite spriteWithSpriteFrameName:#"ani1.png"]; //comes from .plist file
ani.anchorPoint=ccp(0,0);
ani.position = ccp(700,65);
[self addChild:ani z:30];
wake = [NSMutableArray array];
for(int i = 1; i <= 4; i++) {
[wake addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"ani%d.png",i]]];
}
animate = [CCAnimate actionWithAnimation:[CCAnimation animationWithFrames:wake delay:1.0f] restoreOriginalFrame:FALSE];
}
return self;
}
Handling the touch:
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
// run the animation
[ani runAction:animate];
}
Animations in Cocos2d are not designed to be reused. You need to create a new one every time.
Problem solved by creating properties for the array and animation on the class using nonatomic,retain.
You only need to retain the animation but the array can be local.
self.myAnimation = [[CCAnimation animationWithFrames:myAniFramesArray delay:0.1f] retain];
Remember to make the property nonatomic, retain as stated by Chev and to release any objects you retain in the appropriate dealloc method.