Tutorial SDL - Tercera Parte
Indice
Introducción
Bienvenidos otra vez, vamos a seguir avanzando sobre la programación de Videojuegos. El artículo anterior les explicaba como mostrar imágenes en la pantalla y cómo lograr animación muy básica.
Seguramente estarán pensando en cómo controlar esa animación de
alguna manera, ya sea por teclado, mouse o con algún dispositivo que
nos permita capturar la entrada del jugador.
Todo lo necesario para correr los ejemplos estan en este link.
Así que sin mas bla bla; empecemos.
Captura de eventos
Ahora es el turno de ver el tema de la captura de eventos, SDL
soporta esto de manera nativa, así que no tendremos que pasar por todo
el rollo de instalar una 3rd party library ni nada que se le parezca.
SDL tiene 2 maneras de manejar la captura, una de ellas ya la vimos un poco en el primer tutorial
cuando buscábamos el evento de cierre de la ventana; de esta manera
nosotros iteramos por los eventos encolados buscando el que necesitamos
y reaccionando de acuerdo a la entrada del usuario. La otra manera solo
sirve para el teclado y el mouse, esta manera nos permite capturar el
estado del todo el teclado en un determinado momento y verificar el
estado de las teclas, lo mismo para el mouse.
Cabe aclarar que estas 2 técnicas pueden usarse en conjunto, la
segunda para verificar la entrada del usuario con respecto al teclado y
el mouse, y la primera para eventos del gestor de ventanas y el resto
de los eventos tales como la redimension de la ventana o cuando el
usuario minimiza una ventana, solo para dar un ejemplo.
Primer ejemplo
Ahora vamos a ver en código la primera forma de capturar
eventos. Esto es ciclar por la cola de eventos hasta dar con el que
necesitamos.
El archivo se llama eventos.cpp; verán que el programa
responde a los eventos del teclado y del mouse, imprimiendo cuando un
tecla ha sido presionada y liberada y las coordenadas del mouse donde
fue presionado algún botón.
Como siempre explicaré paso a paso las líneas nuevas.
SDL_Event ev;
while(SDL_PollEvent(&ev)) {
Primero necesitamos un SDL_Event y segundo iterar por la cola de eventos.
El SDL_PollEvent completa el SDL_Event con la información
correspondiente al evento y devuelve verdadero mientras haya eventos
encolados; por eso lo usamos dentro de un while, ya que puede haber mas
de uno en ese determinado momento.
switch(ev.type) {
case SDL_KEYDOWN:
puts ("Tecla presionada");
break;
case SDL_KEYUP:
puts ("Tecla liberada");
if (ev.key.keysym.sym == SDLK_q)
fin = true;
break;
Lo primero que hacemos dentro del bucle es determinar que
tipo de evento es el que tenemos y después actuar acorde. Aquí les dejo
la lista de posibles tipos: http://www.libsdl.org/cgi/docwiki.cgi/SDL_5fEvent,
nosotros en este ejemplo solo usamos algunos, así que para una completa
referencia de todos los eventos que pueden manejar asegúrense de mirar
esa lista.
Los 2 tipos que estamos esperando manejar aquí son cuando se
presiona (SDL_KEYDOWN) una tecla del teclado y cuando se libera
(SDL_KEYUP).
El SDL_Event es uno de los tipos de datos mas raros que el lenguaje c tiene: el union;
este tipo de dato hace que la variable cambie su estructura dependiendo
del tipo, es por eso que de acuerdo al tipo que es vamos a tener otros
campos para verificar.
En este caso vía el ev.key.keysym.sym nosotros podemos verificar que tipo de tecla es liberada (o presionada), en este caso esperamos la tecla q.
Aquí les dejo una lista de todas las posibles teclas que puede SDL utilizar: http://www.libsdl.org/cgi/docwiki.cgi/SDLKey.
case SDL_MOUSEBUTTONDOWN:
printf ("Presionado en (%d,%d)\n", ev.button.x, ev.button.y);
break;
case SDL_MOUSEBUTTONUP:
printf ("Liberado en (%d,%d)\n", ev.button.x, ev.button.y);
break;
}
}
}
En este caso esperamos un tipo de evento disparado cuando se presiona o se libera un botón del mouse.
Con ev.button.x o ev.button.y podemos inspeccionar en qué parte de la pantalla el botón se presionó o se liberó.
Segundo ejemplo
El archivo fuente se llama eventos2.cpp.
En este ejemplo en vez de ciclar por la cola de eventos, vamos a
obtener el estado del teclado y del mouse en un momento determinado.
Vamos a explicar las lineas de código.
Uint8 *teclado;
Uint8 boton;
int x,y;
En
vez de definir un SDL_Event ahora definimos un puntero que contendrá
todo el teclado, un botón y 2 variables mas para los coordenadas x e y.
SDL usa el Uint8 como un tipo de dato unsigned y de 8 bits.
Esta
función siempre hay que llamarla antes de obtener el estado del teclado
o del mouse, ya que lo que hace es actualizar todos los eventos.
Esta función no la llamamos usando el otro modo, ya que el SDL_PollEvent se encarga de llamarla por nosotros.
teclado = SDL_GetKeyState(NULL);
boton = SDL_GetMouseState (&x, &y);
La
primer linea nos devuelve un puntero que representa el estado del
teclado y con la segunda obtenemos los botones presionados del mouse y
las coordenadas del cursor.
if (teclado[SDLK_q])
fin = true;
La
manera de acceder al teclado es por índice, usamos las mismas
constantes que usamos en el ejemplo anterior. Cada posición de este
arreglo contiene un 1 si la tecla esta siendo presionada y un 0 si no.
if (boton & SDL_BUTTON(1))
printf ("boton 1 presionado en (%d, %d)\n", x, y);
else if (boton & SDL_BUTTON(2))
printf ("boton 2 presionado en (%d, %d)\n", x, y);
else if (boton & SDL_BUTTON(3))
printf ("boton 3 presionado en (%d, %d)\n", x, y);
Aquí lo que estamos haciendo es checkear que botón fue el presionado, para eso utilizamos la macro SDL_BUTTON, a la cual le pasamos como parámetro el botón que queremos analizar.
Todo Junto
Ok, hasta acá tenemos 2 maneras de obtener la respuesta del
usuario, pero ahora vamos a poner todo junto en un solo fuente: ejemplo.cpp.
En este ejemplo yo uso la primera forma que les explique, no porque
sea peor ni mejor, sino que es una elección sobre la forma de hacerlo.
Si se fijan bien en este ejemplo, separé las cosas un poco para que en el main se pueda ver bien la captura de eventos; y las demás cosas las separé en funciones.
Primero iniciamos SDL, limpio la estructura principal: circulo_t, y cargamos la imagen que vamos a utilizar.
Yo creé una estructura llamada accion_t, la cual va a reflejar lo que el jugador presiona en el teclado; la cual la actualizamos en el bucle principal.
El hecho de que haya una función de actualizar y otra para dibujar
es porque es así como me parece a mi que se debería separar para mayor
claridad las cosas.
Fíjense que la función actualizar lo único que hace es setear las variables del círculo de acuerdo a lo que refleja la variable accion.
Al final, la función dibujar solo toma las variables que tiene circulo y dibuja reflejándolas.
Para Finalizar
Bueno, este tutorial es bastante mas corto que que los
anteriores, ya que por suerte el tema de los eventos es manejado de
manera muy sencilla por SDL.
Recuerden que estos tutoriales solo exploran la superficie de las cosas que se pueden hacer con SDL, siempre lean la documentación oficial, ya que de esta manera, van a poder aprender todo lo que pueden hacer y no solo algunas cosas útiles que yo les muestro aquí.
Si se olvidaron de bajar los ejemplos, aquí le vuelvo a dejar el link.
Y ya saben como siempre, cualquier duda que tengan pueden enviarme un e-mail a nesdavid[arroba]gmail.com
Saludos y hasta la próxima.