How to set the frame of an animation in cocos2d - iphone

I have made a CCAnimationHelper class that performs the following. You give it a fileName, a frameCount, and a Delay and it will give you back an animation. The thing I want to know is how to set the frame of the animation so instead of starting at frame 1, it will start at frame 10 instead. Here is my code
// Creates an animation from sprite frames.
+(CCAnimation*) animationWithFrame:(NSString*)frame frameCount:(int)frameCount delay:(float)delay
{
// load the ship's animation frames as textures and create a sprite frame
NSMutableArray* frames = [NSMutableArray arrayWithCapacity:frameCount];
for (int i = 1; i < frameCount; i++)
{
NSString* file = [NSString stringWithFormat:#"%#%i.png", frame, i];
CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
CCSpriteFrame* frame = [frameCache spriteFrameByName:file];
[frames addObject:frame];
}
// return an animation object from all the sprite animation frames
return [CCAnimation animationWithFrames:frames delay:delay]; //Is there another method I should be using here to set the frame
}

There isn't a built in funcion that does that, but you can simply create your animation and pass it the NSArray starting at the frame you want:
CCAnimation *animation = [CCAnimation animation];
NSArray *offset = [NSArray arrayWithObjects:frame3, frame4, nil];
[animation initWithFrames:offset];

Related

How to put animation between frames spritesheet in cocos2d?

I am new to cocos2d .Can any one suggest me a method to give animation for the transition between one frame to another frame.
this is my code to fetch frames and just display
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"spritesheet.plist"];
// Create a sprite sheet with the Happy Bear images
CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode batchNodeWithFile:#"spritesheet.png"];
[self addChild:spriteSheet];
// Load up the frames of our animation
walkAnimFrames = [NSMutableArray array];
for(int i = 1; i <=7; ++i) {
[walkAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"sprite%d.png", i]]];
}
CCAnimation *walkAnim = [CCAnimation animationWithFrames:walkAnimFrames delay:0.1f];
// Create a sprite for our bear
CGSize winSize = [CCDirector sharedDirector].winSize;
self.sprite = [CCSprite spriteWithSpriteFrameName:#"sprite.png"];
self.sprite.position=ccp(320,480);
self.sprite.anchorPoint=ccp(1,1);
self.walkAction = [CCAnimate actionWithAnimation:walkAnim restoreOriginalFrame:NO];
How to do the animation for the transition between frames
thanks in advance
You can not "transition" (morph) between two frames (images), if that's what you mean.
It sounds to me like you want something that's called keyframe interpolation, which is normally used in 3D animations. A 2D animation displays one frame after another. You can not interpolate between two frames graphically (morphing), you can only interpolate properties like position.

Displaying Multiple CALayers one after another continuously for 60 seconds?

I have a situation over here.
I am using AVFoundation to capture the camera frame.
Now what i want to do is that for certain frames, i need to display a picture which revolves in a step by step fashion.
What I am trying to do is that I am taking 4 CALayers comprising of front back left and right images of an object and using CALayer time property and group animation property, i want to display all the images one by one after certain milli seconds interval of time so that the continuous images seems to be like an animation.
How to go about it ? Please help me with some coding here.
-(void)startMainAnimation
{
//Animationframes is array of images that should be CGImage Type not UIImage..
//animation Layer that is added above view……
CAKeyframeAnimation *frameAnimation = [[CAKeyframeAnimation alloc] init];
[frameAnimation setKeyPath:#"contents"];
frameAnimation.calculationMode = kCAAnimationDiscrete;
[animationLayer setContents:[animationFrames lastObject]];
frameAnimation.autoreverses = NO;
frameAnimation.duration = ((float)[animationFrames count])/4.5;;
frameAnimation.repeatCount = 1;
[frameAnimation setValues:animationFrames];
[frameAnimation setRemovedOnCompletion:YES];
[frameAnimation setDelegate:self];
[animationLayer addAnimation:frameAnimation forKey:#"contents"];
[frameAnimation release];
}
Answer on the basis of Mohit Gupta's pastie link:
Set CALayer on which you want image sequence animation
CALayer *animationLayer = [CALayer layer];
[animationLayer setFrame:CGRectMake(125, 0, 240, 300)];
[self.baseLayer addSublayer:animationLayer];
Define Array of Images needed to be shown in sequence animation
NSArray *animationFrames = [NSArray arrayWithObjects:(id)[UIImageimageNamed:#"1.png"].CGImage, (id)[UIImage imageNamed:#"2.png"].CGImage, (id)[UIImage imageNamed:#"3.png"].CGImage, nil];
Using CAKeyframeAnimation to display array of images in sequential manner
CAKeyframeAnimation *frameAnimation = [[CAKeyframeAnimation alloc] init];
[frameAnimation setKeyPath:#"contents"];
frameAnimation.calculationMode = kCAAnimationDiscrete; //mode of transformation of images
[animationLayer setContents:[animationFrames lastObject]]; //set the array objects as encounterd
frameAnimation.autoreverses = NO; //If set Yes, transition would be in fade in fade out manner
frameAnimation.duration = ((float)[animationFrames count])/4.5; //set image duration , it can be predefined float value
frameAnimation.repeatCount = HUGE_VAL; //this is for inifinite, can be set to any integer value as well
[frameAnimation setValues:animationFrames];
[frameAnimation setRemovedOnCompletion:YES];
[frameAnimation setDelegate:self];
[animationLayer addAnimation:frameAnimation forKey:#"contents"]; //add animation to your CALayer
[frameAnimation release];
Hope this helps

iOS; How to scale UIimageView (permanently) and then move it

I've hit a wall here. I know how to move an Image using "CGAffineTransformMakeTranslation" and I also know how to scale an image using"CGAffineTransformMakeScale" but for the life of me, I can't seem to get one Image to do both of these and stay that way. It scales to the desired size for about a split second and then immediately reverts to its original size and moves to the desired location. What I need is for the image to get big, STAY big, and then move to a new location (while permanently staying its new size).
Here is what I've got going on in my .m file:
-(IBAction)PushZoomButton {
[UIWindow animateWithDuration:1.5
animations:^{
JustinFrame.transform = CGAffineTransformMakeScale(2.0, 2.0);
JustinFrame.transform = CGAffineTransformMakeTranslation(10.0, 10.0);}];
[UIWindow commitAnimations];}
Any help with this would be appreciated!
you can use CGAffineTransformConcat, for instance:
JustinFrame.transform = CGAffineTransformConcat(CGAffineTransformMakeScale(2.0, 2.0), CGAffineTransformMakeTranslation(10.0, 10.0));
You may need to adapt the translation to (5, 5) since you have doubled the scale
The second transform you set overrides the first one. You need to concat both transform actions into one, as Luis said. Another way of writing that would be:
CGAffineTransform transform = CGAffineTransformMakeScale(2.0, 2.0);
transform = CGAffineTransformTranslate(transform, 10, 10);
JustinFrame.transform = transform;
You may need to look into CoreAnimation, basically what UIView animation is controlling under the hood. If you set up a CAAnimation, then what you want to achieve is done with the fillMode property of the animation.
Here's some example code to make a UIView look like it's opening like a door (copy pasted some code I have, but perhaps you could modify it and find it useful):
- (void) pageOpenView:(UIView *)viewToOpen duration:(NSTimeInterval)duration pageTurnDirection:(PageTurnDirection) p{
// Remove existing animations before stating new animation
[viewToOpen.layer removeAllAnimations];
// Make sure view is visible
viewToOpen.hidden = NO;
// disable the view so it’s not doing anythign while animating
viewToOpen.userInteractionEnabled = NO;
float dir = p == 0 ? -1.0f : 1.0f; // for direction calculations
// create an animation to hold the page turning
CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:#"transform"];
transformAnimation.removedOnCompletion = NO;
transformAnimation.duration = duration;
transformAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
CATransform3D startTransform = CATransform3DIdentity;
if (p == NEXT_PAGE) {
// orig values
startTransform.m34 = 0.001f;
}else {
// orig values
startTransform.m34 = -0.001f;
}
// start the animation from the current state
transformAnimation.fromValue = [NSValue valueWithCATransform3D:startTransform];
// this is the basic rotation by 90 degree along the y-axis
CATransform3D endTransform = CATransform3DMakeRotation(3.141f/2.0f,
0.0f,
dir,
0.0f);
// these values control the 3D projection outlook
if (p == NEXT_PAGE) {
endTransform.m34 = 0.001f;
endTransform.m14 = -0.0015f;
}else {
endTransform.m34 = -0.001f;
endTransform.m14 = 0.0015f;
}
transformAnimation.toValue = [NSValue valueWithCATransform3D:endTransform];
// Create an animation group to hold the rotation
CAAnimationGroup *theGroup = [CAAnimationGroup animation];
// Set self as the delegate to receive notification when the animation finishes
theGroup.delegate = self;
theGroup.duration = duration;
// CAAnimation-objects support arbitrary Key-Value pairs, we add the UIView tag
// to identify the animation later when it finishes
[theGroup setValue:[NSNumber numberWithInt:[(BODBookPageView *)viewToOpen pageNum]] forKey:#"animateViewPageNum"]; //STEPHEN: We set the tag to the page number
[theGroup setValue:[NSNumber numberWithInt: p] forKey:#"PageTurnDirection"];
[theGroup setValue:[NSNumber numberWithBool:YES] forKey:#"isAnimationMidpoint"]; // i.e. is this the first half of page-turning or not?
// Here you could add other animations to the array
theGroup.animations = [NSArray arrayWithObjects:transformAnimation, nil];
theGroup.removedOnCompletion = NO; // THIS LINE AND THE LINE BELOW WERE CRUCIAL TO GET RID OF A VERY HARD TO FIND/FIX BUG.
theGroup.fillMode = kCAFillModeForwards; // THIS MEANS THE ANIMATION LAYER WILL STAY IN THE STATE THE ANIMATION ENDED IN, THEREBY PREVENTING THAT ONE FRAME FLICKER BUG.
// Add the animation group to the layer
[viewToOpen.layer addAnimation:theGroup forKey:#"flipViewOpen"];
}

Cocos2d animation from sprite sheet

So i have the action build to make my frog jump but i have 5 images and i want to run them in the order 1,2,3,4,5,4,3,2,1 using the coordinates. I only want to loop them once everytime the from jumps.
Thanks
while defining your image you can use the following code:
CCAnimation* anim = [CCAnimation animationWithName:#"frog"];
CCSpriteFrame* frames[5];
CGRect Rect;
// some code to initialize Rect position
for(int i=0;i<5;i++)
{
frames[i] = [CCSpriteFrame frameWithTexture:#"frog.png" rect:Rect];
// some code to move Rect so that it will mark next frame;
}
for(int i=0;i<5;i++)
[anim addFrame:frames[i]];
for(int i=3;i>=0;i--)
[anim addFrame:frames[i]];
use ccanimation and ccspritebatchnodefile
save your image sequence in spritesheet

Multiple animations and textures with Cocos2d - How to remove texture from memory?

I am writing an application where you push different buttons and a character gets animated. The thing is that I have many images, so I need to use one texture for each animation. Therefore I need to release sprite sheet and frame cash, but it does not seem to be working. Memory gets allocated more and more until the app crashes. Here is the code:
// **** DEFINE THE ANIMATION - EATING 1: ****
// Create a sprite sheet with all the images
CCSpriteSheet *spriteSheet = [CCSpriteSheet spriteSheetWithFile:#"Eating4.png"];
// This loads an image of the same name (but ending in png), and goes through the
// plist to add definitions of each frame to the cache.
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"Eating4.plist"];
[self addChild:spriteSheet];
///[self addChild:spriteSheet2];
// Load up the frames of our animation
NSMutableArray *eating1AnimFrames = [NSMutableArray array];
for(int i = 0; i <= 50; ++i) {
if (i<=9){
[eating1AnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"Eating4_000%d.png", i]]];
}
else if (i>9) {
[eating1AnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"Eating4_00%d.png", i]]];
}
}
CCAnimation *eatingAnim = [CCAnimation animationWithName:#"eating" delay:0.05f frames:eating1AnimFrames];
// Create a sprite for the mouse
CGSize winSize = [CCDirector sharedDirector].winSize;
self.mouse = [CCSprite spriteWithSpriteFrameName:#"Eating4_0000.png"];
_mouse.position = ccp(winSize.width/2+20, winSize.height/2);
// Adjust the size of the Sprite:
[_mouse setScaleX: 1];
[_mouse setScaleY: 1];
//self.eatingAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:eatingAnim restoreOriginalFrame:NO]];
self.eatingAction = [CCAnimate actionWithAnimation:eatingAnim restoreOriginalFrame:NO];
[spriteSheet addChild:_mouse];
[_mouse runAction:_eatingAction];
I try to release memory like this:
[[CCTextureCache sharedTextureCache] removeAllTextures];
[[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFrames];
[[CCTextureCache sharedTextureCache] removeAllTextures];
You don't want to do this! This removes all textures from memory, then reloads all of them that are still in use or the next time they are used. This causes a significant overhead and it's generally bad for your game's performance.
Instead, remove only the texture you need to remove by calling:
[[CCTextureCache sharedTextureCache] removeTexture:tex];
For this to work, you will also have to remove (release) all references to the animation from the Cocos2D node hierarchy.
Calling removeUnusedTextures would be a better choice for clearing up memory used by unused textures:
[[CCTextureCache sharedTextureCache] removeUnusedTextures];
Or you can ask use CCDirector::purgeCachedData that does the same thing internally:
[[CCDirector sharedDirector] purgeCachedData];