几种常见的游戏循环
固定的游戏速度
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时游戏状态就一定会准确,预测只不过使画面更平滑