0

左から右に永久に移動するボール (CCSprite) があります。画面に触れたらボールを​​止めたい。問題は、スプライトの継続時間が速すぎると、停止するまでに 1 ミリ秒の遅延時間が発生するため、少し「異なる」位置に触れても停止位置がほぼ同じ値になることです。

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
}

そのため、中央に触れると、停止するまでに 1 ミリ秒の遅延があります。繰り返しますが、私が触れると、ミリ秒遅れて(ボールがまだ動いている)、停止します。たとえば、位置 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. 240,240,240,239
  2. 219
  3. 260,260

位置 x 235、230、245、250、またはそのパターンを除外する値をクリックしたことがあると確信しています。しかし、私が言ったように、ボールがまだ動いている間に遅延時間があり、その後停止します。

たとえば、速度を 2.8f (またはそれ以上) に変更すると、ボールはすぐに停止し、ボールの xy は、タッチした最後の位置の正確な位置になります。CCMoveTo 速度の持続時間が速すぎるためだと思います。

スケジュールセレクター方式で試してみました。ただし、スケジュールの時間は、CCMoveTo のように速すぎることはできません。そのため、スケジュールを使用した移動は、持続時間が長すぎる 1 ピクセルから 1 ピクセルになります。

これに対する解決策はありますか?または、これを実装する方法はありますか?どうもありがとう!

4

2 に答える 2

0

これは実際には予想される動作であり、スプライトを高速でアニメートしている場合、この効果は特に顕著です。なんで?

アニメーションは基本的に、時間の経過に伴う特定の変数の変化であり、この変化は常に一連の離散時間ステップで実行されます。目標距離が240ピクセルで、希望する持続時間が0.8秒であるとします。その場合、速度は240 * 0.8=300ピクセル/秒です。60の完全に一定のfpsを想定すると、実行されるタイムステップごとに1/60 * 300=5ピクセルの離散的な位置変化が予想されます。

ここで、時刻tにタッチイベントを受信したとします。多くの場合、このtはタイムステップの開始と正確に一致しません。いくつかの時間ステップのペアの間にある可能性が高くなります。stopAllActionsを呼び出すと、現在のタイムステップが完了した後にアニメーションのスケジュールが停止するはずです。いわば、2つのタイムステップの間に停止するだけではありません。これが、常に一定の間隔で距離を報告している理由です。

あなたは本当にピクセル精度である必要がありますか?その場合、正確な位置を見つけるために、2つの時間枠で位置の間を補間する必要があります。

編集:

この場合でも、ピクセル精度のソリューションが必要かどうかは非常に疑わしいです。実際、知覚されるミリ秒の遅延は、タッチイベントが開始するときではなく、終了するときに検出されたことが原因である可能性があります。代わりに、ccTouchBeganでそのイベントをキャプチャしてみてください。

于 2012-12-03T08:09:33.233 に答える
0

2 番目の 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 に答える