c++

游戏循环

Posted by ysd on June 13, 2017

几种常见的游戏循环

固定的游戏速度


while (true) {
  double start = getCurrentTime();
  processInput();
  update();
  render();

  sleep(start + MS_PER_FRAME - getCurrentTime());
}

如果游戏实际推进所需的时间小于设定的时间,则等待;</br> 否则,游戏将跟不上实际时间,体验就是游戏变慢了

可变的游戏速度


double lastTime = getCurrentTime();
while (true) {
  double current = getCurrentTime();
  double elapsed = current - lastTime;
  processInput();
  update(elapsed);
  render();
  lastTime = current;
}

计算两帧之间经历的时间间隔elapsed,这个间隔总和真会时间一致。所以如果某一帧消耗的真实时间多,游戏推进的虚拟时间也多。
缺点是,浮点型总是不精确的,更新越快,误差就会积累的越多,像物理这种对精度要求较高的系统将出现问题

最大fps,固定游戏速度

在第一个实现中,垃圾显卡不仅渲染慢,还将会拖慢游戏速度。实际上,在渲染较慢的情况下,可以以固定的速度更新游戏,保证游戏逻辑的正确和稳定,只不过体验上会掉帧。


double previous = getCurrentTime();
double lag = 0.0;
while (true) {
  double current = getCurrentTime();
  double elapsed = current - previous;
  previous = current;
  lag += elapsed;

  processInput();

  while (lag >= MS_PER_UPDATE) {
    update();
    lag -= MS_PER_UPDATE;
  }

  render();
}

其中,lag表示游戏时间比真实时间落后多少(第一帧没Update,先渲染,真实时间推进了,到了第二帧,游戏时间就要推进lag。假设此时lag为100ms,游戏更新时间30ms,则更新3次,lag还剩10ms。渲染的比较慢,但游戏还是会以固定、正确的速度更新)。 如果游戏时间追上了真实时间,则继续下一帧。 MS_PER_UPDATE至少要大于Update消耗的真实时间(一般比渲染短得多),否则游戏就跟不上真实时间了。可以限制内循环的次数。

预测

有的时候,渲染的真实时刻出现在两次Update的虚拟时刻之间,这很常见,因为Update时间固定,渲染可能在任意时刻。例如渲染的很快,lag不足够一次Update,这时渲染的还是上一帧的内容。
update update | | | | render render
上面第一个update和render之间的就是lag
这时渲染函数可以差值预测两次Update中间的状态,


render(lag / MS_PER_UPDATE);

假如有一个物体正在移动,render知道他每帧移动速度和位置,就可以根据传入的参数预测他的中间位置。例如传入0.3,意味着我要预测上一帧后0.3帧的位置,如果物体一帧移动10,则在预测的这一帧会移动3。
预测可能不准确,但是在下一次Update时游戏状态就一定会准确,预测只不过使画面更平滑