Sign in to follow this  

The game loop and CPU resources...

This topic is 4765 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

At this point, I have read a few game programming books and I see that most games they depict consist of a loop which runs indefinetly until the game finishes, e.g.:
  while(gameon)
  {
   figure->eraseShape();

   if(keypressed())
    getInput();

   updateWorld();

   drawWorld();

   drawText();

   rest(10);
  }


The issue I am curious about are the resources that such a loop consumes. The above code is for a tetris clone which I made some time ago. Everytime I run this game, the CPU usage shoots through the roof. Should such a simple game be so processor intensive? It seems like the better solution might be to code multiple threads, each being called at asynchronously at some specified time, yet such an approach yields very unpredictable code due to scheduling issues (and is a pain in the ass to program). How does one make such games more processor efficient?

Share this post


Link to post
Share on other sites
Normally, you would cap your FPS to a certain value, calculate how much time is remaining till the next frame, and sleep for the appropriate amount of time, in order to free up the spare processor time.

Share this post


Link to post
Share on other sites
if its a full screen game then use all the CPU time you need, if its a windowed game then again use all the CPU time you need and shove a sleep(0) or sleep(1) at the end of the main loop to yeild to let windows know that its free to do something else.

If you're a single player game and you lose focus then worry about the resources you take (either pause the game, or reduce CPU overhead somehow) and if you are an MP game then just keep your network pump going so the game doesnt fall over and die.

Artifical limiting of the fps however is a plan which is, imo at least, very daft.

Share this post


Link to post
Share on other sites
While it is true that you usually don't need to worry too much about how much resources your game is using as long as it has focus, it is perfectly reasonable to cap the frame rate. Mike McShaffy even uses it in the examples in his book "Game Programming Complete". You definately shouldn't cap the frame rate so low that it hurts the performance of your game, but there's really no reason to have a framerate above 60fps. Firstly, your eye can't tell the difference much beyond that point. Secondly, most video cards can't refresh the screen faster than that anyway (although some video modes are a bit faster).

Share this post


Link to post
Share on other sites
first point; dont mention fps rates and eyes around here, it leads to arguements (and for the record the eyes dont see in discrete frames anyways so the mesurement is meaningless), however I'll just point out that at 60fps I get a head/eyeache at 72fps I can get along just fine, guess what refresh rate i force on my monitor [smile] now, you cap your game at 60fps opps, my display is now choppy (some frames displayed twice, some not) unless I bring my v-sync rate back down to 60hz at which point I end up in pain... no fun [smile] (and i'm not alone in this respect)

2nd point; bollox. Depending on the complexity of the scene they can do anything from 1frame per hour to over 100fps and beyond, its depends on the amount of work you make the gfx card do AND the amount of work the CPU has todo.

So, I say again, capping frame rates imo is daft, use v-sync if you are going to cap at all at least then you'll be locked to what the monitor is displaying.

Share this post


Link to post
Share on other sites
Well, it would seem that the topic of Framerate limiting is more contested that I would have imagined. :)

The thing that I wanted to make sure happened was that the tetris-clone worked at the same speed no matter on which computer it is played on. Although minimal, the difference can be felt when played on differnt computers. My initial question was trying to find a way to implement this game loop efficiently such that the CPU's speed would not affect gameplay (withing reason, of course). Surely tetris can run just as well on a 400 Mhz processor as on a 2.6 GHz.

Share this post


Link to post
Share on other sites
Quote:
Original post by _the_phantom_
if its a full screen game then use all the CPU time you need, if its a windowed game then again use all the CPU time you need and shove a sleep(0) or sleep(1) at the end of the main loop to yeild to let windows know that its free to do something else.


I'm not sure, but wasn't that necessary in the days of Win3.x or something? After Windows95, you don't have to "pass" the CPU to Windows, every process gets a chunk of time anyway. The only thing he needs to do is to dispatch the messages every now and then, so the message queue don't get overflowed.

And for fps capping, it's not very good idea, let vsync handle that. In either case, it's good practice to use the extra time to perform CPU calculations(physics,AI...), and not just waste it with sleep().

-EDIT: I just saw now that sleep() "causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run". So if your app is not multithreaded, there's no reason to use it.

Share this post


Link to post
Share on other sites
Quote:
Original post by TheWanderer
Well, it would seem that the topic of Framerate limiting is more contested that I would have imagined. :)

