基于时间的循环和基于帧的循环

Time based loop and Frame based loop

本文关键字:循环 于帧 时间 于时间      更新时间:2023-10-16

试图理解在游戏循环中设置恒定速度的概念。我头疼。我读了deWiTTERS的页面,但我看不出为什么/如何……等我拿到了……它滑落。

while(true)
{
      player->update() ;
      player->draw() ;
}

这将运行得尽可能快,这取决于处理器有多快…我明白了。

要在所有计算机上以相同的速度运行,逻辑是我不明白的。如果我想以60fps的速度运行,那就意味着每16ms物体移动一帧,对吧?我不明白的是为什么update()draw()可能太慢了。

deWiTTERS示例(我使用60):

const int FRAMES_PER_SECOND = 60;
const int SKIP_TICKS = 1000 / FRAMES_PER_SECOND;
DWORD next_game_tick = GetTickCount();
// GetTickCount() returns the current number of milliseconds
// that have elapsed since the system was started
int sleep_time = 0;
bool game_is_running = true;
while( game_is_running ) {
    update_game();
    display_game();
    next_game_tick += SKIP_TICKS;
    sleep_time = next_game_tick - GetTickCount();
    if( sleep_time >= 0 ) {
        Sleep( sleep_time );
    }
    else {
        // Shit, we are running behind!
    }
}

我不明白为什么他在循环开始之前就得到了当前时间。当他增加SKIP_TICKS时,我理解他增加到下一个16ms间隔。但是我不太明白这部分:

sleep_time = nextgametick  - GetTickCount() 

Sleep(sleep_time)是什么意思?处理器离开循环去做别的事情?它是如何实现60fps的?

如果update_game()和display_game()函数以60FPs的速度在少于一个帧间隔的时间内完成,循环将通过休眠(阻塞线程)多余的帧时间来确保下一帧不被处理,直到该间隔结束。似乎它试图确保帧率上限为60FPS,而不是更高。

处理器并没有"离开循环",而是你的循环正在运行的线程被阻塞(阻止继续执行你的代码),直到睡眠时间结束。然后继续到下一帧。在多线程游戏引擎中,像这样休眠主游戏循环的线程可以让CPU有时间执行其他线程中的代码,这可能是管理物理,AI,音频混合等,这取决于设置。

为什么在循环开始之前调用GetTickCount() ?我们从代码中的注释中知道GetTickCount()返回系统启动后的毫秒数。

那么,假设当你启动程序时,系统已经运行了30秒(30,000毫秒),假设在进入循环之前没有调用GetTickCount(),但是将next_game_tick初始化为0。

我们执行更新和绘制调用(作为一个例子,它们需要6ms),然后:

next_game_tick += SKIP_TICKS;  // next_game_tick is now 16
sleep_time = next_game_tick - GetTickCount();   
// GetTickCount() returns 30000!
// So sleep_time is now 16 - 30000 = -29984 !!!

因为我们(理智地)只在sleep_time为正值时睡觉,游戏循环将尽可能快地运行(可能快于60FPS),这不是你想要的。