Sign in to follow this  

Timer Mistake

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

Hello, I have a Timer class that uses SDL_GetTicks() for tick counting. It calls a callback function given by user via function pointer everytime inverval achieved. But it don't work properly. For example if i give 1000 as interval to constructor and start timer, after 7500 ticks, callback is called only for a few times but i was expecting it should be called for 7 times in that case. Some Codes:
ITimer::ITimer(int _iInterval, int _iRunning, void (*_vfCallback)(int, int), int _iLParam, int _iRParam)
{
	iInterval = _iInterval;
	iRunning = _iRunning;
	vfCallback = _vfCallback;
	uiTicks = 0;
	iLParam = _iLParam;
	iRParam = _iRParam;
	uiTicksWhenStarted = SDL_GetTicks();
}

void ITimer::Update()
{
	if(iRunning != 0)
	{
		uiTicks = SDL_GetTicks() - uiTicksWhenStarted;
		if((uiTicks % iInterval) == 0 && vfCallback != NULL)
			vfCallback(iLParam, iRParam);
	}
}

void ITimer::Start()
{
	iRunning = 1;
	uiTicks = 0;
}

void asd(int a, int b)
{
	counter++;
}




int main(int argc, char *argv[])
{
//
//some inits here ...
//

time = new ITimer(123, 1, asd, NULL /*lParam*/, NULL /*rParam*/);
time->Start();

 while(done == 0)
 {
   time->Update();
   //
   // game and render loop code here
   //
 }
//
// deallocs
//
}

I guess (uiTicks % iInterval) doesn't increase by 1. Also an image: http://img49.imageshack.us/img49/9227/clipboard01je1.png

Share this post


Link to post
Share on other sites
Quote:
I guess (uiTicks % iInterval) doesn't increase by 1.


Indeed. You don't want to trigger the event at the time where it was expected to trigger. You want to trigger the event if it should have already happened when you check the time.

Share this post


Link to post
Share on other sites

ITimer::ITimer(int _iInterval, int _iRunning, void (*_vfCallback)(int, int), int _iLParam, int _iRParam)
{
iInterval = _iInterval;
iRunning = _iRunning;
vfCallback = _vfCallback;
uiTicks = 0;
iLParam = _iLParam;
iRParam = _iRParam;
lastTimerTrigger = SDL_GetTicks();
}


void ITimer::Update()
{
if(iRunning != 0)
{
int timeSinceLastUpdate = SDL_GetTicks() - lastTimerTrigger;
if(timeSinceLastUpdate > iInterval && vfCallback != NULL) {
lastTimerTrigger = SDL_GetTicks();
vfCallback(iLParam, iRParam);
}
}
}








Depending on design, you may want to consider what happens when multiple intervals have elapsed since your last update. In which case you could do something like this:



void ITimer::Update()
{
if(iRunning != 0)
{
int timeSinceLastUpdate = SDL_GetTicks() - lastTimerTrigger;
while(timeSinceLastUpdate > iInterval && vfCallback != NULL) {
vfCallback(iLParam, iRParam);
timeSinceLastUpdate -= iInterval;
}
// timeSinceLastUpdate is now some left-over time. Push
// back lastTimerTrigger to account for that amount of elapsed
// time for the next time we get an Update
lastTimerTrigger = SDL_GetTicks() - timeSinceLastUpdate;
}
}








This way, if your interval is 5 seconds, but 11 seconds have passed since your last update, the callback will be called twice.

You may not want exactly that, but hopefully you should get the idea.

[Edited by - Tenbatsu on December 5, 2007 9:11:37 PM]

Share this post


Link to post
Share on other sites

This topic is 3663 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this