Question

I'm making a card game, where I need the cards to "flip over". To be first face down and then flip around, so the face is up. I've made a nice animation to do it and it works nicely, except that half of the view is hidden behind the layer behind during the animation (see screenshot).

When the animation is done, the card view stacks nice on top of the other views.

Any hints on why half of the view is hidden during the animation?

Screenshot: Screenshot 1

Code:

- (void)setFaceDirection:(BOOL)up{
    if(up && !self.faceUp){
        self.faceUp = up;
        [self flip:@"in"];
    }else if(!up && self.faceUp){
        self.faceUp = up;
        [self flip:@"out"];
    }
}

- (void)flip:(NSString *)direction{
    NSLog(@"flip");
    [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(firstFlip) userInfo:nil repeats:NO];
    [NSTimer scheduledTimerWithTimeInterval:1.2 target:self selector:@selector(secondFlip) userInfo:nil repeats:NO];
}

- (void)firstFlip{
    [CATransaction begin];
    CAAnimation* anim1 = [self createAnimDirection:@"in"];
    [CATransaction commit];

    //add perspective
    CATransform3D mt = CATransform3DIdentity;
    mt.m34 = 1.0/1000;
    mt = CATransform3DTranslate(mt, 0.0f, 0.0f, 0.01f);

    CALayer* lr = [self layer];
    lr.transform = mt;

    NSPoint ap = {0.5,0.0}; // Begin from OS X Mountain Lion ancorPoint by default at 0,0;
    lr.anchorPoint = ap;

    // animation delegate to this class to handle message on its completion
    anim1.delegate = self; 

    CGPoint center = CGPointMake(CGRectGetMidX(self.frame), self.frame.origin.y);
    // lr.position = center;  

    [CATransaction begin];
    [lr addAnimation:anim1 forKey:@"flip"];
    [CATransaction commit];
}

- (void)secondFlip{
    [CATransaction begin];
    CAAnimation* anim1 = [self createAnimDirection:@"out"];
    [CATransaction commit];

    //add perspective
    CATransform3D mt = CATransform3DIdentity;
    mt.m34 = 1.0/1000;
    mt = CATransform3DTranslate(mt, 0.0f, 0.0f, 0.01f);

    CALayer* lr = [self layer];
    lr.transform = mt;

    NSPoint ap = {0.5,0}; // Begin from OS X Mountain Lion ancorPoint by default at 0,0;
    lr.anchorPoint = ap;

    // animation delegate to this class to handle message on its completion
    anim1.delegate = self; 

    CGPoint center = CGPointMake(CGRectGetMidX(self.frame), self.frame.origin.y);
    lr.position = center;  

    [CATransaction begin];
    [lr addAnimation:anim1 forKey:@"flip"];
    [CATransaction commit];
}

- (CAAnimation*) createAnimDirection:(NSString *) direction
{
    double from = 0.0;
    double to = M_PI/2;
    if ([direction isEqualToString:@"in"]){
        [self setImage:[NSImage imageNamed:@"Card_Background"]];
    }else{
        from = -M_PI/2;
        to = 0.0;
        [self setImage:self.faceImage];
    }

    NSString* sRotation;
    sRotation = @"transform.rotation.y";
    CABasicAnimation* ba = [CABasicAnimation animationWithKeyPath:sRotation];
    ba.fromValue = [NSNumber numberWithFloat:from];
    ba.toValue = [NSNumber numberWithFloat:to];

    CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
    animationGroup.animations = [NSArray arrayWithObjects:ba, nil];
     animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    animationGroup.duration = 1.2;
    animationGroup.fillMode = kCAFillModeForwards;
    animationGroup.removedOnCompletion = NO;

    return animationGroup;
}

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag{
    if(flag){
        if (self.faceUp){
            [self setImage:self.faceImage];
        }else{
            [self setImage:[NSImage imageNamed:@"Card_Background"]];
        }
    }
}
Was it helpful?

Solution

I ended up messing around with the xIndex of the cards, so now it works.

I've changed the code so much that I can't post it here though.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top