Allegro.cc - Online Community

Allegro.cc Forums » Game Design & Concepts » Timer Method

This thread is locked; no one can reply to it. rss feed Print
 1   2 
Timer Method
Onewing
Member #6,152
August 2005
avatar

When I started using Allegro, I was in a rush to finish a college project with it, hence my study time was low. Originally, I just used the clock() method of somewhat governing my game. For ChristmasHack, I decided to use/learn the allegro methods.

After a little messing around and reading other discussions about timers (there's quite a bit if you do a forum search), I've got a basic understanding. I thought I'd present my methodology and see what the general consensus is, pros and cons.

Without further ado,

My timer function is very simple:

volatile int system_timer;
void GAME_TIMER()
{
    system_timer++;
}
END_OF_FUNCTION(GAME_TIMER);

In the init routine at the beginning of the game, I do the following:
install_int_ex(GAME_TIMER, MSEC_TO_TIMER(1))
where the idea is that system_timer increments every millisecond. The LOCK variable and function commands immediately follow.

Here's where system_timer begins to control things, at least, if I've imagined this correctly. I kind of use a time stamping method. Typically what I do is create timestamp-like integers that remember when a certain time occurs and when there is a certain amount of difference between the timestamp-like integer and the system_timer, then whatever to follow is allowed. e.g.

if(abs(system_timer - some_timestamp_integer_x) > some_determined_amount_of_time)
{
     //do whatever it is that you want to do
     some_timestamp_integer_x = system_timer;
}

To further explain, each one of my AI bots has it's own private int called "move_timer" (defined in the class) and public (this could be private as well) int "move_speed". Changing the "move_speed", I can have my AI bots walking at different speeds:

if(abs(system_timer - bot.move_timer) > bot.move_speed)
{
    // take a step in whatever direction bot is facing
    bot.move_timer = system_timer;
}

The whole idea is to have just one timer variable and the others just pretending like they're timers. What do you think? Is that a bad idea? If so, why?

------------
Solo-Games.org | My Tech Blog: The Digital Helm

Murat AYIK
Member #6,514
October 2005
avatar

I basically use a 200 ticks per second timer to do the job and a 1 tick per second one just for fun! The kernel has global-enough(!) variables like:
current_tick;
previous_tick;
new_ticks;

Calculating new_ticks is obvious. If a bot has a move speed of 0.2(per_tick) then I let it walk (bot.walk_speed * new_ticks) Works flawlessly. There is only one timer variable and it can't be touched by anyone but the kernel.

EDIT: Instead of keeping timer-clones you can better save info about what the bot wants to do and in how much time(rather then "when") Also I'm not sure a milisecond level timer would be accurate in Allegro. I remember complaints about it here. And if you insist on keeping that resolution I suggest you use a variable(like my current_tick) to be used by the logic, instead of testing the volatile one(since it is quite volatile!!)

_____________________________________________________
"The world doesn't care about what storms you sailed through, it is interested in whether you brought the ship to the dock or not!"

razor
Member #2,256
April 2002
avatar

If I rememeber right the allegro timer is only accurate to ~10ms, but that should be good enough for any game.

Whoooo Oregon State University

HoHo
Member #4,534
April 2004
avatar

Quote:

If I rememeber right the allegro timer is only accurate to ~10ms

That depends on the OS. On older windowses it was around 50ms, newer (2k, xp) ~10ms. Newer Linux kernels have 4ms default, configurable up to 1ms (if I understood kernel config correctly).

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

Onewing
Member #6,152
August 2005
avatar

Quote:

Also I'm not sure a milisecond level timer would be accurate in Allegro.

I wouldn't think so either, but I had no idea how accurate allegro could get it, so instead I opted for 1 millisecond and then shoot for an approximation. So if a certain timestamp was waiting for there to be a difference of 50ms, it might not be till 51ms, 52ms, etc. until it actually validates the difference and updates the clone. At least, that was the idea. Since I'd probably never say "when 53ms have passed", I'll probably change it to 10ms or something a little more agreeable.

------------
Solo-Games.org | My Tech Blog: The Digital Helm

Murat AYIK
Member #6,514
October 2005
avatar

Quote:

On older windowses it was arounbd 50ms, newer (2k, xp) ~10ms.

Do you think I should change my 200/sec timer to 100/sec? I chose 200 because it was the value of "i_love_bill" thing! And works well even in long term.

EDIT: Interesting! I edited my post, and it dropped to the bottom of the thread! MATTHEW!! :)

_____________________________________________________
"The world doesn't care about what storms you sailed through, it is interested in whether you brought the ship to the dock or not!"

