I'm working with a basic DirectDraw program.

But It's too fast. (It doesn't have many images. :-) )
It's about 300FPS.

I'd like to slow down the speed to 60FPS

So, I coded below
(I called this 'VSync' function before update frame.)

void VSync(void)
{
static DWORD dwLastTickCount,dwCurrentTickCount;

for ( ; ; )
{
dwCurrentTickCount=timeGetTime();

if (dwCurrentTickCount-dwLastTickCount>(1000/60))
{
dwLastTickCount=dwCurrentTickCount;
return;
}
}
}

But, this code doesn't look like 60FPS.
It is much slow.

How can I slow down the speed to 60 Frame per second.
(I'm working with both Window mode/Full Screen mode,
So I don't use the fourth argument(dwRefreshRate) of IDirectDraw4::SetDisplayMode)

Thank you for reading.
And, Have a nice day!!!
:)
Posted on 2001-11-09 20:11:46 by nyam
Here is some c++ code to lock to about 60 FPS...

// Declare a variable, LastTime, for the time at
// the beginning of the frame
int LastTime = 0;

...In the game loop, first, get the time...

void GameLoop(void)
{
while(true)
{
// Get the time
LastTime = timeGetTime();

....do stuff....

// Lock the game to some frame rate
// (I think... 15 will give about 60, 30 gives 30 FPS)
while((timeGetTime() - LastTime) < 15)
{ /*Do nothing*/}

}

}

...I think that works. I didn't test it and I havent locked to a frame rate in a long time, but something similar to that should do what you need. Have you tried using time based movement instead of frame based? I personally like it better because your game runs the same on all computers. If you need an explaination on how to do time based movement, feel free to ask. Hope I've helped.
Posted on 2001-11-10 00:51:31 by AlexEiffel
I don't recommend locking frame rates in games, Insteaduse a technique to adjust the speed of things in the game. Check the last post is this thread
Posted on 2001-11-10 06:02:20 by Eóin
E?in is right. But if you really want to limit your frame rate to a specific number, do something like this:



/* Time to wait after each frame drawn to gain the desired FPS*/
DelayBetweenFrames = 0
/* Used to count the frames that are drawn each second */
Frames = 0
/* 60 is the frame rate you want */
TempDelay = 1000 / 60

StartTime = Get actual time();

MainGameLoop()
{
DoGameRendering();
delay(DelayBetweenFrames);

/*incrase the frame counter*/
Frames = Frames + 1;

EndTime = Get actual time();

/*check if 1 second has passed*/
If ( (EndTime - StartTime) >= 1000 )
{
Temp = 1000 / Frames;
DelayBetweenFrames = TempDelay - Temp;
StartTime = Get actual time();
Frames = 0;
if( DelayBetweenFrames < 0 )
DelayBetweenFrames = 0;
}
}


The logic is that you have to wait 1 second and see how many frames are drawn in 1 second. With this information you adjust the delay number to limit the frames per second.

*WARNING: The code above and formulas that I used are not tested. I never used a FPS adjuster and the logic above I thinked off now while I was writing this reply.
Posted on 2001-11-10 07:17:15 by eeprom
Thanks to AlexEiffel, E?n, eeprom for your great replies! :)

I'll change the code to not limit the speed.

Thanks to all!!! :)
Posted on 2001-11-10 21:58:56 by nyam
Even easier...

Make a timerproc and have it SendMessage WM_PAINT every 16.6ms. In the WndProc, just have all WM_PAINT messages intercepted and call the renderer.

However, this does not take into account the vertical refresh rate of the video card, and I know there is a way in DX that it will sync it to the vertical refresh.
Posted on 2001-11-15 05:35:14 by Kenny
First of all, don't sendmessage wm_paint. It's a bad thing to do.
Instead, invalidate the window (ie, mark it for redraw). Also, timerproc
has very limited accuracy, and isn't very suitable for game stuff.
Posted on 2001-11-15 07:35:54 by f0dder
Use QueryPerformanceCounter and QueryPerformanceFrequency
and get the Counter at the start of your render loop, then get the counter again at the end of the render loop, make the diffrence and decide if you must wait or not (use sleep to wait)

One more advanced option will be to do some more AI etc on the extra time ... if you have any

For RTS type of game and/or 2D games you MUST lock framerates esp IF you will make it a network game.

2D games will not look better with more frames per second...they will just eat up CPU power...

and indeed you must not lock it for 3D shooter kind of games because they will look better with more frames per second.

PS.

you can use RDTSC instruction to make your own (more accurate) QuerryPerformanceCounter ...
Posted on 2001-11-15 18:46:16 by BogdanOntanu
Sleep isn't terribly accurate :/. I can't remember the figures, but
it wasn't exactly good. It's somewhat better on NT though. But still,
if you need very precise timing, Sleep is no good. Might be okay for
a game, though :).
Posted on 2001-11-15 19:01:57 by f0dder
For all practial purposes even 3ms inaccuracy is acceptable, considering a good ping is 30ms, so that's why I said the timerproc and the WM_PAINT.

Or, you can make your own timer in a thread, and have it sendmessage. (I just like to do things the easy way.)
Posted on 2001-11-15 22:09:04 by Kenny
get the Counter at the start of your render loop, then get the counter again at the end of the render loop, make the diffrence and decide if you must wait or not (use sleep to wait)


Yeah, but you must know "how much" to wait. This is done doing a calculation every second, taking in count how many frames were drawn in that passed second and how many frames you want to have per second.
Posted on 2001-11-15 22:53:57 by eeprom
You can just delay your render loop at every frame to make it take ... lets say 20ms ... then you know you have 50 fps ... no matter
what

if your frame just took more them 20ms...the just delay nothing
if you frame took 10 ms ... the delay extra 10 ms

its simple

QuerryPerformanceCounter and QuerryPerformanceFequency are accurate enough...

I suggested using sleep just to relinquish CPU time to other applications, but obviously you can just delay the start of the next frame
render loop and don't use sleep if you want to eat all CPU time ...

i.e. if your game works full screen and you do not care about MP3 players in the background :)
Posted on 2001-11-19 18:08:47 by BogdanOntanu
I prefer to play a well behaved game that doesn't eat all my CPU time if it don't need too, and when I've been playing it for a while I've had enough of the in game music and would like to hear my mp3's. :) Or even play it windowed with IRC on the side to send shouts out to the enemy. :grin:
Posted on 2001-11-19 18:51:39 by bitRAKE
I will just look like its eating all CPU time, but it will not :)

windows is now multithreaded and it is very hard to eat all CPU time now :), system monitor reports buggy info about that...

HE does the same and you can sure play MP3 in the background, it starts to choke up a little only when DirectPlay starts its own threads in a network game...
Posted on 2001-11-21 18:48:02 by BogdanOntanu