Skip to main content
GameDev.net gamedev.net
🔒 Locked

Timing Question

Started by ehsan2004 Jan 2, 2007 at 3:29 AM 4 replies 1.8k views
Original Post
ehsan2004
ehsan2004
Hi there I use from a high resolution Timer class in my game.The problem is that my game is run with different speeds in different systems! Here's two major functions of this class: code: bool TIMER::Init() { if (!QueryPerformanceFrequency(&m_ticksPerSecond)) { // system doesn't support hi-res timer return false; } else { QueryPerformanceCounter(&m_startTime); return true; } } // end Init() float TIMER::GetElapsedSeconds(unsigned long elapsedFrames) { static LARGE_INTEGER s_lastTime = m_startTime; LARGE_INTEGER currentTime; QueryPerformanceCounter(&currentTime); float seconds = ((float)currentTime.QuadPart - (float)s_lastTime.QuadPart) / (float)m_ticksPerSecond.QuadPart; // reset the timer s_lastTime = currentTime; return seconds; } // end GetElapsedSeconds() I use from this class in this manner: TIMER * timer; In my Init() function I call: timer = new TIMER(); if( !timer->Init() ) { //MessageBox return 0; } At the beginning of Render() function I call: float elapsedTime = timer->GetElapsedSeconds( 1 ); And I use from elapsedTime every time I want to Increment/decrement values. As an example: float index += constant_value * elapsedTime; So what's the problem? -Ehsan- [Edited by - LessBread on January 2, 2007 4:22:34 AM]
Caminman
Caminman
I cannot understand your code much.

For example, why does
float TIMER::GetElapsedSeconds(unsigned long elapsedFrames); take 'elapsedFrames' as parameter if it's not being used?

currentTime seems to be used without being initialized.


And as said, I have no idea how it is supposed to work,
but how timing is commonly done is either:

* halt your loop by only continuing after atleast x milliseconds has passed (bad)
* Use velocities for your objects and just update their positions each loop with dTime * velocity (wiser).
ehsan2004
ehsan2004
This example is from the book OpenGL Game Programming.
here's timer.h:
/***************************************************************Zehne Ziba Corpotarion******************************************************************************HOW TO USE TIMER**********************Docment Written by Ehsan Kamrani***********Files:..\Common\Timer.h..\Common\Timer.cppUsage:1)Include the header file:   #include "Common\Timer.h"2)Declare a timer object:   	TIMER *timer;3)In your initialization function, initialize timer:    timer = new Timer;	if( !timer->Init() )	{        //Report an error message		MessageBox( NULL, "Cannot initialize the timer", "ERROR", MB_OK | MB_ICONINFORMATION );		return 0; 	}4)In your rendering function:    float elapsedTime;	elapsedTime = timer->GetElapsedSeconds( 1 ) ;5)In your release code, write the following code:   delete timer;   timer = NULL;/**************************************************************************************************************************//**************************************************************************** HiResTimer.h  Wrapper for the high-resolution timer. Can't be used if the hi-res timer doesn't exist.   Author   :   Dave Astle Date     :   2/1/2001 Written for OpenGL Game Programming*****************************************************************************/#ifndef __TIMER_H_INCLUDED__#define __TIMER_H_INCLUDED__#include <windows.h>class TIMER{public:  TIMER();  ~TIMER();  bool Init();  float GetElapsedSeconds(unsigned long elapsedFrames = 1);  float GetFPS(unsigned long elapsedFrames = 1);  float LockFPS(unsigned char targetFPS);private:  LARGE_INTEGER   m_startTime;  LARGE_INTEGER   m_ticksPerSecond;};#endif // __TIMER_H_INCLUDED_


And here's timer.c:
#include "Timer.h"/***************************************************************************** Init() If the hi-res timer is present, the tick rate is stored and the function returns true. Otherwise, the function returns false, and the timer should not be used.*****************************************************************************/TIMER::TIMER(){}TIMER::~TIMER(){}bool TIMER::Init(){	if (!QueryPerformanceFrequency(&m_ticksPerSecond))	{		// system doesn't support hi-res timer		return false;	}	else	{		QueryPerformanceCounter(&m_startTime);		return true;	}} // end Init()float TIMER::GetElapsedSeconds(unsigned long elapsedFrames){  static LARGE_INTEGER s_lastTime = m_startTime;  LARGE_INTEGER currentTime;  QueryPerformanceCounter(&currentTime);  float seconds =  ((float)currentTime.QuadPart - (float)s_lastTime.QuadPart) / (float)m_ticksPerSecond.QuadPart;  // reset the timer  s_lastTime = currentTime;  return seconds;} // end GetElapsedSeconds()/*************************************************************************** GetFPS() Returns the average frames per second over elapsedFrames, which defaults to one. If this is not called every frame, the client should track the number of frames itself, and reset the value after this is called.***************************************************************************/float TIMER::GetFPS(unsigned long elapsedFrames){  static LARGE_INTEGER s_lastTime = m_startTime;  LARGE_INTEGER currentTime;  QueryPerformanceCounter(&currentTime);  float fps = (float)elapsedFrames * (float)m_ticksPerSecond.QuadPart / ((float)currentTime.QuadPart - (float)s_lastTime.QuadPart);  // reset the timer  s_lastTime = currentTime;  return fps;} // end GetFPS/*************************************************************************** LockFPS() Used to lock the frame rate to a set amount. This will block until enough time has passed to ensure that the fps won't go over the requested amount. Note that this can only keep the fps from going above the specified level; it can still drop below it. It is assumed that if used, this function will be called every frame. The value returned is the instantaneous fps, which will be <= targetFPS.***************************************************************************/float TIMER::LockFPS(unsigned char targetFPS){  if (targetFPS == 0)     targetFPS = 1;  static LARGE_INTEGER s_lastTime = m_startTime;  LARGE_INTEGER currentTime;  float   fps;  // delay to maintain a constant frame rate  do {    QueryPerformanceCounter(&currentTime);    fps = (float)m_ticksPerSecond.QuadPart/((float)(currentTime.QuadPart - s_lastTime.QuadPart));  } while (fps > (float)targetFPS);  // reset the timer  s_lastTime = m_startTime;  return fps;} // end LockFPS()


-Ehsan-
Nytegard
Nytegard
What are the systems you're running?

There's a post on QPC running on dual cores, that if you have a machine with more than one core you might want to check out.
Xetick
Xetick
My guess would be that this line
float seconds = ((float)currentTime.QuadPart - (float)s_lastTime.QuadPart) / (float)m_ticksPerSecond.QuadPart;
can cause some problems for you.
QuadPart is a 64 bit integer value. float is a 32 bit float value so the precision will suffer.
So change it to
float seconds = (float)((double)(currentTime.QuadPart-m_s_lastTime.QuadPart)/(double)m_ticksPerSecond.QuadPart);
and see if that helps.
Plane9 - Home of the free scene based music visualizer and screensaver
nife
nife
Also be aware of the leap problem when dealing with QPC:
http://support.microsoft.com/kb/274323
Killers don't end up in jailThey end up on a high-score!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.