Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Displaying Animation by Frame?

I have a animation consisting of 100 images. I want to be able to display the animation through a sequence of frames. For example, instead of displaying the animation from 0:00 seconds to 0:32 seconds, I would rather use Frame 0 to Frame 32. I need to do this because I need a LOT of control over the animation (even the difference of one frame would create the wrong result). I have drawn each frame personally, so I know the image of each frame.

Is there anyway I can do this in Cocoa, using Objective-C? How would I do this? All I have is 100 images and I have no idea how to proceed from here. And also, would this be "laggy" compared to specifying by time?

I would prefer a detailed answer because I couldn't find any resources online and am completely new to this.

Note that I am using OS X, not iOS, so please do not provide iOS-related answers. I'm working with Xcode 3.2.6 on Snow Leopard.

like image 806
fdh Avatar asked Feb 20 '12 19:02

fdh


People also ask

How do you frame-by-frame animation?

To create a frame-by-frame animation, define each frame as a keyframe and create a different image for each frame. Each new keyframe initially contains the same contents as the keyframe preceding it, so you can modify the frames in the animation incrementally.

Do animators work frame-by-frame?

Throughout most of the 20th century, animating frame-by-frame was the only method of producing animation. Although it's no longer necessary, it's still used by many animators for the following two purposes: Tradition: To replicate the traditional qualities of hand-drawn animation.

What is frame-by-frame animation called?

Frame-by-frame animation is more commonly known as stop-motion animation. It is achieved by manipulating a physical object and making it appear to move on its own by shooting one frame, manipulating the object, then shooting another frame, and so on.

How do I show frames in Adobe animation?

Insert frames and keyframesClick and hold the mouse on the Keyframe icon to view and select the options. Select a frame in timeline and click Keyframe icon to insert frame, keyframe, or blank keyframe as per the recent selection. Inserting keyframe or blank keyframe in Timeline panel now has a visual feedback.


3 Answers

The way to have the most control would be to store all of your images in an array. If you named your images something like "frame.png" (i.e. "frame1.png") then you can quickly load all of your images like this:

frames = [[NSMutableArray alloc] init]; // In header: NSMutableArray *frames;
for (int i = 1; i < 100; i++) // 100 can be replaced for any number of frames.
{
    NSString *filename = [NSString stringWithFormat:@"frame%i.png", i];
    [frames addObject:[NSImage imageNamed:filename]];
}

What this does is creates an array and fills it with NSImages named after your files. The %i is substituted in the string for the current value of i.

Now, you'll need another variable to keep track of the current frame. Something like unsigned int currentFrame;. This can either be incremented every update loop, or set to a specific value, giving you complete control over the frame displayed.

Then, in your render loop, you can render whichever frame is currently stored like this:

[(NSImage *)[frames objectAtIndex:currentFrame - 1] drawAtPoint:animPos fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f];

where animPos is an NSPoint containing the position you wish to draw at. The - 1 is there in the index so you can refer to your frames starting at 1 rather than 0. This code pulls the image at frame currentFrame and renders it to the screen.

Since you are using an array, also be sure to check currentFrame is never equal to a value greater than the max number of frames, something like: if (currentFrame > 100) currentFrame = 1;. This would cause the animation to loop, since when it gets to the last frame, currentFrame would be set back to the beginning index of the array.

For more information on drawing, you should look at: Cocoa Drawing Guide and NSImage Class Reference. Also, if you need more information on how to update the frame every increment of time, look into NSTimer Class Reference.

like image 180
wquist Avatar answered Oct 23 '22 09:10

wquist


You can use this code for your frame by frame animation. Hope this will help you.

 // create the view that will execute our animation
 UIImageView* imageListView = [[UIImageView alloc] initWithFrame:self.view.frame];

 // load all the frames of our animation
 imageListView.animationImages = [NSArray arrayWithObjects:    
                             [UIImage imageNamed:@"campFire01.gif"],
                             [UIImage imageNamed:@"campFire02.gif"],
                             [UIImage imageNamed:@"campFire03.gif"],
                             [UIImage imageNamed:@"campFire04.gif"],
                             [UIImage imageNamed:@"campFire05.gif"],
                             [UIImage imageNamed:@"campFire06.gif"],
                             [UIImage imageNamed:@"campFire07.gif"],
                             [UIImage imageNamed:@"campFire08.gif"],
                             [UIImage imageNamed:@"campFire09.gif"],
                             [UIImage imageNamed:@"campFire10.gif"],
                             [UIImage imageNamed:@"campFire11.gif"],
                             [UIImage imageNamed:@"campFire12.gif"],
                             [UIImage imageNamed:@"campFire13.gif"],
                             [UIImage imageNamed:@"campFire14.gif"],
                             [UIImage imageNamed:@"campFire15.gif"],
                             [UIImage imageNamed:@"campFire16.gif"],
                             [UIImage imageNamed:@"campFire17.gif"], 
                              //all your 100 images// , nil];

 // all frames will execute in 1.75 seconds
 imageListView.animationDuration = 1.75;
 // repeat the annimation forever
 imageListView.animationRepeatCount = 0;
 // start animating
 [imageListView startAnimating];
 // add the animation view to the main window 
 [self.view addSubview:imageListView];
like image 45
Neeraj Neeru Avatar answered Oct 23 '22 11:10

Neeraj Neeru


You might consider using CADisplayLink. Here's an example on how to use it:

In your initialization method, setup the display link:

CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(playAnimation:)];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];    

Then add the method:

- (void)playAnimation:(CADisplayLink*)displayLink
{
    // Set the right image to display
    self.imageToDisplay = TheRightImageBasedOnYourAnimationSequence

    [self setNeedsDisplay];
}

And lastly, in the drawRect: method, display the image. The CADisplayLink class has attributes to control the frame duration, etc...

like image 1
mprivat Avatar answered Oct 23 '22 11:10

mprivat