Wednesday, February 18, 2009

Timer Tutorial

*This tutorial is taken with permission from user A_Nub at MforMature.net


Well, I am not sure how many people have trouble with this, but hey it is always good to have a reference. This is the second tutorial I have written so bear with me if and when I explain things poorly.

Prerequisite:
* Understanding of C/C++ syntax
* Comfortable Coding in C/C++

Concepts Covered:
* Timing (based on ctime)


Intro:
Ok so lets start with an example. Say you have a variable, and you need it to be updated exactly every 2 seconds. How would you achieve this? Well you could use a loop and stall it the proper amount of time for the CPUs speed to wait 2 seconds. That however would be silly and uncalled for, and wastes CPU time for other processing. So we will use a simple utility found in the standard C library called ctime (time.h).

The Process:
time.h contains many useful functions for time, including but not limited to obtaining the date, the time of day and number of ticks.

Tick - a single iteration of the never ending "loop" on the RTC (Real Time Clock) processor. A ticks interval is always exactly the same time from the previous tick. There is a constant that defines this time, and is relevant to the device being compiled for.

What we are using:
Now we will move into ctime and how we will obtain the time passed by using a simple calculation via ticks. Now you may ask, "if we can just get the time, why waste cpu calculating the time?" this is because obtaining the systems time is actually a lot slower and requires more memory.

So we will need only 2 things from ctime.

1) clock_t clock(); // returns the current tick
2) CLOCKS_PER_SEC;

Now we have introduced some questions. "What is a clock_t?" and "What is CLOCKS_PER_SEC?"
A clock_t is simply a typedef unsigned int.
CLOCKS_PER_SEC is simply the number of ticks per second.

The TUT:
Ok here we go. First off we need to create some variables.

/*
Timer.cpp By: Zachry Thayer (c) 2009
*/

#include

class Timer{
private:
clock_t startTick;//the tick for when we first create an instance
clock_t currTick;//the most recent tick read
clock_t lastTick;//the tick from the last update
clock_t deltaTick;//currTick - lastTick

float elapsedSeconds;// time since created in seconds
float deltaSeconds;// time since last tick in seconds
/*


Now we need to declare our class methods

/*
Constructor
*/
Timer();

/*
Deconstructor
*/
~Timer();

/*
Update Timer (to be called once per main loop[more often for more accuracy])
*/
void update();

/*
Return Elapsed time since the timer was created
*/
float elapsedTime();

/*
Return Delta time since the timer was created
*/
float deltaTime();

/*
Reset elapsed time to 0
*/
void reset();
};


Seems simple enough so far, now we get into the actual code.

/*
Constructor
*/
Timer::Timer(){
startTick = clock();//Obtain current tick
currTick = startTick;//All ticks are the same since we have just been created
lastTick = currTick;//copy ^
deltaTick = 0;// X - X = 0

elapsedSeconds = 0.f;//no time has passed
deltaSeconds = 0.f;//ditto ^
}

/*
Deconstructor
*/
Timer::~Timer(){
//we did not allocate any dynamic data
}


Ok simple enough so far, just initializing variables. Now for the part you all wanted the timer update.


/*
Update Timer (to be called once per main loop[more often for more accuracy])
*/
void Timer::update(){
lastTick = currTick;//store the currTick before we update it
currTick = clock();//update current tick
deltaTick = currTick - lastTick;//calculate the difference in ticks
deltaSeconds = (float)deltaTick/(float)CLOCKS_PER_SEC;//Simple division to calculate seconds based on the number of ticks
elapsedSeconds += deltaSeconds;// add to overall time
}


Pretty Simple huh.
The rest here is self explanatory.

/*
Return Elapsed time since the timer was created
*/
float Timer::elapsedTime(){
return elapsedSeconds;
}

/*
Return Delta time since the timer was created
*/
float Timer::deltaTime(){
return deltaSeconds;
}

/*
Reset elapsed time to 0
*/
void reset(){
elapsedTime = 0.f;
}



Original Tutorial Link

No comments:

Post a Comment