Timing and FPS

Published May 07, 2012
Advertisement
In this tutorial, we will learn how to create a timer to be used in our projects. We can use our timer for Creating a constant experience over multiple configurations, Calculating the FPS(Frames per second) etc.
The timer class will keep track of the Total Running Time, the time elapsed between 2 frames i.e between consecutive calls to Update and the FPS

[subheading]ITimer Interface : Timer.hxx[/subheading]
[spoiler]

namespace Utilities
{
class ITimer
{
public:
virtual ~ITimer(){}
UTILITIES_API virtual void VStartTimer() = 0;
UTILITIES_API virtual void VStopTimer() = 0;
UTILITIES_API virtual void VOnUpdate() = 0;
UTILITIES_API virtual bool VIsStopped() const = 0;
UTILITIES_API virtual float VGetFPS() const = 0;
UTILITIES_API virtual float VGetRunningTime() const = 0;
UTILITIES_API virtual TICK VGetRunningTicks() const = 0;
UTILITIES_API virtual float VGetDeltaTime() const = 0
UTILITIES_API static ITimer * CreateTimer();
};
}

[/spoiler]

[subheading]cTimer Class : Timer.h[/subheading]
The cTimer class handles the creation of the timer
[spoiler]

namespace Utilities
{
class cTimer
: public ITimer
, public Base::cNonCopyable
{
public:
static cTimer * Create();

private:
cTimer();
~cTimer();

void VStartTimer();
void VStopTimer();
void VOnUpdate();
bool VIsStopped() const;
float VGetFPS() const;
float VGetRunningTime() const;
float VGetDeltaTime() const;
TICK VGetRunningTicks() const;

private:
INT64 m_iTicksPerSecond;
INT64 m_iCurrentTime;
INT64 m_iLastUpdateTime;
INT64 m_iLastFPSUpdateTime;
INT64 m_iFPSUpdateInterval;
UINT m_iNumFrames;
float m_fRunningTime;
float m_fDeltaTime;
float m_fFPS;
bool m_bTimerStopped;
};
}

[/spoiler]

[subheading]Implementation : Timer.cpp[/subheading]
Constructor: In the constructor, we check how many times per second the system counter fires by making a call to QueryPerformanceFrequency. We also set the FPS update interval to half a second because if we updated the FPS every frame, it would change too fast for us to see.
[spoiler]

Utilities::cTimer::cTimer()
: m_iCurrentTime(0)
, m_iLastUpdateTime(0)
, m_iLastFPSUpdateTime(0)
, m_iNumFrames(0)
, m_fFPS(0.0f)
, m_fRunningTime(0.0f)
, m_fDeltaTime(0.0f)
, m_bTimerStopped(true)
{
if(!QueryPerformanceFrequency( (LARGE_INTEGER *)&m_iTicksPerSecond ))
{
// error
}

// update every half second
m_iFPSUpdateInterval = m_iTicksPerSecond >> 1;
}

[/spoiler]
Destructor:
[spoiler]

Utilities::cTimer::~cTimer()
{
}

[/spoiler]
Create: This function Create and Returns an object of this class.
[spoiler]

cTimer * Utilities::cTimer::Create()
{
return DEBUG_NEW cTimer();
}

[/spoiler]
VStartTimer: This function starts the timer if it has not already been started by getting the current value of the high-resolution performance counter.
[spoiler]

void Utilities::cTimer::VStartTimer()
{
if (m_bTimerStopped )
{
QueryPerformanceCounter( (LARGE_INTEGER *)&m_iLastUpdateTime );
m_bTimerStopped = false;
}
}

[/spoiler]
VStopTimer: This function stops the timer if it has not already been stopped and update the running time
[spoiler]

void Utilities::cTimer::VStopTimer()
{
if (!m_bTimerStopped )
{
INT64 iStopTime = 0;
QueryPerformanceCounter( (LARGE_INTEGER *)&iStopTime );

m_fRunningTime += (float)(iStopTime - m_iLastUpdateTime) / (float)m_iTicksPerSecond;
m_bTimerStopped = true;
}
}

[/spoiler]
VOnUpdate: This function Calculates the time elapsed since the last update call and updates the FPS and total running time.To calculate the FPS, we divide the frame counter by the time passed since the last time the FPS was calculated. Once the FPS is calculated, we reset the frame counter to 0.
[spoiler]

void Utilities::cTimer::VOnUpdate()
{
if (!m_bTimerStopped )
{
QueryPerformanceCounter( (LARGE_INTEGER *)&m_iCurrentTime );

m_fDeltaTime = (float)(m_iCurrentTime - m_iLastUpdateTime) / (float)m_iTicksPerSecond;
m_fRunningTime += m_fDeltaTime;

m_iNumFrames++;

if ( m_iCurrentTime - m_iLastFPSUpdateTime >= m_iFPSUpdateInterval )
{
// Calculate FPS
float fCurrentTime = (float)m_iCurrentTime / (float)m_iTicksPerSecond;
float fLastTime = (float)m_iLastFPSUpdateTime / (float)m_iTicksPerSecond;
m_fFPS = (float)m_iNumFrames / (fCurrentTime - fLastTime);

m_iLastFPSUpdateTime = m_iCurrentTime;
m_iNumFrames = 0;
}
m_iLastUpdateTime = m_iCurrentTime;
}
}

[/spoiler]
VIsStopped: Returns true if the timer is stopped
[spoiler]

bool cTimer::VIsStopped() const
{
return m_bTimerStopped;
}

[/spoiler]
VGetFPS: Returns the FPS
[spoiler]

float cTimer::VGetFPS() const
{
return m_fFPS;
}

[/spoiler]
VGetRunningTime: Returns the running time
[spoiler]

float cTimer::VGetRunningTime() const
{
return m_fRunningTime;
}

[/spoiler]
VGetRunningTicks: Returns the running ticks
[spoiler]

TICK cTimer::VGetRunningTicks() const
{
return (TICK)m_fRunningTime;
}

[/spoiler]
VGetDeltaTime: Returns the elapsed time between frames
[spoiler]

float cTimer::VGetDeltaTime() const
{
if (m_bTimerStopped)
{
return 0.0f ;
}
return m_fDeltaTime;
}

[/spoiler]
CreateTimer: Creates and returns a pointer to an object of this class
[spoiler]

ITimer * ITimer::CreateTimer()
{
return cTimer::Create();
}

[/spoiler]

[subheading]Using the timer[/subheading]
[spoiler]
Create the timer

pGameTimer = ITimer::CreateTimer();

Start The timer

pGameTimer->VStartTimer();

Update the timer each frame

pGameTimer->VOnUpdate();

Use the accessor functions
[/spoiler]
Next Entry Update
1 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement