void LimitFPS (DWORD fps)
{
static DWORD dwFpsTimerCount = 0;
static DWORD fun = 0; // Used for evener...a very pseudo-random number :)
fun++; // If number overflows, it goes back to zero, so what? ¦*þ
DWORD evener = (1000%fps && !(fun%int(10/(double(1000%fps)/double(fps)))/10))? 1 : 0;
/* Use lazy evaluater to protect against division by zero. Expression uses a predictably
random number to ensure the fps is accurate...fixes the accuracy problem introduced by
the integer while loop below. */
DWORD count = 1000/fps + evener;
if( dwFpsTimerCount != 0 )
while(timeGetTime() < (dwFpsTimerCount + count) );
dwFpsTimerCount = timeGetTime();
}
FPS Limiting
You could use sleep,
but in unix threads(or should I say posix) there is a function called yield() which tells the OS : "I have some free time, so give it to other processes". The advantage of that over sleep is that if no other processes need the power, it will give it back to you, so you have less time imprecision than with sleep.
I have never done threading in windows, so I don''t know if there is something like yield, but I assume there is.
but in unix threads(or should I say posix) there is a function called yield() which tells the OS : "I have some free time, so give it to other processes". The advantage of that over sleep is that if no other processes need the power, it will give it back to you, so you have less time imprecision than with sleep.
I have never done threading in windows, so I don''t know if there is something like yield, but I assume there is.
You _could_ use Sleep(0), your program then uses 100% of the processor but whenever another application wants some CPU time it will free the necessary CPU time for it.
But in the end your processor will still run at 100%.
Using Sleep() is not entirely precise and the time specified for the application to sleep can fluctuate within a 10ms resolution, so if you want exact results Sleep() is not the way to go.
But in the end your processor will still run at 100%.
Using Sleep() is not entirely precise and the time specified for the application to sleep can fluctuate within a 10ms resolution, so if you want exact results Sleep() is not the way to go.
quote:Original post by EinVante
You _could_ use Sleep(0), your program then uses 100% of the processor but whenever another application wants some CPU time it will free the necessary CPU time for it.
erm, no. calling sleep suspends your execution for the specified duration, which means that calling thread will not use any cpu time.
Hmm...I''ve tried this out and I noticed the accuracy isn''t very nice, is there any more accurate solution?
As far as I know, no. However, I built a function called Rest that takes the desired maximum amount of CPU power and calls Sleep every few frames, the net result being that you have a little more control over your usage. I''ve tried running it under full load, and it''s accurate within +-2% on average.
I got the idea from SHilbert, but my implementation uses a static local timer object that packages things up. I''m not posting code here because it''s too implementation specific, but if you want to do something similar, the description I''ve given should be sufficient.
//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links
I got the idea from SHilbert, but my implementation uses a static local timer object that packages things up. I''m not posting code here because it''s too implementation specific, but if you want to do something similar, the description I''ve given should be sufficient.
//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links
ZE: I tried something similar to your idea and it turned out very "jumpy" (a very disturbing effect) and not much more accurate... I think I''ll just resort to sleep when doing text or something more static...
Clearly you did something wrong, because this code works beautifully:
Later,
ZE.
//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links
void CGame::Rest(float TimePercent){ float TimePerSec = 1000*(1-TimePercent); static CTimer SleepTimer; static float Accum = 0; Accum += SleepTimer.GetLastFrameTime()*TimePerSec; if(Accum >= 10) { Sleep(int(Accum)); Accum -= int(Accum); } SleepTimer.Update();}
Later,
ZE.
//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links
ZE: As usual you were right. Although, I wouldn't say that code is overly implementation dependant (it's written clear as a bell). The inaccuracy I reported was due to me sticking with the "evener" setup instead of using a float straight out. However, I believe the "jumpiness" is inherant to the structure of the code. It seems my eye can distinguish between the sleeping frames and the no stop frames. Increasing the interval has proven to stop it from being noticable though. Here's my new code:
This code seems just as accurate as my old code (usu. within 0.1 of the desired fps).
______________________________
And the Phoenix shall rise from the ashes...
--Thunder_Hawk -- ¦þ
______________________________
[edited by - Thunder_Hawk on February 10, 2003 8:38:28 PM]
void LimitFPS (float fps){ if (fps <= 0) return; // Obvious error static DWORD dwFpsTimerCount = 0; static float total = 0; DWORD dMilliseconds; if (dwFpsTimerCount) { dMilliseconds = timeGetTime() - dwFpsTimerCount; } else { dMilliseconds = 0; } total += 1000/fps - dMilliseconds; if (total >= 3) { Sleep (int(total)); total -= int(total); } dwFpsTimerCount = timeGetTime();}
This code seems just as accurate as my old code (usu. within 0.1 of the desired fps).
______________________________
And the Phoenix shall rise from the ashes...
--Thunder_Hawk -- ¦þ
______________________________
[edited by - Thunder_Hawk on February 10, 2003 8:38:28 PM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement