13 septiembre 2010

Juegos con C# usando SDL

SDL es una conocida biblioteca para la realización de juegos, que está disponible para diversos sistemas operativos y que permite tanto dibujar imágenes como comprobar el teclado, el ratón o el joystick, así como reproducir sonidos.

Tao.SDL es una adaptación de esta librería, que permite emplearla desde C#. Se puede descargar desde http://www.mono-project.com/Tao

SDL no es una librería especialmente sencilla, y tampoco lo acaba de ser Tao.SDL, así que los fuentes siguientes pueden resultar difíciles de entender, a pesar de realizar tareas muy básicas. Por eso, muchas veces es preferible "ocultar" los detalles de SDL creando nuestras propias clases "Hardware", "Imagen", etc. Lo haremos más adelante, pero de momento v

amos a ver un primer ejemplo, básico pero completo, que muestre cómo entrar a modo gráfico, cargar una imagen, dibujarla en pantalla, esperar cinco segundos y volver al sistema operativo. Tras el fuente comentaré las principales funciones.




/* Ejemplo de acceso a SDL
desde C# (1),
usando Tao.SDL

Por Nacho Cabanes
*/


using Tao.Sdl;
using System; // Para IntPtr (puntero: imágenes, etc)

public class Juego

{

private static void Main()
{


short ancho = 800;
short alto = 600;

int bitsColor = 24;
int flags = (Sdl.SDL_HWSURFACE|Sdl.SDL_DOUBLEBUF|Sdl.SDL_ANYFORMAT);

IntPtr pantallaOculta;

// Inicializamos SDL
Sdl.SDL_Init(Sdl.SDL_INIT_EVERYTHING);

pantallaOculta = Sdl.SDL_SetVideoMode(
ancho,
alto,
bitsColor,
flags);


// Indicamos que se recorte lo que salga de la pantalla oculta
Sdl.SDL_Rect rect2 =
new Sdl.SDL_Rect(0,0, (short) ancho, (short) alto);

Sdl.SDL_SetClipRect(pantallaOculta, ref rect2);

// Cargamos una imagen
IntPtr imagen;

imagen = Sdl.SDL_LoadBMP("personaje.bmp");
if (imagen == IntPtr.Zero) {

System.Console.WriteLine("Imagen inexistente!");
Environment.Exit(4);

}

// Dibujamos la imagen
short x = 400;
short y = 300;

Sdl.SDL_Rect origen = new Sdl.SDL_Rect(0,0,ancho,alto);

Sdl.SDL_Rect dest = new Sdl.SDL_Rect(x,y,ancho,alto);

Sdl.SDL_BlitSurface(imagen, ref origen, pantallaOculta, ref dest);


// Mostramos la pantalla oculta
Sdl.SDL_Flip(pantallaOculta);

// Y esperamos 5 segundos
System.Threading.Thread.Sleep( 5000 );


// Finalmente, cerramos SDL
Sdl.SDL_Quit();

}

}



Algunas ideas básicas:

· SDL_Init es la rutina de inicialización, que entra a modo gráfico, con cierto ancho y alto de pantalla, cierta cantidad de colores y ciertas opciones adicionales.

· El tipo SDL_Rect define un "rectángulo" a partir de su origen (x e y), su ancho y su alto, y se usa en muchas operaciones.

· SDL_SetClipRect indica la zona de recorte (clipping) del tamaño de la pantalla, para que no tengamos que preocuparnos por si dibujamos una imagen parcialmente (o completamente) fuera de la pantalla visible.

· SDL_LoadBMP carga una imagen en formato BMP (si sólo usamos SDL "puro", no podremos emplear otros tipos que permitan menores tamaños, como el JPG, o transparencia, como el PNG). El tipo de dato que se obtiene es un "IntPtr" (del que no daemos más detalles), y la forma de comprobar si realmente se ha podido cargar la imagen es mirando si el valor obtenido es IntPtr.Zero (y en ese caso, no se habría podido cargar) u otro distinto (y entonces la imagen se habría leido sin problemas).

· SDL_BlitSurface vuelca un rectángulo (SDL_Rect) sobre otro, y lo usamos para ir dibujando todas las imágenes en una pantalla oculta, y finalmente volcar toda esa pantalla oculta a la pantalla visible, con lo que se evitan parpadeos (es una técnica que se conoce como "doble buffer").

· SDL_Flip vuelca esa pantalla oculta a la pantalla visible (el paso final de ese "doble buffer").

· Para la pausa no hemos usado ninguna función de SDL, sino Thread.Sleep, que ya habíamos comentado en el apartado sobre temporización.

· SDL_Quit libera los recursos (algo que generalmente haríamos desde un destructor).

Para compilar este ejemplo usando Mono, deberemos:

· Teclear (o copiar y pegar) el fuente.

· Copiar en la misma carpeta los ficheros DLL (Tao.Sdl.Dll y SDL.Dll) y las imágenes (en este caso, "personaje.bmp").

· Compilar con:

mcs sdl01.cs /r:Tao.Sdl.dll

Y si empleamos Visual Studio o SharpDevelop, tendremos que:

· Crear un proyecto de "aplicación de consola".

· Reemplazar nuestro programa principal por éste.

· Copiar el fichero Tao.Sdl.Dll a la carpeta de fuentes, y añadirlo a las referencias del proyecto (normalmente, pulsando el botón derecho del ratón en la vista de clases del proyecto y escogiendo la opción "Agregar referencia").

· Copiar en la carpeta de ejecutables (típicamente bin/debug) los ficheros DLL (Tao.Sdl.Dll y SDL.Dll) y las imágenes (en este caso, "personaje.bmp").

· Compilar y probar.

Si no vamos a usar imágenes comprimidas (PNG o JPG), ni tipos de letra TTF, ni sonidos en formato MP3, ni funciones adicionales de dibujo (líneas, recuadros, círculos, etc)., no necesitaremos ninguna DLL adicional.

Puedes descargar el fuente y el ejecutable, con las DLL y un personaje de ejemplo, aquí:

http://www.nachocabanes.com/fich/descargar.php?nombre=csharp_sdl_01.zip