Archived

This topic is now archived and is closed to further replies.

Locking FPS- Part II

This topic is 6364 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

ok, I have a question similar to that topic called Locking FPS posted a couple of days ago. I am using OpenGL as my api and I want to rotate a line at constant speed. Now, the difficulty I am having with this is if I don''t "lock" the FPS , then I don''t get a constant rotation! The way I lock the FPS is like this: .... QueryPerformanceCounter((LARGE_INTEGER *) &time); while ( (double)(time - timer.performance_timer_start)*milli < double(DELAY)) QueryPerformanceCounter((LARGE_INTEGER *) &time); TimerInit(); //reset timer .....//draw the line here ...//loop back now if you have noticed, there is a variable called DELAY. This is my set delay variable in ms. If I set that to 1ms, then the line draws sooo fast that I can''t even see! timer.performance_timer_start holds the time since the program started. So how do I make my line rotate at a CONSTANT rate if I want to achieve as much as FPS as possible? P.S: I tried using Sleep() instead of the tight while loop and the program does not respond in Windows 98, but does in Windows NT. That''s another problem I cannot solve!

Share this post


Link to post
Share on other sites
the sole reason why I tried using Sleep() is that it releases the CPU usage. In the while loop I need to waste cycles so I thought sleep() should be ok, but it wasn''t!

Share this post


Link to post
Share on other sites
It''s my firm belief that locking the frame-rate down is a bad idea. There are too many different computer configurations out there for that to work well in practice.

Anyway, a good way to handle this situation is to decide how quickly you want that line to rotate. Maybe one complete rotation every two seconds? Figure out what speed you want, and then you implement it something like this:

