Skip to main content
GameDev.net gamedev.net
🔒 Locked

Game Loop Question

Started by EbonySeraph Dec 3, 2001 at 10:56 PM 22 replies 600+ views
Original Post
EbonySeraph
EbonySeraph
I have a question. I was looking though how a few people/authors create a game loop and I look at it an I thought that one is actually slower than another. The first: while(true) //infinite loop { if(PeekMessage(....) ) { //Handle windows messages } else { //Do game suff } } //Do over The second: while(true) { if( PeekMessage(....)) { //Handle messges } //Do game stuff } As you can see there is barely a difference, but the second one seems to me as if it woud run faster. I know the difference would be minimal(proably neglible) but I think there would be one. Also, in the first version of the game loop, if somehow your program kept handling windows messages it would forget about doing the game code until the next iteration of the loop. The second version does the game loop after a windows message without having to go through the loop again. I personally like the second one better. But I want other opinions. "Ogun''s Laughter Is No Joke!!!" - Ogun Kills On The Right, A Nigerian Poem.
"Ogun's Laughter Is No Joke!!!" - Ogun Kills On The Right, A Nigerian Poem.
Fruny
Fruny
You may have several messages waiting to be processed.
If your game loop takes time to execute, the messages (windows commands, input, mouse ...) will be processed rather slowly.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
EbonySeraph
EbonySeraph
Shouldn''t those messages be ignored by your game, at east asfar s the mouse and input. I thought that should be handled with DirectInput. Also in Tricks of the Windows...(you know the rest), Andre sai the less there is in the message handler the better. Actually more like, the less you let Windows do for you the better.

"Ogun''s Laughter Is No Joke!!!" - Ogun Kills On The Right, A Nigerian Poem.
"Ogun's Laughter Is No Joke!!!" - Ogun Kills On The Right, A Nigerian Poem.
Truth
Truth
What you''re talking about there is the main Windows event loop, not the game loop. And I would use only the if statement to check for any windows messages. No need for the else.
==================================MSN Messenger : [sdrew2000@hotmail.com] ICQ: [6978384] E-mail: [drew@sdsnet.net] Web: [http://www.sdsnet.net] [http://etherealtruth.sdsnet.net]==================================
Beer Hunter
Beer Hunter
This is more or less how I do it:

void ProcessMessages() {
    MSG msg;
    while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
        if(msg.message == WM_QUIT) {
            EndGame();
            exit(0);
        }
        DispatchMessage(&msg);
    }
}

Instead of making my game run from inside the message loop, I make the message loop run from inside the game. I find it less restrictive. You do need to be careful about deleting all your pointers, though.
Kaijin
Kaijin
I''d recommend having your game loop run in a seperate thread to the Windows event loop. It makes things a lot easier.

- Kaijin
granat
granat
Easier ? I don''t see why...
-------------Ban KalvinB !
LordKronos
LordKronos
you should definitely empty your message queue before processing your next game loop. The message queue will never get so full as to hog all the time from your game code, so this isnt a concern. However, occasionally a bunch of messages will show up in the queue at once. If you only pull out one message per frame, it could take a little while to clear the queue out. The problem here is that certain messages can be problematic if not handled right away. For instance, I believe if you dont handle WM_PAINT messages within a reasonable time frame, windows will forcibly repaint your window. This will make your game appear to "flicker" occasionally on some systems.
Ron FrazierKronos Softwarewww.kronos-software.comMiko & Molly - Taking Puzzle Games to A Whole New Dimension
Kaijin
Kaijin
quote:
Original post by granat
Easier ? I don't see why...


It's easier because it allows you to program in a linear fasion like you would with DOS or a computer console game. It eliminates the need for a state machine to track the current state of the game because your game's main method only gets called once rather than within a (message) loop.

i.e.

    
void GameMain() {
Splash();
PlayTheGame();
Splash();
}


rather than:


