23. Pantalla de ayuda y de créditos
Vamos a ver también cómo añadir más opciones al menú principal. Una de ellas mostrará una pequeña ayuda, que recuerde (por ejemplo) las teclas que se pueden usar durante el juego. Otra será una pantalla de "créditos", que muestre datos sobre el autor de nuestro juego.
Crearemos un par de funciones nuevas. Su estructura será muy similar a la que tenía la presentación, salvo que ahora sólo es necesario esperar hasta que se pulse ESC:
public static void MostrarCreditos() { // ---- Pantalla de presentación -- Hardware.BorrarPantallaOculta(0, 0, 0); // Fondo de la presentación fondoCreditos.DibujarOculta(0, 0); // Marcador Hardware.EscribirTextoOculta("Creditos", 250, 200, // Coordenadas 255, 255, 255, // Colores tipoDeLetra); Hardware.EscribirTextoOculta("Por Nacho Cabanes, 2011", 250, 300, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); Hardware.EscribirTextoOculta("ESC- volver", 650, 530, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); Hardware.VisualizarOculta(); do { Hardware.Pausa(20); } while (!Hardware.TeclaPulsada(Hardware.TECLA_ESC)); }
Dejamos una "Pausa" dentro del "do..while" para que no use el 100% del procesador para algo tan sencillo como esperar una tecla. Con esa "pausa" ayudamos a mantener la multitarea del sistema operativo.
Ahora tendremos que ampliar la presentación, para que avise de las nuevas opciones, compruebe las teclas necesarias y llame a las nuevas funciones cuando sea el caso:
public static void MostrarPresentacion() { bool finPresentacion = false; do { // ---- Pantalla de presentación -- Hardware.BorrarPantallaOculta(0, 0, 0); // Fondo de la presentación fondoPresentacion.DibujarOculta(0, 0); // Marcador Hardware.EscribirTextoOculta("Jueguecillo", 340, 200, // Coordenadas 255, 255, 255, // Colores tipoDeLetra); Hardware.EscribirTextoOculta("Escoja una opción:", 310, 300, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); Hardware.EscribirTextoOculta("J.- Jugar una partida", 150, 390, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); Hardware.EscribirTextoOculta("A.- Ayuda", 150, 430, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); Hardware.EscribirTextoOculta("C.- Créditos", 150, 470, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); Hardware.EscribirTextoOculta("S.- Salir", 150, 510, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); Hardware.VisualizarOculta(); Hardware.Pausa(20); if (Hardware.TeclaPulsada(Hardware.TECLA_A)) MostrarAyuda(); if (Hardware.TeclaPulsada(Hardware.TECLA_C)) MostrarCreditos(); if (Hardware.TeclaPulsada(Hardware.TECLA_J)) finPresentacion = true; if (Hardware.TeclaPulsada(Hardware.TECLA_S)) { finPresentacion = true; partidaTerminada = true; juegoTerminado = true; } } while (!finPresentacion); }
Esto se haría antes de la parte repetitiva que comprueba pulsaciones de teclas, porque no tiene sentido cargar la imagen múltiples veces:
public static void MostrarPresentacion() { Imagen fondoPresentacion = new Imagen("present.jpg"); // ---- Pantalla de presentación -- Hardware.BorrarPantallaOculta(0,0,0); // Pantalla de fondo fondoPresentacion.DibujarOculta(0,0); // Marcador Hardware.EscribirTextoOculta("Jueguecillo", 340,200, // Coordenadas 255, 255, 255, // Colores tipoDeLetra); ...
El programa completo sería algo como:
// Primer mini-esqueleto de juego en modo gráfico // Versión "d" using System; using System.Threading; // Para Thread.Sleep public class Juego05d { struct ElemGrafico { public int x; public int y; public int xInicial; public int yInicial; public int incrX; public int incrY; public Imagen imagen; public bool visible; } static ElemGrafico personaje; static Fuente tipoDeLetra; static int numPremios, numEnemigos, numObstaculos; static ElemGrafico[] obstaculos; static ElemGrafico[] enemigos; static ElemGrafico[] premios; static bool juegoTerminado; static int vidas; static int puntos; static bool partidaTerminada; static Random generador; static Imagen fondoPresentacion; static Imagen fondoAyuda; static Imagen fondoCreditos; public static void InicializarJuego() { // Entrar a modo grafico 800x600 bool pantallaCompleta = false; Hardware.Inicializar(800, 600, 24, pantallaCompleta); // Resto de inicializacion tipoDeLetra = new Fuente("FreeSansBold.ttf", 18); juegoTerminado = false; numPremios = 10; numEnemigos = 10; numObstaculos = 20; obstaculos = new ElemGrafico[numObstaculos]; enemigos = new ElemGrafico[numEnemigos]; premios = new ElemGrafico[numPremios]; generador = new Random(); // Cargo imágenes de elementos personaje.imagen = new Imagen("personaje.png"); for (int i = 0; i < numObstaculos; i++) // Obstaculos obstaculos[i].imagen = new Imagen("obstaculo.png"); for (int i = 0; i < numEnemigos; i++) // Enemigos enemigos[i].imagen = new Imagen("enemigo.png"); for (int i = 0; i < numPremios; i++) // Premios premios[i].imagen = new Imagen("premio.png"); // Y cargo las imagenes de la presentación, ayuda y créditos fondoPresentacion = new Imagen("present.jpg"); fondoAyuda = new Imagen("present.jpg"); fondoCreditos = new Imagen("present.jpg"); } public static void InicializarPartida() { // En cada partida, hay que reiniciar ciertas variables vidas = 3; puntos = 0; partidaTerminada = false; personaje.xInicial = 400; personaje.yInicial = 300; personaje.x = personaje.xInicial; personaje.y = personaje.yInicial; personaje.incrX = 10; personaje.incrY = 10; // Genero las posiciones de los elementos al azar for (int i = 0; i < numObstaculos; i++) // Obstaculos { obstaculos[i].x = generador.Next(50, 700); obstaculos[i].y = generador.Next(30, 550); } for (int i = 0; i < numEnemigos; i++) // Enemigos { enemigos[i].x = generador.Next(50, 700); enemigos[i].y = generador.Next(30, 550); enemigos[i].incrX = 5; } for (int i = 0; i < numPremios; i++) // Premios { premios[i].x = generador.Next(50, 700); premios[i].y = generador.Next(30, 550); premios[i].visible = true; } } public static void MostrarPresentacion() { bool finPresentacion = false; do { // ---- Pantalla de presentación -- Hardware.BorrarPantallaOculta(0, 0, 0); // Fondo de la presentación fondoPresentacion.DibujarOculta(0, 0); // Marcador Hardware.EscribirTextoOculta("Jueguecillo", 340, 200, // Coordenadas 255, 255, 255, // Colores tipoDeLetra); Hardware.EscribirTextoOculta("Escoja una opción:", 310, 300, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); Hardware.EscribirTextoOculta("J.- Jugar una partida", 150, 390, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); Hardware.EscribirTextoOculta("A.- Ayuda", 150, 430, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); Hardware.EscribirTextoOculta("C.- Créditos", 150, 470, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); Hardware.EscribirTextoOculta("S.- Salir", 150, 510, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); Hardware.VisualizarOculta(); Hardware.Pausa(20); if (Hardware.TeclaPulsada(Hardware.TECLA_A)) MostrarAyuda(); if (Hardware.TeclaPulsada(Hardware.TECLA_C)) MostrarCreditos(); if (Hardware.TeclaPulsada(Hardware.TECLA_J)) finPresentacion = true; if (Hardware.TeclaPulsada(Hardware.TECLA_S)) { finPresentacion = true; partidaTerminada = true; juegoTerminado = true; } } while (!finPresentacion); } public static void MostrarAyuda() { // ---- Pantalla de presentación -- Hardware.BorrarPantallaOculta(0, 0, 0); // Fondo de la presentación fondoAyuda.DibujarOculta(0, 0); // Marcador Hardware.EscribirTextoOculta("Ayuda", 340, 200, // Coordenadas 255, 255, 255, // Colores tipoDeLetra); Hardware.EscribirTextoOculta("(Texto de ejemplo)", 310, 300, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); Hardware.EscribirTextoOculta("ESC- volver", 650, 530, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); Hardware.VisualizarOculta(); do { Hardware.Pausa(20); } while (!Hardware.TeclaPulsada(Hardware.TECLA_ESC)); } public static void MostrarCreditos() { // ---- Pantalla de presentación -- Hardware.BorrarPantallaOculta(0, 0, 0); // Fondo de la presentación fondoCreditos.DibujarOculta(0, 0); // Marcador Hardware.EscribirTextoOculta("Creditos", 250, 200, // Coordenadas 255, 255, 255, // Colores tipoDeLetra); Hardware.EscribirTextoOculta("Por Nacho Cabanes, 2011", 250, 300, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); Hardware.EscribirTextoOculta("ESC- volver", 650, 530, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); Hardware.VisualizarOculta(); do { Hardware.Pausa(20); } while (!Hardware.TeclaPulsada(Hardware.TECLA_ESC)); } public static void Dibujar() { // -- Dibujar -- Hardware.BorrarPantallaOculta(0, 0, 0); // Marcador Hardware.EscribirTextoOculta("Vidas Puntos", 0, 0, // Coordenadas 255, 255, 255, // Colores tipoDeLetra); Hardware.EscribirTextoOculta(Convert.ToString(vidas), 70, 0, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); Hardware.EscribirTextoOculta(Convert.ToString(puntos), 190, 0, // Coordenadas 200, 200, 200, // Colores tipoDeLetra); for (int i = 0; i < numObstaculos; i++) // Obstáculos { obstaculos[i].imagen.DibujarOculta( (int)obstaculos[i].x, (int)obstaculos[i].y); } for (int i = 0; i < numEnemigos; i++) // Enemigos { enemigos[i].imagen.DibujarOculta( (int)enemigos[i].x, (int)enemigos[i].y); } for (int i = 0; i < numPremios; i++) // Premios { if (premios[i].visible) { premios[i].imagen.DibujarOculta( premios[i].x, premios[i].y); } } personaje.imagen.DibujarOculta( personaje.x, personaje.y); // Finalmente, muestro en pantalla Hardware.VisualizarOculta(); } public static void ComprobarTeclas() { // -- Leer teclas y calcular nueva posición -- if (Hardware.TeclaPulsada(Hardware.TECLA_ESC)) partidaTerminada = true; if (Hardware.TeclaPulsada(Hardware.TECLA_DER)) personaje.x += personaje.incrX; if (Hardware.TeclaPulsada(Hardware.TECLA_IZQ)) personaje.x -= personaje.incrX; if (Hardware.TeclaPulsada(Hardware.TECLA_ARR)) personaje.y -= personaje.incrY; if (Hardware.TeclaPulsada(Hardware.TECLA_ABA)) personaje.y += personaje.incrY; } public static void MoverElementos() { // -- Mover enemigos, entorno -- for (int i = 0; i < numEnemigos; i++) // Enemigos { enemigos[i].x = enemigos[i].x + enemigos[i].incrX; if (((int)enemigos[i].x <= 50) || ((int)enemigos[i].x >= 700)) enemigos[i].incrX = -enemigos[i].incrX; } } public static void ComprobarColisiones() { // -- Colisiones, perder vidas, etc -- for (int i = 0; i < numObstaculos; i++) // Obstáculos { if ((obstaculos[i].x == personaje.x) && (obstaculos[i].y == personaje.y)) { vidas--; if (vidas == 0) partidaTerminada = true; personaje.x = personaje.xInicial; personaje.y = personaje.yInicial; } } for (int i = 0; i < numPremios; i++) // Obstáculos { if ((premios[i].x == personaje.x) && (premios[i].y == personaje.y) && premios[i].visible) { puntos += 10; premios[i].visible = false; } } for (int i = 0; i < numEnemigos; i++) // Enemigos { if (((int)enemigos[i].x == personaje.x) && ((int)enemigos[i].y == personaje.y)) { vidas--; if (vidas == 0) partidaTerminada = true; personaje.x = personaje.xInicial; personaje.y = personaje.yInicial; } } } public static void PausaFotograma() { // -- Pausa hasta el siguiente "fotograma" del juego -- Hardware.Pausa(20); } public static void Main() { InicializarJuego(); while (!juegoTerminado) { InicializarPartida(); MostrarPresentacion(); // ------ Bucle de juego ------ while (!partidaTerminada) { Dibujar(); ComprobarTeclas(); MoverElementos(); ComprobarColisiones(); PausaFotograma(); } // Fin del bucle de juego } // Fin de partida } // Fin de Main }
Ejercicio propuesto: Haz que la ayuda muestre textos más detallados: varias frases, que estarán almacenadas en un "array de strings". Deberás recorrer este array usando "for" o "foreach".
(Nota: nuevamente, si quieres ver cómo quedaría el fuente con estos cambios propuestos... tendrás que mirar en el siguiente apartado, que partirá de ese punto).