Allegro5 - Eventos, temporizadores

Ya la ventana está creada, sin embargo, se presentan algunos problemas. El primero es que la ventana solo se ha pintado una vez, pero si movemos algo sobre ella o la minimizamos y restauramos, la ventana se pintará con lo que le haya pasado encima, otro problema es el hecho de que la ventana está limitada a esperar cierta cantidad de tiempo hasta que termine. Lo que ahora se tratará es de hacer que la ventana recargue si contenido cada cierto tiempo y que responda a eventos de ventana como el de salir.

Trataré de colocar la menor cantidad de comentarios dentro del código para esto explicaré fuera de él las partes principales.


  • const unsigned int FPS: Será la cantidad de Frames Per Second o Fotogramas Por Segundo a la que correrá el programa, un número muy alto hará que el programa se ralentice, un número muy bajo causará que parezca entrecortado.
  • ALLEGRO_EVENT_QUEUE* colaDeEventos: Creará un puntero a una cola de eventos, apuntando por defecto a un espacio NULL.
  • ALLEGRO_TIMER* temporizador: Creará un puntero a un temporizador. Un temporizador nos devolverá un "tick" o evento cada cierto tiempo determinado. Por defecto estará apuntando a NULL.
  • ALLEGRO_EVENT evento; : variable que almacena un evento de cualquier tipo, pueda ser de ventana, de teclado, de ratón, de temporizador, de joystick, de sistema, etc. No es necesario que tenga un valor inicial.
  • temporizador = al_create_timer(1.0 / FPS); : Creará un temporizador que generará un "tick" cada 1.0/FPS segundos. El temporizador inicia apagado por lo que aún no genera eventos. El puntero apuntará al nuevo temporizador creado y dejará de apuntar a NULL si es que la creación a sido satisfactoria.
  • colaDeEventos = al_create_event_queue(); : Crerá una cola de eventos. La cola inicialmente está vacía. Ahora el puntero apuntará a la nueva cola de eventos creada y dejará de apuntar a NULL si es que la creación a sido satisfactoria.
  • al_register_event_source(colaDeEventos, al_get_display_event_source(ventana)); : Lo que hace esta función es registrar en la cola de eventos determinada en el primer parámetro, los eventos generados por la fuente de eventos determinada en el segundo parámetro. En el segundo parámetro está otra función, al_get_display_event_source(ALLEGRO_DISPLAY*), esta función obtiene los eventos del display apuntado por el puntero que se envíe como parámetro, en este caso ventana. Es decir que la cola de eventos recibirá en la cola cualquier evento que realice la ventana como por ejemplo presionar la X para salir, o al maximizar la ventana, etc.
  • al_register_event_source(colaDeEventos, al_get_timer_event_source(temporizador)); : Realiza casi lo mismo que la anterior lo único que está recibiendo como segundo parámetro a los eventos generados por el temporizador. En este caso los eventos que envía el temporizador son los "ticks" que realiza cada cierta cantidad de tiempo.
  • al_start_timer(temporizador); : Inicia el temporizador, a partir de aquí empezará a generar ticks.
  • if (redibujar && al_is_event_queue_empty(colaDeEventos)) : Comprobará si es necesario redibujar y tambien si es que la cola de eventos está vacía la función 
  • al_is_event_queue_empty(ALLEGRO_EVENT_QUEUE*), recibe como parámetro un puntero a una cola de eventos y verificará si la cola apuntada está vacía, si es así devolverá 1 sino 0.
  • al_clear_to_color(al_map_rgb(0, 0, 0)), Borra la pantalla a color negro.
  • al_flip_display(), intercambia el buffer para que salga en la ventana.
  • al_wait_for_event(colaDeEventos, &evento); Espera a que suceda un evento para colocar el evento al contenido de la dirección de memoria indicado en el segundo parámetro
  • evento.type; Es miembro parte de la estructura ALLEGRO_EVENT. Evento es una instancia de ALLEGRO_EVENT
  • evento.type == ALLEGRO_EVENT_TIMER compara si el tipo de evento recibido es el determinado por la constante ALLEGRO_EVENT_TIMER, es decir si fue producto de un temporizador. Los temporizadores generan ticks cada cierto tiempo, estos son los eventos tomados. En este caso cada vez que suceda un evento de temporizador de dará paso al redibujado de la ventana.
  • evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE evalúa si el tipo de evento es u evento de cerrado de ventana. Si es asi se terminará el loop.
  • al_is_event_queue_empty(colaDeEventos) Evalúa si la cola de eventos está vacía, si es así devolverá un valor distinto de 0 sino 0.
  • al_destroy_timer(temporizador);
    al_destroy_display(ventana);
    al_destroy_event_queue(colaDeEventos);

    Destruye cada uno de los objetos creados.

#include <cstdlib>
#include <allegro5/allegro5.h>
#include <iostream>

using namespace std;

int main(int argc, char** argv) {
    
    const unsigned int FPS = 24;
    bool redibujar = true;
    bool loop      = true;
    
    ALLEGRO_DISPLAY*            ventana         =       NULL;
    ALLEGRO_EVENT_QUEUE*        colaDeEventos   =       NULL;
    ALLEGRO_TIMER*              temporizador;
    ALLEGRO_EVENT               evento ;
    
    if(!al_init())
    {
        cout<<"Hubo un error en la inicialización de Allegro";
        return -1;
    }
     
    ventana = al_create_display(640,480);     
    if(!ventana)
    {
        cout<<"Hubo un error en la creación de la ventana";
        return -1;
    }
    
    temporizador = al_create_timer(1.0/FPS);    
    if(!temporizador)
    {
        cout<<"Hubo un error en la creación del temporizador";
        return -1;
    }
    
    colaDeEventos       =   al_create_event_queue();
    if(!colaDeEventos)
    {
        cout<<"Hubo un error en la creación de la cola de eventos";
        return -1;
    }    

    al_register_event_source(colaDeEventos, al_get_display_event_source(ventana));
    al_register_event_source(colaDeEventos, al_get_timer_event_source(temporizador));
    
    al_start_timer(temporizador);
    
    al_clear_to_color(al_map_rgb(0,0,0));
    al_flip_display();
        
    while(loop)
    {     
        al_wait_for_event(colaDeEventos, &evento);
        
        if(evento.type == ALLEGRO_EVENT_TIMER)
        {
            redibujar = true;
        }       
        else if(evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
        {
            loop = false;
        }
        
        if(loop)
        {
            if(redibujar && al_is_event_queue_empty(colaDeEventos))
            {

                al_clear_to_color(al_map_rgb(0,0,0));
                al_flip_display();
                redibujar = false;
            }   
        }        
    }
    
    al_destroy_timer(temporizador);
    al_destroy_display(ventana);
    al_destroy_event_queue(colaDeEventos);
    
    return 0;
}

Código completo

Siguiente
« Post Anterior