Nesta lição veremos como utilizar a entrada do teclado nos programas. Para isso, usaremos os eventos do allegro. Como já de costume das lições anteriores, o código é mostrado e entrão explicado por partes. Caso alguma parte não tenha sida explicada, provavelmente é porque ela já tenha sido explicada antes, então recomendo voltar algumas lições para aprender bem as partes anteriores.
Este programa abre uma janela, e fica esperando o usuário digitar uma tecla. Caso ele digite as teclas relativas às setas para cima, baixo, esquerda ou direita, um texto colorido aparece na tela enquanto a tecla está sendo pressionada. Caso a tecla ESC for pressionada, ou o usuário clicar para fechar a janela, o programa é encerrado.
#include <allegro5/allegro.h> #include <allegro5/allegro_font.h> #include <allegro5/allegro_ttf.h> #include <allegro5/allegro_native_dialog.h> #define LARGURA_TELA 640 #define ALTURA_TELA 480 ALLEGRO_DISPLAY *janela = NULL; ALLEGRO_EVENT_QUEUE *fila_eventos = NULL; ALLEGRO_FONT *fonte = NULL; void error_msg(char *text){ al_show_native_message_box(janela,"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; } al_init_font_addon(); if (!al_init_ttf_addon()){ error_msg("Falha ao inicializar add-on allegro_ttf"); return 0; } if (!al_init_image_addon()){ error_msg("Falha ao inicializar add-on allegro_image"); return 0; } //inicializa addon do teclado if (!al_install_keyboard()){ error_msg("Falha ao inicializar o teclado"); return 0; } janela = al_create_display(LARGURA_TELA, ALTURA_TELA); if (!janela){ error_msg("Falha ao criar janela"); return 0; } al_set_window_title(janela, "Utilizando o Teclado"); fonte = al_load_font("arial.ttf", 72, 0); if (!fonte){ error_msg("Falha ao carregar \"arial.ttf\""); al_destroy_display(janela); return 0; } fila_eventos = al_create_event_queue(); if (!fila_eventos){ error_msg("Falha ao criar fila de eventos"); al_destroy_display(janela); return 0; } //registra duas fontes de eventos na fila. o da janela, e do teclado al_register_event_source(fila_eventos, al_get_keyboard_event_source()); al_register_event_source(fila_eventos, al_get_display_event_source(janela)); return 1; } int main(void) { int sair = 0; int tecla = 0; if (!inicializar()){ return -1; } al_clear_to_color(al_map_rgb(255, 255, 255)); while (!sair){ while(!al_is_event_queue_empty(fila_eventos)){ ALLEGRO_EVENT evento; //espera ate que algum evento esteja na fila al_wait_for_event(fila_eventos, &evento); //se o evento for pressionar uma tecla if (evento.type == ALLEGRO_EVENT_KEY_DOWN){ //verifica qual tecla foi pressionada switch(evento.keyboard.keycode){ //seta para cima case ALLEGRO_KEY_UP: tecla = 1; break; //seta para baixo case ALLEGRO_KEY_DOWN: tecla = 2; break; //seta para esquerda case ALLEGRO_KEY_LEFT: tecla = 3; break; //seta para direita. case ALLEGRO_KEY_RIGHT: tecla = 4; break; //esc. sair=1 faz com que o programa saia do loop principal case ALLEGRO_KEY_ESCAPE: sair = 1; } } //se o evento foi o soltar de uma tecla //tecla=5 significa que alguma foi pressionada mas nao e nenhuma das setas else if (evento.type == ALLEGRO_EVENT_KEY_UP){ tecla = 5; } //se clicou para fechar a janela else if (evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE){ sair = 1; } } //tecla!=0 significa que algo foi pressionado if (tecla){ al_clear_to_color(al_map_rgb(255, 255, 255)); //desenha na tela as palavras relativas a seta preesionada switch (tecla){ case 1: al_draw_text(fonte, al_map_rgb(0, 255, 0), LARGURA_TELA / 2, ALTURA_TELA / 2 - al_get_font_ascent(fonte) / 2, ALLEGRO_ALIGN_CENTRE, "CIMA"); break; case 2: al_draw_text(fonte, al_map_rgb(255, 0, 255), LARGURA_TELA / 2, ALTURA_TELA / 2 - al_get_font_ascent(fonte) / 2, ALLEGRO_ALIGN_CENTRE, "BAIXO"); break; case 3: al_draw_text(fonte, al_map_rgb(255, 0, 0), LARGURA_TELA / 2, ALTURA_TELA / 2 - al_get_font_ascent(fonte) / 2, ALLEGRO_ALIGN_CENTRE, "ESQUERDA"); break; case 4: al_draw_text(fonte, al_map_rgb(0, 0, 255), LARGURA_TELA / 2, ALTURA_TELA / 2 - al_get_font_ascent(fonte) / 2, ALLEGRO_ALIGN_CENTRE, "DIREITA"); break; } //zera a tecla para a proxima vez nao entrar aqui de novo tecla = 0; } al_flip_display(); } al_destroy_display(janela); al_destroy_event_queue(fila_eventos); return 0; }
Na linha 19 declaramos a função inicializar(). Esta função será utilizada lá dentro do main(), e ela retorna 0 caso alguma das diversas funções de inicialização do programa falhar, ou 1 caso chegue ao fim com sucesso. Na linha 77 o main verifica as inicializações através desta função. Este processo foi feito por questões de organização de código.
Na linha 38 chamamos a função al_install_keyboard(), que permite a captura das teclas digitadas no teclado através de eventos.
Na linha 66 chamamos a função al_get_keyboard_event_source() receber os eventos do teclado, e usamos o mesmo na função al_register_event_source() para registrar os eventos vindos do teclado na fila de eventos.
Na linha 90 testamos se o tipo de evento capturado é o ALLEGRO_EVENT_KEY_DOWN, que é o tipo de evento disparado quando é detectado o ato pressionar de uma tecla.
Na linha 92 fazemos um switch para verificar o valor do campo .keyboard.keycode. Como já foi dito anteriormente, a variável ALLEGRO_EVENT é uma struct com diversos campos. E o campo .keyboard.keycode, em caso de disparo de um evento relativo a uma tecla, possuirá um código referente a qual tecla foi pressionada. Consulte a referência para saber sobre os possíveis keycodes.
Nas linhas 94, 98, 102 e 106 verificamos se as teclas pressionadas são as setas para cima, baixo, esquerda e direita, respectivamente. Em cada caso colocamos um valor arbitrário na variável tecla, que será verificado mais adiante.
Na linha 116 verificamos se o evento disparado foi ALLEGRO_EVENT_KEY_UP, que é o evento relacionado ao soltar uma tecla. Em caso verdadeiro, colocamos o valor tecla=5. Este valor vai servir para na parte do código que mostra o texto, o programa saber que é para limpar o conteúdo da tela.
Na linha 120 testamos se o usuário clico no botão de fechar a janela, se sim, colocamos a flag sair=1. Isto fará com que o programa feche na próxima iteração do loop principal (linha 83).
Na linha 126 testamos se tecla!=0. Caso seja, significa que desde a última iteração do loop principal, alguma tecla foi pressionada ou solta. Isto significa que temos que atualizar a tela.
Começamos limpando a tela na linha 127, para então verificar com o switch da linha 130 o valor da tecla. Caso os valores sejam de 1 a 4 significa que o usuário pressionou alguma seta, conforme visto acima. Neste caso, usamos a função al_draw_text para escrever a mensagem na tela. Cada mensagem será de uma cor diferente, todas no centro da tela, com a fonte definida na linha 51.
Como no switch não temos nenhum caso para tecla==5 significa que o progrma apenas limpará a tela (linha 127) sem mostrar nenhum texto.
Ao após escrever o texto, atribuímos tecla=0 para dizer ao programa que não há mais o que atualizar, logo, na próxima vez que o programa chegar na linha 126, se nenhum evento de captura de tecla tiver sido disparado antes, nada mais será escrito.