domingo, 29 de janeiro de 2017

08 - SDL2 - Input, teclado

    Neste tutorial mostrarei como utilizar as tecas “a”, “s”, “d” e “ f” para movimentar uma bola vermelha pela tela e as teclas 1, 2 e 3 para trocar entre a imagem exibida na tela.

    As imagens utilizadas nos exemplos são essas abaixo:

        


Teclado

Vamos ao código do primeiro exemplo:

#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 | SDL_WINDOW_RESIZABLE );
    if(janela == NULL){
        fprintf(stderr, "Erro ao criar a janela: %s", SDL_GetError());
        return 1;
    }

    SDL_Renderer* render = SDL_CreateRenderer(janela, -1, SDL_RENDERER_ACCELERATED);
    if(render == NULL){
        printf("Erro ao criar o reder: %s", SDL_GetError());
    }

    // Imagem 1
    SDL_Surface* green = SDL_LoadBMP("green.bmp");
    if(green == NULL){
        printf("Não foi possivel carregar a imagem");
    }
    // Imagem 2
    SDL_Surface* red = SDL_LoadBMP("red.bmp");
    if(red == NULL){
        printf("Não foi possivel carregar a imagem");
    }
    // Imagem 3
    SDL_Surface* blue = SDL_LoadBMP("blue.bmp");
    if(blue == NULL){
        printf("Não foi possivel carregar a imagem");
    }

    SDL_Texture* tex = SDL_CreateTextureFromSurface(render, green);
    SDL_Rect* rec = new(SDL_Rect);
    rec->x = 0;
    rec->y = 0;
    rec->w = 100;
    rec->h = 100;


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

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

            switch(event.window.event){
                case SDL_WINDOWEVENT_CLOSE:
                    SDL_Log("Fechando o programa.");
                    quit = true;
                    break;
                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;

            }
        } else if(event.type == SDL_KEYDOWN){

            switch(event.key.keysym.sym){
                case SDLK_a: rec->x--; break;
                case SDLK_s: rec->y++; break;
                case SDLK_d: rec->x++; break;
                case SDLK_w: rec->y--; break;
                case SDLK_1:
                    tex = SDL_CreateTextureFromSurface(render, green);
                    break;
                case SDLK_2:
                    tex = SDL_CreateTextureFromSurface(render, red);
                    break;
                case SDLK_3:
                    tex = SDL_CreateTextureFromSurface(render, blue);
                    break;

            }
        

        SDL_RenderClear(render);
        SDL_RenderCopy(render, tex, NULL, rec);
        SDL_RenderPresent(render);


    }
    
    SDL_FreeSurface(red);
    SDL_FreeSurface(green);
    SDL_FreeSurface(blue);
    SDL_DestroyTexture(tex);
    SDL_DestroyRenderer(render);

    SDL_DestroyWindow(janela);
    SDL_Quit();

    return 0;
}


    O primeiro passo, depois de iniciar a biblioteca, foi carregar as imagens para a memória e testar se elas foram realmente carregadas assim como já fizemos em tutoriais anteriores.


// Imagem 1
    SDL_Surface* green = SDL_LoadBMP("green.bmp");
    if(green == NULL){
        printf("Não foi possivel carregar a imagem");
    }
    // Imagem 2
    SDL_Surface* red = SDL_LoadBMP("red.bmp");
    if(red == NULL){
        printf("Não foi possivel carregar a imagem");
    }
    // Imagem 3
    SDL_Surface* blue = SDL_LoadBMP("blue.bmp");
    if(blue == NULL){
        printf("Não foi possivel carregar a imagem");
    }


    Nesta parte do código carregamos para a textura a imagem que queremos desenhar na tela. Uma das imagens tem que ser escolhida pois se a variável tex não for iniciada corretamente ou tiver um valor nulo ocorrerá um erro ao tentar desenhar a imagem na tela.


SDL_Texture* tex = SDL_CreateTextureFromSurface(render, green);

 
 É necessário criar uma variável do tipo SDL_Rect, ela será usada para guardar dados da posição e tamanho da imagem que será desenhada na tela mais para frente no código.

    Os valores de rec->x e rec->y, no código, definem a posição da imagem enquanto os valores de rec->w e rec->h definem o tamanho da imagem, quando a variável é usada como terceiro argumento na função SDL_RenderCopy().


SDL_Rect* rec = new(SDL_Rect);
    rec->x = 0;
    rec->y = 0;
    rec->w = 100;
    rec->h = 100;




    O mesmo bloco while que é usado no tutorial anterior é também usado neste porem com o acréscimo do bloco de código para manipular o evento de teclado logo em seguida ao usado para manipular os eventos de janela.

    Existem dois tipos de evento de teclado: o SDL_KEYDOWN, que ocorre ao pressionar uma tecla e o SDL_KEYUP, que ocorre ao pressionar e soltar uma tecla. Neste último caso ao soltar a tecla o tipo de evento vai continuar sendo SDL_KEYUP até se pressionar outra tecla e a ação que você programou para acontecer ao soltar a tecla irá continuar acontecendo até outra tecla ser pressionada. Teste no seu código, troque SDL_KEYDOWN por SDL_KEYUP e veja o que acontece.

    No bloco de código abaixo é testado se o tipo de evento é SDL_KEYDOWN e se sim verifica através do bloco switch se o atributo key.keysym.sym da variável de manipulação de eventos, que para nós é a variável event corresponde a um dos valores.

    Caso seja pressionada a tecla “a” (SDLK_a) a variável que é usada para definir a posição X (rec->x) da imagem e decrescida, com isso a imagem se desloca para a esquerda (tecla “s” para baixo, “d” para direita e “w” para cima ).

    As teclas “1”, “2” e “3” do teclado, não as do teclado numérico, são usadas para trocar a imagem que é exibida na tela.

    Podemos usar tanto as constantes definidas na biblioteca SDL (SDLK_a, SDLK_s, ...) quanto os caracteres entre aspas simples (‘a’, ‘s’).

    Uma relação de todas as constantes podem ser vistas neste link:

https://wiki.libsdl.org/SDL_Keycode?highlight=%28%5CbCategoryEnum%5Cb%29%7C%28CategoryKeyboard%29


else if(event.type == SDL_KEYDOWN){

            switch(event.key.keysym.sym){
                case SDLK_a: rec->x--; break;
                case SDLK_s: rec->y++; break;
                case SDLK_d: rec->x++; break;
                case SDLK_w: rec->y--; break;
                case SDLK_1:
                    tex = SDL_CreateTextureFromSurface(render, green);
                    break;
                case SDLK_2:
                    tex = SDL_CreateTextureFromSurface(render, red);
                    break;
                case SDLK_3:
                    tex = SDL_CreateTextureFromSurface(render, blue);
                    break;

            }

    Depois de testar os eventos é hora de limpar a tela, jogar a imagem na tela e mostrar ela na tela.



SDL_RenderClear(render);
SDL_RenderCopy(render, tex, NULL, rec);
SDL_RenderPresent(render);

    Na hora de finalizar nosso programa não podemos esquecer de descarregar as imagens que foram carregadas para a memória, destruir a textura e a área de renderização.



SDL_FreeSurface(red);
SDL_FreeSurface(green);
SDL_FreeSurface(blue);
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(render);

    Abaixo está um pequeno vídeo que fiz do funcionamento do programa.


    Espero que tenha gostado do tutorial. E como sempre se encontrar algum erro, tiver alguma sugestão, duvida ou se quiser só me elogiar mesmo ( :P ) é só deixar ai embaixo nos comentários.

    Agradeço sua visita e... até a próxima!

Nenhum comentário:

Postar um comentário