Tutorial SDL – Eventos, detectar quando as teclas forem pressionadas

Continuando com a parte de eventos, vamos agora detectar os eventos quando o usuário pressionar algo no teclado.

Como vimos no primeiro tutorial de eventos, usamos uma função SDL chamada SDL_PollEvent que detecta o tipo (evento.type) do evento. Disse que existem vários tipos como: SDL_KEYDOWN (tecla pressionada), SDL_MOUSEMOTION (movimentação do mouse), SDL_MOUSEBUTTONDOWN (botão do mouse apertado), etc. Nesse tutorial veremos o SDL_KEYDOWN.

C++:
  1. //O Cabeçalho
  2. #include "SDL/SDL.h"
  3. #include "SDL/SDL_image.h"
  4. #include <string>
  5.  
  6. //Atributos da Tela
  7. const int SCREEN_WIDTH = 640;
  8. const int SCREEN_HEIGHT = 480;
  9. const int SCREEN_BPP = 32;
  10.  
  11. //As superfícies
  12. SDL_Surface *imagem = NULL;
  13. SDL_Surface *tela = NULL;
  14.  
  15. //A estrutura que usaremos para capturarmos os eventos
  16. SDL_Event evento;
  17.  
  18. SDL_Surface *carregaImagem( std::string imagem )
  19. {
  20. //Superfície que armazena temporariamente a imagem
  21. SDL_Surface* imagemCarregada = NULL;
  22.  
  23. //Superfície que retorna a imagem otimizada
  24. SDL_Surface* imagemOtimizada = NULL;
  25.  
  26. //Carrega a imagem
  27. imagemCarregada = IMG_Load( imagem.c_str() );
  28.  
  29. //Verifica se tudo deu certinho
  30. if( imagemCarregada != NULL )
  31. {
  32. //Cria a imagem otimizada
  33. imagemOtimizada = SDL_DisplayFormat( imagemCarregada);
  34.  
  35. //Libera a imagem carregada
  36. SDL_FreeSurface( imagemCarregada );
  37. }
  38.  
  39. //Retorna a imagem otimizada
  40. return imagemOtimizada;
  41. }
  42.  
  43. void aplicaSuperficie( int x, int y, SDL_Surface* fonte, SDL_Surface* destino )
  44. {
  45. //Cria um retangulo para a superficie
  46. SDL_Rect retangulo;
  47.  
  48. //Dá as coordenadas para o retangulo
  49. retangulo.x = x;
  50. retangulo.y = y;
  51.  
  52. //encaixa a "fonte" dentro do "destino" através do retangulo
  53. SDL_BlitSurface( fonte, NULL, destino, &amp;retangulo );
  54. }
  55.  
  56. bool inicia()
  57. {
  58. //Inicia os subsistemas da SDL
  59. if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
  60. {
  61. return false;
  62. }
  63.  
  64. //Setando a tela
  65. tela = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );
  66.  
  67. //Verifica se existe algum erro na tela
  68. if( tela == NULL )
  69. {
  70. return false;
  71. }
  72.  
  73. //Setando o caption da janela
  74. SDL_WM_SetCaption( "Tutorial SDL - Eventos", NULL );
  75.  
  76. //Se tudo deu certo
  77. return true;
  78. }</string>

Até aqui, não existe nenhuma diferença se comparado com o código da primeira parte de eventos, a função carrega_arquivos contém uma pequena diferença, agora ela tem um parâmetro sendo passado, pois diferentes imagens serão carregadas durante o programa.

C++:
  1. bool carrega_arquivos(std::string arquivo)
  2. {
  3. //Carrega a imagem
  4. imagem = carregaImagem( arquivo.c_str() );
  5.  
  6. //Verifica se existe algum erro no carregamento da imagem
  7. if( imagem == NULL )
  8. {
  9. return false;
  10. }
  11.  
  12. //se tudo der certo
  13. return true;
  14. }

A função limpa(), apenas libera a imagem e não fecha mais a SDL, tarefa designada agora a função sair().

C++:
  1. void limpa()
  2. {
  3. //Libera a imagem
  4. SDL_FreeSurface( imagem );
  5.  
  6. }
  7.  
  8. void sair()
  9. {
  10. //Fecha a SDL
  11. SDL_Quit();
  12. }

Agora vamos ao main():

C++:
  1. int main( int argc, char* args[] )
  2. {
  3.  
  4. //Variável necessária para saber se o usuário fechou a janela
  5. bool quit = false;
  6.  
  7. //Inicia
  8. if( inicia() == false )
  9. {
  10. return 1;
  11. }
  12.  
  13. //Carrega os arquivos
  14. if( carrega_arquivos("x.jpg") == false )
  15. {
  16. return 1;
  17. }
  18.  
  19. //Aplicando as superfícies na tela
  20. aplicaSuperficie( 0, 0, imagem, tela );
  21.  
  22. //Atualiza a tela
  23. if( SDL_Flip( tela ) == -1 )
  24. {
  25. return 1;
  26. }
  27.  
  28. //Enquanto o usuário não fechar o programa
  29. while( quit == false )
  30. {
  31. //Quando ocorrer um evento
  32. while( SDL_PollEvent( &amp;evento ) )
  33. {
  34. //se o usuário apertou o X da janela

Aqui faremos a verificação se o evento foi uma tecla pressionada.

C++:
  1. //verificando a tecla
  2. if( evento.type == SDL_KEYDOWN )
  3. {
  4. switch( evento.key.keysym.sym )
  5. {
  6. case SDLK_UP:
  7. limpa();
  8. carrega_arquivos("up.jpg");
  9. break;
  10.  
  11. case SDLK_DOWN:
  12. limpa();
  13. carrega_arquivos("down.jpg");
  14. break;
  15.  
  16. case SDLK_LEFT:
  17. limpa();
  18. carrega_arquivos("left.jpg");
  19. break;
  20.  
  21. case SDLK_RIGHT:
  22. limpa();
  23. carrega_arquivos("right.jpg");
  24. break;
  25.  
  26. default:
  27. limpa();
  28. carrega_arquivos("x.jpg");
  29. break;
  30. }
  31.  
  32. //Aplicando as superfícies na tela
  33. aplicaSuperficie( 0, 0, imagem, tela );
  34.  
  35. //dá um refresh na tela
  36. SDL_Flip( tela );
  37. }
  38.  
  39. if( evento.type == SDL_QUIT )
  40. {
  41. //Fecha o programa
  42. quit = true;
  43. }
  44. }
  45. }

Comparamos o tipo do evento (evento.type) e implementamos uma ação para quando esse evento ocorrer. Caso esse evento seja um SDL_KEYDOWN, verifiquei a sua propriedade key.keysym.sym e fiz um switch com as possibilidades das setas, a cada seta apertada (SDLK_UP, SDLK_DOWN, SDLK_LEFT, SDLK_RIGHT)é ativada uma imagem diferente.

C++:
  1. //Libera a superficie e fecha a SDL
  2. limpa();
  3. sair();
  4. return 0;
  5. }

E...fim!
Para mostrar esse tutorial, foi criado 5 arquivos jpg para as diferentes teclas apertadas.

Para baixar o fonte clique aqui.

Alguma Dúvida? romulo@cubagames.com.br ou comentário no site!