Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I've been developing a small framework for OpenGL and WinApi for some research purposes. My biggest problem right now is the game loop. Simplified I did something like this: Main thread:

HANDLE hUpdate = (HANDLE)_beginthreadex(0, 0, updateThread, 0, 0, 0);
while (!done)
{
    if (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))
    {
        if (msg.message == WM_QUIT)
        {
            done = TRUE;
        }
        else
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    else
    {
        Draw();
    }
}

Update thread:

unsigned int __stdcall updateThread(void *params)
{
    QueryPerformanceCounter(&nextTick);
    QueryPerformanceCounter(&lastUpdate);
    while (!done)
    {
        LARGE_INTEGER currentTick;
        QueryPerformanceCounter(&currentTick);

        while (currentTick.QuadPart > nextTick.QuadPart)
        {
            double frameTime = ((currentTick.QuadPart - lastUpdate.QuadPart) * 1.0) / clock.QuadPart;

            QueryPerformanceCounter(&lastUpdate);
            Update(frameTime);

            nextTick.QuadPart += TIME_STEP * clock.QuadPart;
            QueryPerformanceCounter(&currentTick);
        }
    }
    return 0;
}

This way i got fixed time step while draw will be called as much as it can (kinda what I was looking for). The BIG problem is that everything is operating using busy wait, and it just swallows CPU and still no real game logic has been written. Can anyone tell me, or redirect me to some good, efficient implementation of game loop? While I was researching I came across information that Sleep() is bad for game loop.

share|improve this question

3 Answers 3

I'd move your game logic code to the same thread as your message processing/drawing code (i.e. the main thread).

This not only saves you from properly locking ressources to one thread at a time, it also allows you to use vertical synchronisation (VSync) as an alternative to waiting in a busy loop or using your own calls to sleep(). In addition to that, you can introduce a minimum frame time (which would essentially be something like sleeping for 10 ms), which would essentially limit you to 100 frames per second.

Also I see one tiny problem with your logic update: If your processing isn't fast enough to catch up with the time that passed (e.g. one iteration takes 10 ms, while there is supposed to be one update every 5 ms), you'll end up in an infinite loop of updates, that's getting a backlog that's only increasing in size. That's not necessarily a problem in the multithreaded approach, but if you consider merging everything, you've got a problem. In either way, you'd have to check for done in your inner update loop, though.

share|improve this answer
1  
I agree with the advice about doing away with the "update thread." There is no reason for that thread to exist in this implementation. –  Josh Petrie Feb 25 at 15:34

I'd suggest that worrying about CPU usage due to busy-waiting at this stage in your development is a form of pre-emptive optimization. In other words: you haven't written all of your code yet, you don't yet know what your final CPU budget is going to be, so in the absence of that knowledge you shouldn't really be making decisions relating to that budget just yet.

When you do have your game logic written you're likely going to find that you're still hitting 60fps just fine, and you'll be able to profile your full game and get a view on where your CPU usage is going. Armed with that knowledge, you can then start making some more meaningful decisions.

For example, you may find that your game actually does need 100% CPU at all times in order to maintain 60fps, perhaps owing to a heavy or complex physics simulation. Or you may only be able to hit 10fps, in which case you need to optimize. Or the opposite: you may easily hit 200fps in which case you can decide to offer some higher quality simulation, or give some of that CPU time back instead.

Once you've done this a few times you'll be able to make more accurate (and informed) advance judgements, but right now you really can't.

Sleep, by the way, can be perfectly fine for reducing CPU usage, so long as you're aware of the problems with it and take the appropriate steps to work around them. What it's not fine for is controlling framerate. That's not a problem for you as you're already using a proper timer.

share|improve this answer

I think your problem here is simply that your making it run as much as possible, but expecting the CPU usage to be something other than maxed out. If you simply do "while (true) ;" you should expect to see the same thing as your asking the computer to test if "true == true" constantly.

In your loop you doing essentially nothing but constantly querying the time. Sleeping while waiting until the next frame is going to drop your CPU usage, but as you implement your game logic it may be unnecessary (Here is a related topic on sleep).

Try seeing how many times it goes through that loop before (currentTick.QuadPart > nextTick.QuadPart) == true. As you implement logic this number will fall.

To put it another way, your loop won't be consuming all that much CPU time when you actually have your game logic inside the loop. So this is a case of premature optimization. To quote from Gnome;

Traps for the Unwary

It is very easy to be misled by the profiler. There are stories of people optimizing the operating system idle-loop because that is where it spent all its time! Don't optimize code that does nothing the user cares about.

share|improve this answer
    
Well, I'm aware of that. I know that while(true) is the problem. I'm curious about some other game loop implementations that does not use busy wait, because it is really CPU consuming. Thanks –  instancedName Feb 24 at 20:42
    
I really don't think there is much of an alternative, but you can add an else and do some extra updating (like more asset loading) to do some busy work till the next update pass. –  OriginalDaemon Feb 25 at 10:06

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.