Erika Electra
Erika Electra

Reputation: 1882

ios - How to force animations to execute sequentially in a loop?

I have a priority queue of various actions -- UIImageView translations and the HP bar decreases associated with them. I already programmed a bar widget with CALayer animations, so it should handle itself, but for some reason, even though my loop is sequential, all the animations -- bar animations as well as other actions in the queue -- all happen simultaneously. How do I force sequentiality? Here's code from my viewController .m:

while (![selectedMoves isEmpty])
    {
        SelectedMove* nextMove = [selectedMoves dequeueMax];

        // Move the user to clearly indicate who is moving:
        [self animateAttacker:nextMove.user];


        [moveReporter setText:report];
        [self executeMove:nextMove];
    }

executeMove is the wrapper that changes the health bar value to reflect damage.

-(void) executeMove:(SelectedMove*)attack
{
   ... calculate damage dealt by attack...

   // Animate HP bar change on-screen
    double percentage = (double)[currentHP intValue] / (double)[currentStats[HP] intValue];
    [playerHealthBars[slot] updateBarPercentage:percentage andMaxHP:[currentStats[HP] intValue]];


}

My issue is that all of the healthBar animations, as well as the "animateAttacker" calls, are happening at once on the screen. What command forces one to execute before the other, or forces a screen refresh before moving on?

animateAttacker is the wrapper that translates the appropriate UIImage forward according to nextMove. The goal is to have each iteration of the loop -- the health bar and the animateAttacker -- execute simultaneously, or sequentially, and to have separate iterations execute in the order of the loop: :

-(void)animateAttacker:(HonmonBattleState*)attacker 
{
        UIImageView* attackerImageView = playerImages[index];
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:1.0];
        attackerImageView.transform=CGAffineTransformMakeTranslation(ATTACK_PERTURBATION, -ATTACK_PERTURBATION);
        [UIView commitAnimations];

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:1.0];
        attackerImageView.transform=CGAffineTransformIdentity;
        [UIView commitAnimations];
   }

Thanks for your help!

PS> I can use CALayer Core Animations or UIView animations. I have done both, and the health bars are internally done using layers.

Upvotes: 0

Views: 746

Answers (2)

Cyrille
Cyrille

Reputation: 25144

If you want a global, serial queue for your animations, you should look into having your own NSOperationQueue with a maximum parallel task count of one. This way, all operations you run on it will be delayed until the previous ones have finished.

Upvotes: 1

Cyrille
Cyrille

Reputation: 25144

Block-based UIView animations have completion blocks that you can use to chain animations, see this thread over here.

And you can use completion blocks in CAAnimations with this category on GitHub (it's on CocoaPods if you need).

Upvotes: 1

Related Questions