Death Pit Remake
Un remake parcial de un juego... paso a paso
13.- Volver a empezar una partida
El trabajo propuesto
Ahora mismo, cuando se acaban las 5 vidas o cuando se pulsa ESC, se marca la partida como "partidaTerminada=true", termina el juego y se vuelve al sistema operativo.
Ahora queremos que cuando se acaban las vidas o se pulse ESC, se vuelva a la pantalla d presentación, se pueda comenzar una nueva partida, en las condiciones iniciales: otra vez 5 vidas, 0 puntos, el personaje en la casilla inicial...
Forma de conseguirlo
Basta con que "Main" no llame una única vez al "buclePrincipal" del juego, sino que lo haga de forma repetitiva, según si ha terminado o no la sesión de juego, algo que dependería de la tecla que pulse el usuario cuando está en la pantalla de presentación:
public static void Main() { inicializar(); do { mostrarPresentacion(); if (!sesionTerminada) { inicializarPartida(); buclePrincipal(); } } while (!sesionTerminada); }
Por tanto, la pantalla de presentación debería permitir escoger entre la tecla de comenzar una nueva partida o la tecla de abandonar toda la sesión de juego:
static void mostrarPresentacion() { //dibujo la presentacion presentacion.DibujarOculta(); // Esscribo avisos de las teclas utilizables Hardware.EscribirTextoOculta( "Pulsa Espacio para jugar", 300, 550, 0xAA, 0xAA, 0xAA, fuente18); Hardware.EscribirTextoOculta( "o pulsa T para terminar", 300, 575, 0xAA, 0xAA, 0xAA, fuente18); // Finalmente, muestro en pantalla Hardware.VisualizarOculta(); //hasta que se pulse espacio do { } while ((! Hardware.TeclaPulsada(Hardware.TECLA_ESP) ) && (! Hardware.TeclaPulsada(Hardware.TECLA_T))); if (Hardware.TeclaPulsada(Hardware.TECLA_T)) sesionTerminada = true; //borro la presentacion Hardware.BorrarPantallaOculta(0,0,0); }
Y además, necesitamos la función auxiliar "inicializarPartida" , que se encargue de volver a dejar el personaje con 5 vidas, 0 puntos y en su posición inicial:
static void inicializarPartida() { vidas = 5; puntos = 0; // Coloco al personaje x = 1; y = 1; filaHabitacion = 0; columnaHabitacion = 0; colocarEnemigo(); // Y al enemigo en posici�n al azar partidaTerminada = false; vidas++; morir(); // Para que aparezca el aviso de que empieza con 5 vidas }
El conjunto del fuente podría ser así:
/** * 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 0.13 11-Dic-2009 Joaquín, Alejandro, Miguel; retoques por Nacho Cuando acaban las vidas o se pulsa ESC, acaba la partida, se vuelve a la presentación y se puede volver a empezar ---------------------------------------------------- */ 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; // Si ha terminado una partida puntual static bool sesionTerminada; // Si ha terminado una sesion completa de juego // Inicialización al comenzar la sesión de juego 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 ); sesionTerminada = false; } // --- Comienzo de un nueva partida: reiniciar variable --- static void inicializarPartida() { vidas = 5; puntos = 0; // Coloco al personaje x = 1; y = 1; filaHabitacion = 0; columnaHabitacion = 0; colocarEnemigo(); // Y al enemigo en posición al azar partidaTerminada = false; vidas++; morir(); // Para que aparezca el aviso de que empieza con 5 vidas } // --- Mostrar pantalla de presentación --- static void mostrarPresentacion() { //dibujo la presentacion presentacion.DibujarOculta(); // Esscribo avisos de las teclas utilizables Hardware.EscribirTextoOculta( "Pulsa Espacio para jugar", 300, 550, 0xAA, 0xAA, 0xAA, fuente18); Hardware.EscribirTextoOculta( "o pulsa T para terminar", 300, 575, 0xAA, 0xAA, 0xAA, fuente18); // Finalmente, muestro en pantalla Hardware.VisualizarOculta(); //hasta que se pulse espacio do { } while ((! Hardware.TeclaPulsada(Hardware.TECLA_ESP) ) && (! Hardware.TeclaPulsada(Hardware.TECLA_T))); if (Hardware.TeclaPulsada(Hardware.TECLA_T)) sesionTerminada = true; //borro la presentacion Hardware.BorrarPantallaOculta(0,0,0); } // --- Coloca el enemigo en cualquier posición "libre" de la pantalla actual ----- static void comprobarTeclas() { // 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; } // --- Coloca el enemigo en cualquier posición "libre" de la pantalla actual ----- static void colocarEnemigo() { 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 } // --- Animación de los enemigos y demás objetos "que se muevan solos" ----- 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); } // --- Comprobar colisiones de enemigo con personaje, etc --- static void comprobarColisiones() { if ((x==xEnemigo) && (y==yEnemigo)) { if ((direccion == DERECHA) || (direccion == IZQUIERDA)) matarEnemigo(); else morir(); } } // --- Matar enemigo: aumentar puntos y recolocarlo --- static void matarEnemigo() { puntos += 10; colocarEnemigo(); } // --- Morir personaje: mostrar vidas restantes, etc --- 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 al juego", 120, 350, 0xAA, 0xAA, 0xAA, fuente18); // Y quito el aviso de "ESC para salir" Hardware.RectanguloRellenoRGBA( 160, 370, 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; } // --- Dibujar en pantalla todos los elementos visibles del juego --- 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", 170, 380, 0xAA, 0xAA, 0xAA, fuente18); // Finalmente, muestro en pantalla Hardware.VisualizarOculta(); } // --- Pausa tras cada fotograma de juego, para velocidad de 25 fps ----- static void pausaFotograma() { Hardware.Pausa( 40 ); } // --- Bucle principal de juego ----- static void buclePrincipal() { do { comprobarTeclas(); moverElementos(); comprobarColisiones(); dibujarElementos(); pausaFotograma(); } while (! partidaTerminada); } // --- Cuerpo del programa ----- public static void Main() { inicializar(); do { mostrarPresentacion(); if (!sesionTerminada) { inicializarPartida(); buclePrincipal(); } } while (!sesionTerminada); } } /* fin de la clase Juego */Siguiente entrega...
Acceso rápido
- 00.- Motivo
- 01.- Esqueleto vacío
- 02.- Un personaje que se mueve solo
- 03.- Personaje que se mueve con teclado. Enemigo simultáneo
- 04.- Presentación. Dos enemigos con distinto comportamiento
- 05.- Varios enemigos iguales
- 06.- Un fondo formado por "casillas" repetitivas (tiles)
- 07.- El personaje se mueve por el laberinto
- 08.- Un fuente más modular
- 09.- Varias pantallas conectadas
- 10.- Un enemigo que se mueve por el laberinto
- 11.- Varias vidas
- 12.- Distintas imágenes según la dirección. Matar enemigos y obtener puntos.
- 13.- Volver a empezar una partida.
- 14.- Rediseño usando objetos
- 15.- Tabla de records (Aún no)
- 16.- Varios tipos de enemigos (Aún no)
- 17.- Leyendo el mapa desde fichero (Aún no)
- 18.- Gastar aire y "energía" (Aún no)
- 19.- Recoger "premios" (Aún no)
- Orig.- Algunos datos sobre el juego original