HoHo
Member #4,534
April 2004
avatar

Quote:

Do you think I should change my 200/sec timer to 100/sec?

I don't know. If 200ms works for you I don't see a reason. Remember, don't fix it if it isn't broken ;)

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

Murat AYIK
Member #6,514
October 2005
avatar

Quote:

If 200ms works for you I don't see a reason. Remember, don't fix it if it isn't broken

Works perfectly, even in "do stg after this much time" things. And for about two months people are trying my stuff, nothing came about this. Also that 200 value is kept in a constant, I can change it later without any problems if anyone complaints about it.

EDIT: Did any of you see my last post fall down, too?!

_____________________________________________________
"The world doesn't care about what storms you sailed through, it is interested in whether you brought the ship to the dock or not!"

Thomas Harte
Member #33
April 2000
avatar

Quote:

That depends on the OS. On older windowses it was around 50ms, newer (2k, xp) ~10ms.

If you're happy to throw a Win32 specific call in to your code, you can use timeBeginPeriod to get a much better resolution on all Windows since 95.

Quote:

The whole idea is to have just one timer variable and the others just pretending like they're timers. What do you think? Is that a bad idea? If so, why?

It is a good idea. If you aren't using an update method that syncs to the retrace you might also want to consider a frame cap implemented via rest() so that all the laptops and modern desktops can power save and/or switch off some fans.

Felipe Maia
Member #6,190
September 2005
avatar

I think my method is old and stupid, instead of using the global timers, I just use logic cycles as my method to decide if it's time already or not, but that way the game wouldn't run the same on different computers, oh well, need to learn new methods.

EDIT: Actually, it is not that bad since the only harmed targets are old computers, that wouldn't be able to do the logic cycle on time, which would mean very low fps, which would mean game unplayable. No need for new methods :)

Tobias Dammers
Member #2,604
August 2002
avatar

Allegro timers have 2 major problems. First, their granularity, which differs per platform (and possibly per system). While 10ms is short enough an interval, the frequency generated from the interference of the game timer (the rate at which your position variables are updated) and the screen refresh rate (the rate at which they are displayed) can lead to very noticeable "jumps" in what is intended to be smooth movement, since there will not be a constant number of timer ticks between two (screen) frames. For example, if refresh rate is 72 Hz, and the timer runs at 10ms, then there will be 100/72 ticks per frame - some frames will contain a single logic tick, while others contain two. So in some frames, the character will move twice as far as in others.
The second problem is that allegro timers are "active" timers, meaning that for each tick, a function needs to be called, even if the logic doesn't do anything. The finer the timer resolution, the more cpu it will eat. While at 25 Hz (50msec), the cpu load is barely noticable, at 100 Hz (10 msec) the difference starts to play. "Passive" timeing methods (that only read a timer that is running anyway, such as system clock or windows' QPC), OTOH, only require a single function call per screen update; the timer itself is running anyway, you won't need a dedicated thread or process, nor does it need constant polling or updating.
In short: Allegro timing methods look nice, elegant, and useful, but aren't. I only use them as fallback when other methods aren't available.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

HoHo
Member #4,534
April 2004
avatar

I think it 4.3 series and up there should be a better timing framework. Possibly some counter that gets updated frequently* that could be used to compute the time that has passed.

*) probably red from either RDTSC, gettimeofday or whatever the current platform has

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

Murat AYIK
Member #6,514
October 2005
avatar

I was recently misdirected to a page about a timer lib named "ltimer". I didn't check it but it was presented as better than any other. I guess it was win32 only. Maybe Allegro can use the algorithms of that or another nice working one(for matching ports at least) For now, I will stick with Allegro's timers since I don't like using too many external libs together.

_____________________________________________________
"The world doesn't care about what storms you sailed through, it is interested in whether you brought the ship to the dock or not!"

Onewing
Member #6,152
August 2005
avatar

Quote:

In short: Allegro timing methods look nice, elegant, and useful, but aren't. I only use them as fallback when other methods aren't available.

So, should I just keep to the clock() (time.h) functions instead?

------------
Solo-Games.org | My Tech Blog: The Digital Helm

HoHo
Member #4,534
April 2004
avatar

I think clock() is even worse than allegro timers.

If all you need is a variable that gets updated frequently use platform specific stuff. QueryPerformanceCounter on windows and gettimeofday on *nix work perfectly.

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

Onewing
Member #6,152
August 2005
avatar

Quote:

If all you need is a variable that gets updated frequently use platform specific stuff. QueryPerformanceCounter on windows and gettimeofday on *nix work perfectly.

