Picoman Games
Picoman Games

Reputation: 3

Overlapping animations help?

Here is my code for making a bat flap its wings and respond to touches.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSArray * imageArray = [[NSArray alloc] initWithObjects:
                            [UIImage imageNamed:@"Bat1.png"],
                            [UIImage imageNamed:@"Bat2.png"],
                            [UIImage imageNamed:@"Bat3.png"],
                            [UIImage imageNamed:@"Bat2.png"],
                            [UIImage imageNamed:@"Bat1.png"],
                            [UIImage imageNamed:@"Bat4.png"], 
                            [UIImage imageNamed:@"Bat5.png"],
                            [UIImage imageNamed:@"Bat6.png"],
                            [UIImage imageNamed:@"Bat5.png"],
                            [UIImage imageNamed:@"Bat4.png"],
                            nil];

    UIImageView * batView = [[UIImageView alloc] initWithFrame:
                             CGRectMake(0, 0, 80, 56)];
    batView.animationImages = imageArray;
    batView.animationDuration = 0.70;
    [follower1 addSubview:batView];
    [batView startAnimating];
    [UIImageView beginAnimations:@"follow" context:nil];
    [UIImageView setAnimationDuration:1];
    [UIImageView setAnimationBeginsFromCurrentState:YES];
    UITouch *touch = [touches anyObject];
    follower1.center = [touch locationInView:self];
    [UIImageView commitAnimations];
    [batView release]; 
}

The problem is that after the second touch the animations overlap on top of each other so after every touch it looks like there are lots of bats underneath!

Upvotes: 0

Views: 596

Answers (1)

Tyler
Tyler

Reputation: 28874

This is happening because you're adding a new batView each time a touch begins.

One way to fix this is to add the batView once, such as in a superview's or a view controller's init method. If you only want the batView to appear when a touch occurs, you can start it hidden via:

// during initialization
batView.hidden = YES;

Since you're always doing the same animation each time, you might as well set up your animation parameters at the same time, instead of repeating that same set up with each touch:

// still during initialization
NSArray* imageArray = /* set up your image array */;
batView.animationImages = imageArray;
batView.animationDuration = 0.7;

Now, when a touch occurs, you can handle it by starting the animation:

// Within touchesBegan:
    ...
    // Start the batView animation.
    batView.hidden = NO;
    if (![batView isAnimating]) [batView startAnimating];
    // Hide the animation when it's done.
    [self performSelector:@selector(hideBat) withObject:nil afterDelay:0.71];
}

// Later:

- (void) hideBat { batView.hidden = YES; }

You might want to do something different in hideBat if you don't always want it to disappear right after a single animation. For example, if you want to always repeat an animation until the user stops clicking, you could set up an NSTimer object to go off as soon as there has been no user touches for at least 0.7 seconds. Each time the user touches the screen again, you can reset this timer.

Reference: UIImageView docs, which includes brief descriptions of the animation methods.

Upvotes: 1

Related Questions