En este capítulo se realizará el diseño del catálogo de componentes que se van a desarrollar. Antes de empezar a diseñar este catálogo de componentes primero hay que entender la utilidad que debería tener. Para ello, en primer lugar se explorará de dónde surge la idea de hacer un catálogo de comportamientos de enemigos, se explicará qué tipos de atributos se van a diseñar y, finalmente, se justificará que este catálogo es una herramienta para diseñar enemigos de videojuegos 2D, construyendo enemigos del videojuego Cave Story de forma conceptual utilizando los comportamientos descritos.
3.1 Trabajo previo sobre comportamientos de NPCs.
La idea principal de este catálogo de componentes es contar con una herramienta sencilla y accesible, que cuente con un amplio catálogo de componentes para el motor de videojuegos Unity. Como se ha tratado al final del Capítulo 2, Unity puede resultar más abrumador de aprender a utilizar por desarrolladores noveles, que pueden preferir otros motores más sencillos de utilizar como Construct 3 o Game Maker. Esta herramienta apela precisamente a acercar Unity a cualquier persona que quiera crear un videojuego en 2D, para que cualquier persona pueda construir enemigos para sus videojuegos con este catálogo de componentes. De la misma manera, los desarrolladores más expertos pueden utilizar el catálogo de base para construir inteligencia artificial más compleja al combinar los componentes en árboles de comportamiento.
La inspiración principal de hacer este catálogo sencillo de componentes surge de un interesante artículo publicado en la página Gamasutra, y escrito por Bright (2014). En su artículo se recoge una lista de atributos que son muy comunes en los juegos retro, títulos clásicos de las consolas de los años ochenta, que van desde patrones de movimiento a las distintas habilidades de ataque que tenían los enemigos de la época.
Su análisis en el campo ha resultado muy esclarecedor a la hora de entender qué se debería esperar de un componente tan pequeño, lo que haría cada componente así como posibles combinaciones que se podrían hacer. Como se ve en la Figura 3.1, la lista de movimientos que propone Bright (2014) consiste en un nombre explicativo, una breve descripción que permita visualizar el movimiento acompañado con un ejemplo de un juego popular. En su artículo no sólo analiza comportamientos de movimiento sino que también explora las habilidades y formas de ataque que podrían tener los enemigos.
Figura 3.1: Artículo de Bright (2014), Atributos de movimiento
Además de las listas de comportamientos de movimiento y de ataque, Bright (2014) propone una serie de atributos de distinta naturaleza que son los Trigger Attributes, que se pueden definir como atributos de tipo sensor y que se recogen en la Figura 3.2. El autor los define como “eventos y estados de juego que se puedan dar, que pueden cambiar el comportamiento de un enemigo así como sus atributos en ejecución“. Esto quiere decir que un enemigo que posea un sensor sabrá detectar variaciones en su entorno y actuar en consecuencia. Gracias a estos eventos el enemigo es capaz de modificar su estado, por lo que su comportamiento se podría definir con una FSM, que se comentó en el Capítulo 2.
3.2 Análisis de los NPCs de Cave Story.
El primer paso a la hora de disenar esta herramienta fue realizar un estudio de los enemigos de Cave Story, jugando al videojuego para enfrentar a los enemigos y así estudiarlos, tratando de entender sus movimientos y definirlos en función de uno o varios atributos de movimiento que aparecen en la lista de Bright (2014) de la Figura 3.1.
Figura 3.2: Artículo de Bright (2014), Atributos de tipo sensor
Cave Story, la historia de la cueva, en español, es un videojuego de aventuras 2D desarrollado por un sólo desarrollador, el japonés Daisuke Amaya, conocido con el apodo de “Pixel“. El juego original fue publicado de forma totalmente gratuita, algo sorprendente teniendo en cuenta la inusual cantidad de contenido que aporta, y está disponible en la página web oficial o en su página tributo más popular donde además hay traducciones del juego hechas por la comunidad. Es considerado uno de los mejores juegos indie por su magistral diseño, historia, e impacto en la industria de los videojuegos. A pesar de ser un juego desarrollado por una sola persona cuenta con una variedad muy notable de enemigos, cada uno de ellos con comportamientos únicos o combinaciones de comportamientos sencillos.
Un aspecto fundamental de los enemigos en los videojuegos 2D es que su movimiento debe ser sencillo de entender, aportando información en un vistazo acerca de cómo puede atacar dicho enemigo. Xu (2016) explora en su artículo el complejo diseño del juego, mencionando que “ cuantos más enemigos encuentres, más fácil resultará derrotarlos“; además de que “ algunos enemigos tienen pistas visuales para ayudarte“. Por ejemplo, la rana de la Figura 3.3 se puede intuir que saltará por el aspecto visual que tiene, dando pistas de cómo se va a mover. Estas pequeñas pistas visuales son lo que permite al jugador tener una idea de cómo derrotar a cada enemigo.
3.2.1 Enemigo Rana.
Los enemigos de Cave Story son enemigos sencillos en apariencia, pero con mucha diversidad de comportamientos, formas de moverse y de atacar al jugador. Algunos enemigos, como la rana[3] que se ve en la imagen 3.3, avanza hacia el jugador dando saltos cada cierto tiempo. Gráficamente, tiene sentido su movimiento ya que hay una coherencia entre su aspecto visual y su comportamiento. A pesar de su simplicidad, ese movimiento no es trivial: es una combinación de un movimiento hacia arriba con un movimiento lateral hacia la posición del jugador, por lo que además de moverse tiene que conocer dónde se encuentra el jugador en el momento de efectuar el salto. Según los componentes de movimiento de la Figura 3.1, el movimiento de este enemigo se podría construir como un Jumper si se considera que, según la descripción que nos propone Bright (2014) pueden saltar en línea recta o hacia delante en una dirección. Este enemigo, además, tiene una condición de activación que se corresponde con uno de los atributos sensor que aparecen en la Figura 3.2, concretamente con el sensor de “proximidad con el jugador u otro objeto“ porque la rana no salta hacia el jugador a no ser que el jugador esté cerca.
Figura 3.3: Enemigo Rana en Cave Story
3.2.2 Enemigo murciélago.
En la Figura 3.4 se puede ver un enemigo sencillo, un tipo de murciélago 4 que aparece en el primer nivel del videojuego Cave Story. Este enemigo vuela moviéndose verticalmente entre dos puntos fijos: el punto más alto del movimiento y el punto más bajo. Este enemigo se detiene un breve lapso de tiempo en los extremos, y debido a que es un enemigo de los primeros niveles no se mueve de forma brusca, ni ataca de forma activa al jugador.
Para construir este comportamiento con los atributos de la Figura 3.1, se utilizaría el comportamiento Waver porque el movimiento de este personaje describe un movimiento sinusoidal vertical. Este enemigo no cuenta con una condición de activación, sino que se moverán aunque el jugador no se encuentre inmediatamente al lado de los murciélagos.
No obstante, no todos los enemigos de tipo murciélago son tan sencillos. A medida que el jugador avanza en el videojuego se encontrará con ciertos tipos de enemigos que, aunque visualmente sean parecidos tienen movimientos más complejos e incluso incorporan formas de atacar de forma activa al jugador. Un ejemplo de ello son los murciélagos que se encuentran en la imagen 3.3, ocultos debajo de la rana. Estos murciélagos se diferencian por el color, ligeramente más oscuro que los de la Figura 3.4, y que en lugar de flotar permanecen quietos hasta que detectan que el jugador ha pasado por debajo de ellos. Cuando eso sucede, abandonan su posición tras un breve retardo, y se lanzan en picado para atacar al jugador. En la Figura 3.5, se puede apreciar al murciélago precipitarse hacia el jugador porque este está situado justo debajo. Al igual que la rana, estos enemigos dependen de información del entorno para poder llevar a cabo su funcionalidad completa, es necesario que cuenten
Figura 3.4: Enemigo Murciélago en Cave Story
con un elemento sensorial que responda a la pregunta «¿El jugador ha pasado por debajo de mi posición?». Este enemigo se construiría mediante un comportamiento de tipo Faller, acorde a la lista de la Figura 3.1, porque cae desde el techo al suelo pero tiene la condición de sensor de “línea directa de visión con el enemigo“, que aparece en la Figura 3.2.
Figura 3.5: Enemigos Murciélago y Critter en Cave Story
3.2.3 Critter.
Además de los murciélagos negros, se puede ver otro tipo de enemigo en la Figura 3.5 que se asemeja a una bola verde que aparece en el aire encima del jugador. Estos enemigos se denominan Critters 5 y, al igual que la rana, avanzan saltando hacia la posición del jugador. No obstante, estos enemigos no caen inmediatamente sino que al llegar a su punto más alto comienzan a “volar“ hacia el jugador manteniéndose unos instantes en el aire antes de caer. Este movimiento sugiere que es una combinación de componentes: por un lado, se requeriría el componente Jumper que ya se ha visto previamente pero por otro lado, se le debería añadir un componente Floater para que flote antes de caer. No obstante, no sería necesario añadir un componente Faller de la lista de la Figura 3.1 ya que la caída tras el salto es una parte intrínseca del componente Jumper que describe Bright (2014) en su artículo. Estos enemigos no saltan todo el rato, sino que cuando detectan que el jugador está cerca se activan y comenzarán a moverse hacia el jugador pero si este se aleja lo suficiente estos enemigos volverán a su estado inactivo.
3.2.4 Behemoth.
Los Behemoth 6 son criaturas parecidas a un elefante que aparecen en la Figura 3.6. Estos enemigos avanzan en línea recta y cambian el sentido cuando se encuentran con una pared u otro obstáculo que les impide seguir avanzando. No son unidades hostiles, y no atacan al jugador a no ser que este les dispare primero, en ese caso cambian de color marfil al rojo y cambia su comportamiento. Cuando este enemigo está enfurecido, en lugar de moverse lateralmente intentará cargar hacia el jugador a mayor velocidad, pero seguirá sin ser capaz de superar obstáculos del entorno.
Figura 3.6: Enemigo Behemoth en Cave Story
Para crear a este enemigo con los atributos de Bright (2014), se puede emplear un comportamiento de tipo Pacer, dado que este comportamiento se describe como un movimiento que cambia de dirección, aunque el ejemplo que se utiliza en la descripción (Figura 3.1) está mas orientado a no caerse de las plataformas. Debido a esa especificación, en lugar de un comportamiento Pacer sería más correcto definirlo como un comportamiento de tipo Ponger. Este enemigo tiene un evento que modifica su comportamiento que no figura en la lista de la Figura 3.2 de Bright (2014) y ese cambio de estado se da cuando la vida de la unidad baja de cierto porcentaje sin ser derrotado. Cuando esto sucede, se modifican los parámetros de los componentes previos para hacerlos más rápidos o hacer que vayan a por un objetivo particular, convirtiendo al enemigo en una amenaza mayor.
3.3 Diseño de Componentes.
Teniendo en cuenta lo que se ha analizado acerca del artículo de Bright (2014), y utilizando su estudio como inspiración, se procede a disenar los componentes de este catálogo enfocado a enemigos 2D y finalmente se construirán enemigos del videojuego Cave Story comentados en las subsecciones anteriores con los componentes diseñados.
Los componentes con los que va a contar este catálogo se podrían agrupar en dos apartados fundamentales: comportamientos de movimiento, que además deberán ser combinables, y atributos sensoriales que puedan activar o desactivar estos componentes de movimiento.
Estos componentes debían ser sencillos, concisos, y diseñados de tal manera que cada uno realice una sola acción. A continuación, se definirán brevemente cada uno de los apartados de este catálogo y se resumirán los componentes diseñados para cada uno de ellos. En las listas que resumen el diseño final se incluirá el nombre del componente además de una breve descripción de lo que se podría esperar de cada uno de los componentes para ayudar a visualizar el comportamiento que aportarán a la entidad. Los componentes de este catálogo se explicarán con más profundidad en el Capítulo 4, detallando cómo han sido implementados para que formen parte del catálogo y listando los atributos que el usuario puede modificar para personalizar el movimiento.
3.3.1 Componentes de Movimiento.
Los componentes de movimiento sirven para darles atributos de movimiento específicos a las entidades que posean el componente. Es recomendable que cada componente de movimiento tenga una serie de atributos de ese comportamiento para personalizarlo. Estos atributos deberán ser sencillamente números y otras opciones asociadas al comportamiento, que sea simple a la par que permita la personalización individual de cada uno de los componentes. Además, estos componentes deberían ser sencillos y se deberían poder combinar para crear comportamientos nuevos. El diseño final de los componentes de movimiento es el siguiente:
- Floater: Flota entre dos puntos, horizontal o verticalmente.
- Faller: Cae en picado hacia abajo
- Jumper: Salta periódicamente hacia arriba en línea recta.
- Bullet: Avanza en línea recta en una dirección.
- Forward Jumper: Salta hacia delante en la dirección del jugador.
- Liner: Avanza hacia un objetivo en línea recta.
- Follower: Persigue a un objetivo.
- Pacer: Avanza por una plataforma sin caerse. Al llegar al borde, cambia de sentido.
- Bumper: Avanza en línea horizontal y, si detecta un obstáculo cambia de sentido.
- Orbit: Orbita alrededor de un punto dado.
- Wander: Se mueve aleatoriamente dentro de un área.
Además de los componentes de movimiento, este catálogo de componentes debería contar con atributos de tipo sensor que reaccionen ante determinados eventos y activen o desactiven los componentes de movimiento para darle profundidad a la herramienta.
3.3.2 Componentes sensoriales.
Los sensores dan al jugador la sensación de que la entidad enemiga está viva y reacciona ante lo que percibe en el mundo. La mayoría de los enemigos modifica su comportamiento cuando el jugador se acerca a menos de una determinada distancia, por lo que integran sensores de proximidad. Lo que se busca es el efecto de que el enemigo se encuentra alerta debido a que considera al jugador como una amenaza, y que supone un comportamiento perfectamente natural. No obstante, un sensor de proximidad también cumple una función de ahorro de recursos, porque es ineficiente tener cosas en movimiento que el jugador no va a poder apreciar.
- Area Sensor: Define un área donde se detectará si ha entrado el jugador.
- Line Sensor: Define la línea de visión del enemigo.
- Range Sensor: Mide la proximidad con el jugador.
Estos componentes de movimiento y sensoriales son los que conforman la herramienta, son los elementos que constituyen este catálogo de componentes con los que es posible crear enemigos para un videojuego 2D. No se puede negar que este trabajo ha tomado como principal inspiración el artículo de Bright (2014) que se comentaba previamente y, por tanto, existen algunas similitudes con las tablas que aparecen en las Figuras 3.1 y 3.2 pero este catálogo también cuenta con comportamientos modificados y algunos de ellos son totalmente nuevos.
3.4 Diseño de NPCs usando este catálogo.
Una vez se han definido los comportamientos que va a tener nuestra herramienta, se va a definir con ella los movimientos de los enemigos descritos en las secciones anteriores, construyéndolos utilizando estos componentes que se han disenado. La rana de la Figura 3.3 se podría definir utilizando los comportamientos descritos como una entidad con comportamiento Forward Jumper. Debido a que, conceptualmente, Jumper sólo salta hacia arriba, sería necesario un movimiento lateral si se quisiera que avance hacia delante. Con este comportamiento, y un sensor de proximidad de tipo Area o Range Sensor se conseguiría que este enemigo salte hacia el jugador pero que sólo lo haga cuando el jugador se acerca demasiado.
Posteriormente se trataba uno de los enemigos iniciales, los murciélagos de la Figura 3.4 Este enemigo se construiría con un comportamiento Floater, para que se mueva verticalmente entre dos puntos. Gracias a la combinación de comportamientos que permite este catálogo, si a ese movimiento constante entre dos puntos se le anadiera un movimiento en un eje, con un comportamiento Bullet, se conseguiría un enemigo que avance de forma sinusoidal en la dirección que se desee, describiendo un movimiento parecido al Waver que propone Bright (2014) (Figura 3.1).
Se mencionaban también a los murciélagos oscuros de la Figura 3.5, que se lanzan a por el jugador al tener “contacto visual“ con el mismo. Este enemigo se construiría con un componente Faller que se active cuando el componente sensorial Line Sensor detecte al jugador en una línea vertical hacia debajo. Por otra parte, el Critter que también aparece en la Figura 3.5, resultaría una mezcla de Forward Jumper combinado con un movimiento
Faller, debido a que el comportamiento Faller es capaz de controlar cuando debe la entidad precipitarse al suelo. Además, es necesario un sensor de proximidad para saber cuándo el jugador está demasiado cerca para empezar el movimiento, simulando el comportamiento del juego original.
Finalmente, se definió el comportamiento del Behemoth, el enemigo con aspecto de elefante de la Figura 3.6. Utilizando los componentes del catálogo que se ha diseñado, se puede definir este comportamiento como un comportamiento de tipo Bumper debido a sus cambios de sentido al colisionar con las paredes. Un enemigo que posea un comportamiento de este tipo no necesita un sensor que le informe del evento de colisión con una pared porque se considera una parte intrínseca del comportamiento y, por tanto, no es responsabilidad del diseñador crear esa particularidad del movimiento mediante sensores sino que se gestionará de forma interna.
En resumen, en los videojuegos 2D resulta casi indispensable tener enemigos, y para que haya enemigos tiene que existir una serie de componentes que les de vida. Además, a medida que avanza el juego es muy recomendable que sean más complejos, por lo que tienen que incluir más comportamientos y combinarlos. Tener enemigos con dificultad progresiva es un obstáculo que hay que afrontar si se quiere hacer un videojuego retro o neo-retro y, como se ha mostrado de forma teórica gracias a este catálogo de movimientos resulta sencillo hacer enemigos funcionales y personalizables para cualquier videojuego 2D de avance lateral.
Diseñar un catálogo de componentes es fundamental para el desarrollo de sistemas, aplicaciones o cualquier proyecto que involucre la combinación de diferentes partes:
- Identificación de Componentes:
- Enumera y nombra cada componente de manera clara y descriptiva. Asegúrate de que los nombres sean intuitivos y reflejen la función principal de cada componente.
- Descripciones Detalladas:
- Proporciona descripciones detalladas para cada componente. Esto incluye su propósito, funcionalidades, y cómo se integra con otros componentes.
- Jerarquía y Relaciones:
- Organiza los componentes en una jerarquía que refleje sus relaciones. Indica claramente qué componentes son dependientes de otros y cuáles son independientes.
- Atributos y Propiedades:
- Especifica los atributos y propiedades clave de cada componente. Esto puede incluir parámetros de configuración, interfaces de programación de aplicaciones (API), y cualquier otra información relevante.
- Compatibilidad y Requisitos:
- Indica los requisitos específicos de cada componente, como versiones de software, sistemas operativos compatibles u otros componentes necesarios para su funcionamiento.
- Estado de Desarrollo:
- Asigna un estado de desarrollo a cada componente. Puede ser «En Desarrollo», «Listo para Producción», «Beta», etc. Esto ayuda a gestionar el progreso y la madurez de cada componente.
- Documentación Adjunta:
- Proporciona enlaces o referencias a documentación más detallada para cada componente. Esto puede incluir manuales de usuario, guías de desarrollo, o cualquier otro recurso relevante.
- Ejemplos de Uso:
- Incluye ejemplos prácticos de cómo se utilizan cada uno de los componentes. Esto ayuda a los desarrolladores a comprender mejor su funcionalidad y aplicación.
- Versionado:
- Establece un sistema de versionado claro para los componentes. Esto facilita la gestión de cambios y actualizaciones a lo largo del tiempo.
- Pruebas y Validación:
- Indica los procedimientos de prueba y validación para cada componente. Esto incluye pruebas unitarias, pruebas de integración, y cualquier otro método utilizado para asegurar la calidad.
- Compatibilidad con Estándares:
- Asegúrate de que cada componente cumple con los estándares y prácticas recomendadas de la industria. Esto es esencial para la interoperabilidad y la calidad del sistema final.
- Mantenimiento y Soporte:
- Especifica las políticas de mantenimiento y soporte para cada componente. Esto incluye cómo se gestionan las actualizaciones, parches de seguridad, y el soporte técnico asociado.