Advertisement

Using Timers

Started by March 12, 2005 04:48 AM
3 comments, last by lc_overlord 19 years, 8 months ago
anyone had any luck with the timer?? public long currentTimeMillis() { timer.tick(); System.out.println("Timer = " + timer.getTime()); return (long) (timer.getTime()*1000f); } produces some weird results, i thought it might increment but it seems to pass between negatives and positives! :p can the timer be used to move objects at a constant rate, and by varying it, speed them up? thanks
For an excellent example on timers, look at Lesson 21

This timer regulates the speed at which an object moves so that no matter how fast or slow the framerate is, the object is moving at "about" the same speed.

//~~~~~Computer Speed Compensation::nehe.gamedev.net/    struct    {       __int64 frequency;       float resolution;       unsigned long mm_timer_start;       unsigned long mm_timer_elapsed;       bool performance_timer;       __int64 performance_timer_start;       __int64 performance_timer_elapsed;    } timer;    float speed_mod=0.0;...//Initiate Timer Function::nehe.gamedev.net/void TimerInit(void){	memset(&timer, 0, sizeof(timer));	if (!QueryPerformanceFrequency((LARGE_INTEGER *) &timer.frequency))	{		timer.performance_timer	= FALSE;		timer.mm_timer_start	= timeGetTime();		timer.resolution		= 1.0f/1000.0f;		timer.frequency			= 1000;		timer.mm_timer_elapsed	= timer.mm_timer_start;	}	else	{		QueryPerformanceCounter((LARGE_INTEGER *) &timer.performance_timer_start);		timer.performance_timer = TRUE;		timer.resolution = (float)(((double)1.0f)/((double)timer.frequency));		timer.performance_timer_elapsed	= timer.performance_timer_start;	}}...//Very Precise Get Time Function::nehe.gamedev.net/float TimerGetTime(){	__int64 time;	if(timer.performance_timer)	{		QueryPerformanceCounter((LARGE_INTEGER *) &time);		return((float)(time-timer.performance_timer_start)*timer.resolution)*1000.0f;	}	else	{		return((float)(timeGetTime()-timer.mm_timer_start)*timer.resolution)*1000.0f;	}}


Implementation
1. Call the "TimerInit();" function right after you create your opengl window.
2. Call the "TimerGetTime()" function after you switch buffers like this: "speed_mod=(TimerGetTime()-start)/1000.0f;"
3. speed_mod now holds your timing correction, apply to object movement such as translation, rotation, and ect followed by a number to dictate how fast you want the object to be moving overall.

Example:
static float degree=0;
glRotatef(degree, 1.0, 0.0, 0.0);
degree+=5*speed_mod;

When the computer is able to render very fast, the amount of time that passes between each called rotation is short so therefore speed_mod will be something like 0.2. Whereas if the computer is rendering slowly, the amount of time that passes between each called rotation is longer so therefore speed_mod will be something like 0.9 or 1.5.

In one second, the object will advance in rotation about the same in a slow computer or fast computer.
Advertisement
well that is all good and well for simple aplications, but if your doing physics, colition detection or something like that, you might want to choose another method.

basicly you put all those things in a function, and whenever you run that function the time ticks forward a set amount of time(let's say 0.01 seconds, or 100 FPS).
so then for each frame you render you first check how mutch time has passed since the last frame.
Then let's say 0.05 seconds has passed (or 20 fps), then you would have to run your physics and movement functions five times before rendering.
If your rendering at 200 fps you only do the physics every other frame.

It's a bit trickier to code but you do get consistent timing all over the place, and if you want to do matrix style bullet time effects you just reduce the set timevalue that the timing function uses (basicly you make it think that it runs at 200 fps when it actuarly runs at 20).

here is some pseudo code
// timeleft is a global floattimeStep=0.01f;  timeLeft+=getTimePassedSinceLastFrame;while(timeLeft>=timeStep){ runPhysicsAndMovements(timeStep); timeLeft-=timeStep;}renderMyScene();


[Edited by - lc_overlord on March 12, 2005 4:25:39 PM]
I used a bit different verison:

// timeleft is a global floattimeStep=0.01f;  float timeLeft = getTimePassedSinceLastFrame;while( timeLeft >= timeStep ) {  runPhysicsAndMovements( timeStep );  timeLeft -= timeStep;}if ( timeLeft > 0.0f ) runPhysicsAndMovements( timeLeft );renderMyScene();
You should never let your fears become the boundaries of your dreams.
that would work to, sort of.

there are some issues
since you never carry the leftover time to the next frame the simulation will behave badly at framerates over the timestep framrate.
Most significantly, it canot be run with less phys updates than one per frame since you will always run atleast on physupdate per frame.

here is a better phys update(well maybe), in this one timeLeft can actuarly go below 0 so to more equaly spread the phys updates
// timeleft is a global floattimeStep=0.01f;  timeLeft+=getTimePassedSinceLastFrame;while(timeLeft>=(timeStep/2)){ runPhysicsAndMovements(timeStep); timeLeft-=timeStep;}renderMyScene();

This topic is closed to new replies.

Advertisement