Tutorial Allegro 5 #10 – Timers

Padrão

Olá de novo! Hoje temos mais um post da nossa série sobre a biblioteca Allegro 5. Dessa vez, vamos falar sobre o uso de Timers. Eles geralmente são utilizados para disparar ações ou controlar eventos baseados em medidas de tempo.

Assim, vamos fazer um exemplo utilizando dois timers: o primeiro deles será responsável por controlar a cor do plano de fundo da janela, de forma que inicie em preto e vá gradativamente alternando para branco, retornando novamente ao preto e assim sucessivamente. Já o segundo timer exibirá um cronômetro na tela, que será incrementado a cada 1 segundo.

Vamos ver o código e em seguida discutimos seu funcionamento.

#include <allegro5/allegro.h>
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_ttf.h>
#include <stdio.h>
#include <stdbool.h>

bool inicializar();

const int LARGURA_TELA = 640;
const int ALTURA_TELA = 480;

ALLEGRO_DISPLAY *janela = NULL;
ALLEGRO_EVENT_QUEUE *fila_eventos = NULL, *fila_contador = NULL;
ALLEGRO_TIMER *timer = NULL, *contador = 0;
ALLEGRO_FONT *fonte = NULL;

int main(void)
{
    bool sair = false;
    int r = 0, g = 0, b = 0;
    int min = 0, seg = 0;

    if (!inicializar())
    {
        return -1;
    }

    al_start_timer(timer);
    al_start_timer(contador);

    while (!sair)
    {
        if (!al_is_event_queue_empty(fila_eventos))
        {
            ALLEGRO_EVENT evento;
            al_wait_for_event(fila_eventos, &evento);

            if (evento.type == ALLEGRO_EVENT_TIMER)
            {
                if (++r >= 255) r = 0;
                if (++g >= 255) g = 0;
                if (++b >= 255) b = 0;
            }
            else if (evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
            {
                sair = true;
            }
        }

        if (!al_is_event_queue_empty(fila_contador))
        {
            ALLEGRO_EVENT evento;
            al_wait_for_event(fila_contador, &evento);

            if (evento.type == ALLEGRO_EVENT_TIMER)
            {
                seg++;
                if (seg == 60)
                {
                    min++;
                    seg = 0;
                }
            }
        }

        al_clear_to_color(al_map_rgb(r, g, b));
        al_draw_textf(fonte, al_map_rgb(255, 0, 0), LARGURA_TELA / 2, 200, ALLEGRO_ALIGN_CENTRE, "%d:%d", min, seg);
        al_flip_display();
    }

    al_destroy_timer(timer);
    al_destroy_event_queue(fila_eventos);
    al_destroy_display(janela);

    return 0;
}

bool inicializar()
{
    if (!al_init())
    {
        fprintf(stderr, "Falha ao inicializar Allegro.\n");
        return false;
    }

    al_init_font_addon();

    if (!al_init_ttf_addon())
    {
        fprintf(stderr, "Falha ao inicializar allegro_ttf.\n");
        return false;
    }

    janela = al_create_display(LARGURA_TELA, ALTURA_TELA);
    if (!janela)
    {
        fprintf(stderr, "Falha ao criar janela.\n");
        return false;
    }

    al_set_window_title(janela, "Testandos Timers...");

    fila_eventos = al_create_event_queue();
    if (!fila_eventos)
    {
        fprintf(stderr, "Falha ao criar fila de eventos.\n");
        al_destroy_display(janela);
        return false;
    }

    timer = al_create_timer(0.1);
    if (!timer)
    {
        fprintf(stderr, "Falha ao criar timer.\n");
        al_destroy_event_queue(fila_eventos);
        al_destroy_display(janela);
        return false;
    }

    fonte = al_load_font("font.ttf", 120, 0);
    if (!fonte)
    {
        fprintf(stderr, "Falha ao carregar fonte.\n");
        al_destroy_timer(timer);
        al_destroy_event_queue(fila_eventos);
        al_destroy_display(janela);
        return false;
    }

    contador = al_create_timer(1.0);
    if (!contador)
    {
        fprintf(stderr, "Falha ao criar timer.\n");
        al_destroy_font(fonte);
        al_destroy_timer(timer);
        al_destroy_event_queue(fila_eventos);
        al_destroy_display(janela);
        return false;
    }

    fila_contador = al_create_event_queue();
    if (!fila_contador)
    {
        fprintf(stderr, "Falha ao criar fila do contador.\n");
        al_destroy_timer(contador);
        al_destroy_font(fonte);
        al_destroy_timer(timer);
        al_destroy_event_queue(fila_eventos);
        al_destroy_display(janela);
        return false;
    }

    al_register_event_source(fila_eventos, al_get_display_event_source(janela));
    al_register_event_source(fila_eventos, al_get_timer_event_source(timer));
    al_register_event_source(fila_contador, al_get_timer_event_source(contador));

    return true;
}

Neste código, temos o tipo ALLEGRO_TIMER para a declaração das variáveis de controle de nossos dois timers (timer e contador). Para diferenciarmos os eventos referentes de um ou de outro timer, vamos também criar duas filas de eventos (fila_eventos e fila_contador). Muito provavelmente deve ter uma forma mais “elegante” de se fazer a diferenciação… então, se eu achar, eu atualizo o post.

Continuando, a inicialização dos timers é feita chamando-se a função al_create_timer(), que recebe o timer em questão e o intervalo de tempo no qual ele disparará seus eventos. No nosso caso, o timer timer (responsável pela atualização da tela) será disparado a cada 100 milissegundos (0.1) e o timer contador será disparado a cada 1 segundo (1.0). No final da inicialização, vinculamos cada um dos timers a uma fila de eventos.

Já na função main(), na nossa lógica de tratamento de eventos, comparamos o tipo ALLEGRO_EVENT_TIMER que corresponde a eventos disparados por timers. Caso o evento seja do timer timer, incrementamos o nível de cor (r = vermelho, g = verde, b = azul), zerando-o caso exceda 255 (máximo). No caso do timer contador, fazemos o controle de minutos e segundos (com as variáveis min e seg).

Ao final, executamos as rotinas para atualização da tela (fundo e contador). Temos, então, o programa rodando assim:

Para linkar, precisamos incluir os add-ons allegro_font e allegro_ttf, que utilizamos para mostrar a hora na tela.

  • Windows: -lallegro-5.0.5-mt -lallegro_font-5.0.5-mt -lallegro_ttf-5.0.5-mt
  • Linux: -lallegro -lallegro_font -lallegro_ttf

Bom, é isso. Espero que tenham gostado do post e fiquem atentos, pois tem mais coisa vindo por aí logo logo! Até lá

  • Lucas

    Ola Rafael desculpe pela pergunta idiota, mas com sua apostila já criei jogos bem simples. Porem eu utilizei 1 looping. Primeiramente fiz um jogo onde a pessoal escolhia a velocidade da bola e leva a bola ate o quadrado, quando chegasse la aparecia a mensagem você ganhou,no canto da tela aparecia as coordenadas. Porem dentro do looping utilizei funções do teclado, sempre vou usar funções do teclado. você tem alguma ideia como eu executar looping ao mesmo tempo?

  • Para usar uma única fila de eventos para vários contadores, você pode fazer o seguinte:

    if (evento.type == ALLEGRO_EVENT_TIMER)
    if (evento.timer.source == contador)
    printf(“evento contadorn”);
    else if (evento.timer.source == timer)
    printf(“evento timern”);

    • Geisy

      como fazer para mostrar na tela um lançamento oblíquo de projétil?

      Gostaria de ver exemplos de códigos que façam algo similar a isso.

  • mathias

    Falha ao carregar a fonte!