PDA

View Full Version : How to make animation from a set of images?




HARDWARRIOR
Dec 2, 2008, 03:19 AM
Hi!
I have a set of several png files. And I want to make animation from them - just change one to another after specific time period.

So I tried to implement this using layers:
First of all I made a layer for each frame and sorted them in depth:

- (void)viewDidLoad {
[super viewDidLoad];

for(NSUInteger k = 1; k <= 7; k++) {
CALayer *frame = [CALayer layer];
frame.bounds = CGRectMake(0.0f, 0.0f, 100.0f, 100.0f);
frame.position = CGPointMake(160.0f - 20.0f, 240.0f - 20.0f);
frame.zPosition = -k;

NSString *fileName = [NSString stringWithFormat:@"%d", k];
UIImage *image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:fileName ofType:@"png"]];
frame.contents = [image CGImage];

[self.view.layer addSublayer:frame];
}
}


then I implemented a method that increases zPosition on each layer by 1. First layer goes to back:


- (void)nextFrame {
NSArray *layers = self.view.layer.sublayers;
CALayer *firstLayer = (CALayer *)[layers objectAtIndex:0];
[firstLayer removeFromSuperlayer];

CALayer *lastLayer = (CALayer *)[layers objectAtIndex:layers.count];
firstLayer.zPosition = lastLayer.zPosition;

CALayer *layer;
for(layer in layers)
layer.zPosition ++;

[self.view.layer insertSublayer:firstLayer below:lastLayer];
}


calling this method when user touches the screen

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[self nextFrame];
}


It works! But now I need animation to function all by itself without touches on screen. So in viewDidAppear I perform calling of this method in infinite loop in another thread:


- (void)viewDidAppear:(BOOL)animated {
[ NSThread detachNewThreadSelector: @selector(myThreadedMethod) toTarget: self withObject: nil ];
}

- (void)myThreadedMethod {
NSAutoreleasePool *pool = [ [ NSAutoreleasePool alloc ] init ];

while(YES) {
[self nextFrame];
sleep(1);
}

[ pool release ];
}


But such animation does not function. Nothing changes on screen. I even tried to add [self.view.layer setNeedsDisplay] in infinite loop.

Does anybody know what the problem is? Or there is maybe less complicated way to create animation from set of separatte images?



priyank.ranka
Dec 2, 2008, 04:50 AM
Hey just simply use UIImageView cObject and set all ur frames into Animating property of that object.And call the respective funtion fr starting and stoping the animation

jnic
Dec 2, 2008, 05:52 AM
Or there is maybe less complicated way to create animation from set of separatte images?

https://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIImageView_Class/Reference/Reference.html

NSArray *images = // Your images.
UIImageView *yourAnimation = // An image view which will contain your animation.

yourAnimation.animationImages = images;
yourAnimation.animationDuration = 2.0;

[yourAnimation startAnimating];

HARDWARRIOR
Dec 2, 2008, 07:40 AM
I need animation that I can pause and resume then from where is was paused. Not from begining. Also during pause I need to display current frame.

HARDWARRIOR
Dec 2, 2008, 03:03 PM
Now I came to following implementation:

For each frame I create subview with UIImageView in it. This UIImageView has frame as it's image property.

- (void)viewDidLoad {
[super viewDidLoad];

for(NSUInteger k = 1; k <= 9; k++) {
NSString *fileName = [NSString stringWithFormat:@"%d", k];
UIImage *image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:fileName ofType:@"png"]];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.frame];
imageView.image = image;

[self.view insertSubview:imageView atIndex:(self.view.subviews.count + 1)];
}

animationTimer = nil;

NSString *path = [[NSBundle mainBundle] pathForResource:@"music" ofType:@"mp3"];
theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.numberOfLoops = -1;

[self pause_unpause];
}

there is a music at the end)

Then every time timer

- (void)pause_unpause {
if(animationTimer == nil) {
animationTimer = [[NSTimer timerWithTimeInterval:0.01 target:self selector:@selector(timerFired:) userInfo:nil repeats:YES] retain];
[[NSRunLoop currentRunLoop] addTimer:animationTimer forMode:NSDefaultRunLoopMode];
[theAudio play];
} else {
[animationTimer invalidate];
[animationTimer release];
animationTimer = nil;
[theAudio pause];
}

}


ticks I call

- (void)timerFired:(NSTimer *)timer {
[self.view bringSubviewToFront:[self.view.subviews objectAtIndex:0]];
}

that brings current frame to back
If we insert log in this method, we can value fps. On my touch 1G it's around 50 fps.

Anyway fell free to post less complex and more fast approaches to animation task!

The reason why I started all this mess with frame-by-frame animation is task where I suppsed to implement video playing on ipod. But MPMoviePlayerController does not have pause method - after every time it is stopped, it starts plying video from begining. Authors of vlc and mplayer ports to iphone did not publish their source code. So I came to an idea that there is now way no to play video on iphone except frame-by-frame. Or am I wrong?