Win32 Game Loop For Fixed Frame Rate

Started by
15 comments, last by MGB 16 years, 6 months ago
Doubtful, I don't see anything wrong in my quick glance. Don't forget to use timeEndPeriod(2) (or whatever the Begin's value was) to reset it.

Post your window processing code, might be a bug in there.

"Those who would give up essential liberty to purchase a little temporary safety deserve neither liberty nor safety." --Benjamin Franklin

Advertisement
When you get the WM_QUIT message you should not draw any more. Everything has shut down by that point. Actually, you probably should stop drawing after DestroyWindow is called (in the WM_CLOSE handler).
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
Here's my message handler:

LRESULT CALLBACK Game::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){	switch (message)	{		case WM_DESTROY:			PostQuitMessage(WM_QUIT);			break;		case WM_CLOSE:		case WM_QUIT:			Exit();			return 0;		case WM_KEYDOWN:		case WM_KEYUP:			setKeyboardKeyState((int)wParam, (message == WM_KEYDOWN));			return 0;		default:			return DefWindowProc(hWnd, message, wParam, lParam);	}	return 0;}


and my current game loop:

done = false;	MSG msg;	timeBeginPeriod(2);	DWORD target = (DWORD)(1000 / targetFrameRate);	while (!done)	{		DWORD startingPoint = timeGetTime();		while (PeekMessage(&msg, windowHandle, 0, 0, PM_REMOVE))		{			TranslateMessage(&msg);			DispatchMessage(&msg);		}		if (done)			break;		DWORD sleepLength = target - (timeGetTime() - startingPoint);		Sleep((sleepLength > 0) ? sleepLength : 0);		Update(1.0f / (float)targetFrameRate);		Draw();		SwapBuffers(deviceContext);	}
Another one fixed frame rate example (that I'm use in my programs):

int fix_fps = 30;float fFPS;int sleep = 0;static LARGE_INTEGER	base;static LARGE_INTEGER	freq;QueryPerformanceFrequency((LARGE_INTEGER*)&freq);QueryPerformanceCounter((LARGE_INTEGER*)&base);	while (!done)	{     		if (PeekMessage(&msg, windowHandle, 0, 0, PM_REMOVE))		{			if (msg.message == WM_QUIT || 				msg.message == WM_DESTROY || 				msg.message == WM_CLOSE)			{				Exit();				break;			}			TranslateMessage(&msg);			DispatchMessage(&msg);		}  static LARGE_INTEGER cur;		QueryPerformanceCounter(&cur);	// calculate fps		if(cur.QuadPart>=base.QuadPart)	{				fFPS = (float)((double)freq.QuadPart/(double)(cur.QuadPart-base.QuadPart));		}	else	{				fFPS = (float)((double)freq.QuadPart/(double)(base.QuadPart-cur.QuadPart));	}if(fix_fps > 0.0f)		{			if((int)fFPS < fix_fps ) 				sleep--;			else if((int)fFPS > fix_fps ) 				sleep++;			// sleep cant be negative			if(sleep < 0) sleep = 0;			// sleep			Sleep(sleep);		}		Draw();		SwapBuffers(deviceContext);			}
You treat WM_QUIT and WM_CLOSE as the same, they are not:
WM_CLOSE

Quit doesn't return at all.

As per PostQuitMessage() I just use 0. WM_QUIT isn't what you're ment to use ;-)

Hopefully that fixes it.

"Those who would give up essential liberty to purchase a little temporary safety deserve neither liberty nor safety." --Benjamin Franklin

Also remove the HWND from the PeekMessage call. You won't get any thread messages by putting that handle in (WM_QUIT for example).

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

Forgive me the slight necro, but here are some good notes on using Sleep()

This topic is closed to new replies.

Advertisement