你有一个正确的非常基本的架构,因为一切都需要在循环中更新,但你需要让你的循环更加智能化游戏(或其他需要OpenGL动画的应用程序).
但是,我需要能够在按下某个键时暂停.
执行此操作的基本方法是使用布尔值paused并将游戏包装成循环.
while(!finished) {
while(!paused) {
update();
render();
}
}
Run Code Online (Sandbox Code Playgroud)
通常情况下,当你的游戏暂停时,你仍然想做一些事情,比如查看你的库存,制作东西等等,许多游戏在游戏暂停时仍然运行他们的主循环,他们只是不让任何时候玩家知道已经过去了.例如,听起来你的动画帧只是有一些可见的游戏帧.这是一个坏主意,因为如果动画速度在另一台计算机上增加或减少,那么这些计算机上的动画速度将会出错.您可以在此处考虑我的答案,以及链接的示例,以了解如何通过以毫秒持续时间指定动画帧并在更新循环中传递帧时间来实现与帧速率无关的动画.例如,您的主游戏会更改为如下所示:
float previousTime = 0.0f;
float thisTime = 0.0f;
float framePeriod = 0.0f;
while(!finished) {
thisTime = getTimeInMilliseconds();
framePeriod = previousTime - thisTime;
update(framePeriod);
render();
previousTime = thisTime;
}
Run Code Online (Sandbox Code Playgroud)
现在,游戏中更新的所有内容都将知道自上一帧以来已经过了多少时间.这有助于您的所有物理计算,因为我们所有的物理公式都是根据时间+起始因子+衰减因子(例如,SUVAT方程).相同的信息可以用于您的动画,使它们与帧速率无关,正如我在此处描述的一些示例链接所描述的那样.
要回答问题的下一部分:
it eats all of my cycles when the loop is going on.
Run Code Online (Sandbox Code Playgroud)
这是因为你正在使用100%的CPU而且永远不会睡觉.如果我们认为我们想要目标设备上的30fps(我们知道这是可能的),那么我们知道一帧的周期是1/30秒.我们刚刚计算了更新和渲染游戏所需的时间,因此我们可以在任何空闲时间内休息:
float previousTime = 0.0f;
float thisTime = 0.0f;
float framePeriod = 0.0f;
float availablePeriod = 1 / 30.0f;
while (!finished) {
thisTime = getTimeInMilliseconds();
framePeriod = previousTime - thisTime;
update(framePeriod);
render();
previousTime = thisTime;
if (framePeriod < availablePeriod)
sleep(availablePeriod - framePeriod);
}
Run Code Online (Sandbox Code Playgroud)
这种技术称为帧率管理,因为您手动控制渲染和更新的速率.