Post on 08-Jul-2022
Proyecto de desarrollo de videojuego, Boom Away
Daniel Andrés Pardo Chaves, Andrés Felipe Losada y Pablo Andrés Suárez Murillo
Universidad de los Andes. 111711. Bogotá, Colombia.
{da.pardo, af.losada, pa.suarezm} @uniandes.edu.co
Abstract. En este documento presentamos el juego Boom Away, el cual nació
como proyecto de grado diseñado y desarrollado por tres estudiantes de la
Universidad de los Andes en el segundo semestre del 2020. El proyecto empezó
explorando la mecánica experimental de uso de explosivos como modo de
movimiento para completar niveles diseñados alrededor de esta característica.
Sin embargo, en el transcurso del semestre el proyecto, además de lograr lo
anterior, se convirtió en un juego con un amplio rango de funcionalidades
adicionales, implementadas con diferentes soluciones de ingeniería de sistemas
aprendidas durante la carrera. Se utilizó lo nombrado anteriormente, junto con una
arquitectura robusta, implementando patrones de diseño de software y el uso los
principios S.O.L.I.D. para desarrollar una aplicación entendible y escalable. Además
de esto, al recoger analíticas del juego y convertir esos datos en información,
pudimos observar los problemas que nuestros jugadores tuvieron para luego
solucionarlos y finalizar con una experiencia de juego enriquecida y cambiada.
Palabras clave: Videojuego, Mecánica experimental, Creador de mundos, Base
de datos, Analíticas, Sistema de autorización de usuarios.
1. Introducción
La motivación del juego fue crear un juego a partir de una mecánica experimental, lo
cual significa un juego que tenga una mecánica que no haya sido explorada anteriormente
y tenga cierto grado de innovación. En el caso de Boom Away la mecánica era el uso del
famoso salto cohete, visto en juegos como Team Fortress 2, Halo, y Quake, para crear un
juego de un solo jugador que se centre en el manejo de los recursos y la habilidad del
jugador para poder llegar al final del nivel. Esta idea, en principio, se concibió partiendo
de la premisa de “un juego de plataformas donde el jugador no puede saltar”.
El problema que se planteó al inicio del proyecto fue la implementación de la
mecánica principal y el uso de esta para diseñar y generar niveles interesantes. La posible
solución que el equipo pensó fue primero tener organizada una arquitectura que soporte la
expansión de recursos (explosivos) y que también soporte la creación efectiva y rápida de
los niveles a los cuales el jugador se enfrentaría.
El diseño que tuvimos para la arquitectura del juego consistió en la implementación de
un creador de niveles para poder solucionar el problema de creación efectiva y rápida de
estos. Se implementó, en la primera iteración de este creador de niveles, un sistema de
guardado de niveles en archivos los cuales se almacenaban en la carpeta de persistencia
del juego. Sin embargo, más adelante al mudar el proyecto de un ambiente local a la
máquina del jugador a un ambiente web con el build y sus recursos persistidos del lado del
servidor, se tuvo que implementar otra solución para este guardado de niveles. La solución
propuesta para esta segunda iteración fue el guardado de estos niveles en una base de datos
accesible en línea. Usamos la base de datos Real-time Database de Firebase, El primer
problema que encontramos fue el hecho de que el SDK oficial de Firebase para Unity solo
funciona para aplicaciones móviles, razón por la cual implementamos nuestros propios
llamados a través de HTTP a la base de datos. En cuanto al segundo problema, decidimos
implementar una arquitectura basada en principios S.O.L.I.D. con la utilización de
interfaces y un buen diseño a la hora de escribir el código de las mecánicas principales.
Decidimos tener una interfaz que manejara el disparo de las armas y una interfaz para el
manejo de las explosiones, independiente de cual arma fuera. Cada arma implementaría su
propia lógica, pero todas compartirían los mismos métodos.
La primera iteración del creador de niveles nos ayudó a compartir la misma escena en
Unity para todos los niveles por lo cual la estructura del proyecto fue más organizada y
legible. También, nos ayudó a poder crear los niveles de una manera mucho más eficiente
y rápida. La segunda iteración del creador de niveles terminó siendo la adecuada para
resolver el problema. Además, esta solución nos abrió las puertas a otro tipo de
funcionalidades que tendría el juego después, tal como la implementación de un sistema
de usuarios con la funcionalidad de compartir sus niveles creados con otros jugadores.
En cuanto a la arquitectura del proyecto, nos fue de mucha ayuda a la hora de
implementar las armas ya que no hubo necesidad de reescribir código a la hora de
desarrollar los explosivos. Además, dado que los llamados y variables de todos los
explosivos son compartidos, cumpliendo así con el principio de sustitución de Liskov que
hace parte de los principios S.O.L.I.D., nos preocuparnos menos por el manejo de estas
implementaciones en los diferentes scripts que los necesitaban.
Sobre este documento: En primer lugar, se dará una descripción general del proyecto,
en particular sobre qué esperábamos lograr, detallando cuáles eran las herramientas y
conocimiento que teníamos al momento de empezar este proyecto. Después, destacaremos
el problema en cuestión y entraremos en más detalle respecto al diseño de nuestra
solución. Una vez finalizado esto, continuaremos con la implementación del proyecto
describiendo en detalle las diferentes estrategias y herramientas usadas. Finalmente,
nombraremos las diferentes analíticas que implementamos y cómo estas fueron usadas
para perfeccionar el juego.
Agradecimientos especiales al profesor Pablo Figueroa por guiarnos a través de este
proceso, asesorándonos y alentándonos a mejorar. Agradecemos también a las personas
que jugaron nuestro juego y contestaron la encuesta para que pudiéramos ver las falencias
de nuestro juego y así poder mejorar.
2. Trabajo y Conocimiento Previo
Para llegar a la idea “un juego de plataformas sin salto” fue necesaria una investigación
previa respecto a mecánicas no convencionales y sobre cómo plantear (y mejorar) el
diseño de un videojuego. Recursos tales como el canal de YouTube “Game Maker’s
Toolkit” del diseñador y periodista de videojuegos Mark Brown, y las charlas gratuitas de
la Game Developers Conference (GDC) resultaron cruciales a la hora de entender qué
buscamos en un videojuego. Puntualmente, el panel “The 2019 Experimental Gameplay
Workshop” de la GDC nos mostró varias formas de acercarnos a una mecánica no
convencional desde una perspectiva de diseño, y el tema principal del Game Jam que
organizó Brown en 2018 (“Genre Without Mechanic”) nos permitió aventurarnos a
imaginar, ¿cómo sería un videojuego de plataformas donde el jugador no puede saltar? De
los juegos presentados en este Game Jam, varios trabajaron esa misma pregunta:
“FireFlies” creado por el usuario de itch.io DannyVegas, y “Fire Escape” por Nosgoroth
son algunos de estos. En FireFlies, el jugador es una llama que debe escapar atravesando
plataformas de forma vertical, pero sin poder saltar. En vez, uno tiene que usar el mouse
para lanzar la llama de una forma idéntica a cómo se lanzan pájaros en Angry Birds. Por
otra parte, en Fire Escape, el jugador es (de nuevo) una llama que debe atravesar un
escenario horizontal. La forma de pasar entre plataformas y obstáculos es lanzando un
proyectil que puede incinerar ciertos materiales. Si un material empieza a arder, la llama
del jugador se teletransporta a ese punto y puede seguir su camino. Estos juegos, lejos de
ser respuestas absolutas a la premisa de “plataformas sin salto” fueron ideas interesantes
que nos mostraron algunas formas de acercarnos al diseño de nuestro juego.
Más aún, los video ensayos de Mark Brown sobre los conceptos de diseño detrás de
niveles de juegos de plataformas como Super Mario 3D World, y sobre cómo cambios
pequeños a la mecánica del salto pueden moldear todo el juego fueron cruciales a la hora
de pensar en niveles para Boom Away y para entender qué hace que un juego de
plataformas sea exitoso. Esto permitió que al principio del proceso de implementación
concentráramos nuestra atención en hacer que el personaje principal sea interesante y
divertido de controlar. Además, nos permitió guiar el diseño de niveles alrededor de esto,
y así generamos escenarios con varios niveles de complejidad para evolucionar la
mecánica pensada.
3. Desarrollo del diseño
Diseño del juego
El diseño del juego nació pensando en un género ya establecido y eliminando (o
limitando) una mecánica central del juego; en este caso, se pensó en cómo se vería un
juego de plataformas 2D si el jugador fuera incapaz de saltar por sí mismo, y más bien
debiera, de alguna forma, impulsarse o lanzarse entre las plataformas para llegar al
final de cada nivel. Como se puede ver en la figura 3.1 la idea que guio el desarrollo
del juego fue que el jugador se impulsaría usando varias clases de explosivos para
alcanzar su objetivo. Teniendo esta idea como mecánica principal, pensamos en qué
clases de explosivos podrían darle mayor expresividad a este verbo. Nuestra respuesta
se puede ver en la figura 3.2: cohetes a velocidad normal, cohetes a velocidad lenta,
granadas con temporizador automático, explosivos que se pueden poner en superficies
y explotar en cualquier momento a voluntad del jugador (i.e. C4), y un
“implosionador” que en vez de generar una fuerza que lanza al jugador hacia afuera
atrae al jugador hacia el punto donde este implotó. De estas ideas, la única que no fue
implementada fue el implosionador; no vimos escenarios factibles dentro del
desarrollo del juego ni en el diseño de los niveles donde esta herramienta apuntase al
diseño central. Por lo tanto, tomamos la decisión de no incluirlo.
Figura 3.1 Diseño preliminar de la mecánica central
Figura 3.2 Diseño preliminar de los diferentes explosivos
Figura 3.3 Obstáculos Figura 3.4 Coleccionables
Diseño de la interfaz de usuario (GUI)
Figura 3.5 Diseño preliminar del diseño de la página principal
Figura 3.6 Diseño preliminar del diseño de la interfaz de UI para el gameplay
Diseño de la arquitectura del juego
El GameObject preloadManager (figura 3.7) fue creado para mantener una serie de
variables que controlan el estado del juego de manera constante entre los cambios es
escenas. En este caso el componente de DDOL, es el que se encarga de permitir que esto
suceda. Los scripts de Game State Manager y World Save Manager se encargan de
guardar los estados del juego y cada nivel, respectivamente. El World Save Manager es
importante pues es el que se encarga de cargar los niveles, desencriptándolos y leyendo la
información que contienen.
Figura 3.7 Arquitectura del GameObject _preloadManager
Esta escena (figura 3.8) es la primera pantalla que el usuario se encuentra al pasar el
título del juego. En esta están los botones que lo conducen a cada una de las varias
modalidades del juego.
Figura 3.8 Arquitectura de la Escena “Main Menu”
Al presionar el botón de niveles, el usuario se enfrenta a una lista con los niveles de la
historia. Estos aparecen como una lista, y cada elemento cuenta con otro botón para
acceder a la lista de puntuaciones. (figura 3.9)
Figura 3.9 Arquitectura de la lista de niveles
En esta escena (figura 3.10) es donde los diagramas de la GUI se hacen realidad; contiene al jugador, sus
armas, obstáculos y demás. Al cargar un nivel se agregan componentes de tipo Obstacle, Hazard,
Collectable, y Environment. También, tiene el componente de Canvas, el cual maneja toda la GUI.
Figura 3.10 Arquitectura de la Escena “LevelScene”
Esta escena (figura 3.11) es similar a la escena del nivel, pero incluye las
funcionalidades necesarias para crear tiles, modificar armas, y subir y bajar niveles desde
nuestro componente online. El MakerManager es nuestro componente especializado en
cambiar entre el modo de creación y el modo de prueba. Este cambio genera una nueva
GUI y cambia las funcionalidades de acuerdo al modo en que se encuentre.
Figura 3.11 Arquitectura de la Escena “WorldBuilder”
Alternativas de Desarrollo
Tuvimos varias ideas para desarrollar como proyecto de grado, entre ellas me
parece que vale la pena destacar dos. La primera es un juego similar a WarioWare en
el cual los jugadores juegan cada nivel una mezcla de dos géneros distintos de
videojuego (e.g. shooter y puzzle), funcionaría como un Mario Party e incluiría la
posibilidad de jugar niveles creados por los jugadores. La mecánica interesante sería
la mezcla de varios tipos de géneros de videojuegos curados por los creadores y la
implementación de una herramienta para crearlos por parte de los jugadores. El
segundo fue un juego similar a Agar.io pero conformado por bolitas de luz que se van
comiendo unas a otras y transformando su color y aumentando el puntaje. Lo
interesante sería implementar formas de generar nuevos mundos basados en las
decisiones de cada jugador. Es decir, si se come una bola de un color esto afectaría su
población y por lo tanto cambiaría la manera en que se conforma el mundo y el
feedback generado (animación, color, sonidos) crearía una experiencia única para
nuestros jugadores.
Se prefirió Boom Away a las otras ideas por las dificultades que presentaría el
desarrollo de un MVP de cualquiera de las dos ideas anteriores. En el primer caso,
tendrían que hacerse muchos videojuegos en uno y en el segundo, la dependencia con
las visualizaciones para que el juego sea relevante y la dificultad de hacer la mecánica
fundamental fueron factores suficientes para descartar estas ideas dados las
restricciones de tiempo y recursos que tenemos siendo tres estudiantes en el equipo de
desarrollo.
4. Implementación del diseño acordado En esta sección describimos con mayor detalle el proceso de desarrollo. Cada párrafo
incluye una descripción detallada relevante a la sección en que se encuentre y al final se
firma dependiendo de quién haya hecho lo descrito en el párrafo; si fue Andrés Losada
(A.L.), Pablo Suárez (P.S.), o Daniel Pardo (D.P.). Cada uno de los elementos en esta
sección fue planeado, diseñado, y discutido en grupo. Posteriormente, semana a semana, al
momento de decidir en las tareas de la semana se fueron asignando estas implementaciones
dependiendo del tiempo del que cada uno disponía y las fortalezas y debilidades personales
y cómo estas se ajustan mejor a las tareas pendientes. Empezamos creando un tablero en
Trello donde organizamos las tareas para poder tener un mejor flujo de trabajo. Después de
esto empezamos la creación de la base del proyecto y luego la subimos a GitHub para poder
trabajar colaborativamente.
Arquitectura del juego
El acercamiento que tomamos para crear la arquitectura del juego se basó en el
seguimiento de los principios S.O.L.I.D. y de un enfoque modular a la hora de crear la
arquitectura del proyecto, logrando un proyecto limpio y extensible. El principio de Single
Responsability se cumplió asegurándose de que cada clase cumpliera una funcionalidad
única, como la clase de movimiento de jugador, la de disparo, la de explosión, etc. El
principio Open-Closed se implementó mediante el uso de un buen diseño de código que
permita la extensión a través de una lista de variables que puede ser modificada a través del
inspector de Unity. El principio de sustitución de Liskov, el principio de Interface
segregación y el principio de inversión de dependencia fue arreglado con la implementación
de interfaces, como lo observaremos más adelante con el uso de las armas. (D.P.)
Carga de niveles y variables globales
La base del proyecto tenía la escena de pre-load, desde la cual implementamos los
diferentes managers del proyecto. El GameStateManager se encarga de tener aquellas
variables que valía la pena preservar durante todo el juego (e.g. el nivel actual de historia, el
modo del juego (edición o juego), la vida del jugador). Por otro lado, se tenía un
WorldBuilderManager el cual consistía en un manejador de carga de niveles del creador de
mundos que terminó siendo usado como manejador de guardado y cargado de todos los
niveles, incluyendo los de historia y online. También contamos con un manejador de audio,
que contiene la lógica para poder reproducir música o sonidos, o parar la reproducción de
estas. (D.P.)
WorldBuilder
Continuamos implementando el movimiento básico del jugador con un script que
controlaba la velocidad de este al oprimir el axis horizontal de Unity. Decidimos optar por
esta opción ya que nos da mayor precisión y control para los saltos. Después de esto,
implementamos una de las funcionalidades más grandes del juego, el creador de mundos.
Para esta implementación primero empezamos con la selección de los bloques a través de
botones y luego implementamos la visualización de este bloque seleccionado en la posición
del puntero (canvas), pero proyectándolo en el mundo para poder después instanciar este
bloque correctamente. Una vez completado lo anterior procedimos a instanciar el objeto
cuando el jugador hiciera clic derecho y a destruirlo una vez hiciera clic derecho. A
continuación, implementamos la funcionalidad de guardado y cargado de niveles. El
guardado se realizó a través de la serialización de la posición de los bloques actuales y que
tipo de bloque era. Para el cargado de niveles, en el WorldBuilderManager encontrado en la
escena de pre-load se tuvo una lista con los prefabs de los bloques ordenados por tipo. A la
hora de cargar el script instanciaba con la posición y tipo, los diferentes bloques
anteriormente serializados. (D.P.)
Interfaces de armas
Para que el sistema de armas pudiera escalar y ser modificado sencillamente, hicimos
uso de interfaces. Cada arma tenía dos interfaces, una de Shoot y una de Explode. Estas
interfaces, eran usadas por un script general de Gun que las llamaba sin importar el tipo de
arma. Las interfaces definían respectivamente su contrato de disparar y explotar, en forma
de un método con ciertos parámetros. Luego en el script de cada armar, ex:C4, se
implementaba la lógica de disparar y explotar especifica de cada arma. Con esta
implementación fue muy sencillo añadir todas las armas necesarias e implementar la lógica
de cada una sin tener que preocuparse por asegurar que cada arma usara los mismos botones
para disparar y la misma lógica para activar la explosión. (D.P.)
Inicio y fin de nivel
La bandera de inicio de nivel se creó para el WorldBuilder, pues se necesitaba un lugar
en el cual el jugador inicie. El script de esta es sencillo, pues sólo trae al jugador a su
posición y se autodestruye. Por otro lado, el Script de la bandera de fin de nivel es más
complicado, pues tiene dos modalidades y los datos para enviar información a los
leaderboards de manera correcta. Si se está en modo historia nada más cambia la variable
del nivel actual y actualiza la escena. Si está en modo online regresa al menú de título.
(A.L.)
Menú de muerte y menú de pausa
En el menú de pausa agregué una forma rápida de acceder al tutorial al hacer clic a un
botón de interrogación amarillo. El botón instancia el GameObject del Tutorial que se
encuentra en el Canvas, sobreponiéndolo, sobre todo. (A.L.)
Animaciones
Animé la explosión, descargándola como un asset gratuito de la Unity Store y
modificando su tamaño y la velocidad. También, creé animaciones de destrucción para los
tiles destruibles, añadiendo un delay en su destrucción para facilitar la implementación de
mecánicas en el desarrollo de niveles. Luego, los tiles deslizables tienen una pequeña
generación de partículas. Mi intención sería hacerlas parecer nieve, que tengan este toque
frío/deslizante. (A.L.)
También, animé las acciones del jugador (e.g. caminar, hacerse daño) y también los
“fantasmas” del jugador en el nivel del tutorial que enseñan las mecánicas principales y los
controles. Las animaciones del jugador en sí fueron sencillas dado que los assets que
usamos ya venían con los sprites listos para usar, por lo que sólo fue necesario crear la
animación que utilizara dichos sprites en secuencia y cuadrar la máquina de estados para
pasar de un estado de quietud a uno caminando y a uno de daño desde cualquier estado.
Adicionalmente, programé la animación del daño para que el jugador no reciba daño
durante esta y así evitar que el jugador reciba daño de múltiples fuentes al mismo tiempo en
un periodo corto de tiempo. Por otra parte, las animaciones del tutorial se hicieron
prácticamente desde ceros. Estas animaciones se crearon aprovechando los sprites antes
descargados y cuadrando los keyframes de la animación a mano asegurando tiempo
suficiente para que el jugador entienda qué debe hacer, pero no demasiado tiempo para
evitar que la instrucción se vuelva tediosa. Además, el objeto dueño de cada animación
tiene su propio collider el cual, al detectar una colisión con el jugador, activa el objeto para
que sea visible (y lo desactiva cuando el jugador sale del collider). Así, las animaciones
sólo se activan cuando el jugador se encuentra cerca y evitamos cargar la vista con más
información de la necesaria. (P.S.)
Tiles
Hice las tiles deslizables y destruibles. Las deslizables solamente tienen el particle
system especial y el material NoFriction. Las destruibles tienen un script llamado
“Breakable Tile” y un layer especial llamado Destructible. El Script funciona para activar la
animación de la explosión y para detonar la explosión de otros tiles destruibles que se
encuentren en el radio de la explosión. (A.L.)
El desarrollo de las púas fue un reto interesante dado que fue necesario idear un
mecanismo para evitar que el jugador reciba daño una vez al entrar en contacto en vez de
todo el tiempo que esté tocando el collider del tile. La solución fue, primero, al entrar en
contacto con las púas el jugador recibe el daño adecuado y “rebota” fuera del alcance de las
púas a una altura considerable para que pueda recuperarse fácilmente. Además, se programó
al GameObject del jugador para que sea invulnerable al daño durante un tiempo corto luego
de recibir daño. De esta forma, se evita que el jugador sea abrumado con el poco t iempo
que tiene para evitar más daño y se corrigió un problema donde el jugador recibía el doble
de daño si colisionaba con varias púas al tiempo. (P.S.)
Armas
Se implementaron el fast y slow rocket al copiar la manera como se había implementado
el C4 y las bombas. Esto significa que tendrían un Script genérico llamado Shoot y uno
llamado Explosion. A estos se les asignó un collider personalizado para que colisionaran
con la forma del sprite, no con un círculo ni con un rectángulo generado por código sino
con un collider desde en Unity. La lógica detrás de ambos cohetes es similar, pues lo único
que cambia es la velocidad del cohete, el rango de la explosión y su poder. (A.L.)
Firebase (niveles y usuarios)
En cuanto al manejo de la base de datos, todo comenzó al tener la necesidad de guardar
los niveles del juego en un lugar que pudiera ser accedido por la build de WebGL. Como
habíamos explicado anteriormente, los juegos en WebGL no tienen una carpeta para
guardar archivos de persistencia, como si se encuentra en el caso de pc o celular. Es por
esto que decidimos guardar los niveles en una base de datos para poder acceder a esta desde
el juego. La base de datos escogida fue Firebase y utilizamos su servicio de real-time
database para poder hacer llamados HTTP (GET, POST, DELETE) al link directo que
terminaba en .json. Una vez creada la base de datos con el correo de Boom Away,
procedimos a implementar los métodos necesarios en el juego para guardar y cargar los
datos. Los métodos hacían uso de la librería UnityEngine.Networking para hacer llamados a
la URL de Firebase. También usamos el plugin de JSONNode para poder transformar el
string que recibíamos del llamado HTTP en un objeto al cual le podíamos pasar una llave y
nos devolvía el elemento que necesitábamos. Así llamamos el método atreves de una
corrutina para que el juego pudiera darle un tiempo a la petición para que respondiera. La
estructura de Firebase para cada a nivel se divide en las siguientes variables: LevelName
(Nombre de nivel), SAVE (Tiles que contenía el nivel, serializadas), STATE (Numero de
explosivos que contaba el jugador al inicio del nivel), Thumbnail (Screenshot tomado a la
hora de guardar el nivel), UpVotes y DownVotes (Votaciones del nivel), User (Usuario que
subió el nivel), comentarios, Leaderboard (lista de scores del nivel). Mas adelante
explicaremos cada una de estas variables en más detalle. (D.P.)
En cuanto usuarios, hicimos uso de esos métodos anteriormente para registrar y dar
acceso a todos los usuarios. El registro tiene una serie de restricciones, manejadas por el
juego, como por ejemplo que el nombre y contraseña no estén vacíos o que no sea un
usuario ya registrado. Una vez se cumplen estos parámetros, la clave es pasada por un
BinaryFormatter y luego se manda el usuario y la contraseña a la base de datos. En cuanto
al login, se hace una verificación con la base de datos, primero verificando si el nombre
existe y si existe deserializa la contraseña y la compara con el input del usuario, si todo
coincide se le da acceso al creador de mundos y a los niveles online. Un aspecto que cabe
resaltar es el hecho de que este nombre de usuario es usado en el creador de mundo para
que el jugador solo pueda ver, editar y subir los mundos que él ha creado. También es usado
en el online para establecer puntajes altos en los niveles online. (D.P.)
Al realizar este proceso de conexión con la base de datos nos surgieron dudas acerca de
la seguridad de este. Al estar la URL de Firebase abierta a cualquier modificación, se nos
hizo bastante inseguro dejarla así. Es por esto que, como primera medida, configuramos las
rules de Firebase para que cualquier cliente lo pudiera leer, pero solo los clientes
autenticados pudieran modificarlos. Luego para poder autenticar estos clientes, decidimos
no hacer uso de herramientas como Google OAuth, debido a que queríamos que el login de
nuestro juego fuera manejado únicamente por nosotros y no por acceso a una cuenta de
Google. La solución por la que nos decantamos fue la creación de una API con node.js a
través de la cual en este api se tiene la API key de la cuenta de Boom Away que tiene la
base de datos de Firebase. Con este API key la API de Node.js manda una petición POST al
identitytoolkit de Google, el cual devuelve un token con el cual se pueden hacer las
peticiones que el juego requiere a nuestra base de datos. (D.P.)
Tutorial
El primer nivel/sección/área, en cualquier videojuego, es clave en muchos aspectos para
el éxito del videojuego. Si este no deja claros los objetivos del videojuego y las
herramientas de las que dispone el jugador para lograr dicho objetivo, el resto del
videojuego podría terminar siendo confuso y frustrante. Además del contenido del tutorial,
la forma como se presenta también es importante. Por ejemplo, escribir un párrafo que se
muestra al principio del nivel con una descripción detallada del videojuego, los objetivos, y
las mecánicas resulta altamente informativo, pero igualmente aburrido. Con esto en mente,
se tomó la decisión de diseñar un tutorial estructurado de forma que el jugador vea cómo se
juega e inmediatamente ponga en práctica lo que vio. El primer obstáculo del juego se creó
pensando en la figura 3.1; un obstáculo sencillo que le permita al jugador entender a qué se
va a enfrentar momento a momento durante el juego y cuál es la herramienta más básica
que tiene a su disposición para superar dicho reto: debe navegar entre plataformas usando
explosivos para impulsarse hacia donde desea. La forma para transmitirle al jugador esta
información fue por medio de animaciones indicando la secuencia de acciones que debe
tomar para obtener el resultado esperado. La siguiente sección se estructuró de manera
similar, pero se introdujo un elemento adicional: desplazamiento vertical por fuera del
rango de un solo explosivo. De nuevo, se usó la misma estrategia para dar a entender cómo
navegar el obstáculo: mostrar una animación detallando la secuencia de acciones que
permitirán al jugador superar el obstáculo, y permitir al jugador abordar el reto de
inmediato. Por último, la sección final fue más informativa que retadora. La animación se
usó para explicar que existen dos tipos de cohetes: uno de baja velocidad y alta potencia, y
otro de alta velocidad y baja potencia. Luego de esta animación se encuentra el final del
nivel custodiado por un tipo de tile distinto a los del resto del nivel: tiles destruibles. El
nivel del tutorial se desplegó, de esta forma, en el MVP. Sin embargo, la encuesta que
acompañó este MVP mostró que varios jugadores tuvieron problemas entendiendo el
objetivo del juego y la mecánica central; es decir, el tutorial no fue lo suficientemente claro
sobre esta información. Por lo tanto, se decidió incluir un diagrama de instrucciones con la
información esencial para entender el juego en su nivel más básico. Este diagrama aparece
al principio del nivel del tutorial y el jugador puede volver a consultarlo en cualquier
momento desde el menú de pausa en el botón de ayuda. (P.S.)
Puntaje
Cada nivel tiene un contador del puntaje que se va disminuyendo en 1 por segundo. El
contador inicia en 1000 y se actualiza en la función Update. Estos puntajes son
almacenados en cada nivel con el usuario del jugador cuando este termina el nivel. Los
puntajes funcionan de la misma manera en el modo online y offline, por lo que están
almacenados como una variable en el GameStateManager. (A.L.)
Leaderboards
Se implementó un botón en cada uno de los niveles del modo historia y en los niveles
online que tiene un ícono de trofeo dorado. Al hacer clic a este ícono se descarga la lista de
los scores de cada nivel, esta lista se ordena con el score y se despliega. Para acceder al
nivel al que se le está haciendo clic se almacena como una variable dentro del botón cuando
se crea la lista de niveles online, o esta variable se cambia de manera arbitraria y forzada en
Unity. Los niveles son almacenados con el usuario actual, entonces este aparece en la lista
de scores de cada nivel. Si el usuario no se registró, el usuario default es Anonymous.
(A.L.)
Cofres
Los cofres varían en el tipo de munición que otorgan a la hora de ser obtenidos. Esta
munición se determina a la hora de crear el nivel. Para implementar este sistema se decidió
tener una variable global de qué identifica el tipo de munición se pone en el cofre. Esta
variable global cambia cuando se cambia el tipo de cofre en el creador de mundo. Al
instanciar el cofre, se le asigna como numero de Tile en el manejador de mundo de la
escena de pre-load uno de los 4 prefabs de cofres que existen, uno por cada munición.
Entonces a la hora de cargar el nivel, se cargan los diferentes cofres, cada uno con su
munición. (D.P.)
Comentarios
Cada uno de los niveles que se suben online tiene también una lista de comentarios sobre
el nivel, estos se envían de manera anónima y se despliegan como una lista vertical. Los
comentarios se pueden acceder mediante un botón en cada uno de los niveles online. Al
acceder, se ve la lista antes mencionada y se pueden crear nuevos comentarios. Como dije,
los comentarios son creados de manera anónima y son “posteados” directamente a la
sección de comentarios del nivel. (A.L.)
Sprints, tareas, y horas de trabajo
Sprint 1: Diseño e investigación preliminar
En este Sprint, se determinó cuales ideas teníamos para el juego y escogimos la más apropiada. Para escoger una idea se tuvo que hacer un documento de diseño general e
incluir la implementación de una nueva mecánica experimental. Esto sucedió en la primera
semana. En la segunda, ya habíamos escogido una idea y nos dedicamos a definir todo sobre el juego: mecánicas, estilo, niveles tentativos, features. Dentro de las features se
decidió tener un level builder para facilitar la creación de niveles.
Proceso (en horas de trabajo restante para completar las tareas propuestas)
Implementamos este modelo para seguir nuestro avance en horas diarios según la
sugerencia de Pablo Figueroa. El trabajo en horas para este Sprint se hizo de manera coherente a la proyectada.
Sprint 2: Prototipado del Level Builder
Este Sprint se dedicó a la implementación de las mecánicas fundamentales del juego:
lanzamisiles, los tiles y el WorldBuilder. La primera semana fue dedicada a hacer los diferentes explosivos del jugador y su lanzamisiles. La segunda, tuvo un diseño de niveles
tentativos y la creación de los diferentes tiles que servirían para crear niveles: tile
destruible, deslizable, púas, fuego y la bola de demolición. También se puso la cámara sobre el jugador. En la tercera semana se crearon varios niveles de prueba, la bandera para
cambiar la posición del jugador en el WorldBuilder, el menú de pausa y el selector de
niveles de historia.
Proceso (en horas de trabajo restante para completar las tareas propuestas)
Se trabajaron menos horas de las proyectadas para cumplir los objetivos de este Sprint.
Sprint 3: Desarrollo Completo del MVP
En este Sprint se trabajó para que el juego estuviera listo para ser probado por jugadores. En la primera semana se implementaron las variables de analítica. Puesto que no pudimos
implementar el dashboard de analíticas de Unity, en este momento las variables deberían
estar conectadas a este. Además, se arreglaron bugs que identificamos en la transición entre sprints.
En la segunda semana se hicieron todas las animaciones: la explosión, el movimiento del
jugador y los diferentes tiles. También se hicieron los efectos de sonido, la música y 6 niveles de prueba, 3 de dificultad alta y 3 de dificultad media.
En la tercera semana se acabó de pulir las animaciones, la analítica, el build, el feature de muerte del jugador, la subida de niveles a Firebase (puesto que vamos a hacer el build en
WebGL para itch.io), una encuesta de satisfacción, mejora de los controles y el botón de
instrucción en el menú de pausa. Esta semana tuvo la mayor cantidad de entregas individuales, pero esto se debe a que todas requerían una cantidad baja de tiempo en su
desarrollo e incluyó el testeo con usuarios desconocidos para poder arreglar los bugs
encontrados en el juego.
Proceso (en horas de trabajo restante para completar las tareas propuestas)
En esta semana llegamos a valores negativos al subestimar la cantidad de horas que
teníamos que dedicar para cumplir ciertas tareas.
Sprint 4: Pruebas con usuarios
Este Sprint se centró en recibir feedback de usuarios que prueben el juego y en seguir
desarrollando features. La primera semana se diseñó la música del title screen, el puntaje en cada nivel, el timer de la granada, los cofres, y se procesaron los datos que obtuvimos de
Firebase. La segunda semana se dedicó a crear el login de los usuarios, un inicio del
leaderboard (guardar los puntajes en Firebase por usuario por nivel), hacer la animación del daño y crear los comentarios en los niveles. La tercera semana se usó para terminar el
leaderboard, arreglar las analíticas que no se envían porque el usuario se sale del navegador,
crear más niveles, arreglar los comentarios y el registro de usuario, implementar la seguridad de la base de datos (que no se pueda acceder a esta sin un token) y tener una
screenshot en la lista de niveles creados por los usuarios.
Proceso (en horas de trabajo restante para completar las tareas propuestas)
En este Sprint también subestimamos el tiempo que íbamos a dedicar en el desarrollo, esto se vio en el constante arreglo de bugs detectados por los usuarios y dificultades con la
conexión de Firebase.
5. Validación
Firebase
Los métodos de validación que usamos fueron el uso de analíticas a través de una
solución propia en Firebase. Usando los llamados HTTP anteriormente nombrados en la
sección de implementación, creamos una sección llamada Analytics, donde se subirían las
analíticas del juego. En esta sección implementamos: las muertes por sesión, el ultimo
nivel antes de salir del juego, la frecuencia de visita de cada nivel, el número de intentos
de cada nivel antes de pasarlo o salirse, el tiempo que se demora cada nivel, las veces que
han sido usada cada arma y las veces que se ha usado el creador de mundos. En el juego
cada vez que ocurría uno de estos sucesos, en el código se mandaba una petición POST o
PUT, para actualizar estas analíticas.
Encuestas
Adjunto a la página de despliegue del juego se incluyó una encuesta relativamente
corta sobre la experiencia de los jugadores. Esta encuesta consistió en total de 22
preguntas divididas entre tres secciones. La primera sección se enfocó en estadísticas
demográficas de los jugadores: género con el que se identifican, rango de edad, hábitos de
juego, experiencia previa y gustos en videojuegos, ocupación, entre otros. La siguiente
sección se centró en la experiencia de juego como tal; todo lo relacionado a los controles,
el objetivo del juego, la claridad que se tuvo para entender estos elementos, la facilidad o
dificultad de los niveles propuestos. Por último, la tercera sección trató sobre la
herramienta de creación de niveles: qué tan fácil (o difícil fue de usar), si fue divertido
usarla, o si el jugador la usó en sí.
6. Resultados de la Evaluación con Usuarios
Visualización de analíticas
Para visualizar de mejor manera la información obtenida a través de las analíticas de
Firebase se hizo un Jupyter notebook que la permite visualizar con Python y, en
específico, la librería MatPlotLib. Al visualizar toda la información nos dimos cuenta de
que obtuvimos dos analíticas útiles, con resultados analizables que permitieron iterar sobre
el diseño de niveles con el fin de mejorar la experiencia de nuestros jugadores.
Reinicios por Nivel
Estos resultados nos muestran que en el
nivel 5 y 2 los usuarios tienden a hacer más
reinicios. Sobre el dos podemos entender
que esto se debe a que es el primer nivel en
que el jugador se enfrenta al juego sin
tutorial, lo cual lo haría todavía un jugador
inexperto y por lo tanto obligado a probar y
reintentar. En el nivel 5, parece que los
usuarios tienden a morir bastante o a
quedarse sin municiones para superarlo,
esto sucede a que este es uno de los niveles
más complicados.
Tiempo de juego por nivel
En esta gráfica vemos que el jugador
tiende a demorarse lo mismo en todos los
niveles excepto el primero y el segundo.
Creemos que esto sucede porque los
usuarios con más o menos experiencia en
este tipo de juegos tienden a demorarse
mucho más que en el resto de los niveles.
Parece que hay muchos usuarios que se
demoran bastante en avanzar del segundo
nivel, mostrando tal vez que hay un
problema de comprensión de los usuarios
frente a las mecánicas y a los objetivos
del juego.
El resto de la información se volvió inútil pues no se enviaba en los momentos
esperados en el caso de cada usuario. Esto es debido a que se esperaba enviar la
información al cerrar la aplicación, pero al estar en Web no se envía a tiempo o se envía de
manera errónea.
Resultado encuestas
Respecto a la primera sección (demografía) encontramos que casi todas las respuestas
de nuestros jugadores fueron aportadas por hombres cisgénero, a excepción de dos
respuestas que fueron aportadas por una mujer transgénero y por una persona no binaria.
Estos jugadores presentan una distribución de edad entre los 15 y los 24 años con una
moda entre los 20 y los 24 años (a excepción de una persona cuya edad se encuentra entre
los 45 y 49 años). La gran mayoría de estas personas estudia (el 70.6%) y el resto estudian
y trabajan al tiempo. Llama la atención que la mayoría de nuestros jugadores se identifican
como “gamers” (i.e. personas que juega videojuegos, por lo general con alta frecuencia y
por largos periodos de tiempo); el 76.4% de los que respondieron se consideran “gamers”,
donde el 41.2% considera que juega con una frecuencia mayor a la que consideran normal,
el 17.6% considera que juega con una frecuencia que consideran normal, y el otro 17.6%
considera que juega con una frecuencia baja relativa a una frecuencia que consideran
normal (figura 6.1). Con respecto a los dispositivos que nuestros jugadores usan para jugar
videojuegos, encontramos que los tres dispositivos más comunes fueron dispositivos
móviles, navegadores web, y computadores de escritorio (figura 6.2). Con esto,
demostramos que fue una buena decisión de diseño distribuir nuestro juego para que sea
jugable directamente en el navegador web.
Figura 6.1 Percepción de los jugadores frente a sus hábitos de juego
Figura 6.2 Plataformas más usadas por nuestros jugadores
Además, sobre la segunda sección (experiencia de juego) encontramos respuestas que
motivaron varios cambios sobre el diseño e implementación. Primero, vimos que en
general el juego gustó entre nuestros jugadores; el 94.1% de los jugadores estuvieron de
acuerdo en que el juego es divertido e interesante (figura 6.3). Luego, encontramos
información medianamente contradictoria: varios jugadores se sintieron confundidos
respecto a los controles, objetivos, y mecánicas del juego aún después de haber jugado el
tutorial y leer las instrucciones del menú de pausa (figura 6.4). Resulta extraño que a casi
todos los jugadores les haya parecido divertido e interesante nuestro juego, pero que en los
primeros momentos siguieran sintiendo confusión respecto a qué hacer. Esta aparente
contradicción se puede explicar si en vez de preguntarnos “¿cómo el juego pudo haber
gustado luego de que el tutorial y las instrucciones fallaran en su objetivo?” más bien
entendemos que el juego gustó e interesó a nuestros jugadores aún a pesar de estas
falencias. No obstante, los resultados de estas preguntas apuntan a un problema clave:
confusión en cuanto a cómo jugar el juego en varios de nuestros jugadores, y esto a su vez
explica las respuestas divididas que recibimos en las preguntas de la figura 6.5 respecto a
la dificultad y claridad de los niveles. Por último, los comentarios que nuestros jugadores
dejaron respecto a los niveles (figura 6.6), las mecánicas (figura 6.7), y otros comentarios
(figura 6.8) nos permitieron entender mejor qué esperan nuestros jugadores, qué les
gustaría ver, qué bugs encontraron en el juego que nosotros no vimos, y, en general, los
pasos que debíamos tomar para mejorar nuestro juego.
Figura 6.3 Opinión respecto al interés y diversión de los jugadores en Boom Away
Figura 6.4 Opinión respecto a la claridad del juego y la efectividad del tutorial y las instrucciones como
métodos informativos
Figura 6.5 Respuestas respecto a la dificultad y claridad de los niveles propuestos
7. Conclusiones
En el transcurso de este semestre, el desarrollo de nuestro juego terminó en algo más grande de
lo que habíamos planeado. Con todas las funcionalidades que implementamos, aprendimos diferentes
aspectos acerca de la creación de videojuegos: desde una buena arquitectura hasta un sistema online robusto. Sin embargo, algunas ideas que teníamos para el juego no se pudieron realizar debido al
tiempo. Una de ellas fue la creación de coleccionables que tendrían la utilidad de ser canjeados en
una tienda del juego para obtener skins de las armas y de los personajes. Otra funcionalidad que no pudimos realizar fue la implementación de un arma gancho, con el cual el jugador se pudiera
balancear para llegar a otras zonas. No obstante, sentimos que esta mecánica no encajaría bien con la
temática del juego. A pesar de lo anterior, el juego se siente completo dado a su cantidad de niveles, tanto en el modo historia como en el online, junto con la posibilidad de crear más en cualquier
momento con su creador de mundos online. También, sus mecánicas se sienten satisfactorias en
cuanto al sonido, animación y experiencia de usuario. En general el juego fue una experiencia de
aprendizaje única y un proyecto del cual estamos orgullosos.
8. Referencias
1. Brown, M. (2017). YouTube. “The Secret of Mario’s Jump (and other Versatile Verbs) |
Game Maker’s Toolkit”. Recuperado de https://youtu.be/7daTGyVZ60I 2. Brown, M. (2018). YouTube. “The Best Games from GMTK Game Jam 2018”. Recuperado
de https://youtu.be/s2ebZXQ_J8Q 3. Brown, M. (2019). YouTube. “Why Does Celeste Feel So Good to Play? | Game Maker’s
Toolkit”. Recuperado de https://youtu.be/yorTG9at90g 4. Duffy, J. (2008). Gamasutra. “GCG Readers Design Jumpless Platformers”. Recuperado de
https://www.gamasutra.com/view/news/111737/GCG_Readers_Design_Jumpless_Platformers.php
5. GDC. (2019). YouTube. “The 2019 Experimental Gameplay Workshop”. Recuperado de
https://youtu.be/RNA-Eak_aso 6. Unity. (2017). YouTube. “Unite Austin 2017 - S.O.L.I.D. Unity”. Recuperado de
https://youtu.be/eIf3-aDTOOA