Tutorial SDL - Primera parte
(La segunda parte de este tutorial esta aquí)
Indice
Bienvenida
Hola, esta será el primer articulo de una serie de tutoriales sobre SDL y la programación de Videojuegos.
Los primeros tutoriales estarán orientados a los mas nuevitos en el
tema, y la intención es de alguna forma atenuar los primeros dolorosos
pasos en la programación de juegos.
Estoy asumiendo que el lector sabe programar en C usando el
paradigma estructurado, si no les recomiendo que lean algún buen libro
de C. No voy a explicar nociones ni algoritmos básicos de programación,
pero si voy a dar estructuras de datos y algunos algoritmos específicos
para juegos.
Así que, ¡Bienvenidos a bordo, futuros programadores de juegos!
Primeros pensemos a la inversa, ¿Qué necesito para que un
video juego funcione?. Veámoslo desde el punto de vista de un jugador:
Yo pongo el CD de mi juego favorito en mi PC y la magia comienza,
primero un video introductorio me posiciona en el mundo fantástico
donde toda la acción va a ocurrir; la música me envuelve y el conjunto
imagen y sonido cumplen con su cometido de hacerme olvidar que estoy
frente a una PC. Comienzo a jugar y el teclado y el mouse hacen su
trabajo de forma impecable, el personaje que estoy manejando hace
exactamente lo que yo le estoy ordenando...
Examinemos un poco esto que acabo de decir y lo que implica;
necesitamos una librería capaz de mostrar gráficos, reproducir sonidos
y capturar la entrada del teclado y mouse de forma eficiente.
SDL (Simple DirectMedia
Layer ) es una librería escrita en C que proporciona acceso sencillo y
de bajo nivel a los recursos del sistema tales como la placa de video,
placa de sonido, mouse, teclado, joysticks; mas generalmente todo lo
que necesitamos para hacer un videojuego.
Te vuelvo a preguntar: ¿Por qué SDL?
Primero, SDL
es realmente sencillo de usar para un newbie (y lo suficientemente
poderoso para un programador avanzado), los nombres de las funciones
son muy intuitivas y con unas pocas líneas de código uno puede ver
resultados sorprendentes en pantalla.
Segundo, SDL es portable; o sea que el mismo código que funciona para Windows, funciona para GNU/Linux y para Mac.
Y Tercero, se puede usar OpenGL
para renderizar nuestro juego. Esto nos va a permitir poder mostrar
gráficos en 3 dimensiones y tener acceso directo al hardware de la
placa de video.
Me imagino que debes estar muy entusiasmado y pensando “¿Cómo hago mi juego de ROL?”;
ya vamos a llegar a eso, pero primero hay que descargar las
librerías y preparar el entorno, así que sin mas, sigamos
leyendo.
SDL se descarga desde su pagina web www.libsdl.org donde tenemos una introducción de lo que es y un panel de navegación a la izquierda.
En la parte de “Download” apretamos donde dice “SDL 1.2”, bajamos un poco la página hasta la sección “Development Libraries”.
Antes de seguir, te voy a explicar como instalar y setear el
entorno de trabajo, tanto como windows como para Linux, si sos un
usuario de windows, seguí leyendo a continuación. Si preferís usar
Linux, saltéate la sección de windows.
windows
Desde esta página tenemos varias opciones para descargar, lo
que descargaremos serán los binarios de desarrollo, estos vendrán con
todas las cabeceras para desarrollar (archivos .h) y las librerías
(archivos .lib y .dll).
Aquí esta el link de los releases: http://www.libsdl.org/download-1.2.php
¿Qué es un .lib y para que sirve?
Como sabrán, el mundo windows esta lleno de DLLs, estos
archivos son pequeños rejuntes de funciones reutilizables; por ejemplo
existe en Windows una DLL que indica a cada ventana como debe dibujarse
la barra de titulo (además de otras cosas), como esto siempre es igual
para casi todos los programas de Windows sería un desperdicio de
espacio tener ese código en cada aplicación, así que la pusieron en un
solo archivo.
Cuando uno tiene que hacer un programa que utiliza alguna función
contenida dentro de una DLL, uno debe indicarle al compilador en que
parte del archivo se encuentra, algo así como un índice; ese índice es
el archivo LIB.
Una vez descargado los archivos, extraerlos. Yo los voy a extraer en el disco C.
Si exploramos la carpeta creada deberá haber quedado así:
C:\SDL-1.2.13
C:\SDL-1.2.13\lib
C:\SDL-1.2.13\include
Después volveremos con el contenido de cada carpeta.
Si no queres instalarlo (ni saber como) en Linux... salta a la página “preparando el entorno”.
Linux
Dependiendo de la distribución de Linux que tengas; podes
instalar el paquete que corresponda a la librerías de desarrollo de
SDL, explicar esto para cada distribución sería un trabajo tedioso;
entonces en vez de eso voy a explicar como descargar los archivos
fuentes y compilarlo, ya que esto funciona para todas las
distribuciones de Linux y otros sistemas operativos unix.
El código fuente se descarga en la sección “Downloads”, al principio de la página donde dice “Source Code”; o aquí les dejo el link directo del fuente para descargar: http://www.libsdl.org/release/SDL-1.2.13.tar.gz
Vamos a descargarlo en nuestro $HOME en mi caso en /home/david/
Ahora sigamos los siguientes pasos.
Primero entremos como administrador del sistema:
nota: cuando veas el signo $ o el # tenes que escribir esa linea en la consola. El $ es como tu usario, y el # es como root.
Yo generalmente cuando compilo e instalo un software lo instalo en
/usr/local/, el cual voy a usar ahora. Entonces hacemos un cd a ese
directorio y desenpaquetemos la librería.
# cd /usr/local/
# tar -zxvf /home/david/SDL-1.2.13.tar.gz
Esta última acción nos va a dejar todo listo para comenzar la compilación.
Preparando el entorno
Windows
Utilizaremos el Microsoft Visual C++ 6.0 como IDE de cabecera; entonces comencemos.
Una vez que tengamos abierto el IDE haremos clic en File -> New y seleccionaremos Win32 Application, dejamos todo lo demás como está y le ponemos el directorio y el nombre que queramos.
Y pulsamos “OK”.
y le damos “Finish”.
Un pequeño informe nos dirá que fue lo que hizo el entorno por nosotros y aceptamos tranquilamente.
Ahora tenemos un proyecto limpio por donde empezar; primero Projects -> Settings
Y en el Tab "C/C++" en la categoría “Code Generation” ponemos como esta la imagen.
Y en categoría “Preprocessor”, agregar un directorio
adicional para el compilador, que fue donde instalamos SDL apuntando al
directorio donde están las cabeceras.
En el Tab “Link”, la categoría “Input” agregar 2 “library modules”
sdlmain.lib y el sdl.lib que están en el directorio donde instalamos SDL bajo la carpeta “lib”.
Y le damos “OK”
Por último, necesitamos un archivo en el cual escribir, hacemos clic en File -> New.
Elegimos “C++ Source File” y le ponemos el nombre de nuestro agrado.
“OK”
Linux
Aquí realmente no hay mucho que preparar, primero comprobamos
que tengamos instalado un compilador de C, para eso escribimos lo
siguiente desde la línea de comandos:
Si aparece información sobre el compilador, estamos bien.
Luego entramos al directorio donde están los fuentes de la librería SDL.
Que es el directorio que creo el comando tar y a continuación
ejecutamos los tres comandos que comúnmente sirven para compilar e
instalar un soft en GNU/Linux.
#./configure
#make
#make install
Esto no debería tener ningún problema, si lo tienen, entonces les recomiendo que busquen ayuda en el foro de SDL,
el cual siempre hay personas contribuyendo para solucionar los
problemas de los usuarios, así como tips de programación y demás: http://www.libsdl.org/mailing-list.php
para testear que todo haya ido bien vamos a ejecutar el siguiente
comando como un usuario común; así que primero nos deslogeamos de
'root'
# exit
$ sdl-config --version
Este comando nos mostrará la versión de SDL instalada en nuestro sistema: la cual es "1.2.13". Este comando nos servirá mas adelante para poder compilar los programas que hagamos en Linux.
Creamos el directorio que mas les guste en nuestro $HOME donde
vamos a poner el código fuente para ir probando lo que vayamos haciendo
y creamos un archivo con extensión .c ó .cpp y lo editan con su editor
preferido (yo personalmente uso el vim).
$ cd
$ mkdir tutorial_sdl
$ vi hola_mundo.cpp
Hola Mundo!
Esto es igual, sin importar el Sistema Operativo que usen, aquí se ve bien la potencialidad de SDL en cuanto a lo multiplataforma.
Ahora vamos a escribir el primer ejemplo para ver si todo estuvo
bien seteado y para que tengan un primer vistazo de lo fácil que es
crear una ventana con SDL.
Lo que vamos a hacer es una pequeña ventana a la cual le vamos a poner un titulo explicativo.
Así que sin importar que estén usando copien el contenido del siguiente archivo en su editor favorito.
hola_mundo.cpp
windows
Presionemos el icono del signo de admiración (CTRL.+F5) para
ejecutar el programa, antes de ejecutarlo el IDE se dará cuenta
de que no lo compilo, entonces primero lo compilará y
después lo ejecutara.
Linux
$ g++ hola_mundo.cpp -o holamundo `sdl-config --cflags --libs`
$ ./holamundo
Primero explicaré como compilar el fuente en un entorno Linux, y
después paso a paso detallaré que es lo que hace independientemente del
entorno.
El comando g++ es el que se usa para compilar fuentes C++ en un entorno GNU/Linux.
Este comando acepta muchisimos parametros, a continuación les explicaré los que estamos usando:
El g++ espera el nombre del archivo fuente a compilar; hola_mundo.cpp en este caso.
-o le indica el archivo a generar (la letra 'o' es de output --salida en inglés--); holamundo en el ejemplo.
-I en donde debe buscar por cabeceras adicionales.
-L en donde debe buscar por librerias adicionales.
y por último -l seguido de un nombre le dice que librerias adicionales queremos incluir para armar el ejecutable.
Los parametros que nos faltan se lo pasamos invocando un segundo comando:
¿Que es el sdl-config?
El comando sdl-config, le indica al compilador C de
donde puede obtener las cabeceras para compilar (--cflags) y tambien le
dice que opciones debe usar para la link-edición y que librerías debe linkear (--libs).
Si son curiosos pueden ejecutar el comando por el shell y ver la salida que muestra.
$ sdl-config --cflags
-I/usr/local/include/SDL -D_REENTRANT
$ sdl-config --libs
-L/usr/local/lib -Wl,-rpath,/usr/local/lib -lSDL -lpthread
Ahora vamos a explicar paso a paso que es lo que hace cada llamada
SDL_Init (SDL_INIT_VIDEO)
Le indica a SDL
que inicie la librería con soporte para video: SDL_INIT_VIDEO; también
se le pueden indicar módulos adicionales y algunas opciones de inicio.
SDL_SetVideoMode(400, 400, 16, 0)
Esta función crea una ventana con el ancho (400) y alto (400), la profundidad de color (16) y flags adicionales (0) para indicar que no utilice ningún flag y ejecutando el programa en una ventana.
“ancho y alto”
son auto explicativos, los valores están en pixels.
“profundidad de color”
Como ustedes saben, la unidad mínima de información que puede
mostrar el monitor es un Píxel. La profundidad de color es la cantidad
de bits que tiene asociado ese píxel. Por ejemplo si yo utilizo 8 bits
de profundidad, solamente puedo mostrar 256 colores en un solo píxel.
En los juegos modernos se utilizan entre 16 a 32 bytes de profundidad.
Si la placa de video no soporta la cantidad de profundidad
especificada, SDL va a reintentar con una profundidad soportada y
convertirá todas los gráficos a esta profundidad. Esto característica
puede ser desactivada, si se desea pasándole SDL_ANYFORMAT como
parámetro en la parte de flags
SDL_GetError()
Cuando una función de SDL
devuelve un código inválido, la forma de conocer que ocurrió es
llamando a esta función que nos devuelve un char* con un mensaje
descriptivo de lo ocurrido.
Supongamos que hayamos llamado:
SDL_SetVideoMode(400, 400, 16, SDL_ANYFORMAT)
En este caso es posible que la placa de video no soporte 16 bits de
profundidad y devuelva error, en ese caso la función SDL_GetError() nos mostrará que fue lo que paso.
SDL_WM_SetCaption("Hola mundo!", "Hola Mundo!")
Le pone titulo a la ventana y el nombre del icono de la aplicación.
Esto obviamente es necesario si nuestro juego se va a ejecutar en
modo ventana, si vamos a usar modo “full screen”, esta función no es
necesaria.
SDL_Delay(5000)
Es usado para detener la aplicación por la cantidad de milisegundos deseados.
En este caso detenemos la pantalla por 5 segundos.
SDL_Quit()
Cuando terminamos de usar la librería, hay que hacer limpieza y devolver los recursos obtenidos por la aplicación.
Una mejor y mas detallado explicación de estas funciones y todas lo
que pueden hacer con SDL la pueden encontrar en la documentación. Esta
se puede descargar de la página oficial en la parte de Documentación
Eventos
Ya los estoy escuchando diciendo: “la ventana no se mueve, se queda
quieta y no responde a los botones, no se minimiza y no se cierra”
Si, ya se. Un paso por vez.
Les explico, las ventanas en cualquier escritorio se manejan por
eventos, el usuario le envía a la ventana eventos; existen cientos de
eventos que puede una ventana manejar, pero no todos nos sirven para
juegos.
Los eventos que recibe la ventana del usuario que vamos a utilizar
en la mayoría de los casos son: los eventos del movimiento del mouse,
las teclas presionadas del teclado; cuando el usuario presiona para
cerrar la ventana, para minimizarla o cuando la quiere redimensionar.
Para manejar los eventos en nuestra aplicación, vamos a tener un
loop infinito que va a chequear si tiene eventos que procesar, esos
eventos son informados por el manejador de ventanas a nuestra
aplicación y nosotros los capturamos y decidiremos que hacer con ellos,
los podemos ignorar o procesar.
Sin mas charla vamos a un ejemplo.
Hola Mundo 2!
hola_mundo2.cpp
Bueno!, ahora puedo mover la ventana por la pantalla, minimizarla y cerrarla con el botón de cerrar.
Pero ¿Qué son esas líneas de mas?
Ahora paso a explicar que es esto:
//La estructura de eventos de SDL.
SDL_Event ev;
while( true ) {
while( SDL_PollEvent( &ev ) ) {
if( ev.type == SDL_QUIT ){
printf( ">El usuario quiere salir.\n" );
printf( ">SDL Terminado.\n" );
return 0;
}
}
}
SDL_Event es la estructura de SDL
en la cual guarda la información de los eventos del administrador de
ventanas; SDL usa una estructura propia para poder ser multiplataforma,
ya que las diferencias entre windows, Linux y Mac son manejadas
transparentemente para nosotros.
SDL_PollEvent(&ev)
Se encarga de procesar todos los eventos relacionados con la
aplicación y completa por cada uno la estructura SDL_Event. Cuando no
hay mas eventos que manejar devuelve FALSE.
SDL_QUIT.
Después que SDL_PollEvent transforma el evento en un SDL_Event;
nosotros podemos saber que tipo de evento se disparo con solo
inspeccionar la variable “type”.
Uno de los tipos de eventos es el SDL_QUIT, el cual, como el nombre lo dice, nos avisa que el usuario quiere salir.
Tengamos en cuenta que nosotros como programadores estamos
encargados de asignar a cada evento una respuesta acorde, si nosotros
no manejamos adecuadamente el evento de salir, la aplicación no va a
salir.
Despedida
Uff! Cuanto que hicimos con tan poco código, pero los conceptos para asimilar son muchos.
El desarrollo de juegos es un área que requiere aprender muchos
conceptos nuevos y algunas nociones de cómo funciona la PC de bajo
nivel, para poder entender ciertas cosas que estamos haciendo.
Programar juegos no es una tarea sencilla, pero si es altamente
gratificadora; ya que constantemente están saliendo nuevas tecnologías
para desarrollar y tenemos la ayuda de librerías como SDL que nos hacen el trabajo un poco mas cómodo.
Por hoy dejamos acá, ya sabemos como crear una ventana, primer
paso para cualquier aplicación, y como manejar algunos eventos.
Como tarea les dejo que lean la documentación y busquen que otros tipos de eventos soporta SDL, ya que les va a ser útil cuando retomemos el tema de los eventos.
Para la próxima, dejaremos de lado por un momento los eventos y
comenzaremos a ver la forma de mostrar gráficos en pantalla y como
crear el efecto de animación.
Cualquier comentario, duda o sugerencia que tengan; no duden en enviarme un e-mail a nesdavid[arroba]gmail com .
Saludos.
David Roguin.