Search code examples
iosobjective-ccgrectuianimationcadisplaylink

How to prevent UIAnimation from interfering with CADisplayLink


In my current project there are two main mechanics. A series of objects that continually move up the screen, and a mechanic where you press multiple buttons to move 2 objects. For the series of objects that move up the screen, i have utilized a CADisplayLink, and for the other mechanic is use a UIAnimation, however when i run my project, i notice that the UIAnimation, interferes with the movement of the Objects linked with the CADisplayLink for a split second whenever a button is pressed. How do I correct this issue??

Below is my code for these two mechanics

-(IBAction)tap{
    CGRect frame = Person.frame;
    frame.origin.x = 16;
    frame.origin.y = 37;

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:0.2];

    Person.frame = frame;
    [UIView commitAnimations];
}

-(IBAction)tap1{
    CGRect frame = Person.frame;
    frame.origin.x = 241;
    frame.origin.y = 37;

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:0.2];

    Person.frame = frame;
    [UIView commitAnimations];
}

-(IBAction)tapR1{
    CGRect frame = Person1.frame;
    frame.origin.x = 302;
    frame.origin.y = 37;

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:0.2];

    Person1.frame = frame;
    [UIView commitAnimations];
}

-(IBAction)tapR2{
    CGRect frame = Person1.frame;
    frame.origin.x = 526;
    frame.origin.y = 37;

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:0.2];

    Person1.frame = frame;
    [UIView commitAnimations];
}

-(void)GameOver{
}

-(void)Score{
    ScoreNumber = ScoreNumber + 1;
    ScoreLabel.text = [NSString stringWithFormat:@"%i", ScoreNumber];
}

-(IBAction)StartGame:(id)sender{
    StartGame.hidden = YES;
    Spike.hidden = NO;
    Spike1.hidden = NO;
    Spike2.hidden = YES;
    SpikeR.hidden = NO;
    SpikeR1.hidden = NO;
    SpikeR2.hidden = NO;
    circle.hidden = NO;
    ScoreLabel.hidden = NO;

    [self PlaceBars];
    [self PlaceBars1];

    Movement = [CADisplayLink displayLinkWithTarget:self selector:@selector(BarMoving)];
    [Movement addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}

-(void)BarMoving{
    Spike.center = CGPointMake(Spike.center.x, Spike.center.y - 5);
    Spike1.center = CGPointMake(Spike1.center.x, Spike1.center.y - 5);
    Spike2.center = CGPointMake(Spike1.center.x, Spike1.center.y - 5);

    if (Spike2.center.y == -115) {
        [self PlaceBars];
    }

    SpikeR.center = CGPointMake(SpikeR.center.x, SpikeR.center.y - 5);
    SpikeR1.center = CGPointMake(SpikeR1.center.x, SpikeR1.center.y - 5);
    SpikeR2.center = CGPointMake(SpikeR2.center.x, SpikeR2.center.y - 5);

    if (SpikeR2.center.y == -115) {
        [self PlaceBars1];

    }
}

Solution

  • I rekon you use CADisplayLink for all the movement mechanisms.

    However, delegate the logic of movement to your objects, instead of having a parent object that manages all movements. This is the pattern that you will see in Unity.

    In your case, when CADisplayLink updates, loop through your objects and call update() method on each of them. This update method moves that object up 5 points, like what BarMoving() does, on normal state. On tapped state, it moves to [241, 37] gradually.

    When user taps the object, change it state from normal to tapped, setting initial velocity, position algorithms, target point, and update() method mentioned above will handle the tap movement.