2

我需要List<Point>在我的 OpenGL 游戏中按每个像素的路径(轨道)像素移动我的精灵,所以我需要实现一种控制时间的方法。我读到了不同的方法:使用OnRenderUpdate(但我不能比 1/fps 更快)、使用不同的线程来控制时间或使用 a StopWatch(而不是 a 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 将是错误的。

相反,您可以timer.StartNew()在循环中使用。

关于动画时间:我认为秒表暂时还可以。使用 StopWatch 或单独的线程可以让您独立于渲染速度。尽管当您坚持使用 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 回答