19 años en Internet

23 julio 2021

[Dev-Blog] [Proyecto Isekai] [#3] Diseñando el juego

Introducción

    En los últimos días he ido reflexionando sobre todo lo que quiero añadirle a mi juego y acerca de la viabilidad de poder añadirlos o no.

 

    Por si aún no os habéis enterado, me encuentro ahora mismo en fase de concepción de un juego que quiero sacar para Game Boy (con su cartucho y todo) y cada viernes quiero compartiros mis avances y reflexiones sobre el diseño y desarrollo del juego, así como lo efectivas o desastrosas que van siendo las metodologías que voy utilizando.

 

    En lo que al juego se refiere, se trata de un RPG clásico, con tintes de Zelda (para la resolución de mazmorras), Breath of Fire II (como sistema de combates y la elaboración de una aldea propia) y Fire Emblem (con muerte permanente de personajes).

 

 

El sistema de combates

     Un punto en el que estuve rumiando durante bastante tiempo era el sistema de combates, puesto que mi idea inicial era el de hacer un action-RPG con combates estilo beat’em up, pero las limitaciones de la consola sobre el máximo posible de cuadros que se pueden almacenar en la VRAM de la consola: 25 cuadros de 16x16 píxeles.

    Básicamente en esos 25 cuadros debíamos de incluir las distintas animaciones de personajes y enemigos, algo técnicamente imposible si queremos tener una party de 4 personajes y ver al mismo tiempo varios enemigos en pantalla. Así que, con estos datos, la hipótesis de hacer un beat’em up resultó fue descartada de inmediato.

Algo estilo “River City Girls” habría resultado épico, pero no parece viable.

    Después estuve reflexionando sobre la posibilidad de hacer un motor estilo “Breath of Fire II”, donde aparte del background (que sería el escenario del combate y que no estaría incluido en el límite de 25 cuadros) deberíamos de ver los enemigos (un máximo de 4 distintos), la party del héroe (un máximo de 4 personajes distintos) y sus distintas animaciones (recibir daño, atacar, estar malherido, lanzar magias…). Si además copiamos “tal cual” el motor del “Breath of Fire II”, hay que tener en cuenta que el personaje se puede transformar en dragón y los personajes deberían de verse con más detalle que en el mapamundi (fuera de los combates). Con estos números queda claro que hacer un motor similar a este juego resulta también inviable, me gustaría hacerlo, pero técnicamente es imposible.

 

 
Sencillamente, el sistema de combates de BOFII tampoco es viable en GB.

    Así que me puse a hacer una lista de todo lo que quería que tuviera el sistema de combates de mi juego:

  1. Poder ver a 4 enemigos en pantalla.
  2. Poder tener un grupo de hasta 4 personajes.
  3. Tener animaciones de ataque, magia y consumo de ítems.
  4. Poder transformar al personaje principal en dragón.
  5. Utilizar ítems.

 

    Y tras todo ello, se me ocurrió que había únicamente un modelo de motor viable para la realización de todo ello: El del RPG Maker XP, el cual cuenta con un modelo de combate frontal, que te permite ver el enemigo en todo detalle y con miniaturas de cada personaje.
 

Captura de pantalla del tráiler oficial del RPG Maker XP.

    Está claro que, debido a las limitaciones de la consola, no podré hacer algo tan bonito como lo que se ve en la captura de arriba que os comparto (sacada del tailer oficial del RPG Maker XP) y que tendremos que hacer sacrificios en orden de poder mostrar lo mismo, pero de una forma de que se pueda ver toda la información necesaria en la reducidísima resolución de la consola (160x144 píxeles).

 

    Por poneros unos ejemplos, pienso remplazar las miniaturas de los personajes por “portraits” (aka “retratos”) que enfoquen sólo la cara de los personajes. Esos “portraits” variarán en función de si el personaje espera (cuadro normal), ataca o hace magia (compartirán el mismo cuadro) o reciben daño. En caso de muerte, su “portrait” sería remplazado por una calavera. Con todo ello, estamos hablando de consumir 13 cuadros de 16x16 pixeles entre los 4 personajes del grupo del héroe.

 

    Por otro lado, queremos mostrar 4 enemigos en pantalla y que tengan un tamaño decente, por lo que deberían de ocupar 16x32 pixeles. No obstante, duplicar el número de pixeles implica que cada personaje consuma el doble de cuadros y nos quedaban sólo 12 disponibles. Si disponemos de 12 cuadros de 16x16 pixeles y queremos hacer uso de enemigos de 16x32 pixeles, esto implica que contaremos únicamente con 6 cuadros de 16x32 a repartir entre los 4 enemigos… Vamos, que tendremos que hacer enemigos estáticos y reservar únicamente 4 de los 6 cuadros disponibles de 16x32.

 

    Un truco que podemos hacer para simular una animación (y hacer como que atacan) es voltear el cuadro, es decir, aplicarles un modo “espejo”. Por ejemplo, podemos dibujar de forma estática a un enemigo con el garrote en la mano derecha y durante su fase de ataque mostrar brevemente un cuadro donde la imagen esté invertida en el eje X dando una falsa sensación de movimiento.

 

    Con todo ello nos quedarían aún disponibles 4 cuadros de 16x16 píxeles, que podemos emplear para los efectos visuales, por ejemplo:

  • Dibujar un “tajo” que se visualice cuando alguien ataque y que se posicione en el personaje que recibe el daño.
  • Dibujar burbujitas que se visualicen cuando alguien recibe los efectos de una magia (por ejemplo, para magias curativas).
  • Dibujar una llamarada para las magias de fuego, que además podríamos voltear sobre el eje Y para dar sensación de agua o nieve para las magias de tipo hielo.
  • Y nos queda un cuadro aún libre por asignar.

 

    Además, podemos jugar con distintos efectos de pantalla para dar la inmersión de las magias o de los ataques: Podemos, por ejemplo, realizar un efecto de “fade-in” a color blanco con su correspondiente “fade-out” cuando apliquemos animaciones de curación; Hacer el mismo efecto pero sobre color negro cuando apliquemos animaciones de ataque; O hacer temblar la cámara cuando apliquemos magia de tierra (por ejemplo, producir un terremoto); Si alguna vez habéis hecho uso de “DIV Games Studio” o de algún “RPG Maker”, seguramente ya conoceréis este tipo de trucos.

 

    Aún así, con este esquema perdemos un punto que me habría gustado incluir y es que el personaje pueda transformarse en dragón. Sencillamente, no podemos tenerlo todo.

 

    Y ahí es cuando he empezado a pensar en una segunda opción, pero que no me gusta y pasa por dibujar los enemigos dentro del “background”. Esto liberaría todos los cuadros de memoria reservados que podríamos emplear, por ejemplo, en las imágenes del “portrait” del dragón e intercambiarlas por las del jugador cuando éste se transforme. La pega de hacer esto es que reduciremos la aleatoriedad definiendo de antemano la lista de enemigos a los que nos enfrentaremos, puesto que tocaría pegarlos directamente en el “background”: Estamos hablando de imágenes estáticas sin ningún tipo de animación y que deberíamos de aplicar pequeños efectos de “tembleque de cámara” cada vez que un enemigo ataca o recibe daño. Encima, muy importante, cada vez que un enemigo muera no se podría quitar de la pantalla y tocaría ponerle una calaverita encima.

 

    No obstante, esta práctica nos aportaría dos ventajas: Más cuadros libres (hablamos de liberar 8 cuadros de 16x16 pixeles) y enemigos de mayor tamaño. Por ejemplo, si reservamos la mitad de la pantalla para los enemigos y dividimos entre 4 el eje X, obtendríamos enemigos de 40x77 pixeles… Un tamaño enorme para un juego de Game Boy y que valdría la pena probar. Y muy importante, podemos hacer jefes finales de 160x77 píxeles.

 

    Pero hay una cosa más a tener en cuenta, aunque la resolución de pantalla de la consola sea de 160x144 pixeles, realmente no hay una necesidad imperiosa de que el background tenga ese tamaño. Podríamos definir, por ejemplo, un background de 800x144 pixeles dividido en 5 regiones: La primera región sería la imagen con los 4 enemigos y las otras 4 regiones veríamos a uno de los enemigos atacar (por ejemplo, en la región 2 dibujamos al enemigo 1 atacando, en la región 3 al enemigo 2 atacando, etc.). Esto nos permitiría simular animaciones (bastaría con desplazar la cámara en el eje X sin efecto de scroll) e incluso podríamos hacer una animación de respiración, creando una nueva región donde modificaríamos levemente el primer cuadro (para ello nuestro background pasaría a tener 960x144 pixeles). Puede parecer un tamaño enorme, pero recordad que hablamos de PNG de apenas 4 colores y que cada escenario de este tipo debería de ocupar entre 4 y 30 KB de espacio. De hecho, he hecho la prueba de redimensionar la imagen de assets más pesada del proyecto de ejemplo de “GB Studio” a 960x144 pixeles y me ocupa 17 KB. Si queremos limitar el tamaño máximo de este tipo de fondos a 1 MB (para reservarnos por ejemplo otro mega para el resto de recursos) esto indica que podríamos tener unos 60 tipos de encuentros distintos, una lista que no está nada mal.

 

    Por cierto, si os lo estáis preguntando, el tamaño máximo documentado para un cartucho de Game Boy es de 2MB. Yo poseo un cartucho de 4MB, por lo que tendré que hacer una prueba para ver si una Game Boy real puede leer roms de 4MB o si tendré que limitarme a esos 2 MB de tamaño máximo. En caso de poder utilizar esos 4MB, mi objetivo es simple: Utilizarlos en mejorar el juego en todo lo que pueda.

 

    No obstante, cabe destacar que todo esto es teórico y que tendré que hacer una prueba de concepto (POC) para ver si es viable. Digo esto porque en la documentación de GB Studio explican que el framework divide los backgrounds en tilesets (subdivisiones de 8x8 pixeles) y se puede contar únicamente con 192 tipos únicos de tilesets. Si dividimos el tamaño de nuestros enemigos (40x77 píxeles) por el tamaño de nuestros tilesets (8x8), obtenemos que cada enemigo consta de unos 50 tilesets… y sin aplicar animaciones. Lógicamente los números no salen, puesto que la suma de los 4 enemigos hace 200 tilesets de los 192 posibles… Claro, si hablamos de enemigos únicos

 

    En el caso de que tengamos un encuentro y los 4 enemigos sean idénticos, realmente estaríamos consumiendo 50 tilesets en la primera región, 50 tilesets más para las regiones donde un enemigo ataca y 50 tilesets para la falsa animación de “respirar”. Y con ello ocuparíamos ya 150 de los posibles 192 tiles.

 

    En pocas palabras, podemos tener combates contra enemigos gigantes, pero tendrán que ser siempre de la misma raza: Podremos enfrentarnos con uno, dos, tres o cuatro dragones; con uno, dos, tres o cuatro góblins; con uno, dos, tres o cuatro slimes… Pero nunca podremos juntar en el mismo combate dragones con slimes o góblins. Se trataría de una limitación técnica con la que tendríamos que contar con el fin de conseguir buenos gráficos en nuestro juego.

 

   Y si os lo estáis preguntando, no, no podemos hacer el mismo truco con la party del jugador, debido a que esta puede variar de forma dinámica: Uno de los objetivos es la de construir un sistema de muerte definitiva, donde los personajes no puedan revivir.

 

 

El modo exploración

    En lo que se refiere a la jugabilidad, me gustaría contar con un estilo similar al “Link’s Awakening”: Vista aérea, movimiento en 8 ejes (con diagonales), personajes cucos, puzles en medio del mapeado (cortar llevar, usar un ítem X para desbloquear un área, etc).

    El caso es que me gustaría modelar los gráficos en Blender para tener algo que se parezca el “Dokey Kong Land”, pero tras realizar unas pruebas básicas he visto que era inviable. Por ejemplo, he pillado la Midna que he modelado en blender, le he hecho un render de perfil, la he reescalado a 16x32 pixeles y le he reducido el color a una paleta de 4 colores, siendo uno de ellos el color transparente… Y el resultado ha sido horrible: Era imposible distinguir nada. Lo que sí que parece quedar más o menos bien son los escenarios (no es lo mismo comprimir un fondo básico a 160x144 que un personaje a 16x16, lógicamente el escenario consta de más detalle)… Y los personajes creados con el Game Character Hub (una aplicación creada por los creadores de RPG Maker), los cuales también quedan razonablemente bien:


Ejemplo de personaje creado con el “Game Character Hub”, reducido a 6 cuadros de 16x32 (12 cuadros de 16x16) y degradado a 4 colores en tono verdoso y que sirve como animación de caminar.

 

    Si os fijáis en el ejemplo, ese personaje queda realmente precioso para tratarse de un juego de Game Boy, pero ocupa 12 de los 25 cuadros de nuestra VRAM. No obstante, creo que vale la pena apostar por este tipo de personajes. Ahora bien, el coste visual tendría un coste funcional y es que para poder contar con la máxima cantidad posible de NPC en pantalla, estos no podrán moverse: Me reservaría 3 cuadros de 16x32 pixeles para cada uno (uno para mirar a la derecha que aplicaremos en espejo cuando mira a la izquierda; Otro para mirar arriba y otro para mirar abajo), que suponen 6 cuadros más de VRAM (de 16x16 pixeles)… y con esas cifras, los números no salen, podríamos contar únicamente con dos NPC en pantalla, una cifra floja para todo RPG. Además, siempre viene bien contar con un par de cuadros libres en memoria para poder aplicar algún efecto o animación extra.

 

    Así que hice una prueba de como se vería un personaje de 16x16 píxeles generado con “Game Character Hub” y degradado a 4 colores y dio lugar a esta aberración:
 

    Hombre, no está mal, pero gráficamente impresiona poco, así que tuve que tomar una difícil decisión: Optar por la solución de tener personajes de 16x32 píxeles, pero hacer que permanezcan estáticos (no se girarían par hablar con el protagonista). Es la única forma que veo posible de tener la máxima cantidad de NPC posible a 16x32 píxeles.

 

    Entonces, resumiendo:

  1. Contaríamos con 12 cuadros de 16x16 para el personaje principal.
  2. Reservaría 2 cuadros de 16x16 por NCP. Podemos hacer por ejemplo que salgan únicamente 3 a la vez. (6 cuadros reservados únicamente para NPC). Ahora bien, cabe destacar que podemos tener realmente más NPC en pantalla (los que nos permita el framework), pero que simplemente,a nivel gráfico, podremos mostrar en la misma escena sólo 3 clases de NPC.
  3. El resto de cuadros (8 en total) irían destinados a destinados a dibujar cofres, ítems u objetos necesarios para completar puzles.

 

    Para disimular el hecho que los personajes no se muevan o miren al personaje, podemos cargar una nueva escena donde se vea en primer plano un dibujo del NPC, como si se tratara de un “The Elder Scrolls” o de un “Fallout” (cuando en esos juegos hablas con un NPC, la cámara se desplaza para apuntar a su cara). De esta forma podemos incluso poner un sistema de diálogos puramente rolero, con las opciones típicas de “Hablar”, “Extorsionar”, “Ligar”, “Robar”, etc. Y al igual que en el sistema de combates, podemos incluso crear un sistema donde los 80x77 píxeles de la izquierda correspondan a una imagen detallada del héroe, a los 80x77 píxeles de la derecha correspondan a una imagen detallada del NPC y que los 160x77 píxeles de abajo correspondan al área de texto.

 

    Aunque bueno, me decanto más por un dibujo del NPC a 160x77 píxeles en la parte alta de la pantalla, reservando la parte de abajo para diálogos y limitarnos a poner el retrato/portrait del personaje de la party que hable en alguna esquina (para indicar quién habla).

 

    De hecho, ya que estamos en fase de diseño, podemos definir las acciones que nuestro personaje puede hacer sobre los NPC:

  • Hablar.
  • Observar.
  • Robar.
  • Ligar.
  • Extorsionar.
  • Asesinar.
  • Trueque.

 

    Cada una de estas acciones tendría un diálogo distinto y podría causar que cambie el estado de ánimo del NPC y por ende, su relación o comportamiento con nosotros. Ahora bien, recordemos una cosa, y es que nuestra pila de guardado se limita a 32 Kb de memoria y que el framework nos permite la friolera de 521 bytes. Esto quiere decir que se nos hace imposible hacer que cada NPC del juego pueda recordar si les hemos intentado robar, si hemos hecho click en observar para tener más detalles de él… salvo si guardamos la información a nivel del pueblo.

 

    Me explico: Podemos, por ejemplo, reservar el número máximo de aldeanos por pueblo a 8 y cada bit del byte correspondería a un NPC del pueblo. Así que, por ejemplo, el valor inicial del byte “Robar_pueblo_1” tendría el valor 00000000x2, y si los NPC 1 y 3 nos pillan robando, pasarían a tener el valor 00000101x2 (que equivaldría al nº 5 en decimal). Y si más tarde nos pilla el NPC 2, pasaríamos a tener el valor 00000111x2 (que equivaldría al nº7 en decimal). Limitando el número máximo de NPC con los que interactuar y usando esta técnica, podríamos reservarnos un byte por pueblo para memorizar si un NPC nos ha pillado robando, otro byte por pueblo para recordar si hemos “analizado” a un NPC, otro byte por pueblo para memorizar si hemos conseguido “seducir” a un NPC, otro byte para memorizar si hemos asesinado a un NPC, etc.… y así, con unos 12 bytes tendríamos esas tres informaciones a nivel de 3 pueblos.

 

    Pero un punto sensible son las acciones de robar y trueque, puesto que nos va a ser imposible guardar en la pila el inventario de cada NPC del juego y encima no podemos reemplazarlo por dinero (es decir, que el personaje pueda únicamente robar dinero), puesto que trabajamos a nivel de bytes y el valor máximo que nos permite es de 256. No podemos reservar un byte (o varios) por NPC, sencillamente no es viable. Así que cuando robemos, el jugador deberá de recibir una cuantía aleatoria de dinero (es la única forma viable que veo). Ahora bien, una vez hecho el robo (tanto como si el personaje acierta, como si es pillado), pondremos el bit ligado al robo a 1 y el sistema ya no nos dejará volver a robarle y encima el NPC nos mirará mal cuando volvamos a hablar con él. Y respecto al trueque, tendremos que limitarlo a determinados NPC que contengan algún ítem necesario para la aventura y lo único que podremos hacer es comprarles ese ítem. Ahora bien, ese ítem debería de conseguirse de otras formas: Bien asesinando al NPC, bien completando alguna “quest” que nos pida. Con ello, damos al jugador una sensación más alta de inmersión.

 

    De hecho, me gustaría que todas esas habilidades (robar, asesinar, ligar…) no estén disponibles por defecto y que el jugador vaya desbloqueándolos de alguna forma (que aprenda a asesinar tras la rabia de ver a algún compañero muerto, que aprenda a hacer trueque tras recibir una formación de economía, etc…) e incluso podríamos usar la misma táctica de emplear un byte para almacenar de forma booleana todas las habilidades que puede hacer o no el personaje. Por ejemplo, el primer bit podría ser el de “Puedo robar”, el segundo bit el de “Puedo ligar”, el tercero el de “Puedo asesinar” y así hasta llenar 8 posibles habilidades. Si limitados el número posible de personas que pueden unirse a nuestro grupo a 7, estamos hablando de que podríamos tener 8 bytes de habilidades (1 para el prota y 7 para el resto del grupo) para listar todas estas capacidades.

 

    Ahora bien, tengamos en cuenta otros elementos y es que en cada RPG todo miembro de la party tiene puntos de vida (HP), puntos de magia (MP), un nivel (que hace que cambie el valor máximo de los HP y MP), puntos de experiencia y posibles magias (que dependiendo del nivel del personaje podrán usarse o no). Casi toda esta información es dinámica (cambia en función de nuestros progresos) y debe de ser almacenada en la pila de guardado (que ya hemos dicho que está limitada a 512 bytes a nivel de framework).

 

    Tomemos nota de lo que nos hace falta:

  • Cantidad actual de HP (1 byte -> de 0 a 255).
  • Cantidad máxima de HP (1 byte -> de 0 a 255).
  • Cantidad actual de MP (1 byte -> de 0 a 255).
  • Cantidad máxima de MP (1 byte -> de 0 a 255).
  • El nivel del personaje (1 byte -> de 0 a 255).
  • Puntos de ataque físico (1 byte -> de 0 a 255).
  • Puntos de magia (1 byte -> de 0 a 255).
  • Puntos de defensa (1 byte -> de 0 a 255).
  • Los puntos de experiencia (1 byte -> de 0 a 255).
  • Los puntos de experiencia necesarios para pasar al siguiente nivel (1 byte -> de 0 a 255).
  • Árbol de magias aprendidas (1 byte en booleano: 8 magias máx.).
  • Árbol de habilidades aprendidas (1 byte en booleano: 8 skills máx.).

 

    Pues a lo tonto nos plantamos ya en 12 bytes por personaje, algo que parece muy inviable. Si usamos 8 personajes, estaremos consumiendo 96 bytes sólo en la party. Encima, ocho magias posibles parecen pocas… pero podemos solucionar ambas cosas aplicando un sistema de clases. Por ejemplo, podemos hacer curanderos que tengan sólo 8 posibles magias de curación; Podemos tener magos que hagan sólo magia de fuego; Magos que hagan sólo magia de tierra, etc… Este sistema de clases debería de ir definido en hardcode para reducir al máximo la cantidad posible de bytes a guardar en pila. Es decir, a nivel del código el juego ya sabe si los personajes 1, 2 o 3 son de una clase u otra. Rizando el rizo, podemos hacer que la cantidad máxima de HP, de MP, puntos de ataque, de defensa, de magia, puntos de experiencia necesarios para llegar al próximo nivel… dependan directamente de la clase y el nivel que tenga nuestro personaje (es decir, se tratarían de valores calculados o predefinidos “in game”). Y puestos a rizar el rizo, podemos hacer que el árbol de magias aprendidas dependa también directamente del nivel del personaje.

 

    Con todo ello podríamos reducir la cantidad de bytes por personaje a:

  • Cantidad actual de HP (1 byte -> de 0 a 255).
  • Cantidad actual de MP (1 byte -> de 0 a 255).
  • El nivel del personaje (1 byte -> de 0 a 255).
  • Los puntos de experiencia (1 byte -> de 0 a 255).
  • Árbol de habilidades aprendidas (1 byte en booleano: 8 skills máx.).

 

    Pero no olvidemos una cosa y es que queríamos implementar un sistema de “muerte definitiva”. Para esto nos hace fata sólo un bit, donde 0 sea vivo y 1 sea muerto. La fórmula que podríamos seguir para implementar esta función sería robarle un bit a la variable del nivel del personaje. Para poneros en contexto, si hacemos que el nivel pasara a tener 7 bits en vez de 8, tendríamos como posibles valores del 0 al 127 y de hecho, si os habéis fijado, en muchos juegos el nivel máximo suele ser el 99. En este caso, el primer bit del byte “nivel” correspondería a si el personaje está vivo o muerto y los 7 siguientes serían reservados para el nivel del personaje:

  1. Cantidad actual de HP (1 byte -> de 0 a 255).
  2. Cantidad actual de MP (1 byte -> de 0 a 255).
  3. Vivo/muerto + nivel del personaje (1 bit de estado + 7 bits de nivel -> de 0 a 127).
  4. Los puntos de experiencia (1 byte -> de 0 a 255).
  5. Árbol de habilidades aprendidas (1 byte en booleano: 8 skills máx.).

 

    Y con todo ello acabamos con 5 bytes con personaje, pudiendo hacer todo lo que habíamos definido (pero con el costo de fijarlo con valores precalculados). 5x8 = 40 bytes para toda la party, nada mal. De hecho, podríamos aprovechar para crear bytes para el equipo:

  • 1 byte para definir las 8 posibles armaduras que tenga compradas el personaje (8 booleanos).
  • 1 byte para definir cuál de esas prendas está usando.

 

Y lo mismo para las armas:

  • 1 bye para definir las 8 posibles armas que tenga compradas el personaje (8 booleanos).
  • 1 byte para definir cuál de esas armas tiene equipadas.

 

    Estamos hablando de 9 bytes por personaje: 64 bytes para toda la party, que en mi opinión son muchas, pero oye, creo que hay que apostar por esta solución. Y si os lo estáis preguntando, la capacidad del protagonista en dragón constaría como una clase propia y las transformaciones serían magias. 

 

    Así que como veis, estamos ya hablando de reservar 3 bytes de información dinámica por pueblo y 64 bytes para la party. Por ahora no se nos va de madre el diseño y hemos planificado implementar un porrón de cosas.

 

    Hay un punto que se nos olvida y es que puede darse el caso de que aún no dispongamos de un compañero o que éste salga temporalmente del grupo, para ello podemos reservarnos un byte (que sería el 65) en el que cada bit representaría la presencia en el grupo de cada uno de los 8 personajes.
 
 
 

Navegación en grandes urbes

 

    Un punto que puede agilizar el desarrollo pero que afecta de mala forma a la inmersión, es seguir con el esquema de ciudades que se aprecia en juegos como el primer “Sword Art Online” de PSP que tuvo posteriormente una remasterización digital para PS4 y PS Vita (“Sword Art Online: Hollow Fragment”). Por cierto, un servidor considera de que a día de hoy se trata de uno de los mejores juegos de la saga.

 

    En este juego Kirito tiene que ir desde la planta 75 a la 100 y cada planta tiene una ciudad distinta… Pero realmente sólo una de esas ciudades está modelada en 3D, el resto son “backgrounds” (imágenes de fondo) en los que podemos decidir qué hacer: Visitar tiendas, ir a la posada, etc.

 

 
Hollow Fragment tiene muchas ciuades, pero sólo la primera está modelada en 3D.

    Mi idea es la de pillar este concepto para las metrópolis, así podríamos dar una falsa sensación de ciudad gigante y continuar con la limitación de disponer sólo de 8 NPC por pueblo (la limitación de los 3 bytes): Entras en la metrópolis y ves un dibujo chulísimo de la ciudad y se te presenta un cuadro con varias opciones: Ver monumentos, ir a una posada, comprar objetos, buscar trabajos… Cada acción llevaría a un nuevo escenario en vista “tradicional”.  Ahora bien, las aldeas sí que serían modeladas de forma “tradicional” (vista aérea) y este sistema de dibujo + opciones iría únicamente destinada para las grandes urbes.

 
 
 

Gestión del inventario

    Un punto crítico en todo RPG es el sistema de gestión del inventario y aquí vamos a estar terriblemente limitados, ya que, a diferencia del modelo tradicional de programación de este tipo de juegos, no vamos a poder almacenar toda esta información de forma dinámica. Tendremos que crearnos un vector estático.

 

    De hecho, propongo reservar 2 bytes para ítems importantes para la aventura, es decir, emplear 16 booleanos para memorizar si poseemos determinados ítems únicos necesarios para la progresión del juego. En juegos tipo “Zelda”, estos ítems serían por ejemplo las pulseras del poder, las botas para correr, o la pluma para saltar.

 

    También me gustaría reservar 1 byte por mazmorra, ya que, siguiendo el modelo de Zelda, me gustaría disponer con distintas llaves para abrir puertas, la brújula que indica dónde está el jefe final y el mapa de la mazmorra (se trataría de contar con 8 booleanos). Pero realmente tendremos que contar con dos bytes: Uno para saber si disponemos de esos ítems y otro byte para saber si hemos abierto todas las puertas asociadas o si hemos matado al jefe final.

 

    Si cada juego suele tener 8 mazmorras, parece totalmente viable poder reservar esos 16 bytes e incluso podemos plantearnos duplicar el número de mazmorras.

 

    De la misma forma, podemos también definir varios bytes destinado a los cofres que irán repartidos por todo el juego. Si nos reservamos 10 bytes, podremos memorizar en booleanos si hay 80 cofres abiertos o cerrados.

 

    Por cierto, cuando hagamos la documentación, toda esta información de cómo están definidas las variables y en qué las emplearemos, tendremos que definirla en una matriz (fichero Excel), porque podemos liarla parda muy fácilmente si empezamos a codificar sin planificar nada.

 

    También me gustaría reservar 10 bytes para el inventario de consumibles de la party (pócimas, hierbas, objetos de farmeo, etc.). La pega con este tipo de objetos es que no se tratan de objetos únicos y que el jugador puede ir comprando y acumulando esos bienes, por lo que realmente tenemos que utilizar 1 byte por objeto.

 

    Como diez posibles objetos distintos parecen muchos y disponer un máximo de 255 parecen una animalada (demasiados), propongo utilizar 4 bits por objeto. De esta forma podemos disponer de 20 clases de objetos (2 por byte), pero limitando el número máximo de cada uno a 15 unidades. De hecho, si queremos impresionar, duplicar el número de bytes (20 en total) y de esta forma contaríamos con la friolera de 40 tipos de objetos distintos (pero con la limitación de disponer como máximo de 15 unidades por cada uno de ellos).

 

   Punto de atención: Estas variables servirán para definir su posesión en pila, pero su comportamiento, aspecto, descripción y efecto deberán de estar predefinidos en código.


    Un punto que me gustaría tener en cuenta también, es que la party sepa para qué sirve cada objeto. Imaginemos por ejemplo que nuestro personaje coge una hierba curativa que no ha visto en la vida, la consume y ¡puf! ¡Resulta que era una hierba venenosa!

 

    Para poder aplicar esto, me gustaría tener con un booleano por objeto que nos permita saber si la party conoce o no el efecto del ítem. 40 booleanos implica reservar 5 bytes de memoria y la idea es que esos booleanos pasen a 1 en función de:

  1. Las personas que formen nuestra party.
  2. Las conversaciones con los NPC.
  3. Los distintos libros que podamos consultar.

 

    Es muy importante que esos 5 bytes sean a nivel de party, puesto que sería inviable reservarlos a nivel de personaje (5x8 = 40 bytes).

 

 

 

Gestión de las quests

    Aquí quiero diferenciar la quest principal de las quests secundarias. De hecho, podemos definir una quest en varias etapas: Habla con el señor X, ve al lugar Y, vence al bicho Z, etc.

 

    Lo que propongo es tratar el esquema de la aventura con un contador: Es decir, si pillamos un byte podremos contar con 255 etapas, siendo 0 la más simple (la quest no ha comenzado) y 255 la última (quest completada). Y cada vez que cumplimos un hito importante con efecto en la trama, ese contador suma 1. Al hablar con el señor X pasaríamos a tener el valor 1, al ir al lugar Y tendríamos el valor 2, al vencer al bicho Z pasaríamos a tener el valor 3… y así iríamos avanzando por las distintas etapas de nuestra aventura. El problema de este enfoque es que tendremos una historia bastante lineal, por lo que habrá que jugar con variables auxiliares para dar una falsa sensación de libertad.


    Un punto a tener en cuenta es que pienso contar con varios finales, entonces mi idea es contar con 2 bytes:

  • El byte que acabamos de definir con 256 etapas.
  • Un byte que define la rama actual sobre la que nos encontramos (valor 0 -> historia por defecto; valor 1 -> trama favorable al régimen; valor 2-> Trama en contra del régimen; … valor 255 -> Trama a favor de la destrucción de la humanidad.

 

    Jugando con esos dos bytes podemos ir variando la quest principal e ir evolucionándola y derivándola para que deje de ser lineal.

 

    En lo que se refiere a las subquests (o quests secundarias), 255 etapas parecen demasiadas, por lo que he optado por reservar 4 bits por quest secundaria. Es decir, cada byte contaría con dos quests y cada quest tendría un máximo de 16 etapas (con valor 0 la no iniciada y 15 la quest finalizada). Si nos reservamos 30 bytes para quest secundarias, nuestro juego podría contar con hasta 60 quests secundarias, un número bastante loable.
 
 
 

Gestión de pantallas

    Acabamos de diseñar bastantes elementos ligados a nuestro juego, pero una parte bastante importante tendrá que ver con la gestión de las pantallas y de los diferentes menús.


    La pantalla inicial será el logo del desarrollador, que al cabo de X segundos o tras pulsar algún botón, navegará a la pantalla de “Intro”. En esta pantalla veríamos una escena animada estilo “Link’s Awakening” que nos daría el contexto de cómo el personaje ha llegado al planeta. Al pulsar cualquier botón o al finalizar la introducción, pasaríamos a la pantalla de “Pulsa Start”.

 


Link's Awakening, uno de los mejores juegos de la historia de GB.


    La pantalla de “Pulsa Start” mostraría un dibujo a pantalla completa, mostraría el texto de “Press Start”. Si alguna vez nos hemos pasado el juego, el dibujo a mostrar cambiaría. Al pulsar start pasaremos al menú inicial.

 

    El menú inicial contaría con las opciones de “Partida nueva”, “Cargar partida” y “Password”. El botón de “Cargar partida” quedaría deshabilitado si el juego detecta que la pila está vacía.

 

    La elección de “Partida nueva” machacaría el “save” actual, es decir, formatearía la pila. Es por ello que una popup de alerta deberá de mostrarse en caso de existir ya un “save”, dando opción de volver a la pantalla inicial para evitar perder el “save”.

 

    Hay dos cosas que me gustaría implementar en el menú inicial pero que voy a descartar:

  1. Poder cambiar de idioma, pero teniendo en cuenta las limitaciones de memoria y lo ambicioso que parece el juego, creo que me limitaré a escribir los textos en inglés.
  2. Poder exportar el “save” a un código QR (los 512 bytes), para poder jugar una eventual secuela o un remaster en otra plataforma.

 

    Al empezar la partida veríamos la pantalla de juego normal (vista aérea, con el HUD/IHM y el personaje centrado). El HUD deberá de limitarse a:

  • El portrait/retrato de cada jugador de la party (un máximo de 4).
  • La barra de vida y de magia de cada miembro de la party (un máximo de 4).

 

    Al pulsar “Start” pasaríamos al menú de inventario. En este inventario podríamos:

  1. Consumir ítems.
  2. Aplicar magias (p. ex. de curación).
  3. Consultar los estados.
  4. Seguir las quests en curso.
  5. Guardar la partida.

 

    Al consultar un estado que no sea del héroe (vamos, el estado de un compañero), se nos abre la opción de poder hacer un diálogo con él. Este diálogo variará en función de la etapa de la quest principal o de determinadas quests secundarias y servirán para dar pistas.


    Al entrar en un combate pasaríamos a la pantalla de combate y volveríamos al juego “normal” al acabarla.

 

    De la misma forma, al iniciar un diálogo con un NPC pasaríamos a la pantalla de diálogo (estilo Fallout / The Elder Scrolls) y al finalizar éste volveríamos a la pantalla de “juego normal”.


    Al morir el personaje inicial, se mostraría la pantalla de “Game Over” y tras la pantalla de Game Over volveríamos a la de “pulsa start”, dejando la opción al jugador de cargar el último “save” guardado.

 

    Durante la partida, podremos visitar tiendas y posadas. En las tiendas puede darse el caso de que el jugador realice hurtos, mientras que, en las posadas, aparte de dormir el jugador podrá reorganizar los miembros de su party (definir los que nos acompañarán y su equipamiento) y permitir opciones como salir a tomar una caña por las noches para conseguir información local.

 

    Me gusta el tema de poder organizar el equipo únicamente en las posadas, debido a que es un enfoque más realista de lo que estamos acostumbrados. Desde mi punto de vista, es poco real que el héroe deshaga su maleta en medio de una mazmorra para permitirse cambiar el equipo. Una cosa es recibir una espada nueva y equiparla (podemos dar la opción al jugador al abrir un cofre y al comprobar que la arma es mejor), pero otra totalmente distinta es pasearse con todas las armaduras adquiridas. 
 
 
 

Sistema de día y noche y meteorología (descartado)

 

    Un punto que me gustaría implementar es un sistema de día y noche. De noche los negocios estarían cerrados, apenas habría personas paseando; Podríamos hacer que las posadas rechacen hospedarnos si acudimos de buena mañana, etc. Pero me he visto obligado a rechazar esta idea debido a una limitación técnica importante: La Game Boy tiene tres colores, hacer que sea de noche resulta inviable, porque significaría hacer escenarios más oscuros y de 3 colores, mezclando entre ellos el negro y dificultaría la visibilidad de la pantalla. Tampoco puedo hacer el truco de cargar una capa oscura y transparente a pantalla completa. Vamos, que en este juego sólo se permitiría pasear de día.

 

     También me habría gustado un sistema donde una vez por semana lloviera o donde de vez en cuando se asomara algún copo de nieve, pero su implementación me ha parecido complicada debido a las limitaciones del framework. Podremos definir fondos nevados y/o pantanosos, pero serán siempre nevados y/o pantanosos.
 
 
 
 

Combates de batallones

 

    Otro punto que me gustaría implementar son los combates de batallones, donde se simularán combates entre muchos soldados, representados por las formas y movimientos de fichas de ajedrez.


    Para poneros en contexto, a lo largo de la historia principal estallará una guerra civil y si se dan las condiciones (puede darse el caso que no se produzca) el jugador podrá dirigir batallones.

 

    Estos combates no serán igualitarios, es decir, dependiendo de la situación la cantidad de piezas disponibles por cada bando variará, puede darse el caso de tener 3 peones y 4 torres vs 4 alfiles, 2 caballos y una reina, por poneros un ejemplo. El combate acabaría cuando las piezas de un bando desaparezcan (sean “comidas”) o cuando el rival huya del combate.

 

   Además, el tablero cambiará según el combate, puesto que simulará ser un campo de batalla. Si dibujamos por ejemplo un río, un pequeño bosque o montañas…. Las piezas no podrán posicionarse encima de estas áreas, limitando por ende el área de movimiento de las piezas.

 

   Ganar o perder una batalla de este tipo aportará consecuencias a la trama, creando posibles derivaciones o posibles finales. Debido a esto, el número de batallas de este tipo será bastante reducido.




Los comercios


    Habrá tres tipos de comercios:

  1. Las armerías, que venderán equipo y armas.
  2. Las tiendas de ítems, que venderán consumibles.
  3. Las posadas, que además de ofrecer un lugar donde dormir, permitirán la venta de alcohol.

 

    Las armerías y tiendas de ítems sólo permitirán la compra de objetos de su familia. Es decir, no podremos venderle hierbas medicinales a un armero y no podremos venderle espadas o armaduras a una droguería. Las posadas directamente no darán opción de venderles nada. Se podrá hacer uso de habilidades como extorsión o ligar para poder conseguir algún tipo de descuento, pero ojo, que un crítico al usar una de estas habilidades podría causar el resultado inverso.

 

    También podemos crear modelos específicos de tiendas, enfocados por ejemplo a la venta de frutas o de libros. Estas tiendas seguirían el modelo de las tiendas de ítems pero estarían “capadas” para no permitir que el jugador les venda ítems.

 

Fin por hoy

     Y poco más, esto va tomando forma y creo que por hoy ya está bien. Os animo a volver el próximo viernes 30 de julio para compartiros una vez más los avances con el diseño y desarrollo de este juego. Y si se os ocurre una idea más, os animo a compartirla en los comentarios aprovechando que aún estoy en fase de diseño.  

19 julio 2021

Unas pistas sobre mi próximo modelo en Blender


 

 

    Os invito a visitar mi blog el próximo lunes 26 de Julio para descubrir el resumen de las primeras sesiones de mi próximo personaje.

16 julio 2021

[Dev-Blog] [Proyecto Isekai] [#2] El corpus documentario

    Buenos días. Como mencioné la semana pasada, voy a comenzar el desarrollo de un juego para Game Boy y cada viernes me gustaría ir compartiendo con vosotros mis avances. Y bueno, supongo que si estás leyendo esto es porque te interesa el mundo de la programación de videojuegos y/o porque te estás planteando hacer uno.

    La entrada de hoy irá enfocada a la documentación, un apartado que resulta imprescindible para todo proyecto que requiera más de un mes de desarrollo, incluso para proyectos “Juan Palomo” (“yo me lo guiso, yo me lo como”) donde una sola persona se ocupa del 100% del desarrollo). Todo proyecto que busque acabar bien debe de pasar por el empleo de las buenas prácticas y justamente una de las buenas prácticas es documentar todo.

    También quiero aclarar que esto lo que vais a leer a continuación guarda más relación con el mundo de las consultorías informáticas que con el del desarrollo de juegos, pero eso no quita que varios de estos puntos puedan ser reutilizados para vuestro proyecto.

    Y bueno, con todo ello, lo primero que quiero comentar es que definir tu juego en un solo documento suele ser imposible (a no ser que hagas algo extremadamente sencillo), por lo que los proyectos acaban abarcando diferentes tipos de documentos destinados cada uno a un apartado en concreto. El conjunto de toda esta documentación se conoce comúnmente como “corpus” (abreviación de “corpus documentario”).

    Como ya he dicho, este “corpus” está formado por varios documentos, cada uno con un objetivo definido: “Hoja de concepción (también conocido como hoja de diseño)”, “dossier de arquitectura”, “matrices” (que funcionan a modo de anexo y pueden ser de interacción, de derechos de usuario, de flujos, de almacenamiento, etc.), “mapas de interfaz” (para definir los intercambios entre distintas API o webservices), “especificaciones funcionales”, “procesos técnicos de instalación”, “dossier de explotación”, etc.

    Pero el documento básico e inicial debe de ser la “hoja de concepción/diseño”. Se trata de un documento de una o dos páginas en el que se define de forma rápida un resumen de la historia y del estilo de juego. Este documento no busca listar todos los detalles, si no especificar las estructuras básicas del juego. Su objetivo es simple: Definir de qué trata y cómo se juega para poder para poder partir de una base clara y, en proyectos de más de una persona, sirve para unificar criterios en fase de concepción (evitando así posibles malentendidos).

    Este punto es muy importante, debido a que las tasas de abandono son extremadamente altas en los proyectos pequeños (de una o dos personas). A las personas nos gusta andarnos por las ramas e ir añadiendo funcionalidades a mitad del desarrollo, tomamos a veces decisiones sin avisar a compañeros y luego acabamos con un proyecto que un año más tarde no resulta jugable ni divertido y al que seguramente le falte aún más del 50% del desarrollo para acabarlo. También puede servirnos (aunque no es la idea) para compartir el documento entre amigos para que puedan valorar de una forma rápida si desean o no unirse a tu desarrollo.

    Mi consejo es que cada vez que veamos algo que nos gustaría incluir, pero que es costoso de desarrollar y que no se ajuste a la hoja de concepción, lo anotes para desarrollarla en una eventual secuela (o para otro título similar). El objetivo principal de ello es de evitar eternizar los desarrollos pequeños. De hecho, ese tipo de funcionalidades que nos gustaría añadir pueden ir listados en el REX (documento de “retorno de experiencia”, donde al final del desarrollo, o de una iteración, anotamos las dificultades que hemos encontrado y las posibles mejoras para evitarlas).

Para la elaboración de “hoja de concepción” os hace falta tener 5 puntos claros:
  • La idea básica: Una descripción simple y escueta de qué consiste el juego.
  • La historia: Un pequeño contexto o puesta en situación sobre el hilo argumental del juego. No hace falta dar todos los detalles, ni escribir una novela. Mi recomendación es limitarse a cumplir con las 5W del periodismo (who, what, when, where, why), sin destripar la trama o el final (salvo que consideres que sea pertinente indicarlo).
  • El estilo visual: El nombre del apartado lo dice todo. Aquí habría que especificar si pensamos hacer un juego en 2D/3D, si pensamos hacer uso de alguna tecnología en concreto que afecte visualmente (como “cel-shading”), si pensamos hacer personajes enanitos y cabezones estilo RPG de SNES, si emplearemos colores vivos o si pensamos hacer un juego que visualmente luzca oscuro, etc.
  • El estilo de audio: Se trata de uno de los apartados más ignorados y a la vez de los más importantes. ¿Pensamos utilizar música techno machacona? ¿Música de ascensor relajada? ¿Nos limitaremos al ruido ambiente (con pájaros y grillos)? ¿O planeamos poner un silencio total? Una buena elección ayuda a la inmersión, mientras que una mala puede romper por completo la experiencia de juego.
  • El control: Se trata de definir con qué dispositivos se juega. ¿Teclado + ratón? ¿Un gamepad? ¿Un Wii-Mote? ¿Captura de movimiento mediante webcam?
  • Y la interacción: Definir cómo el usuario interacciona con el mundo, si pensamos incluir JvsJ (jugador contra jugador), si nos limitamos a un modo campaña, si será un juego multiplayer, etc.
     La lista de apartados no es canónica y podéis adaptarla a vuestro gusto (añadiendo nuevos o quitando los ya existentes) y además podemos hacer mención a otros juegos del mercado para poder plasmar mejor sobre el papel cuales son las ideas que tenemos (p. ex.: Es un “Asteroids” con toque de rol, donde al final de cada fase podemos realizar modificaciones en nuestra nave).

    Hay que destacar que durante la fase de diseño cada uno de esos apartados pueden derivar en documentos separados y gigantescos para especificar al detalle cada uno de estos apartados, pero conviene tener siempre presente esta “hoja de concepción” porque nos sirve para asentar los cimientos de nuestro juego a la vez que nos ayuda a verificar cada X semanas si nos estamos alejando de la idea inicial que teníamos en mente (por ejemplo: “quería hacer un juego de rol medieval de tipo bélico, pero me he enfocado demasiado en un sistema de citas y romances y ahora parece más una visual novel de ligar”).

    Para profundizar o clarificar estos apartados, os animo a visualizar el siguiente vídeo del Dr. Clinton Woodward de la Swinburne University (Australia). El vídeo es escueto (apenas dura 8 minutos) y se trata de una lección grabada para el curso “Concepts in games development” de la antigua plataforma Open2Study (la cual ya no existe): https://www.youtube.com/watch?v=6kuYrBbDhJ8 (actualización: Parece ser que desde Open2Study se han dado cuenta y han deshabilitado los videos)
 


     Y si os ha gustado el vídeo, os comparto la siguiente lista de Youtube donde he recopilado todas las sesiones del curso que he podido encontrar por internet (los videos eran ocultos, pero el curso era gratuito, además de que la plataforma de Open2Study ya no existe y no lo he encontrado en ningún otro sitio, ni en la nueva Open Universities de Australia): https://www.youtube.com/playlist?list=PLroD_4x-Yzmd2hRASnd5aCwjGYsWXcmg_ (actualización: Parece ser que desde Open2Study se han dado cuenta y han deshabilitado los videos)

    Y tras todo ello, a continuación os presento la hoja de concepción que he preparado para mi juego:


    El segundo documento a tener en cuenta al iniciar un proyecto es el dossier de arquitectura, en el que definimos las tecnologías y herramientas empleadas para el proyecto. Definiremos, por ejemplo, el motor empleado (Unity, GameMaker, C# puro, RPG Maker, etc…), las herramientas de modelado (Blender, Maya, Gimp…), los distintos tipos de soluciones que crearemos (Windows, Linux, Mac, Android, Xbox One, etc…), etc. Muy importante, si nuestro juego tendrá un modelo del estilo cliente/servidor o si haremos uso de webservices externos, debe de salir reflejado en este documento. No hace falta indicar los detalles de los intercambios de información, puesto que los detalles técnicos irán definidos en los distintos mapas de interfaces (que se pueden entender como anexos) y sus funcionalidades asociadas irán descritas en las especificaciones funcionales.

    En caso, por ejemplo, de tener un sistema de guardado de partida, deberéis de definirlo también en este DAT (“dossier de arquitectura”): ¿batería de cartucho de Gameboy? ¿base de datos de psqlite? ¿guardado en un servidor externo? No hace falta definir todos los detalles (el sistema de estructuras podéis definirlo en anexos/matrices/mapas), pero en el DAT debería de ir reflejada toda tecnología empleada.

    Si vais a hacer vuestras propias herramientas internas (crear vuestro propio RPG Maker, por ejemplo), tened en cuenta que todo el “corpus” ligado de esas herramientas irán definidas como si de otro proyecto se tratara (con sus propias “hojas de concepción”, “dossieres de arquitectura” y “especificaciones funcionales”). Habrá que mencionar el empleo de dicha herramienta en nuestro DAT, pero la nueva herramienta propia que tengáis deberá de tener su propio “corpus” (no mezclemos peras con manzanas).

    Por cierto, mi recomendación es que elijáis siempre un framework que os permita hacer tests unitarios automatizados, debido a que es muy común crear regresiones cuando modificáis código fuente que no habéis tocado en semanas o meses (os ayudará a evitar la creación de un bug cuando pretendáis corregir otro que impacte en regiones de código mutualizadas). En mi caso, este paso no voy a poderlo seguir porque he optado por hacer uso del GB Studio, una herramienta muy similar al RPG Maker pero enfocado a hacer juegos de Game Boy.

    También recomiendo algo bastante obvio: Usad un sistema de repositorios como GIT, básicamente porque en caso de cagada (que la cagarás, todos comentemos errores), podrás hacer un “revert” de forma simple. Y el mero hecho de obligarte a poner comentarios te ayudará a entender en el futuro por qué en su día hiciste X y no Z. No hace falta montarse un gitlab o darse de alta en GitHub, os podéis montar un servidor básico de git en vuestro propio PC, la idea es poder trabajar de forma fácil con distintas ramas (actual, desarrollo, evolución XXX, evolución YYY) y tags y poder ir haciendo de forma simple vuestros merges y reverts.

    Volviendo al hilo principal, está bien ir definiendo este documento con antelación (el “dossier de arquitectura”), puesto que las limitaciones de las distintas herramientas impactarán en mayor o menor medida en las especificaciones funcionales y, por ende, en el diseño de vuestro juego.

    Por ejemplo, si hacemos uso de RPG Maker, debemos saber que en caso de hacer una pregunta al usuario, por defecto tenemos sólo 4 posibles opciones de respuesta como máximo; Tampoco podremos cargar animaciones de tipo “png”, pero sí archivos de vídeo; Si hacemos uso, por ejemplo, de GB Studio, pues podemos dar por hecho que el inventario de nuestro personaje será terriblemente limitado (hablamos de “saves” de 32 KB) o que debido a la resolución de la consola no podremos contar con un IHM (interfaz hombre-máquina, aka “Hud”) con numerosos paneles informativos a la vez (vida, energía, maná, dinero, etc.). Bueno, sí, puedes poner un “hud” gigante, pero en vez de un juego se parecerá más a una página web llena de publicidad.

    Como he dicho antes, el juego en el que quiero trabajar utilizará el GB Studio 2.0 y las limitaciones de dicho framework impactará fuertemente en las especificaciones funcionales:
  • El framework permite almacenar un máximo de 512 variables globales de tipo byte (con valor de 0 a 255). En el momento que queramos hacer algo más complejo (hacer un string para ponerle nombre al personaje) debemos de jugar con ellos. 512 variables pueden parecer muchos, pero para un rpg son pocos.
    • Un truco que podría seguirse en fase de desarrollo (tocaría modificar las fuentes de GB Studio) es dividir cada variable en 4 bits, donde los primeros 4 serían para una variable A y los 4 últimos para una variable B. Esto duplicaría el número de variables hasta las 1024, pero limitaría el margen de valor de 0 a 127. Y rizando el rizo se podría incluso personalizar distintos tipos de variable, por ejemplo:
      • 100 variables de tipo byte (8 bits, 100 variables con valor de 0 a 255).
      •  200 variables divididas en 4 bits (400 variables con valores de 0 a 127).
      •  200 variables divididas en 2 bits (800 variables con valores de 0 a 7).
      •  12 variables de 1 bit (12 booleanos).
      •  En resumen: 512 bytes repartidos en 1.212 variables (en vez de las 512 que tendríamos por defecto). Ahora bien, todo esto es teórico y requiere modificar las fuentes de GB Studio.
  • Tener un número limitado de variables globales a nivel documentario implica tener que crear una matriz (un fichero Excel) con la lista de cada una y su funcionalidad, más aún si ya planifico dividir cada byte de variable en subvariables.
  • El framework permite la friolera de 6 actores por escena, pudiendo considerar un actor los objetos como cofres, carteles o puertas, los enemigos, los NPC y el personaje que manejamos. Esta limitación viene dada a que la consola cuenta con 8 KB de SRAM (memoria volátil) y con 8 KB de VRAM (memoria gráfica).
    • No podemos poner en pantalla a la vez, por ejemplo, un cofre del tesoro, un cartel para dar pistas, al jugador, a un NCP y a tres enemigos. El framework no lo permite.
    • Existen trampas para engañar al jugador y dar a entender que se pueden definir más actores. Un truco que se está haciendo famoso es el de dibujar los actores directamente en el fondo (no tendrían sprite propio y por consiguiente permanecen inmóviles en pantalla) y desplazar el actor de posición (el cual tendría un srpite invisible) según el jugador accede a una región A, B o C. Luego, a nivel de código se modificaría el comportamiento del actor en tiempo real (según estemos en la región A, B o C).
  • Sin contar el fondo (que se trataría de una imagen estática pegada, pero que puede ser desplazado por el scroll y puede contar con efectos de parallax), el framework permite cargar en memoria la friolera de 25 sprites de 16x16 píxeles. Esto quiere decir que, si hacemos un personaje con animaciones de andar hacia arriba, abajo y un lado (que pondremos en modo espejo), sólo para la animación de andar consumiremos 6 de esos 25 sprites (cada animación contaría con dos sprites). Si metes un cofre y le pones un cuadro de cofre abierto y cerrado, consumes otros dos cuadros. Lo mismo para las farolas y para cada NPC que pongas en pantalla.
    • Esto hace que tengas que plantearte hacer que los NPC no puedan moverse o bien pegarlos directamente en el background (imagen estática) o hacer que se muevan, pero sin animación para poder consumir la mínima cantidad posible de sprites en memoria.
  • Los sprites están limitados a 4 colores, pero hay que tener en cuenta que para el caso de los 25 sprites cargados en memoria, uno de esos colores se emplea para transparencias, por lo que realmente cuentas con 3 colores para definir a los personajes y objetos. Hacer pixel-art de 4 colores es complicado, pero con tres hay que hacer magia.
  • El tamaño de los sprites es minúsculo (16x16 píxeles). Se podría editar el entorno para hacer que los personajes sean más grandes (por ejemplo, de 32x16), pero eso implica que cada animación del personaje consumiría el doble de sprites (a descontar del límite de 25 sprites). Si antes comentaba que para una animación de caminar en 4 direcciones consumíamos 6 sprites, con esto consumiríamos 12 de los 25 sprites. Si quieres hacer un action RPG, tienes que pensar además en añadir animaciones de ataque o de recibir daño.
  • GB Studio permite que el personaje se mueva en cuatro direcciones: Arriba, Abajo, Izquierda y Derecha… Pero no permite el desplazamiento en diagonal (como en juegos como Zelda). Hay que modificar las fuentes de GB Studio para permitir esto.
  • Los backgrounds tienen una talla máxima de 256x256 pixeles. Si planeas hacer escenarios más grandes te toca hacer trampas con los parallax o dividirlo en varias escenas.
  • El único formato de audio soportado oficialmente es el .mod y con limitaciones. Olvidaros de incluir ningún tipo de voz.
    ¿Por qué os cuento todo esto? Muy sencillo, para que veáis cómo las limitaciones del framework pueden impactar de forma notable en las funcionalidades de vuestro juego y en el diseño de éste. Por ejemplo, si defino que un personaje NPC está pegado en un background, en las especificaciones no puedo poner que éste se pueda mover o desaparecer.

     Ahora que ya somos conscientes de qué queremos que vaya el juego y de las limitaciones técnicas, tenemos que reflexionar sobre cómo diseñar el juego. Hay que pillar papel y lápiz e ir definiendo los diferentes tipos de escenarios y de actores que pueden intervenir y no me refiero a ponerle nombre y apellidos a los lugares o los personajes.

    Como escenas me refiero a las distintas pantallas que tenga nuestro juego (las navegaciones entre menús, los tipos de pantalla de juego, pantallas de Game Over, etc). Por ejemplo, en un menú inicial solemos tener 1 actor de tipo botón y dependiendo de su funcionalidad cuando éste interaccione con el ratón o con el cursor acabaremos yendo a una pantalla u otra. Mientras que en pleno juego (que se considera una escena propia) nuestro personaje (1er actor) interacciona con otros elementos: Al interaccionar con un NPC, éste puede decirnos una frase (actor tipo NPC); Al leer un libro podemos abrir la pantalla de guardado (actor tipo guardado); Al ser tocados por un enemigo podemos perder vida (actor tipo enemigo); Al pulsar una baldosa X (como una puerta), podemos teletransportarnos a otro mapa (actor tipo teletransporte); Cuando tocamos una moneda, esta desaparece y se añade a nuestro inventario (actor tipo inventario); Etc.…

    Y así vamos anotando todos los posibles tipos de actores y sus posibles interacciones. En juego simples, como los mata marcianos, esto no es nada complicado y podemos definir la funcionalidad en un fichero Excel llamado “matriz de interacciones”, donde listamos todos los posibles tipos de actor en horizontal y en vertical y al igual que en una quiniela, definimos en cada casilla el posible tipo de interacción entre todas las posibles combinaciones que deseemos.

    Ahora bien, en juegos más complejos, como puede ser mi caso, para definir el motor/engine necesitamos forzosamente partir de un modelo de desarrollo más clásico y crear un documento de especificaciones funcionales. Este documento actúa como manual de instrucciones y define todas las pantallas y funcionalidades posibles (incluso las que no son evidentes a simple vista). Un ejemplo:

Pantalla de “Pulsa start”:
- Maqueta de la pantalla.

Reglas de gestión:
  • RG-Start-01: Al iniciarse la pantalla suena la melodía XXX.
  •  RG-Start-02: Al iniciarse la pantalla se chequea los saves del juego. Si el jugador se ha pasado ya el juego 1 vez (o más veces), la imagen del fondo cambia a YYYY.
  • RG-Start-03: Al pulsar start suena un pitido, el mensaje de “Pulsa start” parpadea 3 veces seguidas y al cabo de 2 segundos se produce un fade-off de la pantalla y navegamos a la pantalla de “Menú inicial”.
Reglas de visualización:
  • RV-Start-01: El texto de “Pulsa start” parpadea 1 vez cada 5 segundos.
  • RV-Start-02: El texto de “Pulsa start” se ve en itálica.
  • RV-Start-03: El fondo por defecto (a no ser que la regla RG-Start-02 esté activada) es la imagen ZZZZ.

Pantalla de “Mundo libre”
- Maqueta de la pantalla, incluyendo en ella los diferentes hud.

Reglas de gestión:
  • RG-Libre-01: Al recibir un golpe con el jugador desprotegido, el indicador de vida se actualiza con el daño recibido.
  • RG-Libre-02: Al recibir un golpe con el jugador protegido se aprecia una animación y el texto “Block!” encima del jugador.
  • RG-Libre-03: Si tras actualizarse el indicador de vida este tiene 0 puntos de HP o menos, salta la animación de muerte del jugador. Al cabo de 2 segundos salta la animación de “Game Over”. Se produce un fade-off y el jugador es teletransportado al último “save-point”.
  • RB-Libre-04: Al pulsar “Start”, suena el sonido “XXXX”, esperamos 1 segundo y navegamos a la pantalla de “Inventario”.
  • RB-Libre-05: Al mover la rueda del ratón, la cámara se aleja o acerca, produciendo un efecto de Zoom-In/Zoom-Out.
  • RB-Libre-06: Cuando el Zoom es mayor x2 y la configuración gráfica está en “ULTRA”, los objetos y personajes deben de usar sus modelos más detallados (más de 300.000 polígonos por instancia).
  • RB-Libre-07: Cuando el Zoom es menor a x0.5 o la configuración gráfica está en “BAJA”, los objetos y personajes deben de usar sus modelos menos detallados (menos de 10.000 polígonos por instancia).
  • RB-Libre-08: Cuando el Zoom está entre x2 y x0.5 y la configuración gráfica está en “NORMAL” o “ULTRA”, los objetos y personajes deben de usar sus modelos de detalle medio (menos de 100.000 polígonos).
    Como habréis entendido leyendo estos esquemas simples, las especificaciones funcionales describen todas las interacciones posibles del “engine” y (junto al guion que narra la historia de nuestro juego) se trata de un documento que puede ir evolucionando mientras realizamos nuestro desarrollo. Partir de unas funcionalidades simples e ir completándolas a lo largo del tiempo se conoce como “modelo prototipado” y se trata de uno de los modelos tradicionales de elaboración de software. De hecho, cuando trabajamos en un proyecto pequeño, lo mejor es trabajar con un prototipo e ir mejorándolo en cada iteración: Empezamos con unas reglas de gestión básicas y a lo largo de las distintas iteraciones vamos añadiendo nuevas o mejorando las ya existentes. Especificar todo de inicio está bien, pero es poco realista, difícilmente una persona puede listar todas las reglas de gestión y programarlas del tirón.

    Es muy importante señalar que las especificaciones funcionales no deben de definir el guion del juego (al programador a priori debe de darle igual si Zelda es la crush de Link o si el malo mató a sus padres, le han pedido que Link pueda mover rocas grandes y debe de conseguir que Link pueda mover rocas grandes). Con unas especificaciones bien definidas evitamos encontrarnos con sorpresas y reduciremos el número de bugs que puedan surgir durante nuestro desarrollo. Históricamente este documento suele ser el más “gordo” del corpus documentario.

    Ahora que tenemos la “hoja de concepción”, el “DAT” y las “SF” (especificaciones funcionales), ¿qué hacemos? ¿Nos ponemos a programar? ¡NO! El siguiente paso es elaborar una campaña de tests para el motor que hemos definido.

    Y para poder definir esta campaña hay que definir antes un guion básico que nos permita probar todas las funcionalidades que nos permite nuestro motor. Tened en cuenta que cuando defináis esta campaña de tests, el desarrollo aún no está hecho y aún no contáis con el guion final del juego (el cual puede ser cambiante, según inspiración divina) y que a cada vez que hagáis cambios en las especificaciones funcionales (una vez por iteración de tu prototipo), esta campaña de tests debe de ir evolucionando. Puede sonar a construir la casa por el tejado, pero con unas especificaciones funcionales claras y conociendo de antemano los posibles resultados de una campaña de testing, resulta mil veces más fácil programar las distintas tareas: Te han pedido hacer X y sabes que tienes que limitarte a cumplir con Y y Z, evitando reflexiones triviales como “Si pulso A, ¿Link tiene que mover una roca o también puede mover botijos?… oh, espera, no hace falta, en otro test dice que el botijo debe de estar encima de su cabeza si pulso A”. A este tipo de metodología se le conoce como “Test Driven Development”.

    Una forma de crear una campaña básica de testing es creando una habitación vacía y gigante donde podamos testear todas las funcionalidades de forma individual. Un ejemplo de “habitación de testing” (o debug) la tenemos en la mansión del Tomb Raider 1 y 2. Estos dos juegos nos permiten recorrer la mansión de Lara y familiarizarnos con todos los posibles controles que veremos en el juego. Lógicamente, los desarrolladores hacían uso de la casa de lara para poder testear de forma rápida las distintas funcionalidades del juego (disparar a blancos, agacharse, correr, encender bengalas, nadar, activar interruptores, cambios de cámara, etc…) sin tener que guardar 50 save-states. Este tipo de habitación también está presente en los juegos de la saga The Elder Scrolls, pero su uso es menos conocido y sólo es accesible mediante comandos de consola. Esto no quita que cuando acabes tu desarrollo tengas que jugar el modo campaña entero para poder localizar posibles bugs.

    En lo que se refiere a las campañas de tests, existen dos tipos:
  • TNR (tests de no regresión), que incluye probar todas y cada una de las reglas de gestión y visualización que has creado desde el inicio del proyecto. La realización de una campaña de TNR está recomendada cada vez que vayas a liberar una nueva versión al público.
  • De versión, que incluye únicamente las pruebas a hacer sobre las nuevas reglas de gestión y visualización que has creado o que has modificado en la última versión iterativa (no testeas todo, sólo los cambios y los añadidos). Este tipo de campaña es únicamente de tipo interno, para toda versión que no vaya a ser liberada al público. En este tipo de campañas pueden escaparse fácilmente las famosas regresiones, ya que puede darse el caso que la modificación de una parte del código mutualizada por varias reglas de gestión rompa sin querer una o varias de esas reglas. Es por ello que junto a la realización de TNR en las versiones que vayan a ser liberadas al público, intentemos contar en la medida de lo posible con un framework que permita la realización de tests unitarios automatizados.
    Y muy importante, si en tu desarrollo trabajáis más de una persona, para el caso de las campañas de versión, para cada funcionalidad modificada/añadida a probar, la persona que hace el test no debe de ser la persona que ha codificado la evolución.

    Y ahora que hemos definido unas especificaciones funcionales, una campaña de testing y somos conscientes de las limitaciones técnicas… podemos por fin programar. Puede parecer pesado, pero como he dicho antes, una vez que has definido el comportamiento (vía especificaciones funcionales) y que además conoces de antemano los posibles resultados a obtener (vía campaña de test), resulta mucho más fácil programar (ayuda mucho a evitar marcianadas, chapuzas y ñapas).

    Por cierto, cuando codificamos, una buena práctica es el “code peer review”, que básicamente consiste en pedirle a un compañero que revise el código que has hecho para aplicar las nuevas funcionalidades y lo ideal es hacerlo sistemáticamente cuando consideremos que nuestra rama de desarrollo de una funcionalidad X está lista para ser mergeada en la rama principal de desarrollo. Si en tu proyecto no vas a estar sólo, recomiendo encarnizadamente seguir dicha práctica. La gente suele malinterpretarlo, dando a entender que hay que revisar su código por considerarle un incompetente, pero realmente tiene una labor didáctica: Cuando un senior revisa código de un junior, éste le indica las mejoras a aplicar a su código; Cuando un junior revisa el código de un senior, sólo con la lectura sube en competencias de forma indirecta; Cuando un senior revisa a un senior, puede servir a detectar posibles mal entendidos de funcionalidad; Y cuando un junior revisa a un junior, por lo menos uno de los dos acaba aprendiendo algo. Con ello pretendo decir que el “code peer review” no debe de ir ligado siempre a “senior-revisa-a-junior”, puesto que esto puede crear problemas de saturación o de cuello de botella en el perfil senior.

    Existen otros tipos de documentos, como las PTI (proceso técnico de instalación, donde definimos las intervenciones manuales y eventuales a hacer, como por ejemplo instalar nuestro entorno de desarrollo sobre un PC recién comprado o poner en marcha un servidor desde cero) o el DEX (dossier de explotación, donde definimos todos los procesos manuales comunes, como reiniciar un servidor o ponerlo en modo “mantenimiento”)… pero no los mencionaré en esta entrada debido a que no suelen ser pertinentes para proyectos pequeños.

    Y muy importante: No incluyáis ningún password en claro (clave de admin a un servidor, token de acceso, etc…) en estos documentos. La buena práctica pasa por crearse un fichero keypass y hacer referencia a él en el corpus cada vez que sea necesario. El mundo está lleno de malas personas e incluso si pensáis que “no pasa nada, este PC sólo lo uso yo”, puede darse el peligroso caso de que realmente no seas la única persona que lo use.

    Y hasta aquí la entrada de hoy, muchas gracias por vuestra lectura y os invito a volver el viernes 23 de julio para compartiros más acerca de este proyecto y de las metodologías que empleo para llevarlo a cabo.

12 julio 2021

[Blender] Midna (The Legend of Zelda: Twilight Princess), FIN

Coreografía inspirada de la animación de caminar de Sebastian Lague, del meme de baile de Tik Tok de Zero Two (basado a su vez de la canción "2 Phút Hơn" de Pháo) y del "Pac-man Ghosts animation" de Minus8.

     Como véis, he avanzado bastante con el modelado de Midna y lo doy ya por finalizado. Tiene mucho margen de mejora (sobretodo en casco y pelo),  pero no deseo dedicarle más tiempo, puesto que podría pasarme perfectamente otro mes perfeccionándolo. Por lo general he disfrutado mucho con la elaboración de este modelo, sobretodo con la escultura del torso y con la modificación de las partículas (el pelaje que sale de todo el cuerpo).

    Para el sistema de partículas no hay mucho secreto, me limité a añadir muchas de tipo "hair", con dos segmentos y color del material. Después, hice uso del editor de partículas para "peinar" el vello y recortarlo de las zonas azuladas de Midna.





    Después reconstruí la coleta de Midna por completo (adorno inclusive) y la articulé. Sigue sin parecerse mucho a la coleta "real" del personaje, pero por lo menos ahora luce más potable.




 

    Y por último me puse a animar el personaje, dando como resultado el vídeo que habéis visto arriba, al inicio de esta entrada.






09 julio 2021

[Dev-Blog] Proyecto Isekai

     El miércoles me llegó esto desde Australia. Se trata de un "The Joey Jr v2cc" (un flasheador de cartuchos de Game Boy) y de un cartucho virgen de 4 MB de memoria (ojo, mega bytes, equivaldría a 32 mega bits) con una batería de 32 KB de SRAM (para guardar partidas).

    Este dispositivo permite importar y exportar roms y saves de GB, GBC y GBA de una forma muy simple, ya que el equipo de BennVenn lo ha programado de forma que los sistemas operativos lo reconozcan como si se tratara de una memoria USB, viendo las roms y los saves como si de ficheros físicos (con extensiones incluídas) se tratara, haciendo que puedas flashear y extraer contenidos con un simple "drag and drop" (si queréis más información, os invito a ver los vídeos siguientes: https://youtu.be/4koEAEmBk44 y https://www.youtube.com/watch?v=Y1rbQPjSV58).

    Y esto permite hacer muchas virguerías, desde hacer backups de los saves de tus cartuchos de más de 20/30 años (que deben de estar apunto de morir), hasta flashear tus propias copias de juegos que ha día de hoy tienen un precio prohibitivo (https://www.pricecharting.com/console/gameboy, https://www.pricecharting.com/console/pal-gameboy).

    Pero en lo que se refiere a mi persona, no me lo he comprado para hacer mis propias repros, si no para hacer mi propio juego indie. De hecho, recientemente descubrí la existencia de GB Studio, une framework estilo "RPG Maker" que permite hacer tus propias roms de Game Boy y Game Boy Color que funcionan sobre hardware real (https://www.gbstudio.dev/).


    Y ya existen varios juegos indie que hacen uso de este framework, siendo el más famoso Dragonborne.

 

    Y bueno, llevo un par de años con un proyecto de Isekai en mente y me gustaría plasmarlo en un juego. Así que cada viernes os iré compartiendo mis batallitas sobre su desarrollo. Para más información, os invito a visitar mi blog el viernes 16 de julio.

05 julio 2021

[Blender] [WIP] Midna (The Legend of Zelda: Twilight Princess), semana 2

    Bienvenidos a un nuevo "lunes de Seb" en el que os compartiré los avances que llevo hechos con la Midna que estoy modelando en Blender.




    Lo primero que hice fue alterar el tamaño de los muslos, ya que no sólo no eran acordes con la anatomía humana, si no que ni siquiera eran acordes con la anatomía del personaje. Para "solucionarlo" alteré la posición de los vértices en el modo edición  y le di un repaso por el modo escultura.



    Después me puse a darle un repaso a la visera, dándole forma por el modo escultura y comenzando a texturizarla a mano alzada.





    Después hice una pequeña pausa para centrarme en los dientes y en la lengua. Como base de ambas piezas partí de la boca y la lengua que hice para Erufu, pero alterando la dentadura para dar forma al famoso comillo de Midna.





    Después seguí con la texturización del casco y de la visera, dándoles un repaso por Gimp para darles un efecto de mármol. También me pegué bastante con la herramienta del cuchillo para deformar el casco a mi gusto (haciendo uso de "extrudes"), dándole un toque de relieve y de irregularidad.





    Acto seguido me puse a texturizar los tatuajes de Midna que tiene en su muslo derecho, en su tobillo izquierdo y en ambos brazos. Todo a mano alzada y con las herramientas de texturización de Blender.





    Y también le di un repaso a la base del pelo y a la coleta. Aunque bueno, no me han gustado cómo han quedado y seguramente en la siguiente semana le de un repaso a ambas piezas.



    Y para acabar esta semana, me puse también con el esqueleto y las articulaciones del personaje, aplicándole los "inverse kinematics" que me gustan, revisando los vertex groups y los weight paints, etc. De hecho, aprovecho para comentar un bug (que desconozco si estará ligado a la nueva versión 2.93.1) que produce que los "automatic weights" no funcionen si el objeto tiene un número elevado de caras. Nunca antes me había pasado, pero para solucionarlo el workaround fue simple: Aplicar un modificador de "Decimate" para reducir el número de polígonos (si lo aplicáis, recomiendo activar la opción de simetría en el eje "x").



     Y poco más, el modelo se va finalizando y el próximo lunes 12 os compartiré otra vez los avances.