5. Montando un nivel: controles y lógica.

Sin valoraciones

5. Montando un nivel: controles y lógica.

Ya hemos implementado todas las pantallas excepto la última, la pantalla para jugar a un nivel. En este capítulo nos centraremos en esta pantalla a falta de los enemigos y su inteligencia artificial que lo reservaremos para capítulo 6.

Antes de describir todo el proceso, describiremos brevemente la jugabilidad y la física del movimiento de los objetos. Con Unity3d sería muy fácil implementar el movimiento libre del personaje y otros objetos en un escenario mediante el uso de sus colisiones. Sin embargo, en el juego original “Boulder Dash” el movimiento de éstos se realizar por cuadrículas a consecuencia de las limitaciones técnicas de su época.

5. Montando un nivel: controles y lógica.

Figura 5.1. Pantalla de nuestro juego (izquierda) y pantalla del juego original Boulder Dash para C64 (derecha).

Para conseguir ese efecto de movimiento, se ha utilizado la siguiente estructura de la Figura 5.2.

5. Montando un nivel: controles y lógica.

Figura 5.2. Estructura de datos de la lógica de un nivel.

Usaremos una matriz (“arraySquare”) para guardar la posición de cada objeto. En el caso de las rocas que pueden caerse y ser movidas, se guardará en otra matriz (“arrayStateRocks”) sus estados (stop, left, right, down) para tener controlado sus movimientos mediante estados y además existirá otra matriz (“arrayTimeRocks”) que controlará el movimiento de una cuadrícula a otra. Para simplificar la física del juego, un solo objeto (roca o diamante) podrá moverse a la vez en una columna y para ello se utiliza
el array “arrayBusyColumns” que bloqueará una columna para que solo una roca o diamante caía por ella a la vez.

videojuegos

Dado la rapidez del movimiento, esta limitación no resultará molesta a la hora de jugar y nos dará facilidad para controlar el movimiento de los objetos mediante código.

5.1 Carga del escenario desde fichero.

Podríamos crear un nivel directamente en la escena como hemos hecho con las demás pantallas, sin embargo, esto implicaría crear una nueva escena para cada uno de los niveles. Además de lo trabajoso que sería crear una escena por cada nivel, estaríamos limitados cuando quisiésemos actualizar nuestro juego con nuevos niveles. Es por ello, que en estos tipos de juegos se suelen cargar niveles predefinidos desde ficheros y así reutilizar la misma escena y código.

Existen muchas formas de cargar un fichero pero nos hemos decantado por un fichero de texto plano en vez de otros ficheros más complejos como el XML que proporciona un mayor control de los datos. La razón de esta elección es porque resulta muy sencillo su lectura y además previsualizar el nivel de una forma más fácil que un XML.

5. Montando un nivel: controles y lógica.

Figura 5.3. Visualización de un documento en texto plano (izquierda) y de un documento XML (derecha).

Lo primero es definir que representará cada uno de los caracteres: “W” pared, “R” roca, “E” enemigo, “G” y “H” diamantes. Una vez tenemos construido nuestro fichero como muestra la figura 5.3, lo guardamos en el directorio “Resources” que es el directorio donde se suelen guardar los recursos que se cargarán posteriormente desde scripts.

Para cargar un fichero u otro, en la pantalla previa de elegir un nivel, guardamos con PlayerPrefs el nombre del fichero del nivel a cargar y después en el script del nivel recogemos ese nombre y cargamos el fichero como se muestra en las Figuras 5.4 y 5.5.

5. Montando un nivel: controles y lógica.
Figura 5.4. Carga del fichero e inicialización de las estructuras.

5. Montando un nivel: controles y lógica.

Figura 5.5. Instancia de cada objeto en las estructuras

5.2 Control del personaje.

Para controlar el personaje, lo primero es chequear los toques en la pantalla mediante un joystick virtual. No sería demasiado complicado utilizando las funciones vistas en el capítulo 3:

videojuegos

1 – Un script asociado a la cámara que incluya una función “OnMouseDown” que compruebe cuando se pulsa la pantalla.

2 – Al pulsar la pantalla, en la función “OnMouseDown” se instancia un objeto “Prefab” (joystick) en la posición del toque.

3 – En el “Update» del script asociado al joystick, se recoge el input.touches y se calcula la dirección de los toques.

