2

List<Point>OpenGL ゲームでパス (トラック) ピクセルごとにスプライトを移動する必要があるため、タイミングを制御する方法を実装する必要があります。私はさまざまな方法について読みました: を使用するOnRenderUpdate(ただし、1/fps よりも速くすることはできません)、別のスレッドを使用して時間を制御する、またはStopWatch(の代わりにTimer) を使用する。私は最後のものを試しています:

private void Sprite_Move(Sprite sprite, List<Point> path) {
  track.Clear();
  for (int i = 1; i < path.Count; i++) {
    //memorize all track pixel, so I can update pixel per pixel my sprite position
    Bresenham2(path[i-1], path[i]);
  }
  //moving flag
  sprite.moving = true;
  //start my StopWatch
  timer.Start();
  Loop(timer, sprite);

}

private void Loop(Stopwatch timer, Sprite sprite) {
  int i = 1;
  while (timer.IsRunning) {
    //moving each 0.03s?
    if ((sprite.moving) & (timer.Elapsed.Milliseconds >= 30)) {
      if (i < track.Count) {
        //change sprite position to the i-th track pixel
        Sprite_Position(skinny, track[i]);
        i++;
        timer = StopWatch.StartNew();
        Console.WriteLine("Tick");
      }
      //if I'm on the end of the track I can exit
      else timer.Stop();
    }
  }
}

スプライトが動いているのが見えません。最後の反復まですべてがブロックされ、トラックの最後のピクセルにスプライトが表示されます...テレポート!

4

2 に答える 2

2

特定の間隔で正確に時を刻むタイマーに頼る代わりに、代わりにある種のグローバル時間値を使用できます。これは、フレームワークまたはストップウォッチに依存し、その経過時間を調べます。

たとえば、アニメーションに N ステップがあり、アニメーション全体の実行に T 秒かかる場合、次の方法でアニメーションの正しいステップを見つけることができます。

int frame = (int)((CurrentTimeInSeconds / (float)T) * N)

(オーバーフローに注意してください。つまり、frame>= N の場合は、もう何もしません。)

于 2012-07-31T13:23:09.750 に答える
0

さて、StopWatch.Reset()タイマーも停止します。ここを参照してください。したがって、最初の反復の後、timer.IsRunning は false になります。

timer.StartNew()代わりに、ループで使用できます。

アニメーションのタイミングについて:ストップウォッチは今のところ大丈夫だと思います。ストップウォッチまたは別のスレッドを使用すると、レンダリング速度から独立できます。ただし、アニメーションに 2D スプライトを使用している間は問題になりません。

私の古いプロジェクトから:

    m_LastPoll.Stop();
    System.Diagnostics.Debug.Print("{0}:\t{1}", this.VendorID, m_LastPoll.ElapsedMilliseconds);
    m_LastPoll.Reset();
    m_LastPoll.Start();

それは間違いなくうまくいきました。

于 2012-07-31T13:05:52.683 に答える