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

Entendendo eventos

O allegro 5 introduziu o uso de eventos. Eventos são coisa que acontecem no programa desde cliques e movimentos do mouse, teclas serem pressionadas, um temporizador disparou, dentre outras coisas.

Caso o allegro não tivesse suporte a eventos, teríamos que verificar quando cada uma destas coisas acontecessem no programa em determinados espaços de tempo, e esta tarefa deixaria é demandante para o processador.

Para lidar com eventos, usamos uma fila de eventos. Cada vez que um evento acontece, ele é colocado na fila. Então quando o programa verificar se existe algum evento a ser tratado, removemos da fila o evento mais antigo e tratamos ele.

No exemplo abaixo, iremos criar um evento que permite tratar o que acontece ao clicar no botão X que fecha a janela. Analisemos o código:

// Os arquivos de cabeçalho
#include <allegro5/allegro.h>
#include <allegro5/allegro_native_dialog.h>
#include <allegro5/allegro_image.h>

// Atributos da tela
#define LARGURA_TELA 640
#define ALTURA_TELA 480

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 main(void){
	ALLEGRO_DISPLAY *janela = NULL;
	ALLEGRO_BITMAP *imagem = NULL;
	//declara a fila de eventos
	ALLEGRO_EVENT_QUEUE *fila_eventos = NULL;

    //Inicialização da biblioteca Allegro
	if (!al_init()){
		error_msg("Falha ao inicializar a Allegro");
		return -1;
	}

	//tenta iniciar o módulo de imagens
	if (!al_init_image_addon()){
		error_msg("Falha ao inicializar add-on allegro_image");
		return -1;
	}

	//cria display em janela
	janela = al_create_display(LARGURA_TELA, ALTURA_TELA);
	//caso al_create_display retorne NULL, encerra programa
	if (!janela){
		error_msg("Falha ao criar janela");
		return -1;
	}

	//carrega imagem
	imagem = al_load_bitmap("hu3.bmp");
	//caso al_load_bitmap retorne NULL, encerra programa
	if (!imagem){
		error_msg("Falha ao carregar o arquivo de imagem");
		al_destroy_display(janela);
		return -1;
	}

	//cria fila de eventos
	fila_eventos = al_create_event_queue();
	//caso al_create_event_queue retorne NULL, destroi a janela e encerra o programa
	if (!fila_eventos){
		error_msg("Falha ao criar fila de eventos");
		al_destroy_display(janela);
		return -1;
	}

	//registra eventos da janela em fila_eventos
	al_register_event_source(fila_eventos, al_get_display_event_source(janela));

	//desenha imagem no display ativo em X:0 Y:0
	al_draw_bitmap(imagem, 0, 0, 0);

	//atualiza tela
	al_flip_display();

	while (1){
		//declara vriavel que recebe evento e timeout
		ALLEGRO_EVENT evento;
		//espero por um evento da fila, e guarda em evento
		al_wait_for_event(fila_eventos, &evento);

		//se teve eventos e foi um evento de fechar janela, encerra repetição
		if (evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
			int resp = al_show_native_message_box(janela,"Fechar",
				"Deseja sair do programa?","",NULL,ALLEGRO_MESSAGEBOX_YES_NO);
			if (resp)
				break;
		}

		al_draw_bitmap(imagem, 0, 0, 0);
		al_flip_display();
	}

	//destroi janela e fila de eventos ao fim
	al_destroy_display(janela);
	al_destroy_event_queue(fila_eventos);

	return 0;
}

ALLEGRO_EVENT_QUEUE

Na linha 20 criamos a variável que será usada como a fila de eventos, explicada anteriormente. Toda vez que um evento for disparado, ele será guardado nesta fila. E toda vez que quisermos remover um evento da fila (para resolver ele), sempre será removido o evento que está aguardando a mais tempo, como numa fila de pessoas esperando por atendimento.

al_create_event_queue()

Na linha 52 chamamos a função al_create_event_queue(), que cria uma fila de eventos vazia. A fila é atribuída á variável fila_eventos. Em caso de falha retorna NULL. O caso de falha está sendo verificado na linha 54.

51-61

al_register_event_source()

Na linha 61 chamamos a função al_register_event_source() que serve para ligar uma fonte de eventos à fila de eventos criada. Sem isto, por mais que os eventos ocorressem, o programa não iria colocá-los na fila. A função recebe por parâmetro a fila de eventos e a fonte dos eventos. Como queremos que a nossa fonte de eventos seja a janela, então chamamos a função al_get_display_event_source(), que retorna a fonte de eventos da janela passada por parâmetro.

A seguir desenhamos a imagem na janela (linha 64) e atualizamos a tela (linha 67).

69-85

O while acima é onde futuramente ficará toda lógica dos jogos que criaremos. Todo jogo se baseia em atualizar a tela em um intervalo de tempo predeterminado (idealmente 60 vezes por segundo, ou 60 fps), além de capturar entrada do usuário (por teclado, mouse, ou outros) e executar a lógica específica do jogo. Este processo acontece repetidamente até que o jogo termine. Neste nosso tutorial que trata de eventos, iremos utilizar o while para ficar "escutando" o evento do clique do X da janela.

ALLEGRO_EVENT

Na linha 71 criamos uma variável que irá guardar um evento. Basicamente pegaremos um evento da fila (quando um estiver disponível) e colocamos ele na variável evento. As variáveis ALLEGRO_EVENT são structs, cujo campo type indica o tipo de evento que foi disparado. Consulte a referência para a lista completa de tipos de eventos possíveis.

al_wait_for_event()

Na linha 73 chamamos a função al_wait_for_event(), que remove o primeiro item da fila de eventos e coloca na variável evento.

Na linha 76 verificamos se o tipo do evento (campo type da variável ALLEGRO_EVENT) disparado foi ALLEGRO_EVENT_DISPLAY_CLOSE. Em caso afirmativo, significa que o usuário clicou no botão para fechar a janela.

Na linha 77 mostramos uma mensagem perguntando se o usuário deseja fechar o programa. Caso o botão Sim seja clicando, o break na linha 80 fará com que o while encerre.

Ao fim do programa, nas linhas 88 e 89, os espaços de memória para a janela e fila de eventos são liberados.

Outros links