SDLDoc-ptBR/Tratando_o_Teclado - SDL Documentation Wiki
Tratando_o_Teclado
Estruturas Relacionadas ao Teclado
Deverá ser bem mais fácil entender este tutorial se você estiver familiarizado com os tipos de dados envolvidos no acesso ao teclado, então eu os explicarei primeiro.
SDLKey é um tipo enumerado definido em SDL/include/SDL_keysym.h e detalhado aqui. Cada símbolo de SDLKey representa uma tecla, SDLK_a corresponde a tecla 'a' no teclado, SDLK_SPACE corresponde a barra de espaço, e assim por diante.
SDLMod é um tipo enumerado, similar ao SDLKey, mas ele enumera teclas modificadoras (Control, Alt, Shift). A lista completa dos modificadores está aqui. Os valores de SDLMod juntos podem E PODERIAM representar vários modificadores.
A estrutura SDL_keysym descreve uma tecla pressionada ou uma tecla liberada. O campo scancode é específico ao hardware e deve ser ignorado ao menos que você saiba o que está fazendo. O campo sym é o valor de SDLKey da tecla pressionada ou liberada. O campo mod descreve o estado dos modificadores de teclado no momento em que a tecla foi pressionada ou liberada. Então, um valor de KMOD_NUM | KMOD_CAPS | KMOD_LSHIFT significariam que as teclas Numlock, Capslock e o Shift esquerdo estão todas pressionadas (ou habilitadas no caso das teclas de travamento). Finalmente, o campo unicode armazena o valor de 16-bit unicode da tecla.
Nota: Deve ser observado e entendido que este campo é valido somente quando o SDL_keysym está descrevendo uma tecla pressionada, não uma tecla liberada. Valores unicodes apenas percebem teclas pressionadas porque o valor unicode descreve um caractere internacional e somente teclas pressionadas produzem caracteres. Mais informações podem ser encontradas em www.unicode.org
Nota: A conversão unicode deve ser habilitada usando a função SDL_EnableUNICODE
A SDL_KeyboardEvent descreve um evento de teclado (obviamente). O membro key da união SDL_Event é uma estrutura SDL_KeyboardEvent. O campo type especifica se o evento é um evento de tecla liberada (SDL_KEYUP) ou tecla pressionada (SDL_KEYDOWN). O state é totalmente redundante, ele reporta a mesma informação do campo type, mas, usa valores diferentes (SDL_RELEASED e SDL_PRESSED). O keysym contém informações sobre a tecla pressionada ou liberada que este evento representa. (veja acima).
Lendo Eventos do Teclado
Ler a pilha de eventos do teclado é realmente simples (a pilha de eventos, e como usá-la está descrito aqui). Nós lemos os eventos usando SDL_PollEvent em um loop while() e checando pelos eventos SDL_KEYUP e SDL_KEYDOWN usando uma declaração switch, como esta:
Exemplo 3-10. Lendo Eventos do Teclado
/* Pesquisa por eventos. SDL_PollEvent() retorna 0 quando não há mais */
/* eventos na pilha de eventos, nosso loop while irá terminar quando */
/* isto acontecer.                                                  */
/* Nós estamos interessados nos eventos SDL_KEYDOWN e SDL_KEYUP */
printf( "Tecla pressionada\n" );
printf( "Tecla liberada\n" );
Este é um exemplo muito simples. Nenhuma informação sobre as tecla pressionada ou liberada é interpretada. Nós iremos explorar os outros extremos em nosso primeiro exemplo completo abaixo – reportando toda informação disponível sobre um evento de teclado.
Antes de podermos ler eventos, a SDL deve ser iniciada com SDL_Init e um modo de vídeo deve ser estabelecido usando SDL_SetVideoMode. Existem também duas outras funções que vamos usar para obter todas as informações requeridas. Vamos habilitar a conversão unicode chamando SDL_EnableUNICODE(1) e devemos converter valores SDLKey em algo imprimível, usando SDL_GetKeyName
Nota: É útil notar que valores unicodes < que 0x80 convertem diretamente caracteres de valor ASCII. Isto é usado no exemplo abaixo
Exemplo 3-11. Interpretando Informações de Eventos de Teclado
/* Protótipos de função */
/* Inicia a SDL */
fprintf( stderr, "Não foi possível iniciar SDL: %s\n", SDL_GetError() );
/* Estabelecendo um modo de vídeo */
fprintf( stderr, "Não foi possível estabelecer um modo de vídeo: %s\n", SDL_GetError() );
/* Habilita conversão unicode */
/* Laço rodando até que um evento SDL_QUIT ocorra */
/* Consulta de eventos */
/* Eventos de teclado */
/* Passa os dados do evento para PrintKeyInfo() */
/* Evento SDL_QUIT (window close) */
/* Imprime toda a informação sobre um evento de tecla */
/* Está sendo liberado ou pressionado? */
printf( "Liberada:- " );
printf( "Pressionada:- " );
/* Imprime o scancode do hardware primeiro */
/* Imprime o nome da tecla */
printf( ", Nome: %s", SDL_GetKeyName( key->keysym.sym ) );
/* Nós queremos imprimir a informação unicode, mas nós precisamos */
/* ter certeza que isso é um evento de tecla pressionada (lembre-se, */
/* eventos de teclas liberadas não possuem informação unicode) */
/* Se o valor unicode for menor que 0x80 então o valor  */
/* unicode pode ser usado para pegar uma  representação */
/* imprimível da tecla, usando (char)unicode  */
/* Imprime as informações dos modificadores */
/* Imprime informações dos modificadores */
printf( "Modificadores: " );
/* Se não existirem então diz isso e retorna */
printf( "Nenhum\n" );
/* Checa a presença de cada valor de SDLMod */
/* Isto parece sujo, mas realmente não existe */
/* uma maneira limpa.                        */
Entrada Para Jogos
Eu tenho encontrado pessoas usando eventos de teclado para jogos e outras aplicações interativas muitas vezes não entendendo um ponto fundamental.
Eventos de teclado apenas acontecem quanto o estado de uma tecla muda de não-pressionado para pressionado e vice versa.
Imagine que você possui uma imagem de um alienígena que você deseja mover usando as teclas de cursor – quando você pressiona a tecla da esquerda você quer que ele deslize para a esquerda, quando você pressiona a tecla para baixo você quer que ele deslize para baixo do vídeo. Olhe o código seguinte, ele sinaliza um erro que muitas pessoas cometem.
/* Coordenadas do alienígena na tela */
/* Inicializa SDL, vídeo e todas aquelas coisas... */
/* Laço principal do jogo */
/* Checa os eventos */
/* Procura por um evento de tecla pressionada */
/* Checa os valores de SDLKey para modificar as coordenadas */
A principio você pode pensar que isto é o pedaço de código ideal para esta tarefa, mas ele não é. Como eu disse, eventos de teclado apenas ocorrem quando uma tecla muda de estado, então o usuário teria que pressionar e soltar a tecla de cursor para esquerda 100 vezes para mover o alienígena 100 pixels para esquerda.
Para contornar este problema, não devemos usar os eventos para mudar a posição do alienígena, nós usaremos os eventos para definir "flags" que serão usadas em uma seção separada de código para mover o alienígena. Algo como isto:
Exemplo 3-12. Movimento Adequado Para Jogos
/* Procura por uma tecla pressionada */
/* Devemos também usar os eventos SDL_KEYUP para zerar as variáveis */
/* de velocidade x e y. Mas temos que ser cuidadosos para não zerarmos */
/* velocidades que não deveríamos                                     */
/* Vamos checar para ter certeza de que o alienígena */
/* está movendo para esquerda. Se estiver então nós  */
/* zeramos a velocidade. Se o alienígena estiver se  */
/* movendo para direita, então a tecla para direita  */
/* continua pressionada, logo, não devemos mexer     */
/* nessa velocidade                                  */
/* Atualiza as coordenadas do alienígena */
Como pode ser visto, usamos duas variáveis extras, alien_xvel e alien_yvel, que representam o movimento da nave, são estas variáveis que nós atualizamos quando detectamos teclas pressionadas e liberadas.