我在这里贴一些东西来恢复这个问题......主要是出于便携性。我通过研究 OLC Pixel Game Engine 发现,它与 do{}while 循环和 std::chrono 一起使用来检查帧的时间以计算 fElapsed Time。下面是我写的一些代码来做同样的事情。它还添加了一个化妆部分,以控制高于某个值的拍摄帧率,在本例中为 60 FPS。
c++代码
int maxSpeedMicros = 16700;
float fTimingBelt; //used to calculate fElapsedTime for internal calls.
std::chrono::steady_clock::time_point timingBelt[2];
bool engineRunning = false; //always have it true, until the engine stops.
bool isPaused = false;
do {
timingBelt[1] = std::chrono::steady_clock::now();
fTimingBelt = std::chrono::duration_cast<std::chrono::microseconds>(timingBelt[1] - timingBelt[0]).count() * 0.000001;
if (isPaused) {
do {
std::this_thread::sleep_for (std::chrono::milliseconds(100));
timingBelt[1] = std::chrono::steady_clock::now();
} while (isPaused);
}
timingBelt[0] = std::chrono::steady_clock::now();
// do updating stuff here.
timingBelt[1] = std::chrono::steady_clock::now();
int frameMakeup = std::chrono::duration_cast<std::chrono::microseconds>(timingBelt[1] - timingBelt[0]).count();
if (frameMakeup < maxSpeedMicros) {
int micros = maxSpeedMicros - frameMakeup;
std::this_thread::sleep_for (std::chrono::microseconds(micros));
}
} while (engineRunning);
但是,该代码与 Cocoa 的事件驱动模型直接冲突。
可可中的自定义主应用程序循环
因此,作为一个创可贴,我注释掉了整个循环,并创建了一个运行循环一次迭代的新方法。然后我在我的 AppDelegate 中实现了这个:
目标 C 代码
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
engine->resetTimer();
[NSTimer scheduledTimerWithTimeInterval:0.016666666667 target:self selector:@selector(engineLoop) userInfo:nil repeats:YES];
}
-(void) engineLoop { //Let's handle this by the engine object. That's too complicated!
engine->updateState();
[glView update]; //Since the engine is doing all of its drawing to a GLView
[[glView openGLContext] flushBuffer];
}
仍然要做的是调整计时器对象的容差。Apple Developer 文档指出,如果计时器对象错过了下一个窗口,它将等待下一个帧时间。但是,容差允许它改变未来事件的时间,以实现更平滑的帧速率转换和更好地利用 CPU 能力。
所以在这一点上,我愿意接受其他人为制作更便携的代码所做的建议和意见。我计划在名为“eventDriven”的引擎的构造函数中使用一个布尔参数,如果为 false,将启动自己的游戏循环线程,然后拆分顶部事件循环以调用处理所有代码的“engineUpdate”方法可以是事件驱动的。然后,在构建事件驱动系统的情况下,代理可以只使用 engineUpdate = TRUE 构建引擎,并让他们的事件驱动游戏更新。
有人做过吗?如果是这样,它如何执行跨平台?