【问题标题】:Animation completion block running too soon动画完成块运行得太快
【发布时间】:2013-06-10 19:58:58
【问题描述】:

我正在尝试按照用户定义的路径移动飞机,类似于 Flight Control 中的控件。我能够绘制路径,尽管效率低下,但我无法让飞机顺利地沿着路径设置动画。

我最初尝试使用通过更改位置提供的隐式动画来沿路径移动飞机,但因为它不允许我改变动画的速度,所以飞机表现不佳。

我现在正在尝试递归地使用动画块,但完成块被调用得太快了,导致飞机只跟随绘制的路径。

这是设置代码:

- (CALayer *)plane{
    if(!_plane){
        _plane = [CALayer layer];
        UIImage *planeImage = [UIImage imageNamed:@"airplane.png"];
        _plane.bounds = CGRectMake(20.0, 20.0, planeImage.size.width, planeImage.size.height);
        _plane.contents = (id)(planeImage.CGImage);
        [self.layer addSublayer:_plane];
    }
    return _plane;
}
- (void)touchesEnded:(NSSet *)touches
           withEvent:(UIEvent *)event{
    if(isDrawingPath){
        [self.trackPath addLineToPoint:[[touches anyObject] locationInView:self]];
        NSLog(@"%@", self.trackPath);

        UITouch *touch = [touches anyObject];
        CGPoint toPoint = [touch locationInView:self];
        //now, save each point in order to make the path
        [self.points addObject:[NSValue valueWithCGPoint:toPoint]];
        [self setNeedsDisplay];
        [self goToPointWithIndex:0];
    }
    isDrawingPath = NO;
}

此实现有效,但效果不佳。飞机沿路径行驶,但波涛汹涌:

- (void)goToPointWithIndex:(NSNumber *)indexer{
    int toIndex = [indexer intValue];

    if(toIndex < self.points.count){
        //extract the value from array
        CGPoint toPoint = [(NSValue *)[self.points objectAtIndex:toIndex] CGPointValue];
        CGPoint pos = self.plane.position;
        float delay = PLANE_SPEED * (sqrt( pow(toPoint.x - pos.x, 2) + pow(toPoint.y - pos.y, 2)));
        self.plane.position = toPoint;

        // Allows animation to continue running
        if(toIndex < self.points.count - 1){
            toIndex++;
        }

        //float delay = 0.2;
        NSLog(@"%f", delay);
        //repeat the method with a new index
        //this method will stop repeating as soon as this "if" gets FALSE
        NSLog(@"index: %d, x: %f, y: %f", toIndex, toPoint.x, toPoint.y);
        [self performSelector:@selector(goToPointWithIndex:) withObject:[NSNumber numberWithInt:toIndex] afterDelay:delay];
    }
}

这就是我试图用块做的事情。它只是跳到绘制路径的末尾,而不是跟随整个路径。

- (void)goToPointWithIndex:(int)toIndex{
    if(self.resetPath) return;
    //extract the value from array
    if(toIndex < self.points.count) {
        CGPoint toPoint = [(NSValue *)[self.points objectAtIndex:toIndex] CGPointValue];
        NSLog(@"index: %d, x: %f, y: %f", toIndex, toPoint.x, toPoint.y);
        CGPoint pos = self.plane.position;
        //float delay = PLANE_SPEED * (sqrt( pow(toPoint.x - pos.x, 2) + pow(toPoint.y - pos.y, 2)));

        // Allows animation to continue running
        if(toIndex < self.points.count - 1){
            toIndex++;
        }

        [UIView animateWithDuration:0.2
                     animations:^{
                         self.plane.position = toPoint;
                     }
                completion:^(BOOL finished) {
                    if(finished == YES) {NSLog(@"Complete");[self goToPointWithIndex:toIndex];}
        }];
    }
}

我不知道我哪里出错了。我是objective-c和blocks的新手。完成块是否应该在动画开始后立即运行?这对我来说没有意义,但这是我能找到的唯一解释。


编辑:我最终使飞机成为 UIView,因此我仍然可以使用块动画。 CALayer 事务根本不喜欢我的递归。

【问题讨论】:

  • 我自己并不是一个游戏开发者,但我认为像 cocos2d 这样的东西更适合你的任务。我可能是错的,但我只是不认为 CoreAnimations 是为这样的任务设计的,至少不是干净的。

标签: ios objective-c animation recursion completion-block


【解决方案1】:

由于这里的self.plane 是一个自定义的CALayer(与支持UIView 的层相反),它不会尊重UIView animateWithDuration: 的参数

来自docs

自定义层对象忽略基于视图的动画块参数,并使用默认的核心动画参数。

改为使用CABasicAnimationCALayer's addAnimation:forKey: 方法(在这种情况下可能是CAAnimationGroup)。如何像这样为CALayers 设置动画在"Animating Layer Content." 下的文档中进行了描述

【讨论】:

    【解决方案2】:

    您只覆盖 touchesEnded 的某些原因?然后,您只会为屏幕上的任何手指路径拾取一个点。在我看来,您应该覆盖 touchesMoved 和 touchesBegan (并且或多或少地做与 touchesEnded 相同的事情)。

    【讨论】:

    • 我也覆盖了其他两个。由于动画效果不佳,我将开始动画调用结束,以便更好地观看。
    • 好的,所以,[self.points addObject:[NSValue valueWithCGPoint:toPoint]]; 出现在所有的触摸方法中,但[self goToPointWithIndex:0]; 只出现在touchesEnded 中?我猜这应该可行。
    猜你喜欢
    • 2013-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-23
    • 2014-01-16
    相关资源
    最近更新 更多