精确控制FPS的程序框架

经常看到有人讨论如何在主循环中控制帧速的问题,很多人使用Sleep之类的函数,其实Sleep本身虽然能释放CPU,但无法做到精确控制FPS的值,这里介绍一种比较巧妙的框架,对FPS可以做到比较精确的控制,而且也不会占用CPU。
这个框架用到了两个比较关键的函数:
    timeSetEvent,调用这个函数后,操作系统创建了一个后台线程,这个线程由winmm.dll控制,按照指定的频率执行指定某函数或者将某个信号设置为“有信号”。
    MsgWaitForMultipleObjects,这个函数和WaitForMultipleObjects相比,除了等待多个信号外,同时还可以同时等待指定的窗口消息。

这个框架的原理就是首先创建一个Event作为渲染信号,并且用timeSetEvent函数按照帧速频率控制它变为“有信号”


// Create render signal event
HANDLE g_hTickEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
ResetEvent(g_hTickEvent);
 
// Create time event
MMRESULT g_hEventTimer = ::timeSetEvent(
    (INT)(1000.0f/MAX_FPS), 
    1, 
    (LPTIMECALLBACK)g_hTickEvent, 
    0, 
    TIME_PERIODIC|TIME_CALLBACK_EVENT_SET);

在主循环中,使用MsgWaitForMultipleObjects释放CPU,如果等待的结果是渲染信号,则进入渲染函数,如果是窗口消息,则进入消息处理函数


MSG msg;
ZeroMemory( &msg, sizeof(msg) );
 
while(msg.message!=WM_QUIT)
{
    if(WAIT_OBJECT_0 == MsgWaitForMultipleObjects(1, &g_hTickEvent, FALSE, 1000, QS_ALLINPUT))
    {
        Render();
    }
    else
    {
        while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
        { 
            if(msg.message==WM_QUIT) break;
        
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        };
    }
}



你可能感兴趣的:(框架,object,null,callback,Signal)