寻找一个非常准确的delta时间计数器。想在blitting游戏中限制帧数

时间:2015-03-20 14:43:52

标签: c++ windows game-engine

我想做的是:

start a timer;
calculate and render stuff;
wait until time==enough;

首先;我听说Windows的GetTickCount函数精度不高。这是真的吗?

其次;如果它不准确。我该怎么用呢?

第三;还有另一种方法可以限制基于blitting的游戏中的帧吗?

1 个答案:

答案 0 :(得分:1)

假设这是针对Windows的,请注意Visual Studio 2012和2013仅使用std :: chrono :: high_resolution_clock的标准自动收录器(64hz默认值,1000hz可选和BeginTimePeriod())),因此最好使用性能计数器在Vista及更高版本上运行大约3mhz(或XP上的cpu时钟速率)。以固定频率运行的线程示例,与Windows XP兼容,其中Sleep(1)最多可能需要2 ms。 dwLateStep是一个调试辅助工具,每当一个周期花费太长时间就会增加(如果可能,它会赶上)。延迟是基于计数器的原始读数(使用uWait和uRem),所以在很长一段时间内没有漂移。

typedef unsigned long long UI64;        /* unsigned 64 bit int */
#define FREQ    400                     /* frequency */
DWORD    dwLateStep;                    /* late step count */
LARGE_INTEGER liPerfFreq;               /* 64 bit frequency */
LARGE_INTEGER liPerfTemp;               /* used for query */
UI64 uFreq = FREQ;                      /* process frequency */
UI64 uOrig;                             /* original tick */
UI64 uWait;                             /* tick rate / freq */
UI64 uRem = 0;                          /* tick rate % freq */
UI64 uPrev;                             /* previous tick based on original tick */
UI64 uDelta;                            /* current tick - previous */
UI64 u2ms;                              /* 2ms of ticks */
UI64 i;

    /* ... */ /* wait for some event to start thread */
    QueryPerformanceFrequency(&liPerfFreq);
    u2ms = ((UI64)(liPerfFreq.QuadPart)+499) / ((UI64)500);

    timeBeginPeriod(1);                 /* set period to 1ms */
    Sleep(128);                         /* wait for it to stabilize */

    QueryPerformanceCounter((PLARGE_INTEGER)&liPerfTemp);
    uOrig = uPrev = liPerfTemp.QuadPart;

    for(i = 0; i < (uFreq*30); i++){
        /* update uWait and uRem based on uRem */
        uWait = ((UI64)(liPerfFreq.QuadPart) + uRem) / uFreq;
        uRem  = ((UI64)(liPerfFreq.QuadPart) + uRem) % uFreq;
        /* wait for uWait ticks */
        while(1){
            QueryPerformanceCounter((PLARGE_INTEGER)&liPerfTemp);
            uDelta = (UI64)(liPerfTemp.QuadPart - uPrev);
            if(uDelta >= uWait)
                break;
            if((uWait - uDelta) > u2ms)
                Sleep(1);
        }
        if(uDelta >= (uWait*2))
            dwLateStep += 1;
        uPrev += uWait;
        /* fixed frequency code goes here */
        /*  along with some type of break when done */
    }

    timeEndPeriod(1);                   /* restore period */