Aprendendo Allegro 5
Início Janela Imagens Mensagem Fontes e texto Eventos Mouse Teclado Audio Timer Animações Sprites Jogo exemplo

Criando animações

Agora que já sabemos usar timers, vamos ver como fazer para que um objeto se movimente em uma taxa pré-definida.

Para isso, iremos utilizar o conceito de taxa de atualização de tela aprendido anteriormente. O objetivo desta lição é criar um quadrado vermelho, e fazer com que ele se movimente pela tela com uma velocidade fixa. Com isso, podemos demonstrar como criar animações sem que a velocidade destas sejam afetadas pelo desempenho do computador as executando.

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

//fps = frames per second = atualizacoes de tela por segundo
#define FPS 60.0
#define LARGURA_TELA 640
#define ALTURA_TELA 480

ALLEGRO_DISPLAY *janela = NULL;
ALLEGRO_EVENT_QUEUE *fila_eventos = NULL;
ALLEGRO_TIMER *timer = NULL;
ALLEGRO_BITMAP *quadrado = NULL;

void error_msg(char *text){
	al_show_native_message_box(NULL,"ERRO",
		"Ocorreu o seguinte erro e o programa sera finalizado:",
		text,NULL,ALLEGRO_MESSAGEBOX_ERROR);
}

int inicializar(){
    if (!al_init()){
        error_msg("Falha ao inicializar a Allegro");
        return 0;
    }

    //cria o timer com o intervalo de tempo que ele ira disparar
    timer = al_create_timer(1.0 / FPS);
    if(!timer) {
        error_msg("Falha ao criar temporizador");
        return 0;
    }

    janela = al_create_display(LARGURA_TELA, ALTURA_TELA);
    if(!janela) {
        error_msg("Falha ao criar janela");
        al_destroy_timer(timer);
        return 0;
    }

    al_set_window_title(janela, "Testando FPS");

    quadrado = al_create_bitmap(50, 50);
    if (!quadrado){
        error_msg("Falha ao criar bitmap");
        al_destroy_timer(timer);
        al_destroy_display(janela);
        return 0;
    }
    al_set_target_bitmap(quadrado);
    al_clear_to_color(al_map_rgb(255, 0, 0));
    al_set_target_bitmap(al_get_backbuffer(janela));

    fila_eventos = al_create_event_queue();
    if(!fila_eventos) {
        error_msg("Falha ao criar fila de eventos");
        al_destroy_timer(timer);
        al_destroy_display(janela);
        al_destroy_bitmap(quadrado);
        return 0;
    }

    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_clear_to_color(al_map_rgb(0,0,0));
    al_flip_display();
    al_start_timer(timer);

    return 1;
}

int main(void){
    //define quando a tela sera atualizada
    int desenha = 1;
    //quando o loop principal deve encerrar
    int sair = 0;
    //posicao do quadrado e quanto ele andara a cada disparo do timer, para coordenada X e Y
    int posx=50, dir_x=5;
    int posy=100, dir_y=5;

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

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

        /* -- EVENTOS -- */
        //se o tipo do evento for o disparo de um timer
        if(evento.type == ALLEGRO_EVENT_TIMER){
            posx+=dir_x;
            posy+=dir_y;
            //se passou das bordas, inverte a direcao
            if (posx<=10 || posx>=LARGURA_TELA-60)
                dir_x*=-1;
            if (posy<=10 || posy>=ALTURA_TELA-60)
                dir_y*=-1;
            desenha=1;
        }
        else if(evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
            sair = 1;
        }

        /* -- ATUALIZA TELA -- */
        if(desenha && al_is_event_queue_empty(fila_eventos)) {

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

            //desenha o quadrado na tela nas posicoes X e Y
            al_draw_bitmap(quadrado, posx, posy, 0);

            al_flip_display();

            //zera flag para nao entrar aqui no proximo loop
            desenha = 0;
        }
    }

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

    return 0;
}

Na linha 12 declaramos o bitmap que representará o quadrado vermelho que ficará se movendo na tela, e na linha 42 criamos ele com as dimensões 50x50 pixels.

Na linha 49 mudamos o bitmap alvo para o quadrado, colorimos ele com a cor vermelha na linha 50 e na linha 51 mudamos o alvo de volta para o backbuffer da janela.

O timer timer, que como explicado anteriormente serve para controlar a taxa de atualização da tela possui a frequencia de disparo de 60 Hz (60 vezes por segundo, ou 1/60s). Ele é criado na linha 11, seu tempo é definido na linha 27, ele é adicionado na fila de eventos na linha 63 e iniciado na linha 66

Lógica do programa:

90-99
105-116
  • Verifica se o timer foi disparado (linha 90).
  • Incrementa a posição X (linha 91) e Y (linha 92) do quadrado.
  • Verifica se posição X e Y do quadrado alcançou os limites da tela (linhas 94 e 96). Em caso afirmativo inverte o sentido do movimento do respectivo eixo (+1 vira -1 e vice-versa) (linhas 95 e 97). Assim o conteúdo de dir_x e dir_y irá somar 1 ou decrementar 1, dependendo do sentido desejado.
  • Seta a flag desenha=1 (linha 98) fazendo com que na etapa de atualização de tela, a mesma seja atualizada.
  • Caso a tela precise ser atualizada (desenha==1) (linha 105), mostra o quadrado na posição designada (linha 110).

Outros links