void UpdateWorld() {
static int state=0;

switch(state) {
case 0: // display a splash screen and return

if(FINISHED(Splash()))
state=1;
break;
case 1:
if(FINISHED(PlayTheGame())
state=2;
break;
case 2:
if(FINISHED(Splash()))
TerminateApp();
break;
}
}


Where UpdateWorld() is being called in each iteration of the message loop.

Check out this article if you want to know more.

- Kaijin

Edited by - Kaijin on December 5, 2001 4:49:07 PM
Kaijin
Kaijin
What do you mean by nested message loops?

- Kaijin
Justin Nixon
Justin Nixon
I’m sorry for the delay in replying. The easiest way to explain what I mean is to show an example. Here’s some partial pseudo-code:

    
int APIENTRY WinMain(…)
{
MSG Message;

// Initialise the application here…


InitialiseTitleScreenScene();

do {
if(PeekMessage(Message…))
{
DispatchMessage();
}
else
{
UpdateSceneObjects();
RenderScene();
ScanDirectInputDevices();

if(KeyPressed==F1)
{
// Clean up the title scene here…


Message=PlayGame();
InitialiseTitleScreenScene();
}
}
} while(Message.message!=WM_QUIT && KeyPressed!=Escape)

// Clean up the application here.


return(Message.wParam);
}


MSG PlayGame()
{
// Initialise a new game here…


// Another message loop would be placed here…


// Do a bit of end-of-game cleaning up here…


return(Message); // Return the last message, maybe WM_QUIT.

}


The PlayGame() message loop is nested inside the WinMain() loop. No need for state-machine programming. The above example will also process all queued messages at once, rather than one per frame, hence the “else” in the if(PeekMessage()) structure.

I haven’t found any problems handling messages in this way.

Justin.


Edited by - Justin Nixon on December 6, 2001 1:14:54 PM
CaptainJester
CaptainJester
I would go with the second metond. If you are in full screen mode, which all good commercial games use, you should not receive any WM_PAINT messages. Secondly, in a shooter or any game that is not turn based, skipping your game loop on each iteration will kill the game. Third, seeing that you could probably handle a minimum of 30 messages per iteration, how many windows apps are going to get so deluged with messages, that the queue will burst. If you get 30 messages a second or less your laughing. You would have to get something like 60 messages per second, on a slow machine, for at least 10 seconds to get bogged down, otherwise the messages will clear very rapidly.

---
Make it work.
Make it right.
Make it fast.
"None of us learn in a vacuum; we all stand on the shoulders of giants such as Wirth and Knuth and thousands of others. Lend your shoulders to building the future!" - Michael Abrash[JavaGaming.org][The Java Tutorial][Slick][LWJGL][
Truth
Truth
I noticed that almost none of you guys used TranslateMessage() before DispatchMessage() in your code snippets. Is it not necessary to use the Translate.. before the Dispatch..?

Just curious. =)
==================================MSN Messenger : [sdrew2000@hotmail.com] ICQ: [6978384] E-mail: [drew@sdsnet.net] Web: [http://www.sdsnet.net] [http://etherealtruth.sdsnet.net]==================================
invective
invective
quote:

Is it not necessary to use the Translate.. before the Dispatch..?



TranslateMessage Just converts the WM_KEY messages for key up and down into WM_CHAR messages, which maybe nice for word processors, but it is pretty useless for most games. So no, its not necessary, unless you expect to handle WM_CHAR messages in your windProc ().

See:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/messques_8vj9.asp?frame=true

Truth
Truth
Cool. Thanks for clearing that up.
==================================MSN Messenger : [sdrew2000@hotmail.com] ICQ: [6978384] E-mail: [drew@sdsnet.net] Web: [http://www.sdsnet.net] [http://etherealtruth.sdsnet.net]==================================
Kaijin
Kaijin
quote:
Original post by Justin Nixon

The PlayGame() message loop is nested inside the WinMain() loop. No need for state-machine programming. The above example will also process all queued messages at once, rather than one per frame, hence the “else” in the if(PeekMessage()) structure.



Oh, I see what you mean. But that still means that your game loop is inside your message handler. There''s nothing wrong with that, I just like to completly seperate my Windows stuff from my games stuff so it''s like windows doesn''t even exist

It prefer that method because it gives me more freedom with the structure of my code and is how I program on the Game Boy Advance.

- Kaijin

Beer Hunter
Beer Hunter
Kaijin - did you see my method up above? I think you might like that way of doing things, too
Justin Nixon
Justin Nixon
quote:
I prefer that method because it gives me more freedom with the structure of my code and is how I program on the Game Boy Advance.


I wasn’t aware of the dual-thread approach to message handling (I only do programming for a hobby) but having read the article on the topic, I agree, it’s the least restrictive way of doing it. I maintain that my nested message loops were a lot easier than state-machine programming, though, but I think I’ll utilise the dual-thread method in future.

Justin.

Edited by - Justin Nixon on December 7, 2001 1:08:54 PM
jassmith
jassmith
I''ve tried placing my message loop and game loop in seperate threads. The problem I had was that using OpenGL, I can''t handle resizes (or anything OpenGL related) through the message loop since the other thread is the current rendering thread for OpenGL. I didn''t want to worry about synchronization of the rendering context between the two threads so I placed the message loop in the SwapBuffers() function of my window wrapper. It works pretty well for me, but I''m curious how others have solved this problem.

Jason
Ultima7
Ultima7
This doesn''t really work, because you have to create your windows and with OpenGL anyways, it just doesn''t work if you manage the window in the main thread and call OpenGL in a seperate thread.

What *I* do is have a function ProcessMessages that I call from my game function. Like someone else said, it''s less restrictive that way.

quote:
Original post by Kaijin
[quote]Original post by granat
Easier ? I don''t see why...


It''s easier because it allows you to program in a linear fasion like you would with DOS or a computer console game. It eliminates the need for a state machine to track the current state of the game because your game''s main method only gets called once rather than within a (message) loop.

i.e.

      
void GameMain() {
Splash();
PlayTheGame();
Splash();
}


rather than:


void UpdateWorld() {
static int state=0;

switch(state) {
case 0: // display a splash screen and return

if(FINISHED(Splash()))
state=1;
break;
case 1:
if(FINISHED(PlayTheGame())
state=2;
break;
case 2:
if(FINISHED(Splash()))
TerminateApp();
break;
}
}


Where UpdateWorld() is being called in each iteration of the message loop.

Check out this article if you want to know more.

- Kaijin

Edited by - Kaijin on December 5, 2001 4:49:07 PM

' Target=_Blank>Link

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.