0

I have a ball (CCSprite) that move from left to right forever. When I touch the screen, I want the ball stop. The problem is if the duration of the sprite is too fast, it has a delay time a millisecond before it stop, so the stop position is almost same value even when I touch in a bit 'different' position.

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]
        ]];

Then when I touch the screen I want to stop the sprite, and log the ball position:

-(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
}

So when I touch at the center, it has a delay a millisecond time before it stopped. Once again, I mean when I touch, it delay millisecond time (the ball still moving) then it stop. For example, when I click at position x 240, it stopped at x 240,1122, when I click at position x 230, it stopped at 239,222. Not immediately stop after I touch.

Here is the sample log of the position I touch.

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

See? The x position when stop is always 'can be divided by 20'.

  1. 240,240,240,239
  2. 219
  3. 260,260

I'm quite sure I have ever click at position x 235,230 or 245 or 250 or anything value exclude that pattern. But like I said, there is a delay time the ball still moving, then it stop.

If I change the speed become 2.8f (or higher) for example, the ball will stop immediately, and the x y of the ball is exact position in the last position when I touch. I think it is because the duration of CCMoveTo speed is too fast.

I have tried with schedule selector method. But the time of the schedule cannot be too fast as the CCMoveTo does. So the movement using schedule will be one pixel to one pixel with duration too long time.

Is there any solution for this? Or there is such a way to implement this? Many thanks!

4

2 回答 2

0

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

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

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

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

编辑:

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

于 2012-12-03T08:09:33.233 回答
0

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

[self.ball runAction:[CCRepeatForever actionWithAction:
    [CCSequence actions:
        [CCMoveTo actionWithDuration:speed position:destinationPoint],
        [CCCallBlock actionWithBlock:^
        {
            self.ball.position = ccp(0, 156);
        }],
     nil]
    ]];

编辑:道歉 - 我不明白这个问题(但仍然建议改变)。插值是您正在寻找的。

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

于 2012-12-04T18:58:50.433 回答