Sin embargo, aunque la lógica del joystick es sencilla, depende de otras características como su estética para que resulte atractivo y útil al usuario. En este caso, es una buena oportunidad para hacer uso de la Asset Store, la tienda con recursos gratuitos y de pago de Unity3d. En ella tenemos multitud de joysticks gratuitos y de pago completamente personalizables por lo que nos ahorrará tiempo. Como se suele decir, no hay que reinventar la rueda. Para acceder a la tienda, vamos al menú “Windows/Asset Store”.

5. Montando un nivel: controles y lógica.

Figura 5.6. Asset Store de Unity3d.

La Asset Store está disponible desde las versiones iniciales y en ella podemos encontrar todo tipo de recursos para utilizar en nuestros proyectos. Escribimos “joystick” en la búsqueda y elegimos el recurso destacado en la Figura 5.6 y que en el momento de desarrollar este juego era gratuito. Aun así, hay muchas alternativas a elegir. Lo importamos y se creará la carpeta “TouchInputManager” dentro del directorio “Assets”. Además, en el menú Windows nos aparecerá la opción “Touch Input Manager” donde podremos configurar todos los parámetros del joystick o añadir más de un joystick o botones.

videojuegos

Puesto que no es una funcionalidad nativa de Unity3d y que puede cambiar si hemos elegido otro recurso, nos centramos directamente en su utilización para recoger los valores que nos interesa como se muestra en la Figura 5.7.

5. Montando un nivel: controles y lógica.

Figura 5.7. Inicialización y uso del joystick de la Asset Store

Una vez que tenemos el joystick virtual, podemos empezar a definir el comportamiento y control de nuestro personaje. Nuestro personaje también se moverá por estados (down, up, left, right) para controlar el movimiento de una cuadrícula a otra.

5. Montando un nivel: controles y lógica.

Figura 5.8. Método Update con la lógica del movimiento del personaje

En el método “Update” lo primero que hacemos es comprobar que el usuario no esté bloqueado (ha muerto por una piedra o un enemigo) y realizamos los siguientes pasos:

1. Comprobamos que el personaje está en estado “stop”, es decir, ha llegado a una cuadrícula. En ese caso, actualizamos el estado según los valores que nos devuelva el joystick.

5. Montando un nivel: controles y lógica.

Figura 5.9. Método updateStatePlayer

En la figura 5.9 se muestra la lógica para el estado “left”. Si la cuadrícula a la izquierda del personaje no es de tipo pared, cambia el estado a “left”. Además, si en dicha cuadricula existe una piedra que se puede empujar, cambiará el estado de la piedra a “left”. El método “Flip” lo que hace es voltear horizontalmente la imagen del personaje ya que inicialmente nuestro personaje mira hacia la derecha y “checkPosition” comprueba si es accesible esa posición.

2. Lo siguiente es actualizar la posición del personaje según el estado en el que nos encontremos.

3.

5. Montando un nivel: controles y lógica.

Figura 5.10. Método movePlayerByState.

4. Por último en la Figura 5.8, comprobamos si en la cuadricula existe un objeto de tipo arena (“Sand”) o gema (“Gem”) y lo eliminamos. En el caso de ser una gema, actualizamos el marcador con la puntuación. En el capítulo 7 implementaremos la puntuación y las diferentes pantallas de “game over” y “victoria”.

videojuegos

5.3 Lógica de las rocas.

La lógica de las rocas se controlará en el método “Update” del script principal del nivel ya que si una roca no tiene suelo debajo o a los lados, ésta automáticamente caerá.

1. Comprobamos el estado de las rocas.

5. Montando un nivel: controles y lógica.

Figura 5.11. Método que actualiza el estado de las rocas.

En el script de la Figura 5.11 recorremos la matriz y para cada roca o gema, comprobamos si no existe ningún objeto a cada lado que les impida caerse (Figura 5.12), y en caso afirmativo, cambia su estado hacía el lado que se va a caer. Bloqueamos la columna en el array “arrayBusyColumns” para impedir que otra roca caiga a la vez por la misma columna.

Figura 5.12: cuadriculas que se comprueban para cambiar el estado de una roca.

Para evitar que la roca comience a caer instantáneamente aplastando al personaje, se utiliza un temporizador antes de cambiar su estado.

2. Actualizamos la posición de las rocas o gemas según el estado en el que se encuentren.

5. Montando un nivel: controles y lógica.

Figura 5.13. Método que actualiza la posición de las rocas y gemas.

