Por Nacho Cabanes
El personaje debe mostrar distintas imágenes según la direccion en que se mueva (por ejemplo, "personajei1.png" cuando se mueva hacia la izquierda, "personajed1.png" cuando vaya hacia la derecha, y "personajea1.png" cuando suba o baje; esas imágenes las tienes en el fichero ZIP de la entrega 11).
Y ya que empezamos a controlar direcciones, imitaremos la forma de matar "enemigos" que tiene el juego original: si no estamos moviendo hacia un lado u otro, cuando el enemigo choque con nosotros morirá (aunque venga por nuestra espalda, o estemos en una escalera); si nos estamos moviendo hacia arriba o hacia abajo, seremos nosotros los que moriremos si el enemigo choca con nosotros.
Cada vez que matemos un enemigo, tendremos 10 puntos más (que se deberán mostrar en la parte derecha de la pantalla de juego) y volverá a aparecer el enemigo en otra posición de la pantalla. De momento no habrá ninguna animación cuando muera el enemigo o nuestro personaje.
Por una parte, tendremos nuevas imágenes que declarar y cargar:
static ElemGrafico imagenPersonajeD, imagenPersonajeI, imagenPersonajeA; ... imagenPersonajeD = new ElemGrafico("imagenes/personajed1.png"); imagenPersonajeI = new ElemGrafico("imagenes/personajei1.png"); imagenPersonajeA = new ElemGrafico("imagenes/personajea1.png");
Necesitaremos también llevar cuenta de los puntos que ha obtenido el jugador, y nos puede interesar también crear constantes para cada una de las direcciones, que ayuden a que el fuente sea más legible:
static int puntos = 0; const int DERECHA = 0; const int IZQUIERDA = 1; const int ARRIBA = 2; const int ABAJO = 3; static int direccion = DERECHA;
Ahora, cuando se pulse una tecla cambiará la imagen del personaje que mostramos, y memorizaremos también en qué dirección se mueve, para poder imitar el comportamiento del juego original, en el que cuando nos movemos de lado y un enemigo choca con nosotros, es el enemigo quien muere:
if (Hardware.TeclaPulsada(Hardware.TECLA_DER) ) { imagenPersonaje = imagenPersonajeD; direccion = DERECHA;
Por tanto, la función encargada de comprobar colisiones hará que muera el enemigo o nosotros según en qué dirección nos estemos moviendo:
if ((x==xEnemigo) && (y==yEnemigo)) { if ((direccion == DERECHA) || (direccion == IZQUIERDA)) matarEnemigo(); else morir(); }
Donde esa función "matarEnemigo" se encargaría de aumentar nuestra puntuación y de colocar al enemigo en otra posición de la pantalla (para que no nos mate varias veces seguidas hasta que perdamos todas las vidas):
static void matarEnemigo() { puntos += 10; colocarEnemigo(); }
Eso es casi todo. Sólo falta mostrar la puntuación en pantalla, como parte de la función "dibujarElementos":
Hardware.EscribirTextoOculta( "Puntos", 600, 100, 0xAA, 0xAA, 0xAA, fuente18); Hardware.EscribirTextoOculta( puntos.ToString(), 600, 140, 0xAA, 0xAA, 0xAA, fuente18);
El resultado sería
/** * Juego: Logica de juego * * @see Hardware * @author 1-DAI IES San Vicente 2009/10 */ /* -------------------------------------------------- Parte de Death Pit - Remake Versiones hasta la fecha: Num. Fecha Por / Cambios --------------------------------------------------- 0.01 08-Sep-2009 Nacho Cabanes Version inicial: muestra una imagen 0.02 07-Oct-2009 Nacho Cabanes Mueve el personaje hacia la derecha hasta llegar al margen 0.03 13-Oct-2009 Nacho Cabanes El personaje se mueve con flechas Un primer enemigo que se mueve a la vez 0.04 16-Oct-2009 Nacho Cabanes Primera pantalla de presentacion El primer enemigo rebota en los lados Un segundo enemigo nos persigue 0.05 20-Oct-2009 Nacho Cabanes Array de enemigos (murcielagos) que rebotan en los lados 0.06 28-Oct-2009 Nacho Cabanes Array bidimensional para imagen de fondo 0.07 04-Nov-2009 Nacho Cabanes El personaje se mueve solo por los "huecos" Eliminados los enemigos (por ahora) Renombradas variables i,j a fila,colum 0.08 10-Nov-2009 Nacho Cabanes Varias funciones para que el fuente sea mas modular 0.09 16-Nov-2009 Nacho Cabanes Varias pantallas conectadas 0.10 24-Nov-2009 Nacho Cabanes Un enemigo que se mueve "por los huecos" 0.11 02-Dic-2009 Nacho Cabanes Si chocamos con enemigo perdemos una vida 0.12 04-Dic-2009 Nacho Cabanes El personaje cambia de imagen según la dirección Si choco con un enemigo de lado, muere él y me da puntos ---------------------------------------------------- */ using System; // Para numeros aleatorios: System.Random public class Juego { // Variables que usaremos: una imagen y un tipo de letra static ElemGrafico imagenPersonaje,imagenEnemigo, presentacion; static ElemGrafico imagenPersonajeD, imagenPersonajeI, imagenPersonajeA; static ElemGrafico imagenFondoHoriz,imagenFondoHorizAcido, imagenFondoVert, imagenEscalera; static Fuente fuente18; static int fila, colum; // Para recorrer static short x=1, y=1; static short xEnemigo=1, yEnemigo=1; static short incrXEnemigo=1, incrYEnemigo=0; static short contadorFotogramasEnemigo = 0; static short pausaFotogramasEnemigo = 10; static short minX = 0, maxX = 6, minY = 0, maxY = 6; // Tamaño de cada pantalla de juego static int filasPantalla = 7; static int columnasPantalla = 7; // Situación de la pantalla actual dentro del mapa de habitaciones static int filaHabitacion = 0; static int columnaHabitacion = 0; // Vidas en cada partida static int vidas = 5; static int puntos = 0; const int DERECHA = 0; const int IZQUIERDA = 1; const int ARRIBA = 2; const int ABAJO = 3; static int direccion = DERECHA; static Random numAleatorio; // Para que el enemigo se mueva al azar static int[,,,] mapa = { // Comienzo del mapa de casillas { // Primera fila de habitaciones { // Habitacion (0,0) {1,2,1,1,1,2,1}, {3,0,0,0,0,0,0}, {3,4,3,4,3,1,1}, {3,4,0,4,0,0,0}, {3,4,3,4,3,4,3}, {3,4,0,0,0,4,3}, {3,1,1,4,1,4,3} }, { // Habitacion (0,1) {1,2,1,1,1,2,1}, {0,0,0,0,0,0,3}, {1,1,3,4,3,4,3}, {0,0,3,4,3,4,3}, {3,4,3,4,3,4,3}, {3,4,3,4,3,4,3}, {3,1,3,4,3,4,3} }, }, { // Segunda fila de habitaciones { // Habitacion (1,0) {3,2,1,4,1,4,1}, {3,0,0,0,0,0,0}, {3,1,1,4,3,1,1}, {3,0,0,4,3,0,0}, {3,4,3,4,3,4,3}, {3,4,3,4,0,4,3}, {1,1,1,1,1,1,3} }, { // Habitacion (1,1) {1,2,1,4,1,4,1}, {0,0,0,0,0,0,3}, {1,1,1,4,1,1,3}, {0,0,0,4,0,0,3}, {1,4,3,4,3,4,3}, {3,4,3,4,0,4,3}, {1,1,1,1,1,1,3} }, }, }; static bool partidaTerminada; static void inicializar() { // Inicializo modo grafico 800x600 puntos, 24 bits de color Hardware.Inicializar(800, 600, 24); // Cargo imagenes y tipos de letra imagenPersonaje = new ElemGrafico("imagenes/personaje.png"); imagenEnemigo = new ElemGrafico("imagenes/escorpion.png"); imagenPersonajeD = new ElemGrafico("imagenes/personajed1.png"); imagenPersonajeI = new ElemGrafico("imagenes/personajei1.png"); imagenPersonajeA = new ElemGrafico("imagenes/personajea1.png"); imagenFondoHoriz = new ElemGrafico("imagenes/fondo1.png"); imagenFondoHorizAcido = new ElemGrafico("imagenes/fondo2.png"); imagenFondoVert = new ElemGrafico("imagenes/fondo3.png"); imagenEscalera = new ElemGrafico("imagenes/escalera.png"); fuente18 = new Fuente("FreeSansBold.ttf", 18); presentacion = new ElemGrafico("imagenes/present.png"); // Para que el enemigo se mueva al azar numAleatorio = new Random( DateTime.Now.Millisecond ); colocarEnemigo(); } static void mostrarPresentacion() { //dibujo la presentacion presentacion.DibujarOculta(); // Finalmente, muestro en pantalla Hardware.VisualizarOculta(); //hasta que se pulse espacio do { } while (! Hardware.TeclaPulsada(Hardware.TECLA_ESP) ); //borro la presentacion Hardware.BorrarPantallaOculta(0,0,0); } static void comprobarTeclas() { // Y lo muevo si se pulsa alguna flecha del teclado if (Hardware.TeclaPulsada(Hardware.TECLA_DER) ) { imagenPersonaje = imagenPersonajeD; direccion = DERECHA; if (x == maxX) { x = 0; columnaHabitacion++; colocarEnemigo(); } else if (x < maxX) if ((mapa[filaHabitacion, columnaHabitacion, y,x+1] == 0) // Espacio en blanco || (mapa[filaHabitacion, columnaHabitacion, y,x+1] == 4) )// Escalera x++; } if(Hardware.TeclaPulsada(Hardware.TECLA_ARR) ) { imagenPersonaje = imagenPersonajeA; direccion = ARRIBA; if (y == 0) { y = maxY; filaHabitacion--; colocarEnemigo(); } else if ( y > 0) if ((mapa[filaHabitacion, columnaHabitacion, y-1,x] == 0) // Espacio en blanco || (mapa[filaHabitacion, columnaHabitacion, y-1,x] == 4) )// Escalera y--; } if (Hardware.TeclaPulsada(Hardware.TECLA_IZQ) ) { imagenPersonaje = imagenPersonajeI; direccion = IZQUIERDA; if (x == 0) { x = maxX; columnaHabitacion--; colocarEnemigo(); } else if ( x > 0) if ((mapa[filaHabitacion, columnaHabitacion, y,x-1] == 0) // Espacio en blanco || (mapa[filaHabitacion, columnaHabitacion, y,x-1] == 4) )// Escalera x--; } if (Hardware.TeclaPulsada(Hardware.TECLA_ABA) ) { imagenPersonaje = imagenPersonajeA; direccion = ABAJO; if (y == maxY) { y = 0; filaHabitacion++; colocarEnemigo(); } else if (y < maxY) if ((mapa[filaHabitacion, columnaHabitacion, y+1,x] == 0) // Espacio en blanco || (mapa[filaHabitacion, columnaHabitacion, y+1,x] == 4) )// Escalera y++; } if (Hardware.TeclaPulsada(Hardware.TECLA_ESC)) partidaTerminada = true; } static void colocarEnemigo() { // Coloca el enemigo en cualquier posición "libre" de la pantalla actual do { xEnemigo = (short) (numAleatorio.Next(0,columnasPantalla-2)+1); yEnemigo = (short) (numAleatorio.Next(0,filasPantalla-2)+1); } while ((mapa[filaHabitacion, columnaHabitacion, yEnemigo,xEnemigo] != 0) // Espacio en blanco && (mapa[filaHabitacion, columnaHabitacion, yEnemigo,xEnemigo] != 4)); // Escalera } static void moverElementos() { // El enemigo solo se mueve un fotograma de cada varios contadorFotogramasEnemigo ++; if (contadorFotogramasEnemigo == pausaFotogramasEnemigo) { contadorFotogramasEnemigo = 0; xEnemigo += incrXEnemigo; yEnemigo += incrYEnemigo; } // Para la siguiente posición, escojo al azar y miro si realmente se puede mover bool posibleMover = false; do { int numeroAzar = (int) numAleatorio.Next(0,100); if (numeroAzar < 25) // Intento derecha { if ((xEnemigo < maxX) && // Si no ha llegado al borde ((mapa[filaHabitacion, columnaHabitacion, yEnemigo,xEnemigo+1] == 0) // Espacio en blanco || (mapa[filaHabitacion, columnaHabitacion, yEnemigo,xEnemigo+1] == 4)) )// Escalera { incrXEnemigo = 1; incrYEnemigo = 0; posibleMover = true; } } else if (numeroAzar < 50) // Intento izquierda { if ((xEnemigo > 0) && // Si no ha llegado al borde ((mapa[filaHabitacion, columnaHabitacion, yEnemigo,xEnemigo-1] == 0) // Espacio en blanco || (mapa[filaHabitacion, columnaHabitacion, yEnemigo,xEnemigo-1] == 4)) )// Escalera { incrXEnemigo = -1; incrYEnemigo = 0; posibleMover = true; } } else if (numeroAzar < 75) // Intento arriba { if ((yEnemigo > 0) && // Si no ha llegado al borde ((mapa[filaHabitacion, columnaHabitacion, yEnemigo-1,xEnemigo] == 0) // Espacio en blanco || (mapa[filaHabitacion, columnaHabitacion, yEnemigo-1,xEnemigo] == 4)) )// Escalera { incrXEnemigo = 0; incrYEnemigo = -1; posibleMover = true; } } else // Intento abajo { if ((yEnemigo < maxY) && // Si no ha llegado al borde ((mapa[filaHabitacion, columnaHabitacion, yEnemigo+1,xEnemigo] == 0) // Espacio en blanco || (mapa[filaHabitacion, columnaHabitacion, yEnemigo+1,xEnemigo] == 4)) )// Escalera { incrXEnemigo = 0; incrYEnemigo = 1; posibleMover = true; } } } while (! posibleMover); } static void comprobarColisiones() { if ((x==xEnemigo) && (y==yEnemigo)) { if ((direccion == DERECHA) || (direccion == IZQUIERDA)) matarEnemigo(); else morir(); } } static void matarEnemigo() { puntos += 10; colocarEnemigo(); } static void morir() { int i; vidas --; // Rectángulo verde Hardware.RectanguloRellenoRGBA( 0,0,490,350, // Posicion, ancho y alto de la pantalla 0,255,0, // En color verde 200); // Con algo de transparencia // Dibujo las vidas restantes Hardware.EscribirTextoOculta( "Te quedan", 250, 100, 0, 0, 0, fuente18); Hardware.EscribirTextoOculta( vidas.ToString(), 250, 150, 0xFF, 0, 0, fuente18); Hardware.EscribirTextoOculta( "vidas", 250, 200, 0, 0, 0, fuente18); for (i=0; i<vidas; i++) { imagenPersonaje.MoverA( 130 , (short) (50+ i*50) ); imagenPersonaje.DibujarOculta(); } // Aviso de la tecla para volver Hardware.EscribirTextoOculta( "Pulsa V para volver", 300, 400, 0xAA, 0xAA, 0xAA, fuente18); // Y quito el aviso de "ESC para salir" Hardware.RectanguloRellenoRGBA( 300, 500, 600,550, 0,0,0, 255); // Finalmente, muestro en pantalla Hardware.VisualizarOculta(); // Espero hasta que se pulse la tecla de volver do { } while (! Hardware.TeclaPulsada(Hardware.TECLA_V) ); // Vuelvo a colocar el enemigo al azar colocarEnemigo(); // Si no hay vidas, se acabó la partida if (vidas == 0) partidaTerminada = true; } static void dibujarElementos() { Hardware.BorrarPantallaOculta(0,0,0); // Dibujo el fondo de la pantalla for (fila=0; fila<filasPantalla; fila++) for (colum=0; colum<columnasPantalla; colum++) switch (mapa[filaHabitacion, columnaHabitacion, fila,colum]) { case 0: // Espacio en blanco, no dibujo nada break; case 1: imagenFondoHoriz.MoverA( (short) (colum*70) , (short) (fila*50)); imagenFondoHoriz.DibujarOculta(); break; case 2: imagenFondoHorizAcido.MoverA( (short) (colum*70) , (short) (fila*50)); imagenFondoHorizAcido.DibujarOculta(); break; case 3: imagenFondoVert.MoverA( (short) (colum*70) , (short) (fila*50)); imagenFondoVert.DibujarOculta(); break; case 4: imagenEscalera.MoverA( (short) (colum*70) , (short) (fila*50)); imagenEscalera.DibujarOculta(); break; } // Dibujo el personaje, el enemigo y un texto en la pantalla oculta imagenPersonaje.MoverA( (short) (x*70) , (short) (y*50) ); imagenPersonaje.DibujarOculta(); imagenEnemigo.MoverA( (short) (xEnemigo*70) , (short) (yEnemigo*50) ); imagenEnemigo.DibujarOculta(); Hardware.EscribirTextoOculta( "Puntos", 600, 100, 0xAA, 0xAA, 0xAA, fuente18); Hardware.EscribirTextoOculta( puntos.ToString(), 600, 140, 0xAA, 0xAA, 0xAA, fuente18); Hardware.EscribirTextoOculta( "Pulsa ESC para salir", 300, 500, 0xAA, 0xAA, 0xAA, fuente18); // Finalmente, muestro en pantalla Hardware.VisualizarOculta(); } static void pausaFotograma() { // Pausa para 25 fps Hardware.Pausa( 40 ); } static void buclePrincipal() { partidaTerminada = false; vidas++; morir(); // Para que aparezca el aviso de que empieza con 5 vidas do { comprobarTeclas(); moverElementos(); comprobarColisiones(); dibujarElementos(); pausaFotograma(); } while (! partidaTerminada); } public static void Main() { inicializar(); mostrarPresentacion(); buclePrincipal(); } } /* fin de la clase Juego */Siguiente entrega...