寻找一个非常准确的增量时间计数器。想要在 blitting 游戏中限制帧数
looking for a very accurate delta-time counter. Want to limit frames in blitting game
我想做的是:
start a timer;
calculate and render stuff;
wait until time==enough;
首先;我听说来自 windows 的 GetTickCount 函数的准确性很低。这是真的吗?
其次;如果不准确。我应该改用什么?
第三;在基于 blitting 的游戏中还有其他方法可以限制帧数吗?
假设这是 windows,请注意 Visual Studio 2012 和 2013 仅使用 std::chrono::high_resolution_clock 的标准代码(默认 64hz,BeginTimePeriod()) 可选 1000hz),所以最好使用性能计数器,它在 Vista 及更高版本上以大约 3mhz 的频率运行(或在 XP 上以 cpu 时钟频率运行)。固定频率 运行 和 Windows XP 兼容的线程示例,其中 Sleep(1) 最多可能需要 2 毫秒。 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 */
我想做的是:
start a timer;
calculate and render stuff;
wait until time==enough;
首先;我听说来自 windows 的 GetTickCount 函数的准确性很低。这是真的吗?
其次;如果不准确。我应该改用什么?
第三;在基于 blitting 的游戏中还有其他方法可以限制帧数吗?
假设这是 windows,请注意 Visual Studio 2012 和 2013 仅使用 std::chrono::high_resolution_clock 的标准代码(默认 64hz,BeginTimePeriod()) 可选 1000hz),所以最好使用性能计数器,它在 Vista 及更高版本上以大约 3mhz 的频率运行(或在 XP 上以 cpu 时钟频率运行)。固定频率 运行 和 Windows XP 兼容的线程示例,其中 Sleep(1) 最多可能需要 2 毫秒。 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 */