Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [A5] Main() timer's effect on called functions?

This thread is locked; no one can reply to it. rss feed Print
[A5] Main() timer's effect on called functions?
Phrasz
Member #10,091
August 2008

So I finally understand the use of the timer with a single function. (see the fade animation post)
Now I'm hoping to expand my knowledge of timers and function calls.

How should I go about having a "global timer".

The Current Method:

#SelectExpand
1main(){ 2 //create timer 3 4 timer = al_create_timer(1.0 / 60); 5 queue = al_create_event_queue(); 6 al_register_event_source(queue, al_get_keyboard_event_source()); 7 al_register_event_source(queue, al_get_display_event_source(display)); 8 al_register_event_source(queue, al_get_timer_event_source(timer)); 9 al_start_timer(timer); 10 11 while (1) { 12 //The magic happens here 13 ALLEGRO_EVENT event; 14 al_wait_for_event(queue, &event); 15 16 } 17}

From my understanding when you call a function within the while loop it will not be under the control of the timers. (I'm basing this off of the experience of having a for loop execute. When a for loop is within while it will run at the speed of the machine vs the speed of the timer. )

Without functions the code would get messy real quick.

Hopefully, I am missing something simple here...anyone able to instruct me on this vacancy?

To be able to implement:

#SelectExpand
1main(){ 2 //create timer 3 4 timer = al_create_timer(1.0 / 60); 5 queue = al_create_event_queue(); 6 al_register_event_source(queue, al_get_keyboard_event_source()); 7 al_register_event_source(queue, al_get_display_event_source(display)); 8 al_register_event_source(queue, al_get_timer_event_source(timer)); 9 al_start_timer(timer); 10 11 while (1) { 12 //The magic happens here 13 ALLEGRO_EVENT event; 14 al_wait_for_event(queue, &event); 15 function(); 16 } 17} 18 19function(){ 20}

Thomas Fjellstrom
Member #476
June 2000
avatar

Yes, as your code is, it won't be restricted to the timer. It will be close, but other events will cause the al_wait_for_event function to return. (at least if you had added other event sources to the queue) But try this instead:

#SelectExpand
1void main(int argc, char **argv) 2{ 3 //create timer 4 5 timer = al_create_timer(1.0 / 60); 6 queue = al_create_event_queue(); 7 al_register_event_source(queue, al_get_keyboard_event_source()); 8 al_register_event_source(queue, al_get_display_event_source(display)); 9 al_register_event_source(queue, al_get_timer_event_source(timer)); 10 al_start_timer(timer); 11 12 while (1) { 13 //The magic happens here 14 ALLEGRO_EVENT event; 15 al_wait_for_event(queue, &event); 16 17 if(event.type == ALLEGRO_EVENT_TIMER && event.source == timer) { 18 function(); 19 } 20 } 21} 22 23void function(){ 24}

That should do what you want, even if you add more timers or other event sources.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

J-Gamer
Member #12,491
January 2011
avatar

Don't you need al_get_timer_event_source(timer) instead of timer?

" There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo
"If your body was a business, thought would be like micro-management and emotions would be like macro-management. If you primarily live your life with emotions, then you are prone to error on the details. If you over-think things all the time you tend to lose scope of priorities." - Mark Oates

Thomas Fjellstrom
Member #476
June 2000
avatar

That would be more technically correct yes.[1][2]

References

  1. but due to how allegro's timers are implemented, ALLGERO_EVENT_SOURCE is the first item in the ALLEGRO_TIMER struct, meaning the timer's event source is the same pointer as the timer itself
  2. It was intentionally planned that way, any object that happens to be a source of events "IS A" ALLEGRO_EVENT_SOURCE.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

J-Gamer
Member #12,491
January 2011
avatar

I didn't know that... that's pretty handy ;)

" There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo
"If your body was a business, thought would be like micro-management and emotions would be like macro-management. If you primarily live your life with emotions, then you are prone to error on the details. If you over-think things all the time you tend to lose scope of priorities." - Mark Oates

Phrasz
Member #10,091
August 2008

I'm glad to see I'm on the right track, but wouldn't the function then operate at the system's speed vs the timers speed?

Would I need to install a new set of timers? Also shouldn't I stop the main() timer until function() with new timer complete?

Also, were you guys speaking of this implementation?:

#SelectExpand
1 if(event.type == ALLEGRO_EVENT_TIMER && event.source == al_get_timer_event_source(timer)){ 2 function(); 3 }

Thomas Fjellstrom
Member #476
June 2000
avatar

Phrasz said:

I'm glad to see I'm on the right track, but wouldn't the function then operate at the system's speed vs the timers speed?

Your code would just call the function every time through the loop. Wrapping it in that if will only call it when a timer event is fetched from the queue.

Of course, due to the al_wait_for_event call, the loop will sleep till it gets a timer event, so right now even without the if() it won't actually get around to executing the function till any event arrives.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Phrasz
Member #10,091
August 2008

Excellent to hear.

So let's say that the function(); was desired to run at 60 fps. Would I need this function to have it's own timers? Since the first timer declarations are within the main() function?

#SelectExpand
1void main(int argc, char **argv) 2{ 3 //create timer 4 5 timer = al_create_timer(1.0 / 60); 6 queue = al_create_event_queue(); 7 al_register_event_source(queue, al_get_keyboard_event_source()); 8 al_register_event_source(queue, al_get_display_event_source(display)); 9 al_register_event_source(queue, al_get_timer_event_source(timer)); 10 al_start_timer(timer); 11 12 while (1) { 13 //The magic happens here 14 ALLEGRO_EVENT event; 15 al_wait_for_event(queue, &event); 16 17 if(event.type == ALLEGRO_EVENT_TIMER && event.source == timer) { 18 al_stop_timer(timer); 19 function(); //Stop the timer to run during the function(); 20 al_start_timer(timer); 21 } 22 } 23} 24 25void function(){ 26 //create timer2 27 28 timer2 = al_create_timer(1.0 / 60); 29 queue2 = al_create_event_queue(); 30 al_register_event_source(queue2, al_get_keyboard_event_source()); 31 al_register_event_source(queue2, al_get_timer_event_source(timer2)); 32 al_start_timer(timer2); 33 34 //do more magic 35 36 //destroy queue2 and timer2 37 38}

Thomas Fjellstrom
Member #476
June 2000
avatar

Phrasz said:

So let's say that the function(); was desired to run at 60 fps

Thats how that code will run function() as it is. You don't need a second timer or any other queue. that if(event.type == ALLEGRO_EVENT_TIMER && event.source == timer) { ... } block will only be run 60 times a second. There is no need for any further tricks. Also, you probably don't want to stop/start the timer like that either.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Phrasz
Member #10,091
August 2008

There isn't any nesting issues?
What happens if the function called takes longer than the timer(in this case greater than 1/60 of a second)?

(trying to implement these ideas in my code as I've been responding)

Thomas Fjellstrom
Member #476
June 2000
avatar

Phrasz said:

What happens if the function called takes longer than the timer(in this case greater than 1/60 of a second)?

Timer events will stack up, and you'll end up getting behind. What I do in some of my code, is use the al_peek_next_event function to check to see if the next event is also a TIMER event, and pop it off (I actually do it in a while loop, to pop off all TIMER events from the main timer) after I've handled the frame.

But generally you don't want to be doing so much that your function takes more than a single frame, or your game is going to end up being slow.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Phrasz
Member #10,091
August 2008

Perfect... I'm stoked to see I'm think about this correctly.

Basically, I'm making animations as functions, but they will take longer than a frame. So I'm trying to determine the best way to accomplish this w/o having a HUGE main file with a single while loop to get lost in.

Thomas Fjellstrom
Member #476
June 2000
avatar

Phrasz said:

Basically, I'm making animations as functions, but they will take longer than a frame.

Theres no way changing the frame of the animation will take more than a frame. I think you're making a simple mistake, you don't want to do the entire animation sequence in a single function. Instead, store your animations in such a way, so that you can just draw the current frame of all animations in your main loop (or in a single function that your main loop calls).

That is to say, you don't want to think of the animation as a separate thread of execution. Instead, just draw the current frame of the animation in your normal drawing. Then your logic code will advance the animation's current frame when its supposed to.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

I wrote a class to handle animations using Allegro 4, you can download the source code and a working executable here :
Allegro 4 animation

It wouldn't be that hard to port it to Allegro 5. Just count the number of timer ticks, multiply by the number of seconds per tick, and pass that to AdvanceFrameTime. Replace BITMAP*'s with ALLEGRO_BITMAP*'s and replace the drawing calls with al_draw_bitmap calls and it should work.

There's no need to put the entire animation inside it's own function, but you still could for clarity or modularity.

Phrasz
Member #10,091
August 2008

I was shooting to make the code more modular, and I was currently doing the prescribed method of animation per frame vs per function. (I had the fade animation that used a for loop to step through the rendered,modified alpha versions of the bit map to "fade" the image.H/e the for loop was too much for the pre-defined timer).

Thanks for the help. I'll look into "cleaning" the code into functions that doesn't exceed the frame rate.

However, has anyone looked into a global timer? Don't ask me how to accomplish this ... I'm just the Comp Engineer...

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Phrasz
Member #10,091
August 2008

So if that's the case wouldn't all the functions then work (main() to function() to etc) under this global timer?

Or is it a queue issue at that point? (can't have multiple if (queue event ) across the functions)

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Phrasz said:

Or is it a queue issue at that point? (can't have multiple if (queue event ) across the functions)

You probably want to have a single ALLEGRO_EVENT_QUEUE and distribute the ALLEGRO_EVENT's that you receive from it to your different objects.

Phrasz
Member #10,091
August 2008

Thanks again guys. Sadly I've given up and I'm back to good old brute forcing code... ;D

Go to: