Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Code Snippets / [DBC][DBP][GDK] Decoupling the Display Loop from the Game Loop

Author
Message
KISTech
16
Years of Service
User Offline
Joined: 8th Feb 2008
Location: Aloha, Oregon
Posted: 8th Sep 2010 18:11
The examples are written in DBP, but the principles would apply to any game development environment.

We have all done it. Hacked out a simple program or demo without any timer based movement code, and with little regard to how fast or slow the user's computer will run it. Which is ok, because it accomplished whatever we were attempting to show to those people.

When we move on to making an actual game for release, it becomes more important to consider the speed of the user's computer.

This is not a discussion on Timer Based Movement. I think we've already covered that well enough, and if not I'll be happy to write an in-depth tutorial for it.

This is a discussion on how to get more performance out of your main loop, while maintaining a good framerate.

What we typically see in the forums is something like this.


There's no Timer Based Movement, sync rate is set to 60, and it does it's thing at an inconsistent rate from computer to computer. Setting VSYNC ON instead of setting sync rate has basically the same effect, but with the benefit of not taking up all of the CPU's cycles.

Another approach is to turn VSYNC OFF and set sync rate to 0 and just let it fly as fast as it can, but again that is going to run at different speeds on different computers, and eats up all available CPU cycles.

This example shows this with Timer Based Movement included just to keep things running at an even pace. Take notice of the FPS that DBPro reports. This isn't just how many times the screen is drawn, but also how many times your main loop runs.


On a fast computer you can get quite high framerates with that, but again, it eats up all the available CPU cycles.


The solution I've come up with, although I'm sure I'm not the first, is to Separate the Game Loop and Display Loop and let them run independently.

The main objective here is to put in the Display Loop only those things that need to be drawn, created, modified, grabbed, or pasted to the screen right before the sync, which is the only time they are needed. Everything in the Game Loop should be the rest of the game that needs constant updating, such as object movement, calculations, collision detection, networking, etc..

The following example aims for an FPS of 30. So every 33 milliseconds it executes the Display Loop. The Game Loop is set to run at 4 times that rate. If the computer is fast enough, it will achieve this, and the Overall Loop Count will be quite high. If it's not, then the Game Loop slows to match up with the Display Loop, but no matter how fast the Game Loop runs, the Display Loop will always run at the desired framerate if it can. If things slow down to where they are at the same rate, even if the Display Loop rate drops below 30, the Game Loop rate will stay with it because it's trying to run faster, but can't. Timer Based Movement keeps the objects moving at the same speed no matter what the FPS or LPS.



Remember the FPS shown in the second example? That was your code running flat out. What we've done is made better use of that processing power by only requiring the display to be updated when it's needed, and giving the power over to the real meat of the program, where the more important stuff happens.

Using this method on the server app for Worlds Apart Online, it runs the Game Loop at around 23,000 loops per second with a Display Loop rate of 5 FPS. Perfect for a server that needs to handle lots of network traffic but doesn't need much of a display.

The client for Worlds Apart Online is able to maintain 40 FPS with a Game Loop rate of 80-90 loops per second.

I'm sharing this to help others who are pushing DBPro to it's limits and need more performance out of it while still achieving a good framerate.

I hope it helps.

Questions? Ask away...

[edit]
I've updated the code to use the HITIMER() function from IanM's Matrix1Utils plugin, since it is more accurate and reliable than the Windows TIMER() function.
[/edit]

GIDustin
15
Years of Service
User Offline
Joined: 30th May 2008
Location:
Posted: 9th Sep 2010 01:49
Hey, this is the same concept that my games use, except you did a much better job at describing it than I would have. My game server keeps a constant FPS of 4, and gets about 130,000 loops per second, (but it is in its very early stages). My template also adds another line to the display loop:

This gives the rest of the system a bit more CPU so that my programs aren't hogging it all. Since the server application only calls this 4 times a second, it hardly affects the performance, but CPU usage goes from 100% to 20%.

I have also heard rumors where some games can actually push more "syncs" to a video card than the eye can even discern. Using code like this to cap the sync rate not only reduces useless syncs that the human eye would never detect, but it also increases the life of the video card.

KISTech
16
Years of Service
User Offline
Joined: 8th Feb 2008
Location: Aloha, Oregon
Posted: 9th Sep 2010 01:56
I've been playing around with where to put a NICE WAIT 1, and make it conditional so that when more power is needed it doesn't do it.

I knew I wasn't the first one to come up with the idea.

Quel
15
Years of Service
User Offline
Joined: 13th Mar 2009
Location:
Posted: 24th Sep 2010 20:32
What loop values are you getting running this sample program?

I'm getting 17fps on all four in stand by, and 7-8 varies when clicking. Is my laptop really this piece of cr*p?
KISTech
16
Years of Service
User Offline
Joined: 8th Feb 2008
Location: Aloha, Oregon
Posted: 25th Sep 2010 20:22
Quote: "I'm getting 17fps on all four in stand by"


I'm not sure what that means, but I did answer your question in the other thread.

Basically there are 2 values that you can change to alter how the program runs. Ideally the game loop rate would adjust dynamically based on the current framerate.

So in the code where the 2 if statements are checking the timer variables, if you change the second one from an 8 to 16, you'll get a much higher framerate.

See the other thread in the DBPro forum for more details.

Login to post a reply

Server time is: 2024-04-19 11:38:46
Your offset time is: 2024-04-19 11:38:46