CCMoveTo持续时间问题

时间:2012-12-02 17:53:45

标签: objective-c ios xcode cocos2d-iphone

我有一个球(CCSprite)永远从左到右移动。当我触摸屏幕时,我希望球停止。 问题是如果精灵的持续时间太快,它在停止前有一个毫秒的延迟时间,所以即使我触摸了一个“不同”的位置,停止位置几乎是相同的值。

CGSize winSize = [[CCDirector sharedDirector] winSize];

self.ball = [CCSprite spriteWithFile:@"ball.png"];
self.ball.position = ccp(0, 156);

CGPoint destinationPoint = self.ball.position;
destinationPoint.x = winSize.width;

CGPoint startPoint = self.ball.position;
startPoint.x = 0;

float speed = 0.8f;

[self.ball runAction:[CCRepeatForever actionWithAction:
        [CCSequence actions:
            [CCMoveTo actionWithDuration:speed position:destinationPoint],
            [CCMoveTo actionWithDuration:0.f position:startPoint],
         nil]
        ]];

然后,当我触摸屏幕时,我想停止精灵,并记录球的位置:

-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
    [self.ball stopAllActions];
    NSLog(@"Ball x y: %f %f\n", self.ball.position.x, self.ball.position.y);
    // Then repeat again the movement of the ball
}

因此,当我触摸中心时,它在停止前有一个毫秒的延迟。再一次,我的意思是当我触摸时,它会延迟毫秒时间(球仍在移动)然后停止。例如,当我点击位置x 240时,它停在x 240,1122处,当我点击位置x 230时,它停在239,222处。我触摸后没有立即停止。

以下是我触摸的位置的示例日志。

Ball x y: 240.211624 156.000000
Ball x y: 240.369995 156.000000
Ball x y: 240.291992 156.000000
Ball x y: 219.913574 156.000000
Ball x y: 260.425598 156.000000
Ball x y: 260.004364 156.000000
Ball x y: 239.953186 156.000000

请参阅?停止时的x位置始终为“可以除以20”。

  1. 240240240239
  2. 219
  3. 260260
  4. 我很确定我曾经点击位置x 235,230或245或250或任何值排除该模式。但就像我说的那样,球有一段延迟时间仍在移动,然后停止。

    例如,如果我改变速度变为2.8f(或更高),球会立即停止,当我触摸时,球的x y位于最后位置的准确位置。我认为这是因为CCMoveTo速度的持续时间太快了。

    我尝试过使用计划选择器方法。但是时间表的时间不能像CCMoveTo那样快。因此,使用计划的运动将是一个像素到一个像素,持续时间太长。

    这有什么解决方案吗?或者有这样的方法来实现这个?非常感谢!

2 个答案:

答案 0 :(得分:0)

这实际上是预期的行为,如果你以高速动画精灵,效果尤其明显。为什么呢?

动画本质上是某个变量随时间的变化,这种变化总是在一系列离散的时间步骤上进行。假设你的目标距离是240像素,你想要的持续时间是0.8秒。然后你的速度是240 * 0.8 = 300像素/秒。假设完全恒定的fps为60,那么对于每个执行的时间步长,您将期望离散位置变化为1/60 * 300 = 5像素。

现在假设您在 t 时收到触摸事件。通常,这个 t 与任何时间步的开始都不完全一致;它更可能介于某对时间步之间。调用stopAllActions应该在当前时间步长完成后停止调度动画,它不会在两个时间步之间停止,可以这么说。这正是您报告距离总是相隔一定距离的原因。

你真的需要像素精确吗?如果是这样,您需要在两个时间帧的位置之间进行插值以找到精确的位置。

修改

我实际上非常怀疑在这种情况下需要像素精确的解决方案。事实上,我怀疑感知到的第二次延迟可能是由于在触摸事件结束时而不是在触摸事件开始时检测到触摸事件。您可能想尝试在ccTouchBegan中捕获该事件。

答案 1 :(得分:0)

你的第二个CCMoveTo动作是不必要的 - 你不想执行0秒的移动动画,你想立即将它移回到开始。我建议您将动画更改为以下内容:

[self.ball runAction:[CCRepeatForever actionWithAction:
    [CCSequence actions:
        [CCMoveTo actionWithDuration:speed position:destinationPoint],
        [CCCallBlock actionWithBlock:^
        {
            self.ball.position = ccp(0, 156);
        }],
     nil]
    ]];
编辑:道歉 - 我不明白这个问题(但仍然建议改变)。插值是你正在寻找的。

您可以在动画开始时设置计时器,并在球重置位置时重置计时器。根据已知的持续时间,球将在屏幕和屏幕的宽度上移动,您可以在给定时间计算球的预期位置。