我在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;
}
Run Code Online (Sandbox Code Playgroud)
当然,我发现由于某些系统上睡眠功能的不精确性,帧速率与预期完全不同.睡眠功能的精度只有大约15毫秒,所以你不能等待.奇怪的是,有些系统使用此代码可以实现完美的帧速率,并且可以完美地实现一系列帧速率.但其他系统则没有.我可以删除睡眠功能,然后其他系统将实现帧速率,但随后它们占用了CPU.
我读过有关睡眠功能的其他文章:
编码器是做什么的?我不是要求保证帧速率(换句话说,保证睡眠时间),只是一般行为.我希望能够睡眠(例如)7毫秒来为操作系统提供一些CPU,并且通常在7毫秒或更短的时间内返回控制(只要它恢复一些CPU时间),如果需要更有时候,那没关系.所以我的问题如下:
您可以使用timeBeginPeriod来提高计时器/睡眠精度.请注意,这会对系统产生全局影响,并可能会增加功耗.
你可以timeBeginPeriod(1)在程序的开头打电话.在您观察到更高计时器精度的系统上,另一个正在运行的程序可能会这样做.
我不打算计算睡眠时间,只是sleep(1)在循环中使用.
但即使只有16ms的精度,您也可以编写代码,以便随着时间的推移平均误差.这就是我要做的.编写代码并不难,并且应该很少适应当前的代码.
或者您可以切换到使移动与经过时间成比例的代码.但即使在这种情况下,您也应该实现帧速率限制器,这样您就不会获得无用的高帧率和不必要的功耗.
编辑:根据这个答案中的想法和评论,制定了接受的答案.
根据对 CodeInChaos 答案的想法和评论,这是我得出的最终代码。我最初编辑了该答案,但 CodeInChaos 建议这是一个单独的答案。
public virtual void LimitFrameRate(int fps)
{
long freq;
long frame;
freq = System.Diagnostics.Stopwatch.Frequency;
frame = System.Diagnostics.Stopwatch.GetTimestamp();
while ((frame - fpsStartTime) * fps < freq * fpsFrameCount)
{
int sleepTime = (int)((fpsStartTime * fps + freq * fpsFrameCount - frame * fps) * 1000 / (freq * fps));
if (sleepTime > 0) System.Threading.Thread.Sleep(sleepTime);
frame = System.Diagnostics.Stopwatch.GetTimestamp();
}
if (++fpsFrameCount > fps)
{
fpsFrameCount = 0;
fpsStartTime = frame;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3643 次 |
| 最近记录: |