Para ler eventos, usaremos uma função chamada
SDL_PollEvent, que lerá a fila de eventos e colocará o mais antigo numa variável
SDL_Event.
Internamente, o SDL enfileira os eventos e a cada chamada de
SDL_PollEvent, será posto numa variável
SDL_Event, o evento mais antigo e assim poderá ser processado da maneira que quisermos.
O próximo programa mostrará como fechar a janela principal, esse programa servirá de base para os próximos.
Fechando uma janela
Arquivo:
eventos_01.c
#include <SDL/SDL.h>
int main()
{
SDL_Init(SDL_INIT_VIDEO); // Inicializa o SDL e o sistema de vídeo
SDL_Surface * screen; // A janela principal
SDL_Event event; // Para os eventos
screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE); // Cria a janela
int done = 0; // Variável de controle do loop
while (done == 0) // Loop principal
{
// Lê a fila de eventos e põe o evento mais antigo em "event"
while (SDL_PollEvent(&event)) // Loop de eventos
{
// Verifica se o evento mais antigo é do tipo SDL_QUIT
if (event.type == SDL_QUIT) // Se o usuário clicou para fechar a janela
done = 1; // Encerre o loop
}
}
SDL_Quit(); // Fecha o SDL
return 0;
}
Para compilar:
gcc -o eventos_01 eventos_01.c -lSDL
SDL_Event event; :: variável para tratar os eventos.
SDL_Event é a estrutura de todos os eventos do SDL. Tem dois usos específicos: ler eventos da fila de eventos e colocar evento na fila de eventos. Por enquanto, apenas ler os evento é o bastante. Há duas funções que leem eventos, que são: SDL_PollEvent e SDL_PeepEvetns. Mas vamos usar somente
SDL_PollEvent.
while (SDL_PollEvent(&event)) :: aqui estamos lendo toda a fila de eventos. Esse é o motivo de usar um
while, se usássemos um
if, apenas um evento seria lido (o mais antigo, é claro). Enquanto houver eventos na fila
SDL_PollEvent, retornará 1, se não houver retorna 0. Ele recebe um ponteiro para um
SDL_Event que será preenchido com o evento mais antigo da fila de eventos.
if (event.type == SDL_QUIT) :: verifica se o evento atual lido da fila de eventos é do tipo
SDL_QUIT. Esse evento é chamado assim que o usuário clica sobre o botão fechar da janela.
Manipulação do mouse
1. Movimento do mouse:
Arquivo:
eventos_02.c
#include <SDL/SDL.h>
#include <stdio.h>
int main()
{
SDL_Init(SDL_INIT_VIDEO); // Inicializa o SDL e o sistema de vídeo
SDL_Surface * screen; // A janela principal
SDL_Event event; // Para os eventos
screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE); // Cria a janela
int done = 0; // Variável de controle do loop
while (done == 0) // Loop principal
{
// Lê a fila de eventos e põe o evento mais antigo em "event"
while (SDL_PollEvent(&event)) // Loop de eventos
{
// Verifica se o evento mais antigo é do tipo SDL_QUIT
if (event.type == SDL_QUIT) // Se o usuário clicou para fechar a janela
done = 1; // Encerre o loop
// Verifica se o evento mais antigo é do tipo SDL_MOUSEMOTION
if (event.type == SDL_MOUSEMOTION) // Se o usuário moveu o cursor sobre a tela
{
printf("Moveu o cursor para X = %d, Y = %d\n", event.motion.x, event.motion.y);
}
}
}
SDL_Quit(); // Fecha o SDL
return 0;
}
Para compilar:
gcc -o eventos_02 eventos_02.c -lSDL
if (event.type == SDL_MOUSEMOTION) :: verifica se o tipo de evento é
SDL_MOUSEMOTION (movimento do mouse). Esse tipo de evento só é identificado se o cursor estiver sobre a janela principal. Fora dela, mesmo com movimento do mouse, nenhum evento é disparado.
Poderia alterar o programa para colocar uma imagem sob o ponteiro do mouse. Bastava apenas criar uma variável
SDL_Rect com nome
dest e setar as coordenadas para a posição do cursor. Veja abaixo:
Arquivo:
eventos_03.c
#include <SDL/SDL.h>
#include <stdio.h>
int main()
{
SDL_Init(SDL_INIT_VIDEO); // Inicializa o SDL e o sistema de vídeo
SDL_Surface * screen; // A janela principal
SDL_Surface * image; // A imagem
SDL_Event event; // Para os eventos
SDL_Rect dest; // Destino da imagem dentro do screen
screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE); // Cria a janela
image = SDL_LoadBMP("ball.bmp"); // Carrega o arquivo de imagem
// Verifica se carregou a imagem
if (image == NULL)
{
printf("Não foi possivel abrir ball.bmp\n");
return 1;
}
int done = 0; // Variável de controle do loop
while (done == 0) // Loop principal
{
while (SDL_PollEvent(&event)) // Lê a fila de eventos e põe o evento mais antigo em "event"
{
// Verifica se o evento mais antigo é do tipo SDL_QUIT
if (event.type == SDL_QUIT) // Se o usuário clicou para fechar a janela
done = 1; // Encerre o loop
// Verifica se o evento mais antigo é do tipo SDL_MOUSEMOTION
if (event.type == SDL_MOUSEMOTION) // Se o usuário moveu o cursor sobre a tela
{
printf("Moveu o cursor para X = %d, Y = %d\n", event.motion.x, event.motion.y);
// Seta o destino da imagem para as coordenadas do cursor
dest.x = event.motion.x; // Posição do cursor no eixo X
dest.y = event.motion.y; // Posição do cursor no eixo Y
}
}
SDL_FillRect(screen, NULL, 0x0); // Pinta de preto todo o screen
SDL_BlitSurface(image, NULL, screen, &dest); // Joga a imagem no "screen" em "dest"
SDL_UpdateRect(screen, 0,0,0,0); // Atualiza todo o screen
SDL_Delay(60); // Espera 60 milissegundos
}
SDL_Quit(); // Fecha o SDL
return 0;
}
Para compilar:
gcc -o eventos_03 eventos_03.c -lSDL
Se você apagar a linha com
SDL_FillRect(screen, NULL, 0x0); poderá ver o por quê de ter que pintar todo o screen com uma cor antes de "blitar" uma imagem. A tela ficará toda "suja" com blitagem passadas de "image". Fica parecendo até bug do Windows. (rsrs)
2. Botão do mouse:
Arquivo:
eventos_04.c
#include <SDL/SDL.h>
#include <stdio.h>
int main()
{
SDL_Init(SDL_INIT_VIDEO); // Inicializa o SDL e o sistema de vídeo
SDL_Surface * screen; // A janela principal
SDL_Event event; // Para os eventos
screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE); // Cria a janela
int done = 0; // Variável de controle do loop
while (done == 0) // Loop principal
{
while (SDL_PollEvent(&event)) // Lê a fila de eventos e põe o evento mais antigo em "event"
{
// Verifica se o evento mais antigo é do tipo SDL_QUIT
if (event.type == SDL_QUIT) // Se o usuário clicou para fechar a janela
done = 1; // Encerre o loop
// Verifica se o evento mais antigo é do tipo SDL_MOUSEBUTTONDOWN
if (event.type == SDL_MOUSEBUTTONDOWN) // Se o usuário clicou
{
if (event.button.button == SDL_BUTTON_LEFT)
printf("APERTOU o botão do mouse: botão ESQUERDO\n");
else if (event.button.button == SDL_BUTTON_RIGHT)
printf("APERTOU o botão do mouse: botão DIREITO\n");
}
// Verifica se o evento mais antigo é do tipo SDL_MOUSEBUTTONUP
if (event.type == SDL_MOUSEBUTTONUP) // Se o usuário clicou
{
if (event.button.button == SDL_BUTTON_LEFT)
printf("SOLTOU o botão do mouse: botão ESQUERDO\n");
else if (event.button.button == SDL_BUTTON_RIGHT)
printf("SOLTOU o botão do mouse: botão DIREITO\n");
}
}
}
SDL_Quit(); // Fecha o SDL
return 0;
}
Para compilar:
gcc -o eventos_04 eventos_04.c -lSDL
if (event.type == SDL_MOUSEBUTTONDOWN) :: verifica se apertou um botão do mouse.
if (event.type == SDL_MOUSEBUTTONUP) :: verifica se soltou um botão do mouse. Em event o botão pressionado ou solto fica armazenado em button que é do tipo SDL_MouseButtonEvent. Essa estrutura contém outros membros como posição do clique (x e y) e estado do botão (state).
Exercício: colocar uma imagem na posição onde o usuário clicar. Use
man SDL_MouseButtonEvent, para mais informação.
Manipulando o teclado
1. Evento de pressionar e soltar de tecla:
Arquivo:
eventos_05.c
#include <SDL/SDL.h>
#include <stdio.h>
int main()
{
SDL_Init(SDL_INIT_VIDEO); // Inicializa o SDL e o sistema de vídeo
SDL_Surface * screen; // A janela principal
SDL_Event event; // Para os eventos
screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE); // Cria a janela
int done = 0; // Variável de controle do loop
while (done == 0) // Loop principal
{
while (SDL_PollEvent(&event)) // Lê a fila de eventos e põe o evento mais antigo em "event"
{
// Verifica se o evento mais antigo é do tipo SDL_QUIT
if (event.type == SDL_QUIT) // Se o usuário clicou para fechar a janela
done = 1; // Encerre o loop
// Verifica se o evento mais antigo é do tipo SDL_KEYDOWN
if (event.type == SDL_KEYDOWN) // Se o usuário apertou um botão do teclado
{
printf("APERTOU uma tecla\n");
}
// Verifica se o evento mais antigo é do tipo SDL_KEYUP
if (event.type == SDL_KEYUP) // Se o usuário soltou um botão do teclado
{
printf("SOLTOU uma tecla\n");
}
}
}
SDL_Quit(); // Fecha o SDL
return 0;
}
Para compilar:
gcc -o eventos_05 eventos_05.c -lSDL
if (event.type == SDL_KEYDOWN) :: verifica se o usuário apertou uma tecla do teclado.
if (event.type == SDL_KEYUP) :: verifica se o usuário soltou uma tecla do teclado. O teclado só produz esses dois tipos de eventos.
2. Identificando teclas pressionada ou solta:
Arquivo:
eventos_06.c
#include <SDL/SDL.h>
#include <stdio.h>
int main()
{
SDL_Init(SDL_INIT_VIDEO); // Inicializa o SDL e o sistema de vídeo
SDL_Surface * screen; // A janela principal
SDL_Event event; // Para os eventos
screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE); // Cria a janela
int done = 0; // Variável de controle do loop
while (done == 0) // Loop principal
{
// Lê a fila de eventos e põe o evento mais antigo em "event"
while (SDL_PollEvent(&event)) // Loop de eventos
{
// Verifica se o evento mais antigo é do tipo SDL_QUIT
if (event.type == SDL_QUIT) // Se o usuário clicou para fechar a janela
done = 1; // Encerre o loop
// Verifica se o evento mais antigo é do tipo SDL_KEYDOWN
if (event.type == SDL_KEYDOWN) // Se o usuário apertou um botão do teclado
{
printf("APERTOU uma tecla: ");
// Verifica qual tecla foi apertada
switch (event.key.keysym.sym)
{
case SDLK_UP:
printf("Seta para CIMA\n");
break;
case SDLK_DOWN:
printf("Seta para BAIXO\n"):
break;
case SDLK_RIGHT:
printf("Seta DIREITA\n");
break;
case SDLK_LEFT:
printf("Seta ESQUERDA\n");
break;
default:
break;
}
}
if (event.type == SDL_KEYUP) // Se o usuário soltou um botão do teclado
{
printf("SOLTOU uma tecla: ");
// Verifica qual tecla foi solta
switch (event.key.keysym.sym)
{
case SDLK_UP:
printf("Seta para CIMA\n");
break;
case SDLK_DOWN:
printf("Seta para BAIXO\n"):
break;
case SDLK_RIGHT:
printf("Seta DIREITA\n");
break;
case SDLK_LEFT:
printf("Seta ESQUERDA\n");
break;
default:
break;
}
}
}
}
SDL_Quit(); // Fecha o SDL
return 0;
}
Para compilar:
gcc -o eventos_06 eventos_06.c -lSDL
switch (event.key.keysym.sym)
case SDLK_UP:
printf("Seta para CIMA\n");
break;
Aqui estamos verificando qual tecla foi apertada/solta. Dessa vez, a estrutura das tecla é um pouco mais longa,
event.key.keysym.sym é preciso acessar duas estruturas para saber o código/símbolo da tecla apertada/solta.
Todo símbolo de tecla no SDL começa com
SDLK_ seguida da tecla. Então, se, por exemplo, quisermos a tecla
a use
SDLK_a, tecla
b use
SDLK_b e assim por diante.
Mas, há teclas que não seguem esse padrão, as teclas do teclado numérico, por exemplo, use
SDLK_KP_"número da tecla". Para saber sobre todos os símbolos, use
man SDLKey no terminal.