The thing that I wanted to make sure happened was that the tetris-clone worked at the same speed no matter on which computer it is played on. Although minimal, the difference can be felt when played on differnt computers. My initial question was trying to find a way to implement this game loop efficiently such that the CPU's speed would not affect gameplay (withing reason, of course). Surely tetris can run just as well on a 400 Mhz processor as on a 2.6 GHz.


For this, instead of moving the block down by say 2 units every time the updateWorld function is called, simply movie it down by 2 units times the ammount of time since the last time the block was moved. Example:

do not do:
block.y -= 2;

instead do:
block.y -= 120 * time_since_last_frame;

you will need to apply this to all places where something happens every frame with some consant value. That constant value should be scaled by the amount of time elapsed.

Hope I've helped!

Share this post


Link to post
Share on other sites
Quote:
Original post by Dwiel
For this, instead of moving the block down by say 2 units every time the updateWorld function is called, simply movie it down by 2 units times the ammount of time since the last time the block was moved. Example:

do not do:
block.y -= 2;

instead do:
block.y -= 120 * time_since_last_frame;

you will need to apply this to all places where something happens every frame with some consant value. That constant value should be scaled by the amount of time elapsed.

Hope I've helped!


You have indeed. A question though. Would not the above example result in "smooth" movement of the block? How would you give it a more "staggered" feel (i.e. drops, stops, drops, stops, etc).? (Hmm... it might be time for me to get a home page where I can post examples and code...)

Thanks to all for the comments. :)

Share this post


Link to post
Share on other sites
Maybe you could round to the nearest X where X is the size of one square on your "grid" (probably the size of a block in your tetris game). Youd need 2 sets of coordinates, the actual position and the drawing coordinates, the latter being the ones you round. I hope I understood you correctly there heh.

Share this post


Link to post
Share on other sites
we are having this same discussion in this thread. maybe it will help you make a decision. but basically i agree with everything the phantom says (except his recommendation for a Sleep(1)). putting a Sleep(1) is asking for trouble. it may work perfectly on your computer, give the CPU some rest, however, on other machines it could be choppy. had personal experiance with this exact thing happening. Sleep(0) is best.

Share this post


Link to post
Share on other sites
Just a clarification. In my previous post I considered using v-sync as one way of "capping the framerate". A difference in terminology, perhaps. So, I agree with _the_phantom_ that using v-sync is probably a better way of doing it.

Share this post


Link to post
Share on other sites
Quote:
Original post by TheWanderer
Quote:
Original post by Dwiel
For this, instead of moving the block down by say 2 units every time the updateWorld function is called, simply movie it down by 2 units times the ammount of time since the last time the block was moved. Example:

do not do:
block.y -= 2;

instead do:
block.y -= 120 * time_since_last_frame;

you will need to apply this to all places where something happens every frame with some consant value. That constant value should be scaled by the amount of time elapsed.

Hope I've helped!


You have indeed. A question though. Would not the above example result in "smooth" movement of the block? How would you give it a more "staggered" feel (i.e. drops, stops, drops, stops, etc).? (Hmm... it might be time for me to get a home page where I can post examples and code...)

Thanks to all for the comments. :)


There are a few ways I can think of off hand. here's one:

say you would like to stagger by STAG # of units:

block.y -= 120 * elapsed_time;
block.display_y = floor(block.y / STAG) * STAG;

The above code will first divide the block's y position by STAG. After that it will be rounded down to the nearest integer value. we can then scale the number back up to where it was. depeneding on how you want your block to stagger, you might experiment by using floor() and ceil(). floor rounds down and ceil up.

The reason why we need 2 variables to do this is so that we always know how close the block is to moving down to the next step.

glad I could be of assistance!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:

-EDIT: I just saw now that sleep() "causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run". So if your app is not multithreaded, there's no reason to use it.


That's an incorrect assumption. Just because your process only has one thread doesn't mean there aren't (many) other threads in the system at the same priority level waiting for CPU time. Take a look at the process manager sometime. :)

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
Quote:

-EDIT: I just saw now that sleep() "causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run". So if your app is not multithreaded, there's no reason to use it.


That's an incorrect assumption. Just because your process only has one thread doesn't mean there aren't (many) other threads in the system at the same priority level waiting for CPU time. Take a look at the process manager sometime. :)


If I'm not mistaken, the process manager displays only processes, not threads, but you're right about the rest. I thought MSDN meant "to any other thread in the same process", but apparently that's not true.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
In the task manager, on the Process tab you can add the column "Thread Count" and see how many threads a process has.

Share this post


Link to post
Share on other sites

This topic is 4765 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this