Tutorial Allegro 5 #13 – Utilizando Joystick

Padrão

Olá pessoal! Hoje temos mais um post da série sobre Allegro 5, dessa vez tratando sobre como programar uma aplicação para utilizar o joystick como dispositivo de entrada.

A biblioteca Allegro possui suporte nativo a esse tipo de dispositivo. Teoricamente, qualquer joystick USB reconhecido por seu sistema operacional deve funcionar corretamente junto com a biblioteca (pra dizer a verdade, nunca tive a oportunidade de testar um joystick com qualquer outro tipo de conexão).

Na versão 5, temos ainda uma nova funcionalidade: os joysticks podem ser conectados e desconectados mesmo durante a execução do seu aplicativo, bastando apenas realizar uma nova chamada à função al_reconfigure_joysticks(). Além disso, você pode utilizar, também, mais de um joystick ao mesmo tempo (infelizmente ainda não tenho 2 joysticks pra testar e fazer um tutorial… mas quem sabe num futuro próximo?).

Para esse tutorial, testei em um joystick bem mais ou menos que eu tenho aqui (é um Foston, modelo imitação do Dual Shock do Playstation), mas, como disse, deve funcionar com qualquer joystick USB que você tiver por aí.

O nosso exemplo consiste em mover um círculo pela tela utilizando os direcionais do joystick. Ao pressionar as teclas 1, 2, 3 ou 4, o círculo muda de cor, alternando entre branco, verde, azul e vermelho. Vamos dar uma olhada no código e já comentamos o que temos de novo nele:

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

#include <stdio.h>
#include <stdbool.h>

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

ALLEGRO_DISPLAY *janela = NULL;
ALLEGRO_EVENT_QUEUE *fila_eventos = NULL;
ALLEGRO_JOYSTICK *joystick = NULL;

bool inicializar();

int main(void)
{
    bool sair = false;

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

    const int raio = 25;
    int x = raio;
    int y = raio;
    int inc_x = 0, inc_y = 0;
    ALLEGRO_COLOR cor = al_map_rgb(255, 255, 255);

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

            if (evento.type == ALLEGRO_EVENT_JOYSTICK_AXIS)
            {
                if (evento.joystick.axis == 0)
                {
                    inc_x = evento.joystick.pos;
                }
                else if (evento.joystick.axis == 1)
                {
                    inc_y = evento.joystick.pos;
                }
            }
            else if (evento.type == ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN)
            {
                switch (evento.joystick.button)
                {
                case 1:
                    cor = al_map_rgb(255, 0, 0);
                    break;
                case 2:
                    cor = al_map_rgb(0, 0, 255);
                    break;
                case 3:
                    cor = al_map_rgb(0, 255, 0);
                    break;
                case 0:
                default:
                    cor = al_map_rgb(255, 255, 255);
                    break;
                }
            }
            else if (evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
            {
                sair = true;
            }
        }

        x += inc_x;
        if (x > LARGURA_TELA - raio)
        {
            x = LARGURA_TELA - raio;
        }
        else if (x < raio)
        {
            x = raio;
        }

        y += inc_y;
        if (y > ALTURA_TELA - raio)
        {
            y = ALTURA_TELA - raio;
        }
        else if (y < raio)
        {
            y = raio;
        }

        al_clear_to_color(al_map_rgb(0, 0, 0));
        al_draw_filled_circle(x, y, raio, cor);
        al_flip_display();
    }

    al_destroy_event_queue(fila_eventos);
    al_destroy_display(janela);

    return 0;
}

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

    if (!al_init_primitives_addon())
    {
        fprintf(stderr, "Falha ao inicializar add-on de primitivas.\n");
        return false;
    }

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

    al_reconfigure_joysticks();

    if (al_get_num_joysticks() == 0)
    {
        fprintf(stderr, "Nenhum joystick encontrado.\n");
        return false;
    }
    joystick = al_get_joystick(al_get_num_joysticks() - 1);

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

    al_set_window_title(janela, "Testando Joystick");

    fila_eventos = al_create_event_queue();
    if (!fila_eventos)
    {
        fprintf(stderr, "Falha ao criar fila de eventos.\n");
        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_joystick_event_source());

    return true;
}

