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.

SDL_PumpEvents();
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.