Advertisement

Designing a game loop.

Started by May 19, 2021 09:12 AM
11 comments, last by Endurion 3 years, 5 months ago

I'm developing a simple Win game. Here is my 2 similar implementations of the game loop (in c++):

approach #1:

   while (Msg.message != WM_QUIT) {
   
     if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE) > 0) {
      TranslateMessage(&Msg);
      DispatchMessage(&Msg);
     }
     else {
               // Do update, rendering and all the real game loop stuff
           }
   }

approach #2:

   while (Msg.message != WM_QUIT) {
   
     if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE) > 0) {
      TranslateMessage(&Msg);
      DispatchMessage(&Msg);
     }
     
           // Do update, rendering and all the real game loop stuff
           
   }}

My question is which one is better and which one should i choose? Is it better to do the update and rendering stuff in the else closure as in the #1 approach or just in the `while` loop block as in the #2 approach?

Moved from Game Design And Theory to For Beginners. Game Design And Theory is not a programming forum. Sorry I can't answer your question.

-- Tom Sloper -- sloperama.com

Advertisement

Do you have hard evidence to support a decision?

I mean, how often does 0 events happen in an iteration, how often does 1 event happen, and 2, 3, …

You can have long discussions about “better”, but without evidence that more than 1 event in an iteration is common, your entire question could be purely academic. Nice as discussion topic, but not very efficient in spending time for making a game.

I don't think this really matters if you are running the loop at a reasonable frequency. The more interesting part would be how you handle update steps (fixed or variable), frame limiting, recovering from lag, etc. which you didn't show.

The only small thing that comes to mind is because of how you did while (Msg.message != WM_QUIT) it will try to run update/render one last time after exit in example #2, but even that isn't really a big deal unless you already deleted some stuff before calling PostQuitMessage.

Not sure which one is better but I use #1 for the sole reason I started with one of Frank Luna's books and that's how he did it. So far it hasn't been an issue. I actually now have 3 game loops. The main rendering/game loop, one that does LOD in the background and one that runs the universe since in my case I have planets and a sun.

I would probably go with the 2nd approach. Process the various Windows messages first (if any), do game logic next, draw the frame. With approach 1 it seems like it'd be possible processing Windows messages could result in your game not being updated in iterations through the loop. I'm picturing simply moving the mouse around over your window results in game logic and frame drawing never being done. Unless you're planning on using WM_TIMER and WM_PAINT messages to run your logic and draw functions, which is what I used to do when I was first learning but I wouldn't really recommend that technique now.

Advertisement

From a pure code view, the first one is the better one because of the else statement in there. This allows the CPU to handle branching on your loop more efficient and can propably speed things up while it is unpredictable for the second version.

I however would like to bring in a third version and replace the if statement of the second one with a while statement. From my experience, Windows events appear in groups most of the time, even if you don't handle all of those messages, there are coming multiple of them in usually. For example when resizing or moving a window.

However, the first one is my favorite way to go because you can react to a quit message more efficiently than in the other two

At this point, all that matters (besides everything working) is that you think your code is easy to understand, and preferably that others can read it too.

Consider optimisations some other time.

You may find this article useful, as it goes into detail on why the “standard” event loop that most tutorials use can be a problem for CPU usage.

If we start talking about “the standard loop” and games, then we should also talk about why it is recommendable to avoid putting everything into the loop on the main thread and instead let that loop do what it is supposed to do, catching OS events and nothing else. I've seen this in Godot for example, where the event loop is also performing calls into the game. This is wrong in so many points, first but foremost is it slowing down the framerate when there is something happening on the Desktop at the same time, which is the case for every newer game these days, starting in windowed mode. So every OS message interrupts the game for milliseconds. Also stop catching user input in the main loop!

This topic is closed to new replies.

Advertisement