I did a google on QueryPerformanceCounter (being that I've never heard of that before) and noticed that, from microsoft, they say:

Quote:

However, you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL).

So it's still not going to be perfectly accurate. How comparable to clock() and allegro timer functions is that statement?

------------
Solo-Games.org | My Tech Blog: The Digital Helm

Felipe Maia
Member #6,190
September 2005
avatar

Steven it's a game, it's not a nuclear station control software. Allegro is more than enough for a game.

Onewing
Member #6,152
August 2005
avatar

Quote:

Steven it's a game

But my game is a nuclear station control software simulation! j/k ;D

Nah, I just find all of this interesting and want to know as much as possible to make the most efficient game that I can.

------------
Solo-Games.org | My Tech Blog: The Digital Helm

HoHo
Member #4,534
April 2004
avatar

Quote:

So it's still not going to be perfectly accurate.

I think that doesn't stop almost every professional game developer from using it :)

As fro clock, this s what manual says about it:

       Note that the time can wrap around.  On a 32bit system where CLOCKS_PER_SEC equals  1000000  this  function
       will return the same value approximately every 72 minutes.

       On  several  other  implementations,  the value returned by clock() also includes the times of any children
       whose status has been collected via wait() (or another wait-type call).  Linux does not include  the  times
       of  waited-for  children  in the value returned by clock().  The times() function, which explicitly returns
       (separate) information about the caller and its children, may be preferable.

I don't remember the granuality of it but I think it was quite bad. The CLOCKS_PER_SEC usually don't mean anything because:
POSIX requires that CLOCKS_PER_SEC equals 1000000 independent of the actual resolution.

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

Onewing
Member #6,152
August 2005
avatar

Quote:

On a 32bit system where CLOCKS_PER_SEC equals 1000000 this function
will return the same value approximately every 72 minutes.

In my timer method above, I used the abs() of the difference for this very reason. Nonetheless, I'm going to see if I can't get the QueryPerformanceCounter to work in place of the timer. Thanks for the info, Hoho!

------------
Solo-Games.org | My Tech Blog: The Digital Helm

Tobias Dammers
Member #2,604
August 2002
avatar

Up until now, I have found only three methods that produce smooth animation.
Number 1 updates logic along with screen refreshes. That is, every physical vsync equals one logic tick. Unfortunately, this means that the speed of your game depends on screen refresh rate, and unfortunately, modern system may or may not allow you to set it to a value of your choice. For all other systems, you have to either adjust all time-related variables (acceleration, speed, etc.) to fit the actual refresh rate.
Number 2 uses the RTSCXVKR-whatever counter. This method has several flaws though. First of all, it only works on pentium compatible cpus. Macs are out (though there may be similar mechanisms there). Secondly, there are cpus with variable clock frequencies (notebooks mainly), and since the counter counts cpu clock cycles, its speed may vary on such machines. And thirdly, there is no reliable way to detect the exact cpu speed except measuring it against yet another timing source, like for example RTC.
Number 3 uses QueryPerformanceCounter. It's windows-only, but Linux has gettimeofday() which is supposed to be comparably precise. I haven't found any problem with these yet, except that QPC is not guaranteed to work (but windows can tell you whether it does or not).
So what I did is this: I wrote a rather simple wrapper that uses QPC when available, and falls back on allegro timers in the rare cases when QPC isn't available. With some clever defines, this can easily be extended to support gettimeofday as well. In every project that needs timing, I include that wrapper, providing me with a fool-proof 3-function api (init_timers(), get_timer_delta() and done_timers()).

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

Onewing
Member #6,152
August 2005
avatar

Number 3 appears to be the most efficient, not to mention clear. ;)

EDIT: I'd give you and HoHo cookies, but I don't know if I can since I didn't make the right kind of thread (unless I can change that).

------------
Solo-Games.org | My Tech Blog: The Digital Helm

gnolam
Member #2,030
March 2002
avatar

Quote:

EDIT: I'd give you and HoHo cookies, but I don't know if I can since I didn't make the right kind of thread (unless I can change that).

Try these: http://www.twinkies.com/images/box_hohos.jpg HoHos

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

Tobias Dammers
Member #2,604
August 2002
avatar

Yum. On a side note, these have been known to me as "Cadbury's Mini Rolls" since that one holiday I spent cycling the south coast or Ireland. Although I did at least 60 km's a day with heavy luggage, I gained something like 3 to 5 kg's. Damn you, Mini rolls!

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

HoHo
Member #4,534
April 2004
avatar

heh, they look tasty :)

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

 1   2 


Go to: