quarta-feira, 22 de junho de 2016

07 - SDL2 - Input, interagindo com a janela

Nos últimos tutoriais uma janela era criada e passado um tempo que ela estava sendo exibida ela se fechava automaticamente, não havia nenhuma interação do usuário com a janela. Neste tutorial vou ensinar como interagir com os botões de minimizar, maximizar e fechar da janela.
Para ficar mais simples de compreender vou utilizar o código onde e criada apenas uma janela em branco assim como a utilizada no tutorial 3.



Vamos ao código de exemplo e em seguida as explicações:



#include <stdio.h>
#include <SDL2/SDL.h>

int main(int argc,char* argv[]){

    if(SDL_Init(SDL_INIT_VIDEO) != 0){
        fprintf(stderr, "Erro ao iniciar a biblioteca: %s", SDL_GetError());
        return 1;
    }

    SDL_Window* janela;

    janela = SDL_CreateWindow("janela", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
    if(janela == NULL){
        fprintf(stderr, "Erro ao criar a janela: %s", SDL_GetError());
        return 1;
    }

    SDL_Event event;
    while(1){

        SDL_PollEvent(&event);
        if(event.type == SDL_QUIT){
            break;
        }

    }


    SDL_DestroyWindow(janela);
    SDL_Quit();

    return 0;
}


O que tem de diferente entre este e o primeiro exemplo é a substituição do trecho onde estava a função SDL_Dealy() pelo trecho:



SDL_Event event;
    while(1){

        SDL_PollEvent(&event);
        if(event.type == SDL_QUIT){
            break;
        }

    }


    Neste trecho do código é criado uma variável do tipo SDL_Event ela, então, é usada dentro do bloco while pela função SDL_PollEvent() que tira da fila de eventos o evento que está ocorrendo naquele momento que a função está sendo executada. Em seguida o tipo de evento que está ocorrendo é testado pelo bloco if, e no nosso exemplo, se ele for do tipo SDL_QUIT é executado um break que faz o loop while parar e dar continuidade ao restante do código onde finaliza e fecha o programa.
    De acordo com a documentação da SLD este é o método preferencial receber eventos do sistema já que pode se fazer uso da função SDL_PollEvent() no loop principal sem o suspender enquanto espera um evento ocorrer.
    Agora podemos executar nosso exemplo e ele continuará em execução até pressionarmos o botão fechar da janela.

    Bem, este foi um exemplo simples de como fechar a nossa janela quando clicarmos no botão fechar mas, podemos vir a precisar de algo mais elaborado, por exemplo: E se precisássemos que algo ocorresse ao clicar no botão minimizar, ou no botão maximizar?
    Para termos um controle maior sobre os eventos que ocorrem com a janela do programa podemos usar a função SDL_PollEvent() em conjunto com o tipo de evento SDL_WINDOWEVENT.

Veja o exemplo abaixo:



#include <stdio.h>
#include &ltSDL2/SDL.h>


int main(int argc,char* argv[]){

    if(SDL_Init(SDL_INIT_VIDEO) != 0){
        fprintf(stderr, "Erro ao iniciar a biblioteca: %s", SDL_GetError());
        return 1;
    }

    SDL_Window* janela;

    janela = SDL_CreateWindow("janela", 100, 100, 640, 480, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE );
    if(janela == NULL){
        fprintf(stderr, "Erro ao criar a janela: %s", SDL_GetError());
        return 1;
    }


    SDL_Event event;
bool quit = false; 
    while(!quit){

        SDL_PollEvent(&event);
        if(event.type == SDL_WINDOWEVENT){

            switch(event.window.event){               
                case SDL_WINDOWEVENT_SIZE_CHANGED:
                    SDL_Log("Maximizado para %d de largura e %d  de altura", event.window.data1, event.window.data2);
                    break;
                case SDL_WINDOWEVENT_MINIMIZED:
                    SDL_Log("O programa foi minimizado!");
                    break;
      case SDL_WINDOWEVENT_CLOSE:
                    SDL_Log("Fechando o programa.");
  quit = true;
                    break;
            }
        }else if (event.type == SDL_QUIT){
            SDL_DestroyWindow(janela);
            SDL_Quit();
            return 0;
        }

    }

    SDL_DestroyWindow(janela);
    SDL_Quit();

    return 0;
}


    A primeira mudança está na criação da janela onde foi colocada a opção para permitir que a janela possa ser redimensionada e também habilita o botão maximizar na janela.


janela = SDL_CreateWindow("janela", 100, 100, 640, 480, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE );



    Para este exemplo que é um pouco mais complexo uma boa opção é criar uma variável do tipo booleana e deixar ela com o falor false, e usamos ela de forma que o laço while continue em execução (!quit equivale a true).


bool quit = false; 
    while(!quit){

Nesta parte do código vemos que evento testado é do tipo SDL_WINDOWEVENT, que são eventos que ocorrem com a janela criada.


if(event.type == SDL_WINDOWEVENT){


    No bloco switch testamos qual o tipo de evento que está ocorrendo na janela.


switch(event.window.event){


    Caso o evento seja a mudança de tamanho da janela usa a função SDL_Log() que joga uma mensagem para o console. Quando há este tipo de evento as variáveis data1 e data2 guardam o valor da largura e altura que a nova janela possui.

case SDL_WINDOWEVENT_SIZE_CHANGED:
                    SDL_Log("Maximizado para %d de largura e %d  de altura", event.window.data1, event.window.data2);
         break;


    No segundo case é testado se a janela está minimizada, se estiver novamente joga pra o console uma mensagem.

case SDL_WINDOWEVENT_MINIMIZED:
                    SDL_Log("O programa foi minimizado!");
                    break;

    No último teste verificamos se o botão de fechar da janela foi pressionado, se sim mandamos uma mensagem para o console e modificamos o valor de quit para true, o que equivale a passar o valor false para o nosso while.  

case SDL_WINDOWEVENT_CLOSE:
                    SDL_Log("Fechando o programa.");
                    quit = true;
                    break;

    Com isso o loop para de ser executado e passa então para os comandos seguintes que finalizam a janela a biblioteca SDL e o programa.



SDL_DestroyWindow(janela);
 SDL_Quit();

 return 0;

    Para terminar abaixo está a tabela de eventos que pode ser usada em conjunto com eventos do tipo SDL_WINDOWEVENT.


SDL_WINDOWEVENT_SHOWN
a janela foi exibida.
SDL_WINDOWEVENT_HIDDEN
a janela foi escondida.
SDL_WINDOWEVENT_EXPOSED
a janela foi exposta e deve ser redesenhada
SDL_WINDOWEVENT_MOVED
a janela foi movida, as variáveis data1 e data2 guardam a posição X e Y para onde a janela foi movida
SDL_WINDOWEVENT_RESIZED
a janela foi redimensionada, as variáveis data1 e data2 guardam a largura e a altura da janela depois de redimensionada. Ela é sempre precedida pela SDL_WINDOWEVENT_SIZE_CHANGED.
SDL_WINDOWEVENT_SIZE_CHANGED
o tamanho da janela foi alterado, seja por um chamada da API, pelo sistema ou usuário alterando o tamanho da janela; este evento é seguido por SDL_WINDOWEVENT_RESIZED se o tamanho foi alterado por um evento externo, exp. o usuário ou gerenciador de janela.
SDL_WINDOWEVENT_MINIMIZED
a janela foi minimizada.
SDL_WINDOWEVENT_MAXIMIZED
a janela foi maximizada.
SDL_WINDOWEVENT_RESTORED
a janela foi restaurada para o tamanho e posição normal.
SDL_WINDOWEVENT_ENTER
a janela ganhou o foco do mouse.
SDL_WINDOWEVENT_LEAVE
a janela perdeu o foco do mouse.
SDL_WINDOWEVENT_FOCUS_GAINED
a janela ganhou o foco do teclado.
SDL_WINDOWEVENT_FOCUS_LOST
a janela perdeu o foco do teclado.
SDL_WINDOWEVENT_CLOSE
O gerenciador de janelas requer que a janela seja fechada.

     Bom pessoal, acabou mais este tutorial, agradeço pela leitura. Qualquer dúvida, sugestão é só deixar nos comentários abaixo.

Nenhum comentário:

Postar um comentário