Sign in to follow this  
billhsu

HELP! How to lock FPS Correctly

Recommended Posts

Help me!I am a kid new in game programing. I want to Lock my 3d game to 60 FPS.How to lock FPS Correctly. I tried timeGetTime() ,but it doesn't work properly Here is my code,but it didn't work properly . the game didn't run smoothly while(true) { DWORD start_time = GetTickCount(); if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if (msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } update(float(GetTickCount() - start_time)); while((GetTickCount() - start_time) < 30) Sleep(1); } How to lock FPS Correctly

Share this post


Link to post
Share on other sites
1. Are you absolutely sure you want to lock the FPS instead of making your game run at any frame rate?
2. Enable v-sync. That'll lock you to the monitors refresh rate (Although not necessarily 60 FPS).
3. You should be processing all messages before running a game tick, not just one.
4. GetTickCount() is only accurate to ~15ms. Using it to measure 30ms is a pretty high margin of error.
5. Sleep(1) will sleep for at least 1ms. Usually it'll sleep for between 10 and 250ms (>= One scheduler timeslice).
6. That looks suspiciously like DirectXTutorial source code, which is (IMO) a pretty terrible site to be learning from.

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
1. Are you absolutely sure you want to lock the FPS instead of making your game run at any frame rate?


I just want to make sure that the game can run at a same speed no matter on a quick machine or a slow one,how to do it?

Share this post


Link to post
Share on other sites
Quote:
Original post by billhsu
Quote:
Original post by Evil Steve
1. Are you absolutely sure you want to lock the FPS instead of making your game run at any frame rate?


I just want to make sure that the game can run at a same speed no matter on a quick machine or a slow one,how to do it?
The best way is to base movement on time, not a fixed step. So, if you were previously moving a sprite 1 pixel per frame at 60 FPS, you'd want to move it 60 pixels per second. Then it doesn't matter if your app is running at 1000 FPS or 2 FPS, you'll still move things at the same speed.

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
Quote:
Original post by billhsu
Quote:
Original post by Evil Steve
1. Are you absolutely sure you want to lock the FPS instead of making your game run at any frame rate?


I just want to make sure that the game can run at a same speed no matter on a quick machine or a slow one,how to do it?
The best way is to base movement on time, not a fixed step. So, if you were previously moving a sprite 1 pixel per frame at 60 FPS, you'd want to move it 60 pixels per second. Then it doesn't matter if your app is running at 1000 FPS or 2 FPS, you'll still move things at the same speed.


Thanks,
but should i use timeGetTime()or QueryPerformanceCounter & QueryPerformanceFrequency

Share this post


Link to post
Share on other sites
Quote:
Original post by billhsu
but should i use timeGetTime()or QueryPerformanceCounter & QueryPerformanceFrequency
Usually timeGetTime() is sufficient. If you find you're running faster than you can measure with timeGetTime(), then you can start Sleep()ing or waiting longer.

There's been a few discussions about different types of timer on these forums, it should be fairly easy to track some of them down.

Share this post


Link to post
Share on other sites
Personally I am a big fan of fixed timesteps. Glenn Fiedler has a good article about that: Fix your timestep.

(sidenote: I brushed coffee over my display after reading about the internet stalker. I remember that guy from either gd.net or devmaster.net, but didn't know about his crusade :D)

Share this post


Link to post
Share on other sites
Quote:
Original post by phresnel(sidenote: I brushed coffee over my display after reading about the internet stalker. I remember that guy from either gd.net or devmaster.net, but didn't know about his crusade :D)


That's hilarious. [lol]

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
1. Are you absolutely sure you want to lock the FPS instead of making your game run at any frame rate?
2. Enable v-sync. That'll lock you to the monitors refresh rate (Although not necessarily 60 FPS).
3. You should be processing all messages before running a game tick, not just one.
4. GetTickCount() is only accurate to ~15ms. Using it to measure 30ms is a pretty high margin of error.
5. Sleep(1) will sleep for at least 1ms. Usually it'll sleep for between 10 and 250ms (>= One scheduler timeslice).
6. That looks suspiciously like DirectXTutorial source code, which is (IMO) a pretty terrible site to be learning from.


Maybe I'm doing something wrong but I let my game run as fast as it can. And when using the time based movement if the framerate drops then movement gets choppy because objects travel so much farther between frames.

Share this post


Link to post
Share on other sites
Hi!
What do you experienced programmers think of that?

initializing:

QueryPerformanceFrequency((_LARGE_INTEGER*)(&Sys_Freq));

Main loop:

...
while( delta < Sys_Freq/MAX_FPS ) // maximize fps
{ QueryPerformanceCounter((_LARGE_INTEGER*)(&ticks));
delta = ticks - PrevTicks;
}

PrevTicks = ticks;
...


Why is timeGetTime used more in games than QueryPerformanceCounter?

Share this post


Link to post
Share on other sites
Quote:
Original post by szecs
Hi!
What do you experienced programmers think of that?


I don't know if I qualify as "experienced", but what I think is that your approach is a great way of literally "doing nothing" by wasting CPU cycles and pointlessly hogging ressources that could be used by other threads/processes. And since you a) can't rely on being woken up in time even after a sleep(0) (depending on the platform should give up the remaining time slice so someone else can do something useful) and b) can't control when the scheduler will put you to sleep and for how long it's pretty likely that you won't do the next frame when you intended to.

With time based movement that's not a big issue. With fixed time steps, you will correct accumulated errors by occasionally doing two steps. With the "sitting on my thumbs"-approach you will end up waiting longer than intended by 15-100ms (or longer, depending on the platform), pretend that it was exactly 16.6ms and after a few seconds your object will be nowhere near the position it should be.

I might be missing some factor that fixes the issue, but from my understanding the approach is not just wasteful, but also won't work the way you expect.

Share this post


Link to post
Share on other sites
It's not clear, that you are saying (I'm not so good in English), But this method is precise(ok not too precise, but enough), but wasteful, that's truth (same wasteful as running on full 3000 fps, but my videocard doesn't like it)

