我在一个2d游戏引擎上工作,它有一个名为limitframerate的函数来确保游戏不会运行得太快以至于用户无法玩游戏。在这个游戏引擎中,游戏的速度与帧速率挂钩。所以一般来说,人们希望将帧速率限制在60 fps左右。这个函数的代码相对简单:计算在下一帧开始工作之前剩余的时间量,将其转换为毫秒,睡眠数为毫秒(可能为0),重复直到它正是正确的时间,然后退出。代码如下:

public virtual void LimitFrameRate(int fps)
{
  long freq;
  long frame;
  freq = System.Diagnostics.Stopwatch.Frequency;
  frame = System.Diagnostics.Stopwatch.GetTimestamp();
  while ((frame - previousFrame) * fps < freq)
  {
     int sleepTime = (int)((previousFrame * fps + freq - frame * fps) * 1000 / (freq * fps));
     System.Threading.Thread.Sleep(sleepTime);
     frame = System.Diagnostics.Stopwatch.GetTimestamp();
  }
  previousFrame = frame;
}

当然,我已经发现,由于某些系统的睡眠功能的不精确性,帧速率与预期相差甚远。sleep函数的精度只有15毫秒左右,所以您不能等待时间少于15毫秒。奇怪的是,有些系统用这段代码可以达到完美的帧速率,并且可以达到一系列完美的帧速率。但其他系统没有,我可以去掉休眠功能,然后其他系统将达到帧速率,但然后他们占用CPU。
我读过其他关于睡眠功能的文章:
Sleep function in c in windows. Does a function with better precision exist?
Sleep Function Error In C
编码员该怎么做?我并不是要求保证帧速率(或者保证睡眠时间,换句话说),只是一种普通的行为。我希望能够睡眠(例如)7毫秒,以便为操作系统提供一些CPU,并让它通常在7毫秒或更短的时间内返回控制(只要它能返回一些CPU时间),如果有时需要更多时间,那就可以了。所以我的问题如下:
为什么睡眠在某些windows环境中可以完美而精确地工作,而在其他环境中则不行?(有没有办法在所有环境中获得相同的行为?)
如何在不占用C代码CPU的情况下获得一般精确的帧速率?

最佳答案

您可以使用timeBeginPeriod来提高计时器/睡眠精度。请注意,这会对系统产生全局影响,并可能会增加功耗。
您可以在程序开始时调用timeBeginPeriod(1)。在你观察到计时器精度更高的系统上,另一个正在运行的程序可能做到了这一点。
我不需要计算睡眠时间,只需循环使用sleep(1)
但即使只有16毫秒的精度,你也可以写你的代码,这样错误会随着时间的推移而平均化。那就是我要做的。不难编写代码,只需对当前代码进行少量修改即可。
或者可以切换到使移动与经过的时间成比例的代码。但即使在这种情况下,您也应该实现一个帧速率限制器,这样您就不会得到无用的高帧速率和不必要的功耗。
编辑:根据本答案中的观点和评论,制定了接受的答案。

07-24 17:50