Question
WIN32 game loop is slow, can't handle 60HZ or 30HZ. What to do?
I'm just trying to learn to program a few things, and a game loop is one of those.
This game loop only process Windows messages, but it can not even handle 30 fps.
This is true also if the message processing is done only once per loop, replacing WHILE with IF.
I use QueryPerformanceCounter() function to get number of 100ns ticks before work is done and after, subtracting them to get time used. Loop time is 100ns * 166666 * 2 = 0.0333332s.
The boolean 'timeExceeded' is set if the the wait time is positive, indicating that time used is more than the intended loop time.
What to do?
#include <Windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
// windows class information
static const wchar_t class_name[] = L"Test";
WNDCLASS wc{ };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = class_name;
if (!RegisterClassW(&wc))
return 0;
// Get correct windows size based on disered client area
RECT client_rect;
client_rect.left = 0;
client_rect.top = 0;
client_rect.right = 800;
client_rect.bottom = 600;
if (!AdjustWindowRect(&client_rect, WS_OVERLAPPEDWINDOW, FALSE))
return 0;
// create windows
HWND hwnd = CreateWindowEx(
WS_EX_OVERLAPPEDWINDOW, class_name, L"Test",
WS_CAPTION | WS_SYSMENU | WS_OVERLAPPED,
100, 100, -client_rect.left + client_rect.right, -client_rect.top + client_rect.bottom,
0, 0, hInstance, 0
);
if (hwnd == 0)
return 0;
// Show Window
ShowWindow(hwnd, SW_SHOWNORMAL);
// Timer & setup
LARGE_INTEGER frequency;
if (!QueryPerformanceFrequency(&frequency))
return 0;
if (frequency.QuadPart != 10000000LL)
return 0;
HANDLE hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
if (hTimer == 0)
return 0;
// timer data
LARGE_INTEGER start_time;
LARGE_INTEGER end_time;
LARGE_INTEGER rest_time;
LARGE_INTEGER loop_time;
loop_time.QuadPart = -166666LL*2; // loop time
bool timeExceeded = false; // does time exceeds loop time
// message loop data
MSG msg = { };
bool running = true;
while (running)
{
// measure time
if (!QueryPerformanceCounter(&start_time))
break;
// process messages
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
running = false;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// other work
// Get elapsed time and wait for 30hz - elapsed time
if (!QueryPerformanceCounter(&end_time))
break;
rest_time.QuadPart = loop_time.QuadPart + (end_time.QuadPart - start_time.QuadPart);
if (rest_time.QuadPart >= 0)
{
timeExceeded = true;
continue;
}
if (!SetWaitableTimer(hTimer, &rest_time, 0, 0, 0, 0))
break;
if (WaitForSingleObject(hTimer, INFINITE) != 0)
break;
}
// clean up
CloseHandle(hTimer);
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
4 195
4