I don't use sleep().

The rest of the code:

__int64 ticks, delta = 0;

while( delta < Sys_Freq/MAX_FPS )
{ QueryPerformanceCounter((_LARGE_INTEGER*)(&ticks));
delta = ticks - PrevTicks;
}

PrevTicks = ticks;

Frame_Per_Sec = (double)Sys_Freq/delta;

for example particle motion:

double dt = 1.0/Frame_Per_Sec;

Particles[i].vx += accel[0]*dt;
Particles[i].vy += accel[1]*dt;
Particles[i].vz += accel[2]*dt;

Particles[i].x += Particles[i].vx*dt;
Particles[i].y += Particles[i].vy*dt;
Particles[i].z += Particles[i].vz*dt;



How can this wasting be replaced when using QueryPerformanceCounter?
For some reason, the VSYNC doesn't work, but that's OFF.

[Edited by - szecs on July 3, 2009 3:40:29 AM]

Share this post


Link to post
Share on other sites
You CANNOT control the FPS speed of your program on a PC.

If you try to lock the framerate with vsync, I might disable it in my graphics card utility. Or my PC may not be fast enough to keep up.

The gaffer article linked to is encouraging you to fix your logic timestep but to render as fast as possible. It then explains how to use interpolation to smooth out the artifacts this can create.

It really is the best solution. On a PC, trying to run everything at a fixed FPS is simply not workable.

Share this post


Link to post
Share on other sites
Quote:
Original post by szecsWhy is timeGetTime used more in games than QueryPerformanceCounter?

QueryPerformanceCounter is broken on a range of AMD processors, and you can't expect end users to download a driver update to fix it, because most won't. Personally, I think QueryPerformanceCounter is the best option because it has the highest resolution, but you need to use a secondary timing method as well, and compare the delta from both methods, switching to the secondary result if the difference between the two is ever over a certain threshold.

On the topic in general, I just want to add that I agree with those recommending the timing method discussed by Glenn Fiedler. His article should be considered the Gospel on game timing as far as I'm concerned, and it's from a guy who worked on heavy-duty networked physics-laden FPSs, so you know it covers all bases. Time-based movement is fine for very simple games with no networking and no real physics though.

Share this post


Link to post
Share on other sites
Quote:
Original post by szecs
I don't use sleep().


But unless you're on some kind of console with different rules, the OS and the scheduler are deciding when and for how long you get to run. It doesn't matter if you use sleep(), at some point the OS will decide that you've been running long enough and that it's someone elses turn. And nobody knows when you get to continue. So in a way using sleep() (as bad a solution as it is) might still be better than this approach, because at least the scheduler will know when you want to run again.

However, in the rest of your code it seems that you DO use the time that has really passed, so all movements should still be correct.

Just keep in mind that a worst case will look like this:

loop, loop, loop, 1ms left to wait, OS puts you to sleep, 10-200ms later you finally get to continue, delta is now Sys_Freq/MAX_FPS + X (with X being 0-x00ms). Eventually you didn't do any better than someone using sleep() (or even worse), but wasted more ressources.

Share this post


Link to post
Share on other sites
The while code is only used to limit the framerate, because my demo runs at nearly 3000 fps without it, and my videocard emits a strange noise, I don't know , maybe the cooler.
But it's clear for me now that it isn't a good method I'm using, but I don't really want to go deeper in the thing, I'm only a hobby "programmer". But thanks for the replies anyway.

Share this post


Link to post
Share on other sites
Quote:
Original post by szecs
The while code is only used to limit the framerate, because my demo runs at nearly 3000 fps without it, and my videocard emits a strange noise, I don't know , maybe the cooler.
But it's clear for me now that it isn't a good method I'm using, but I don't really want to go deeper in the thing, I'm only a hobby "programmer". But thanks for the replies anyway.



The noise you hear is 'coil whine'. It's harmless.

Share this post


Link to post
Share on other sites

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