Allegro 5 Tutorial/Timers

From Allegro Wiki
Jump to: navigation, search

In this section we learn about Timers, and how to use them to regulate your update loop.

What Are Timers?

Timers are event sources that will send regular timed events at a given interval.

Why do I want Timers?

Timers can be used to regulate your main update loop, so you only run at a given FPS, or they can be used to know when an animation needs to update, etc.

Building on the previous example we will extend the program to have a regular update frequency.

#include <stdio.h>
#include <allegro5/allegro.h>

const float FPS = 60;

int main(int argc, char **argv){

   ALLEGRO_DISPLAY *display = NULL;
   ALLEGRO_EVENT_QUEUE *event_queue = NULL;
   ALLEGRO_TIMER *timer = NULL;
   bool redraw = true;

   if(!al_init()) {
      fprintf(stderr, "failed to initialize allegro!\n");
      return -1;
   }

   timer = al_create_timer(1.0 / FPS);
   if(!timer) {
      fprintf(stderr, "failed to create timer!\n");
      return -1;
   }

   display = al_create_display(640, 480);
   if(!display) {
      fprintf(stderr, "failed to create display!\n");
      al_destroy_timer(timer);
      return -1;
   }
 
   event_queue = al_create_event_queue();
   if(!event_queue) {
      fprintf(stderr, "failed to create event_queue!\n");
      al_destroy_display(display);
      al_destroy_timer(timer);
      return -1;
   }
 
   al_register_event_source(event_queue, al_get_display_event_source(display));

   al_register_event_source(event_queue, al_get_timer_event_source(timer));

   al_clear_to_color(al_map_rgb(0,0,0));

   al_flip_display();

   al_start_timer(timer);
 
   while(1)
   {
      ALLEGRO_EVENT ev;
      al_wait_for_event(event_queue, &ev);

      if(ev.type == ALLEGRO_EVENT_TIMER) {
         redraw = true;
      }
      else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
         break;
      }

      if(redraw && al_is_event_queue_empty(event_queue)) {
         redraw = false;
         al_clear_to_color(al_map_rgb(0,0,0));
         al_flip_display();
      }
   }

   al_destroy_timer(timer);
   al_destroy_display(display);
   al_destroy_event_queue(event_queue);
 
   return 0;
}

Walk through

A few new things, and a few changed things this time.

const float FPS = 60;

Here's the rate we want to limit our update logic to.

   timer = al_create_timer(1.0 / FPS);

Initialize our timer to tick 1.0 / FPS seconds per tick.

   al_register_event_source(event_queue, al_get_timer_event_source(timer));

Register the timer's event source in our event queue so we can fetch the events later.

   al_start_timer(timer);

Obvious? This starts our timer. Without this, it won't generate any events.

      al_wait_for_event(event_queue, &ev);

Changed up the event handling a bit. Since we now have regular events coming in, we don't need to worry about getting stuck in the wait function. al_wait_for_event will wait forever if no event comes in.

      if(event.type == ALLEGRO_EVENT_TIMER) {
         redraw = true;
      }

And here we check for the timer event, if this event is a timer event, trigger a redraw. If we had any game logic to take care of, it would go in here.

      if(redraw && al_is_event_queue_empty(event_queue)) {
         redraw = false;
         al_clear_to_color(al_map_rgb(0,0,0));
         al_flip_display();
      }

Why the crazy logical AND? We want to make sure the event queue is completely empty before we actually do our redraw, otherwise the update loop could fall very far behind. Sure, that doesn't matter right now, but it will in future examples.

So we check if redraw is true, and the queue is empty, and if both are true, we clear the current display, flip the display, clear the redraw flag, and resume the loop.

Like the previous example, this one will exit when you press the window's close button.

   al_destroy_timer(timer);

Uninstall our timer.

And that wraps up basic frame limiting with timers in Allegro 5.