Better game loops than endless loop + block?

Each game tutorial and game environment (even the fairly new XNA infrastructure) starts with an endless loop that has the equivalent of DoEvents () to prevent OS blocking.

Acting from a point of view that is not based on the game, I feel that such a code smells pretty scared.
Are there any better alternatives?

- EDIT -
Many answers say that each program is basically a cycle. True, but I believe that the cycle should be performed by your OS, and not by you. Only the OS has all the necessary information for the optimal allocation of its resources. Or did I miss an important point here?

+6
language-agnostic
source share
9 answers

Each Windows application basically has a loop that looks something like this:

BOOL bRet; while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0 ) { if (bRet == -1 ) { // handle the error and possibly exit } else { TranslateMessage( &msg ); DispatchMessage( &msg ); } } 

This application is an application, not an operating system, to enable sending messages.

As you probably know, in early Windows games an alternative method was used, where instead of calling the GetMessage lock function they would PeekMessage and then would call the main game processing cycle if there was no message to process, Various forms of delays were used to try to get an adequate frame rate without using 100% CPU. There was not a good enough timer to ensure a smooth frame rate.

Today, it may not be necessary to explicitly write a loop that calls DoEvents . Now it would be possible to get a smooth frame rate using the built-in timers for the timer (set in .NET using System.Threading.Timer and wrapped in System.Timers.Timer ).

As far as I remember, there were also problems with mouse and keyboard operations. We used direct access to the keyboard and mouse, and not depending on the message cycle, because the message cycle was often too slow and sometimes led to loss of information.

I have not written games for several years, and I do not know what .NET is like a gaming platform. It is possible that input is still a problem - the message queue is simply not fast enough to give the lightning fast response that game developers want. Therefore, they bypass the message queue for critical tasks.

+5
source share

Games (in most cases) are simulations. Traditionally, this means that you update the simulation, imagine its current state (for example, visualize the graphics) and repeat. The natural view for this is a loop.

The Win32 message pump, on the other hand, is a platform-specific feature that focuses on the event-driven applications that make up most Windows applications. This is by no means the standard for applications on all platforms, so it is not surprising that not all software fits perfectly into the model. Therefore, to make changes to a typical program suitable for the Win32 model, you usually drop this queue at a time, in one iteration of the loop, using PeekMessage until it is empty. Or you put this logic in a separate thread and use GetMessage if necessary.

For most games, given performance, there is no other practical way to do this. First, if you tried to make an event-driven game, not a poll, you will need a higher resolution than Windows, which can reliably give you if you want to maintain the high performance that many games play. Secondly, Windows is only one of the platforms on which games are written, and game processing ideal for the Win32 model will be simply an inconvenience for dedicated gaming platforms that expect a canonical game cycle.

Finally, problems with "adopting 100% CPU" are inappropriate. Most modern games are designed to be used in full screen mode with exclusive access to hardware, and not just in one of several other existing applications. Customers of such games actually require the game to make the most of their equipment, and this cannot be done if intentional Sleep () calls or updates depend on external timers that wake the application N times per second. Obviously, there are exceptions for many games, for example. those that are designed to work mainly in the window, but it is important to note the difference.

+2
source share

All running programs never end in cycles. Although in some cases you do not interact with the loop (for example, in web programming or other minor programs)

Your OS is a loop awaiting command input. Same thing with the game. A web server is a loop waiting for requests.

Great explanation from slim user on one of my own questions.

+1
source share

The best loop is an endless loop with a blocking call to send events / messages. If you have nothing to do, you really should not sleep, but block, waiting for the OS. But if the OS doesn’t really block when you are polling for events, sleeping between polls is the only solution that prevents the use of 100% CPU.

+1
source share

I don’t see how it could be done differently?

Your program runs inside a thread (or multiple threads, if you're interested). Having a gameloop (or win32 GetMessage / DispatchMessage pump) is waiting for an event and then managing it. An alternative would be to register callbacks and then call HandleAllMyMessages (), which internally would do almost the same thing ... and in fact you would not buy anything.

The OS will not be able to magically divide your program into several threads, because it does not know what you want to do in these threads. The emergence of a new thread for each incoming message would be both a success and a synchronization of hell.

+1
source share

In Win32, I use the MultiMedia timer to call my halologic tick ...

 // request 1ms period for timer g_mmTimer = timeBeginPeriod(1); if (g_mmTimer != TIMERR_NOERROR) return false; //start game loop event timer/thread g_mmTimer = timeSetEvent(10, 10, DoUpdate, 0, TIME_PERIODIC ); 

If you wish, you can make all the drawings in another thread, so that the game logic automatically depends on the frame rate.

+1
source share

Message queues are also infinite loops, which makes all programs infinite loops.

0
source share

MsgWaitForMultipleEvents combines the GetMessage / PeekMessage with a timeout and the ability to wait for kernel objects such as WaitableTimer .

I used CreateWaitableTimer to set the desired frame rate along with MsgWaitForMultipleEvents to send messages with great success for very smooth animations in the past, without lively waiting. I would like other OSs to have something good.

0
source share

If you don’t feel comfortable, a package with class and interface,

this is what we say "open and close principle": to open an interface that has never changed, to close the dirty part.

why do we use a loop? because this is the basic structure of our computer!

-3
source share

All Articles