Is there a better way to create this game loop? (C++/Windows)
-
05-07-2019 - |
Question
I'm working on a Windows game, and I have this:
bool game_cont;
LRESULT WINAPI WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_QUIT: case WM_CLOSE: case WM_DESTROY: game_cont = false; break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
int WINAPI WinMain(/*lots of parameters*/)
{
//tedious initialization
//game loop
while(game_cont)
{
//give message to WinProc
if(!GameRun()) game_cont = false;
}
return 0;
}
and I am wondering if there is a better way to do this (ignoring timers &c. for right now) than to have game_cont
be global. In short, I need to be able to exit the while in WinMain
from WinProc
, so that if the user presses the closes out of the game in a way other that the game's in game menu, the program wont keep running in memory. (As it did when I tested this without the game_cont..
statement in WinProc
.
Oh, and on a side note, GameRun
is basically a bool that returns false when the game ends, and true otherwise.
Solution
Yes, use PeekMessage, it's the standard in game development.
This is the best approach, I believe:
int Run()
{
MSG msg;
while(true)
{
if(::PeekMessage(&msg,0,0,0 PM_REMOVE))
{
if(msg.message == WM_QUIT ||
msg.message == WM_CLOSE ||
msg.message == WM_DESTROY)
break;
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
else
{
//Run game code
if(!GameRun())
break;
}
}
}
Also, look at this (specially the first answer)
OTHER TIPS
You could make game_cont
static
to your main file which has WinMain
/WinProc
, but I don't know of a significantly better structure.
No, don't do that.
WM_QUIT
is your flag. GetMessage
return value indicates when WM_QUIT
is encountered.
Your main window will never receive WM_QUIT
, as it isn't sent to a window. WM_CLOSE
will call DestroyWindow
by default, so you don't need any special handling for that. Handle WM_DESTROY
by calling PostQuitMessage
, which results in WM_QUIT
on your thread, the special return value from GetMessage
, and stops your message dispatch loop.