1

当我在实现一个游戏时,我只是在前面,我认为这很容易,但不知道如何解决它。从我的声誉可以看出,我在 Objective-c 方面有点新意 :(

问题是,我有一个动画,它可以正常工作。这是代码:

CABasicAnimation * bordgauche = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
bordgauche.fromValue = [NSNumber numberWithFloat:0.0f];
bordgauche.toValue = [NSNumber numberWithFloat:749.0f];
bordgauche.duration = t;
bordgauche.repeatCount = 1;
[ImageSuivante.layer addAnimation:bordgauche forKey:@"bordgauche"];

我想得到我的形象的当前位置。所以我使用:

CALayer *currentLayer = (CALayer *)[ImageSuivante.layer presentationLayer];
currentX = [(NSNumber *)[currentLayer valueForKeyPath:@"transform.translation.x"] floatValue];

但我没有立即明白。当我使用 nslog 打印它时,我得到一次“Current = 0.0000”,这是起始值,但之后没有其他值。我一直不知道如何获取我的图像 currentX 的即时位置。

我想我是不稳定的。谢谢你的帮助 :)

4

4 回答 4

4

您可以从图层的表示层获取值。

CGPoint currentPos = [ImageSuivante.layer.presentationLayer position];
NSLog(@"%f %f",currentPos.x,currentPos.y);
于 2013-06-20T16:52:18.753 回答
3

我认为您在这里有 3 个选项(如果有更多选项,请发表评论):

选项1:将您的第一个动画分成两部分,当前半部分结束时开始动画的后半部分加上另一个动画

...
bordgauche.toValue = [NSNumber numberWithFloat:749.0f / 2];
bordgauche.duration = t/2;
bordgauche.delegate = self // necessary to catch end of anim
[bordgauche setValue:@"bordgauche_1" forKey: @"animname"]; // to identify anim if more exist

...

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
    if ([theAnimation valueForKey: @"animname"]==@"bordgauche_1") {
         CABasicAnimation * bordgauche = [CABasicAnimation
                  animationWithKeyPath:@"transform.translation.x"];
         bordgauche.fromValue = [NSNumber numberWithFloat:749.0f / 2];
         bordgauche.toValue = [NSNumber numberWithFloat:749.0f];
         bordgauche.duration = t/2;
         bordgauche.repeatCount = 1;
         [ImageSuivante.layer addAnimation:bordgauche forKey:@"bordgauche_2"];


         // plus start your second anim 
}

选项 2:设置 NSTimer 或 CADisplayLink(这更好)回调并不断检查动画层的参数。测试触发第二个动画所需值的参数。

displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(check_ca_anim)];
[displayLink setFrameInterval:1];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

... or
animationTimer = [NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval)(1.0 / 60.0) target:self selector:@selector(check_ca_anim) userInfo:nil repeats:TRUE];
[[NSRunLoop mainRunLoop] addTimer:animationTimer forMode:NSRunLoopCommonModes];

- (void) check_ca_anim {
    ...
    CGPoint currentPosition = [[ImageSuivante.layer presentationLayer] position];
    // test it and conditionally start something
    ...
}

选项3:设置一个CADisplayLink(现在可以称为“gameloop”)并通过计算和设置动画对象的适当参数自己管理动画。不知道你想创建什么样的游戏我会说游戏循环可能对其他游戏特定的原因有用。另外在这里我提到了 Cocos2d,它是一个很棒的游戏开发框架。

于 2013-03-18T21:18:11.887 回答
2

您可以尝试从图层的表示层获取值,该值应该接近屏幕上显示的内容:

[ [ ImageSuivante.layer presentationLayer ] valueForKeyPath:@"transform.translation.x" ] ;
于 2013-03-18T20:39:49.977 回答
0

我会在@codedad指出的内容中添加一个选项。有趣的是,它可以精确地获取动画层的即时值(您可以查看 CALayer 的动画属性列表),而且非常简单。

如果你覆盖方法

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;

在您的 UIView 类中(是的,您需要为您的“ImageSuivante”视图实现一个从UIView派生的自定义类),然后在那里传递的参数层将为您提供您所需要的。它包含用于绘图的精确值。

例如,在这种方法中,您可以更新一个适当的即时变量(以便稍后使用),然后如果您不用手绘制,则调用 super:

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context {
    self.instantOpacity = layer.opacity;
    self.instantTransform = layer.transform;
    [super drawLayer:layer inContext:context];
}

请注意,此处的通常与self.layer不同的对象(其中self是您的自定义 UIView),因此例如self.layer.opacity会给您目标不透明度,但不是即时的,而self.instantOpacity在代码之后上面将包含您想要的即时值。

请注意,这是一种绘图方法,它可能会被非常频繁地调用,因此无需进行不必要的计算或任何繁重的操作。

这个想法的来源是 Apple 的Custom Animatable Property项目。

于 2015-09-30T14:57:49.530 回答