Por Nacho Cabanes
En este apartado puedes encontrar:
Para no necesitar conocer demasiado los detalles internos de SDL y de su adaptación como parte del "Tao Framework", el esqueleto incluye varias clases auxiliares, como:
Para evitar parpadeos, las imágenes y los textos se dibujan en una pantalla oculta (un "doble buffer"), que se muestra cuando todos los elementos están preparados, por lo que tanto nuestros textos como nuestros tipos de letra se dibujarán en dicha pantalla oculta y se mostrarán posteriormente.
La pantalla de presentación simplemente muestra una imagen como ésta, escribe un poco de texto aclaratorio y espera a que se pulse la tecla Espacio para jugar, C para ver los créditos o S para salir:
Y su fuente debería ser sencillo de seguir: apenas hay un método "Ejecutar", que se encarga de dibujar la imagen de ejemplo, escribir el texto, esperar a que se pulse una tecla (25 veces por segundo, para no saturar el sistema) y memorizar la tecla pulsada:
public void Ejecutar() { // Dibujo la imagen de la presentacion imagen.DibujarOculta(0,0); // Escribo avisos de las teclas utilizables Hardware.EscribirTextoOculta( "Pulsa Espacio para jugar", 300, 550, 0xAA, 0xAA, 0xAA, fuenteSans18); Hardware.EscribirTextoOculta( "S para salir, C para créditos", 290, 575, 0xAA, 0xAA, 0xAA, fuenteSans18); // Finalmente, muestro en pantalla Hardware.VisualizarOculta(); //hasta que se pulse espacio (sin saturar la CPU) do { Hardware.Pausa(40); } while ((! Hardware.TeclaPulsada(Hardware.TECLA_ESP) ) && (! Hardware.TeclaPulsada(Hardware.TECLA_S)) && (! Hardware.TeclaPulsada(Hardware.TECLA_C))); opcionEscogida = OPC_PARTIDA; if (Hardware.TeclaPulsada(Hardware.TECLA_S)) opcionEscogida = OPC_SALIR; if (Hardware.TeclaPulsada(Hardware.TECLA_C)) opcionEscogida = OPC_CREDITOS; }
(Si quieres ver más detalles, puedes ver el fuente completo en Google Code).
La pantalla de créditos solo escribe algo de texto:
Y su fuente es muy similar: poco más que un método "Ejecutar", que se encarga de escribir los textos de ejemplo y esperar a que se pulse la tecla ESC. Para que no sea totalmente igual a la presentación, en este caso se escribe el texto dentro de la parte repetitiva (algo que sserá totalmente necesario cuando queramos que el texto incluya alguna animación, pero que por ahora podríamos haber evitado, como hemos hecho con la presentación):
public void Ejecutar() { bool salir = false; while (! salir ) { Hardware.BorrarPantallaOculta(0,0,0); // Borro en negro Hardware.EscribirTextoOculta( "XXX (Remake) - Creditos", 110, 100, 0x77, 0x77, color, fuenteSans18); [...] Hardware.EscribirTextoOculta( "Pulsa ESC para volver a la presentación...", 110,550,0xAA, 0xAA, 0xAA, fuenteSans12); Hardware.VisualizarOculta(); Hardware.Pausa(40); salir = Hardware.TeclaPulsada (Hardware.TECLA_ESC); } }
La clase "Juego" (un poco más adelante tienes toda la estructura de clases) se limita a coordinar a las demás: lanza la presentación y, según lo que se escoja en ella, muestra la pantalla de créditos o comienza una nueva partida (una sesión real de juego):
public class Juego { private Presentacion presentacion; private Partida partida; private Creditos creditos; // Inicialización al comenzar la sesión de juego public Juego() { // Inicializo modo grafico 800x600 puntos, 24 bits de color bool pantallaCompleta = false; Hardware.Inicializar(800, 600, 24, pantallaCompleta); // Inicializo componentes del juego presentacion = new Presentacion(); partida = new Partida(); creditos = new Creditos(); } // --- Comienzo de un nueva partida: reiniciar variables --- public void Ejecutar() { do { presentacion.Ejecutar(); switch( presentacion.GetOpcionEscogida() ) { case Presentacion.OPC_CREDITOS: creditos.Ejecutar(); break; case Presentacion.OPC_PARTIDA: partida.BuclePrincipal(); break; } } while (presentacion.GetOpcionEscogida() != Presentacion.OPC_SALIR ); } // --- Cuerpo del programa ----- public static void Main() { Juego juego = new Juego(); juego.Ejecutar(); } } /* fin de la clase Juego */
Finalmente, la clase "Partida" es la que contiene la lógica "real" de una sesión de juego. La parte más importante es el "bucle principal", que repite la secuencia de pasos habituales en este tipo de juegos:
public class Partida { // Componentes del juego private Personaje miPersonaje; // Otros datos del juego int puntos; // Puntuacion obtenida por el usuario bool partidaTerminada; // Si ha terminado una partida // Inicialización al comenzar la sesión de juego public Partida() { miPersonaje = new Personaje(this); puntos = 0; partidaTerminada = false; } // --- Comprobación de teclas, ratón y joystick ----- void comprobarTeclas() { // Muevo si se pulsa alguna flecha del teclado if (Hardware.TeclaPulsada(Hardware.TECLA_DER) ) miPersonaje.MoverDerecha(); if (Hardware.TeclaPulsada(Hardware.TECLA_IZQ)) miPersonaje.MoverIzquierda(); if (Hardware.TeclaPulsada(Hardware.TECLA_ARR)) miPersonaje.MoverArriba(); if (Hardware.TeclaPulsada(Hardware.TECLA_ABA)) miPersonaje.MoverAbajo(); if (Hardware.TeclaPulsada(Hardware.TECLA_ESP)) miPersonaje.Disparar(); // Compruebo el Joystick if (Hardware.JoystickPulsado(0)) miPersonaje.Disparar(); int posXJoystick, posYJoystick; if (Hardware.JoystickMovido(out posXJoystick, out posYJoystick)) { if (posXJoystick > 0) miPersonaje.MoverDerecha(); else if (posXJoystick < 0) miPersonaje.MoverIzquierda(); else if (posYJoystick > 0) miPersonaje.MoverAbajo(); else if (posYJoystick < 0) miPersonaje.MoverArriba(); } // Compruebo el raton int posXRaton = 0, posYRaton = 0; if (Hardware.RatonPulsado(out posXRaton, out posYRaton)) { miPersonaje.MoverA(posXRaton, posYRaton); } // Si se pulsa ESC, por ahora termina la partida... y el juego if (Hardware.TeclaPulsada(Hardware.TECLA_ESC)) partidaTerminada = true; } // --- Animación de los enemigos y demás objetos "que se muevan solos" ----- void moverElementos() { // Nada por ahora } // --- Comprobar colisiones de enemigo con personaje, etc --- void comprobarColisiones() { // Nada por ahora } // --- Dibujar en pantalla todos los elementos visibles del juego --- void dibujarElementos() { // Borro pantalla Hardware.BorrarPantallaOculta(0,0,0); // Dibujo el personaje miPersonaje.DibujarOculta(); // Finalmente, muestro en pantalla Hardware.VisualizarOculta(); } // --- Pausa tras cada fotograma de juego, para velocidad de 25 fps ----- void pausaFotograma() { Hardware.Pausa( 40 ); } // --- Bucle principal de juego ----- public void BuclePrincipal() { partidaTerminada = false; do { comprobarTeclas(); moverElementos(); comprobarColisiones(); dibujarElementos(); pausaFotograma(); } while (! partidaTerminada); } } /* fin de la clase Partida */
Como clases "del juego" tenemos las ya comentadas: Juego, Presentacion, Creditos, Partida. Como clases auxiliares que ocultan el acceso al sistema: Hardware, Imagen, Fuente, Sonido y ElemGrafico (haz clic en la imagen para verla más grande):
El proyecto compila en Windows, pero me temo que no en Linux (o al menos yo no lo he conseguido, la DLL de Tao.SDL no parece funcionar correctamente en este sistema operativo). Se puede utilizar como entorno de desarrollo Visual Studio: incluyo un proyecto para la versión Visual Studio 2008 Express.
En equipos más antiguos o menos potentes, en los que Visual Studio no se mueva con soltura, se puede usar SharpDevelop: incluyo también un proyecto para SharpDevelop 2.2 (o Visual Studio 2005), que sólo necesita la plataforma .Net versión 2, por lo que se podría usar cualquier ordenador que tenga Windows XP SP2.
También se podría usar como compilador Mono (www.mono-project.com), pero al tratarse de varios fuentes habría que crearse un fichero BAT para compilarlos todos juntos. No incluyo dicho fichero BAT (al menos por ahora), así que quien quiera usar Mono tendrá que buscarse la vida un poco más... o preguntar.
Como siempre, si quieres saber más, sólo tienes que seguir leyendo...
Si te surgen dudas y eres alumno mío, ya sabes dónde preguntar ;-) pero si no eres alumno mío, tampoco lo tienes especialmente difícil: puedes localizarme en un foro de AprendeAProgramar.com que está dedicado a este proyecto.
Y si quieres descargar el proyecto para verlo con más detenimiento o para usarlo como base para cualquier proyecto tuyo, puedes hacerlo desde la página del proyecto en Google Code (ésta es la versión 0.01, claro).
Siguiente entrega...