mskw
mskw

Reputation: 10348

The correct way to animate multiple frames while moving

I want to know if this is the right way to animate a game character while it moves from point a to point b, ALSO while displaying different moving images simulating a person's movement.

Here is a persudo code of what I did:

    [UIView animateWithDuration:dMAN_MOVEMENT_SPEED/3 animations:^{
            //Set Target Image
            //Set target position
    }completion:^(BOOL finished){
        //2nd to 3rd Frame
        [UIView animateWithDuration:dMAN_MOVEMENT_SPEED/3 animations:^{
            //Set Target Image
            //Set target position
        }completion:^(BOOL finished){
            //3rd to final Frame
            [UIView animateWithDuration:dMAN_MOVEMENT_SPEED/3 animations:^{
                //Set Target Image
                //Set target position
            }completion:^(BOOL finished){
                //do nothing
            }];
        }];
    }];

Is this the correct way? I did it this way because I can control each frame and each frame's duration.

Upvotes: 1

Views: 765

Answers (1)

Rob
Rob

Reputation: 438027

Seems like there might be better ways. If you didn't have too many images, I would probably just recommend using animationImages property of UIImageView and then startAnimating:

NSArray *images = @[[UIImage imageNamed:@"0.jpg"],
                    [UIImage imageNamed:@"1.jpg"],
                    [UIImage imageNamed:@"2.jpg"],
                    [UIImage imageNamed:@"3.jpg"],
                    [UIImage imageNamed:@"4.jpg"],
                    [UIImage imageNamed:@"5.jpg"],
                    [UIImage imageNamed:@"6.jpg"],
                    [UIImage imageNamed:@"7.jpg"]];

self.imageView.image = images[0];

self.imageView.animationImages = images;
self.imageView.animationDuration = kAnimationDuration;
self.imageView.animationRepeatCount = 1;

[self.imageView startAnimating];

[UIView animateWithDuration:kAnimationDuration
                 animations:^{
                     self.imageView.center = ... // set this to whatever you want
}];

If you were concerned about loading all of that into memory, you could also use a CADisplayLink to load the images as appropriate, something like the following:

- (void)animateImageUsingDisplayLink
{
    self.imageNames = @[@"0.jpg",
                        @"1.jpg",
                        @"2.jpg",
                        @"3.jpg",
                        @"4.jpg",
                        @"5.jpg",
                        @"6.jpg",
                        @"7.jpg"];

    self.imageView.image = [UIImage imageNamed:self.imageNames[0]];

    [self startDisplayLink];

    [UIView animateWithDuration:kAnimationDuration
                     animations:^{
                         self.imageView.center = ... // set this to whatever you want
    }];
}

- (void)startDisplayLink
{
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
    self.startTime = CACurrentMediaTime();
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopDisplayLink
{
    [self.displayLink invalidate];
    self.displayLink = nil;
}

- (void)handleDisplayLink:(CADisplayLink *)displayLink
{
    CFTimeInterval elapsed = displayLink.timestamp - self.startTime;

    // If you want it to repeat, then comment out the following `if` statement

    if (elapsed >= kAnimationDuration)
    {
        [self stopDisplayLink];
        return;
    }

    NSInteger frameNumber = ((NSInteger) elapsed * [self.imageNames count] / kAnimationDuration) % [self.imageNames count];

    if (frameNumber != self.currentFrameNumber)
    {
        self.imageView.image = [UIImage imageNamed:self.imageNames[frameNumber]];
        self.currentFrameNumber = frameNumber;
    }
}

Upvotes: 3

Related Questions