这在程序员中似乎是一个巨大的秘密,没有人愿意为此分享他们的代码。为什么?
我找不到可以在不使用垂直同步的情况下将 FPS 至少限制为 60 的有效 FPS 限制器。
当然,我希望以正确的方式去做。所以我还没有自己做,因为他们都说他们花了一年的时间来学习 fps 限制器的所有技巧......
编辑:这是我的 fps 限制器代码,它并不完美,但我能做到最好,但它仍然流泪:
timeBeginPeriod(1);
frame_start_time = TimerGetTime();
while(!done){
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
if(msg.message == WM_QUIT){
done = 1;
}else{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}else if(active){
draw_everything();
SwapBuffers(hDC);
// fps limiter:
one_frame_limit = 1000.0f/(float)framerate_limit; // 16.666 ms
while((time_left = one_frame_limit-(TimerGetTime()-frame_start_time)) > 0){
if(time_left >= 6.0f){
Sleep((int)(time_left/6.0f));
}else{
Sleep(0); // sleep less than 1ms
}
}
frame_start_time = TimerGetTime();
}
}
EDIT2:这是我的第二次尝试,按照建议使用等待计时器:
float one_frame_limit = 1000.0f/(float)framerate_limit;
float time_left = one_frame_limit-(TimerGetTime()-frame_start_time); // 4.7432ms
liDueTime.QuadPart = -(LONGLONG)(time_left*10000.0f);
if(SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0)){
WaitForSingleObject(hTimer, INFINITE);
}
while((time_left = one_frame_limit-(TimerGetTime()-frame_start_time)) > 0.003f){
Sleep(0);
}
frame_start_time = TimerGetTime();
我认为效果更好。但仍然在撕裂......请注意,我在那里添加了 while 循环,因为它比没有它更撕裂。
--
另一个问题:这个初始化安全吗?
HANDLE hTimer = NULL;
LARGE_INTEGER liDueTime;
liDueTime.QuadPart = -100000LL; // testing timer: wait for 10ms
hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
if(hTimer == NULL){
waitable_timer_supported = 0;
}else if(!SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0)){
waitable_timer_supported = 0;
}else if(WaitForSingleObject(hTimer, INFINITE) != WAIT_OBJECT_0){
waitable_timer_supported = 0;
}
即使支持等待计时器,我担心最后 2 次检查可能会失败......到目前为止它还没有失败。这是检查其支持的正确方法吗?