First, when you''re setting up your quick timers in the first place, you want to call QueryPerformanceFrequency(). (I think that''s what its called) You save this value, and calculate it''s reciprocal. Now, every frame you''re finding out how much time has past since the last frame, right? Take that variable, and multiply it by that reciprocal you found, and you''ll have a fraction of a second to work with. (Calculate the reciprocal of that and I think you get the frame rate.

Now, I''m not sure how you''re representing that rotation, in radians or degrees. But, if you wanted say, a full rotation every two seconds, you''d define a rotation speed of 180 degrees/sec or 1 pi/sec for the line. Then, each frame, you multiply that value by the fraction of a second you calculated. That tells you how far to rotate your line. Update your rotation variable, move on to the next frame, find the time that''s elapsed, and do it all over again. There ya go, smooth rotation, and it will run as fast as is can.

Jonathan

Share this post


Link to post
Share on other sites
What he''s trying to say is not as hard as it sounds, and it is -THE- correct way to do what you''re trying to do. See if you can understand this pseudocode:

Const RotationRate = 360 //rotate 360 degrees in one second
myAngle = 0

StartLoop

BeginTimer = currentTick
DrawLine
EndTimer = currentTick

elapsedTime = (endTimer - BeginTimer) //calculate elasped time
myAngle = myAngle + RotationRate * elapsedTime

EndLoop

This is the fundamental algorithm you should use. It''s very easy to understand and is completely independent of the framerate, since the more FPS you get, the lower the elapsedTime will be (and so the movement per frame is less).

If you want to actually have your units in seconds, as the previous poster said, just be sure to divide your ElapsedTime by (1/QueryPerformanceFrequency()).

G''luck


Share this post


Link to post
Share on other sites
I just realized I had a question along the same lines as this. Obviously, I understand how to write framerate independent code, multiplying by DeltaTime or whatever. I have particles like this:

x = x + velocityX * ElapsedTime
y = y + velocityY * ElapsedTime

Which works wonderfully. -BUT-

The particles are subject to gravity, so I have to do a little

velocityY = velocityY + gravity * ElapsedTime

Which sort of makes "y" doubly dependant on the ElapsedTime, or something strange like that -- or is it my imagination? Is this code valid, or do I need to figure out some sort of integration or something? I can convince myself that it''s right but I''m not 100% sure, it seems to stutter a little when the game runs.

Thanks!

Share this post


Link to post
Share on other sites
Compare your implementation with the formulae from physics and judge for yourself

Pos = Pos + Vel*dt
Vel = Vel + Acc*dt

In this case Acc is your gravity, and dt is an infinitely small timedifference. To get the pos after say 1 sec you would have to integrate the formulae over 1 sec. But with numerical representations it is difficult to use infinitely small numbers so just use the time since last frame instead. Oh, and you are already integrating your formulae in your implementation, the difference is that you are doing it iteratively.

- WitchLord

Share this post


Link to post
Share on other sites
I think it''s better to have just one "timer" that updates the elapsed time when a frame is shown to the user (with a flip or a blit or whatever) and then uses that as a base in all calculations. If you have one timer for each object things drawn just before the frame is updated will appear to move much faster than things that are drawn shortly after the frame was updated.

Or something like that...

/CMN

Share this post


Link to post
Share on other sites
Thanks Witchlord, and I know the formulas are correct, but are you 100% sure that your logic holds?

Let''s say the initial Y velocity was ZERO pixels/sec and gravity was 10 pixels/sec^2.

Now let''s say we''ve got one computer that can manage this simulation at 1 FPS, and another that can manage 2FPS.

On the computer with 1FPS, after one second, we increase the velocity to 10 p/s and then update the position, so y = 10.

On the computer with 2FPS, after .5 seconds, we increase velocity to 5 p/s and the position also, so y = 2.5. (Because deltaTime = .5 and velocity is 5). Then, after another .5 seconds, we increase velocity to 10 p/s (which is EQUAL!) and the position to y = 7.5, because deltaTime = .5 and velocity is 10.

So despite having an equal amount of time elapsed, the final POSITIONS are different, because they are intuitively "second-degree" (wrong mathematical term I''m sure) deltaTime functions. Note that the velocities are equal, however.

Please help, or point out a flaw in my logic!

Share this post


Link to post
Share on other sites
There is no flaw in your logic. Because the two computers update at different intervals they are going to get different results. This is because the iterative integration that we perform in these formulae are only approximations of the true integration. This is the only reason why you should lock the framerate at times, because you need to get the exact same result on both machines. Note you don''t have to lock the frame rate of your game, only the rate of updating the positions and velocities.

You should also know that with the simple formulae we have in our particle example can be integrated to a higher formula (of second degree) that can then be used to compute the position of the particle each frame without using iterative integration.

- WitchLord

Share this post


Link to post
Share on other sites
ahhhh this thing is driving me insaneeeee!!!
Ok Masterworks I did what you told me in your pseudocode but it still runs too fast!
what mistake(s) am I making?

Here is the code I used:
beginning of the code i have this:
....
QueryPerformanceFrequency((LARGE_INTEGER *) &timer.frequency);
QueryPerformanceCounter((LARGE_INTEGER *)&timer.performance_timer_start);
timer.resolution = (float)1.0/timer.frequency;
....

now in the draw routine I have this:

{
__int64 time;
static double angle = 0.0, nt = 0.0;
double milli = timer.resolution*1000.0; //convert to ms
QueryPerformanceCounter((LARGE_INTEGER *) &time);

nt = (double)(time - timer.performance_timer_start)*milli;

angle= angle+(360*nt/1000.0);
....//rotate the line using angle.
...swap buffer
}

and it still doesn''t work!! (well its out of control)


sig u say?

Share this post


Link to post
Share on other sites
ok i managed to get it work!!!
all i had to do was to reset the timer:

quote:
Original post by Xtreme

ahhhh this thing is driving me insaneeeee!!!
Ok Masterworks I did what you told me in your pseudocode but it still runs too fast!
what mistake(s) am I making?

Here is the code I used:
beginning of the code i have this:
....
QueryPerformanceFrequency((LARGE_INTEGER *) &timer.frequency);
QueryPerformanceCounter((LARGE_INTEGER *)&timer.performance_timer_start);
timer.resolution = (float)1.0/timer.frequency;
....

now in the draw routine I have this:

{
__int64 time;
static double angle = 0.0, nt = 0.0;
double milli = timer.resolution*1000.0; //convert to ms
QueryPerformanceCounter((LARGE_INTEGER *) &time);

nt = (double)(time - timer.performance_timer_start)*milli;
<-----reset timer here----->
angle= angle+(360*nt/1000.0);
....//rotate the line using angle.
...swap buffer
}

and it still doesn''t work!! (well its out of control)


sig u say?


thanks to all those who have helped me


sig u say?

Share this post


Link to post
Share on other sites