En la figura 5.13 se muestra la parte del método “updatePhysicsRocksGems” que actualiza la posición de una roca o gema que está en el estado “down” (caída hacia abajo). Mientras no llegue al recuadro destino, seguirá actualizando su posición. Si llega al recuadro destino y éste no tiene ningún objeto debajo, el estado seguirá siendo “down”. En caso contrario, su estado pasará a “stop” y desbloqueará la columna.

3. Por último comprobamos si el personaje ha empujado alguna roca.

5. Montando un nivel: controles y lógica.

Figura 5.14. Método que comprueba si el personaje ha empujado alguna roca.

En el script asociado al personaje, indicábamos que una piedra era movida con las variables “pushDir”, “pushi” y “pushj” que son públicas y estáticas, es decir, pueden ser accedidas desde otros scripts. Moveremos la roca que se encuentra en la posición indicada al estado que hemos indicado. Al igual que cuando cae, con un temporizador simularemos el “empujón” para que no salga despedida instantáneamente.

 

 

Montar un nivel en Unity implica crear el entorno del juego, gestionar los controles del jugador y establecer la lógica del juego:

1. Creación del Entorno:

  • Escenario:
    • Diseña y crea los elementos visuales del nivel utilizando el Editor de Unity.
    • Añade terrenos, plataformas, obstáculos y cualquier otro elemento necesario.
  • Iluminación:
    • Configura la iluminación de la escena utilizando luces y sombras para crear el ambiente deseado.
  • Cámaras:
    • Ajusta la posición y configuración de las cámaras para proporcionar la mejor perspectiva del juego.

2. Controles del Jugador:

  • Movimiento del Jugador:
    • Implementa el script de control del jugador para gestionar el movimiento.
    • Utiliza las entradas del teclado, ratón o controles táctiles según la plataforma.
  • Saltos y Habilidades:
    • Si el juego implica saltos o habilidades especiales, implementa scripts para gestionar estas acciones.
  • Cámara Seguidora (Opcional):
    • Si es necesario, crea una cámara que siga al jugador para mantenerlo centrado en la pantalla.
  • Interacción con Objetos:
    • Permite al jugador interactuar con objetos dentro del nivel (puertas, interruptores, etc.).

3. Lógica del Juego:

  • Condición de Victoria/Derrota:
    • Define las condiciones que determinarán si el jugador ha ganado o perdido el nivel.
    • Esto podría incluir alcanzar un objetivo, derrotar a un jefe, recoger objetos, etc.
  • Puntuación y Recompensas:
    • Implementa sistemas de puntuación y recompensas si son relevantes para tu juego.
    • Asocia puntuaciones con acciones específicas para motivar al jugador.
  • Guardado del Progreso (Opcional):
    • Si tu juego tiene varios niveles, considera implementar un sistema de guardado del progreso del jugador.

4. Eventos del Juego:

  • Desencadenadores de Eventos:
    • Establece desencadenadores de eventos para situaciones específicas (por ejemplo, al recoger un ítem especial).
  • Sonidos y Música:
    • Implementa sonidos y música que se reproduzcan en respuesta a eventos específicos en el juego.

5. Pruebas y Ajustes:

  • Pruebas de Jugabilidad:
    • Juega el nivel repetidamente para asegurarte de que la experiencia sea fluida y desafiante.
  • Optimización:
    • Realiza optimizaciones para garantizar un rendimiento suave del juego.
  • Ajustes de Equilibrio:
    • Ajusta la dificultad y otros elementos de juego según el feedback obtenido durante las pruebas.

6. Simulación y Debugging:

  • Herramientas de Debugging:
    • Utiliza herramientas de debugging para identificar y solucionar problemas en la lógica del juego.
  • Simulación de Escenarios:
    • Simula diferentes escenarios para asegurarte de que la lógica del juego maneje todas las situaciones posibles.

7. Documentación:

  • Notas de Diseño:
    • Documenta la lógica del juego y cualquier decisión de diseño importante.

8. Iteración:

  • Feedback del Jugador:
    • Recopila feedback del jugador y realiza iteraciones en el diseño y la lógica del nivel.

Compártelo en tus redes

Share on facebook
Share on twitter
Share on linkedin
Share on pinterest

Valore este curso

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Utilizamos cookies para asegurar que damos la mejor experiencia al usuario en nuestra web. Si sigues utilizando este sitio asumimos que estás de acuerdo. VER