Search code examples
iosxcoded-pad

How to implement a D-Pad Xcode 5 on an iPad


I have tried many times to implement a D-Pad for my new maze game, but am having trouble doing so. I am doing it in the style of 4 UIButtons and if you press one, it moves another image up, down, left or right. I have tried using the quartzcore and CAAnimation, but only know limited code.

I have the methods and the buttons declared, but cannot code a working one.

I was doing:

-(IBAction)Up:(id)sender{

CGPoint origin1 = self.Player.center;
CGPoint target1 = CGPointMake(self.Player.center.x, self.Player.center.y-124);
CABasicAnimation *bounce1 = [CABasicAnimation animationWithKeyPath:@"position.y"];
bounce1.duration = 0.1;
bounce1.fromValue = [NSNumber numberWithInt:origin1.y];
bounce1.toValue = [NSNumber numberWithInt:target1.y];
[self.Player.layer addAnimation:bounce1 forKey:@"position"];

}

The ghost moves down, but bops back up immediately. I've been stumped for hours and it may be glaring me in the face, but please understand my noobishness.


Solution

  • In Core Animation, there are two layer hierarchies: one of model layers and one of presentation layers. Presentation layers are what you see; model layers are what you often interact with in code. This separation is valuable because it lets you create implicit animation -- e.g. set the position of a layer, and it'll animate to the new spot. (But if you assign a value to position, you want that to be the value you read back immediately thereafter, even if the animation is still in progress.)

    When you use addAnimation:forKey:, you're affecting the presentation, not the model. So, during the animation, you see the Player layer moving, but that layer is "really" still where you left it. As soon as the animation ends, it's removed from the layer, so the presentation matches the model again -- you see it at its original position.

    If you want the model position to change as well, you need to change it separately:

    self.player.layer.position = CGPointMake(self.player.layer.position.x, target1.y);
    

    You can either update the model immediately after adding the animation (you'll see the change after the animation completes), or use a completion block to schedule it at the end of the animation. There are subtleties to consider for either approach.

    Often, though, if you just want to animate a specific change like that, especially for the main layer of a UIView, it's simpler to use the implicit animation API on UIView:

    [UIView animateWithDuration:0.1 animations: ^{
        self.player.center = CGPointMake(self.player.center.x, target1.y);
    }];
    

    This will both update the model value and create and run an animation for moving from the current position to the target position.


    BTW: It helps to follow Cocoa code style conventions: use initial caps only for class names or other type names, and lowercase for variable/property/method names.