Na inicialização, temos algumas funções novas sendo chamadas. A primeira delas é a função al_install_joystick(), necessária para utilizarmos esse dispositivo (assim como temos funções de inicialização específicas para mouse e teclado). Logo após, temos uma chamada à função al_reconfigure_joysticks(), necessária para o correto funcionamento dos joysticks dentro da aplicação. Em seguida, verificamos se algum dispositivo foi encontrado, através da função al_get_num_joysticks() que retorna o número de joysticks encontrados. A partir desta funções, obtemos o joystick através da função al_get_joystick() que retorna um ponteiro para o tipo ALLEGRO_JOYSTICK. Neste exemplo em questão, não utilizaremos tal estrutura (mostrei apenas como obtê-la). Ela é útil para diferenciar eventos quando temos mais de um joystick conectado. Por fim, adicionamos a nossa fila de eventos os eventos originados no joystick, passando para a função al_register_event_source() a função al_get_joystick_event_source().

Na parte de tratamento de eventos é onde realizamos a manipulação dos dados do joystick. No caso do nosso aplicativo, temos o tratamento dos eventos ALLEGRO_EVENT_JOYSTICK_AXIS (eventos originados pelos botões direcionais) e ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN (eventos originados ao pressionar-se algum dos botões numerados).

No tratamento dos eventos ALLEGRO_EVENT_JOYSTICK_AXIS, temos o campos joystick.axis dentro do evento. Caso seu valor seja 0, o movimento foi horizontal e caso seja 1 o movimento foi vertical. Através do seu valor, ajustamos o incremento da posição x e y do círculo, controlado pelas variáveis inc_x e inc_y. Com isso, conseguiremos mover o círculo pela tela, incrementando com o valor do campo joystick.pos, que é um valor float oscilando entre -1 e 1. No caso, como o meu joystick não possui direcionais analógicos, ele só retornará -1, 0 e 1 (caso seu joystick possua direcionais analógicos, esses valores podem ser fracionários, de forma que você pode controlar a intensidade do movimento em seu jogo).

No caso dos botões, tratados pelo evento ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN (também há o evento ALLEGRO_EVENT_JOYSTICK_BUTTON_UP), verificamos qual botão foi pressionado, conferindo o valor do campo joystick.button. No caso do Windows, você pode conferir o mapeamento dos botões através do utilitário do próprio sistema (disponível em Painel de Controle -> Dispositivos e Impressoras). No caso do meu joystick, ele possui 12 botões, então terei números dos botões reconhecidos pela Allegro com números de 0 a 11.

Para testar, basta ir pressionando os botões e eles serão destacados no utilitário.

Voltando ao nosso aplicativo, mapeei 4 botões, colocando uma opção padrão (default) para o caso de algum outro botão seja pressionado. Com isso, temos a variável cor do tipo ALLEGRO_COLOR que recebe uma cor de acordo com o botão que foi pressionado.

Ao final, limpamos a tela, e desenhamos o círculo na posição indicada e com a cor selecionada. Fazemos também um mapeamento das coordenadas para que o círculo não saia da tela. O nosso aplicativo deve ficar semelhante a isso:

Para compilar:

  • Windows: -lallegro-5.0.5-mt -lallegro_primitives-5.0.5-mt
  • Linux: -lallegro -lallegro_primitives

Bom pessoal, é isso! Até a próxima!

Um comentário sobre “Tutorial Allegro 5 #13 – Utilizando Joystick

  1. Gostei do código. Parabéns. Só não entendi uma coisa. Pra que você declarou a variável ALLEGRO_JOYSTICK e recebeu a função para obter os parâmetros do mesmo se essa variável “ficou boiando no programa”? Poderia nos mostrar um exemplo do uso da variável joystick? Obrigado

Deixe uma resposta