1

所以我做了一个游戏循环,使用SDL_Delay函数来限制frames per second,它看起来像这样:

//While the user hasn't qui

while( stateID != STATE_EXIT )
{
    //Start the frame timer
    fps.start();

    //Do state event handling
    currentState->handle_events();

    //Do state logic
    currentState->logic();

    //Change state if needed
    change_state();

    //Do state rendering
    currentState->render();

    //Update the screen
    if( SDL_Flip( screen ) == -1 )
    {
        return 1;    
    }

    //Cap the frame rate
    if( fps.get_ticks() < 1000 / FRAMES_PER_SECOND )
    {
        SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps.get_ticks() );
    }
}

所以当我运行我的游戏时60 frames per second(我假设这是“眼帽”),我仍然可以看到滞后类型的运动,这意味着我看到帧独立出现,导致运动不流畅。
这是因为显然SDL_Delay功能不太准确,导致+,- 15 milliseconds帧之间的差异大于我想要的。
(所有这些只是我的假设)

所以我只是在寻找一个好的和准确的计时器来帮助我解决这个问题。

有什么建议么?

4

5 回答 5

4

我认为How to make thread sleep less than a ms on Windows中有一个类似的问题

但作为一名游戏程序员,我并不依赖睡眠函数来管理帧率(它们采用的参数只是最小值)。我只是尽可能快地在屏幕上画东西。我的游戏循环中有一堆函数调用,然后我会跟踪调用它们的频率。例如,我经常检查输入(1000 次/秒)以使游戏响应更快,但我检查网络收件箱的速度不会超过 100 次/秒。

例如:

#define NW_CHECK_INTERVAL    10
#define INPUT_CHECK_INTERVAL  1
uint32_t last_nw_check = 0, last_input_check = 0;

while (game_running) {
    uint32_t now = SDL_GetTicks();

    if (now - last_nw_check > NW_CHECK_INTERVAL) {
        check_network();
        last_nw_check = now;
    }

    if (now - last_input_check > INPUT_CHECK_INTERVAL) {
        check_input();
        last_input_check = now;
    }

    check_video();

    // and so on...
}
于 2012-09-26T14:35:27.947 回答
2

为此使用 QueryPerformanceCounter / Frequency。

LARGE_INTEGER start, end, tps; //tps = ticks per second
QueryPerformanceFrequency( &tps );
QueryPerformanceCounter( &start );
QueryPerformanceCounter( &end );
int usPassed = (end.QuadPart - start.QuadPart) * 1000000 / tps.QuadPart;
于 2012-09-26T14:33:31.207 回答
2

这是我为定时 MIDI 序列创建的一个小等待函数,使用QueryPerformanceCounter

void wait(int waitTime) {
    LARGE_INTEGER time1, time2, freq;

    if(waitTime == 0)
        return;

    QueryPerformanceCounter(&time1);
    QueryPerformanceFrequency(&freq);

    do {
        QueryPerformanceCounter(&time2);
    } while((time2.QuadPart - time1.QuadPart) * 1000000ll / freq.QuadPart < waitTime);
}

要将滴答声转换为微秒,请计算滴答声的差异,乘以 1,000,000(微秒/秒)并除以每秒滴答声的频率。

请注意,有些事情可能会导致这一点,例如高分辨率计数器的精度不太可能降至一微秒。例如,如果您要等待 10 微秒,并且精度/频率是每 6 微秒一个滴答声,那么您的 10 微秒等待实际上将不少于 12 微秒。同样,此频率取决于系统,并且会因系统而异。

此外,Windows 不是实时操作系统。进程可能随时被抢占,由 Windows 决定何时重新安排进程。应用程序可能会在此函数的中间被抢占,并且在预期的等待时间过去很久之后才会再次重新启动。你真的无能为力,但如果它发生,你可能永远不会注意到它。

于 2012-09-26T14:31:41.463 回答
0

SDL_延迟:

This function waits a specified number of milliseconds before returning. It waits at least the specified time, but possible longer due to OS scheduling. The delay granularity is at least 10 ms. Some platforms have shorter clock ticks but this is the most common.

使用此功能观察到的实际延迟取决于操作系统设置。我建议查看 Mutimemedia Timer API,特别是timeBeginPeriod 函数,以根据您的要求调整中断频率。

获取和设置定时器分辨率显示了如何将中断周期更改为大约 1ms 的示例。这样你就不再有 15ms 的打嗝了。BTW:醒目的周期约为 40 毫秒。

获得固定周期计时也可以通过等待定时器对象来解决。但是无论如何,必须使用多媒体计时器才能获得不错的分辨率。

此处讨论了使用其他工具来提高计时功能。

于 2012-09-26T15:44:51.637 回答
0

60 fame per second is just the frequency of power in US (50 in Europe, Africa and Asia are somehow mixed) and is the frequency of video refreshing for hardware comfortable reasons (It can be an integer multiple on more sophisticated monitors). It was a mandatory constrains for CRT dispaly, and it is still a comfortable reference for LCD (that's how frequently the frame buffer is uploaded to the display)

The eye-cap is no more than 20-25 fps - not to be confused with retina persistency, that's about one-half - and that's why TV interlace two squares upon every refresh.

independently on the timing accuracy, whatever hardware device cannot be updated during its buffer-scan (otherwise the image changes while it is shown, resulting in half-drawn broken frames), hence, if you go faster than one half of the device refresh you are queued behind it and forced to wait for it.

60 fps in a game loop serves only to help CPU manufacturers to sell new faster CPUs. Slow down under 25 and everything will look more fluid.

于 2012-09-26T15:05:49.000 回答