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 want my game run at 60 fps, but i don't know where to start, i have the simple loop:

while(device->run()){

How do i lock the fps to 60?

share|improve this question
    
I would just like to know, why would you need to lock it to 60 FPS? Because I have never ever ever heard of anyone wanting to clip the FPS. –  Matt Jensen Mar 11 '12 at 22:28
    
at 4000fps, some (my included) video card start 'screaming'. Guess it's a sort of coil whining :-) but I defenitely prefer 200fps. Sometimes a too high fps trashes delta time too (if you use an integer with milliseconds you don't want to get close to 500fps). –  Valmond Mar 12 '12 at 10:41
    
That's an odd problem, my game engine runs at about 1500 FPS with a basic level and a few entities and I have none of those problems. –  Matt Jensen Mar 12 '12 at 11:51
    
Here is the code that made my card scream :-) www.mindoki.com/download/SimpleTerrain.rar Another card screamed here : irrlicht.sourceforge.net/forum/… –  Valmond Mar 12 '12 at 12:34

4 Answers 4

Sleep is a very bad idea for the reasons already pointed out - the only justifiable case to use it is for saving battery on mobile devices.

If you want to lock to 60 fps one way would be to measure the time that's elapsed since the last frame ran; if that equals or exceeds (1.0 / 60.0) seconds then run a frame. Of course you'll need a high resolution timer to get this right, and of course it's a busy-wait loop that will chew up CPU time, but it works.

(You might even find some useful work to do during that busy-wait period, such as updating dynamic resources or whatever).

Another way is to use vsync. Most monitors nowadays will run at 60hz, and those that don't are extremely likely to support it, so just enable vsync, set your refresh rate if needed, and run as normal.

share|improve this answer
    
I proposed Sleep() because it will give a chance to have other things happened while you wait. For example you could have another critical thread in the game that absolutely need to absolutely need to run at same time (eg: getting network packets, mixing sound or reading player input). it will still works, even on single core architecture. It is also the way it is done on some professional game engines like quake 4 (check here : github.com/TTimo/doom3.gpl/blob/master/neo/framework/…). –  tigrou Mar 11 '12 at 16:48
    
Sleep (0) is sufficient to yield the CPU to other threads in the same process, and won't have the same precision issues that a normal Sleep does. The Doom 3/Quake 4 code uses Sleep in a multithreaded environment and explicitly where there is no work for the engine to do otherwise, which is quite different to recommending it as a general case solution for locking FPS (it's actually the spin loop that locks the ticrate in that example, not the Sleep; the Sleep just yields CPU while the spin loop is running). –  Darth Satan Mar 12 '12 at 13:35

Do you want to synchronize on vsync ? There are differents solutions depending on your platform. Search vsync on google. On directx, you can limit on fullscreen app with D3DPRESENT_INTERVAL_ONE or use WaitForVerticalBlank on windowed app.

Look this article

share|improve this answer

Depends what you mean by saying "you want to lock the game at 60fps".

If you want to limit the game rendering at max 60fps its very simple :

Each frame, just check if the game is running to fast, if so just wait :

//to call each frame
while( true )
{
    int elapsed_time = getcurrenttime() - oldtime;
    if(elapsed_time >= minimum_elapsed_time)
      break;
    sleep(1); //yield cpu to other game thread or processes...
}

Please note that if vertical sync is enabled, rendering will already be limited to 60fps.

But if you want to have your game logic locked at 60fps, no more no less, that's different. Then you have to separate code you want to run at 60fps from rendering code and make necessary changes to make sure that code is called at same fixed time intervals. It is called "fixed timestep". Make a search on gamedev or google. There is a lot of info on this.


EDIT : as Roy T. pointed out, code is not guaranteed to works because sleep(1); may wait more than 1ms. calling timeBeginPeriod(1); at game start (and timeEndPeriod(1); at end) should fix the problem (but have some consequences). I choose to call sleep instead of busy-wait loop to give other threads and processes a chance to run while game is waiting...

share|improve this answer
    
You can't use sleep to wait for very small periods because after the thread is yielded you're not entirely sure when the thread will be activated again. All you know is that it's not going to be sooner than 1ms this way. If you want your game to run at exactly 60fps you will have to use a busy loop. –  Roy T. Mar 11 '12 at 15:49
    
please can you provide me a while example? –  fracedo Mar 11 '12 at 15:56
    
gamedev.stackexchange.com/questions/18898/… especially see the link to Gaffer on Games there. –  Roy T. Mar 11 '12 at 16:24
    
Yes you're right, it will wait a little more than 1ms in most cases (typically 10ms on win32 systems?). So basically you will accumulate some "delay" after a few frames. I have updated code to make sure "delay" will be absorbed over the time. Running the game at a perfect 60fps (that means 16.6667 ms between each frames) is impossible... –  tigrou Mar 11 '12 at 16:34
    
this is what i have so far, the fps locks in 59. irr::ITimer* timer = device->getTimer(); irr::u32 timeThisFrame = timer->getTime(); timeThisFrame = timer->getTime(); while( (timer->getTime() - timeThisFrame) <= 16 ) { timer->tick(); }; This is the best solution? –  fracedo Mar 11 '12 at 16:46

If you are measuring time you also really need to be using QueryPerformanceCounter as timeGetTime jumps in large increments.

There is a fairly involved blog post on the subject of windows timing:

http://www.geisswerks.com/ryan/FAQS/timing.html

Also, if there are no other threads needing to work Sleep(0) will return immediately, you need to use SwitchToThread, and if that 'fails' call Sleep with a non-zero amount instead to actually go to sleep.

That said, I would still recommend using the vsync features, as that can be turned into a kernel wait on an interrupt behind the scenes and also context switch out properly while waiting, much like the sleep. Also, sleeping is a bit odd of a thing to do as you dont actually know when the vsyncs really occur, even with vsync enabled, so it is hard to sleep a proper amount and not miss the vsync on the next frame in a lot of cases (esp if youre CPU overhead is pushing 15+ milliseconds)

share|improve this answer

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.