Advertisement
  1. Game Development
  2. Tile-Based Games

Cómo utilizar Tile Bitmasking para formar automáticamente sus diseños de nivel

Scroll to top
Read Time: 13 min

() translation by (you can also view the original English article)

Elaborar un conjunto de fichas visualmente atractivo y variado es un proceso lento, pero los resultados a menudo lo valen. Sin embargo, incluso después de crear el arte, ¡todavía tienes que unirlo todo dentro de tu nivel!

Puede colocar cada mosaico, uno por uno, a mano, o puede automatizar el proceso mediante el uso de máscara de bits, por lo que solo necesita dibujar la forma del terreno.

¿Qué es Tile Bitmasking?

What is tile bitmaskingWhat is tile bitmaskingWhat is tile bitmasking

La máscara de bits en mosaico es un método para seleccionar automáticamente el sprite apropiado de un conjunto de fichas definido. Esto le permite colocar un mosaico de marcador de posición genérico donde quiera que aparezca un tipo particular de terreno en lugar de colocar una selección potencialmente enorme de varios mosaicos.

Vea este video para una demostración:

(Puede descargar las demos y los archivos fuente desde el repositorio de GitHub).

Cuando se trata de múltiples tipos de terreno, el número de variaciones diferentes puede exceder 300 o más fichas. Dibujar estos muchos sprites diferentes es definitivamente un proceso que lleva mucho tiempo, pero el enmascaramiento de los mosaicos asegura que el acto de colocar estos mosaicos sea rápido y eficiente.

Con una implementación estática de enmascaramiento de bits, los mapas se generan en tiempo de ejecución. Con algunos pequeños retoques, puedes expandir el enmascaramiento de bits para permitir que los mosaicos dinámicos cambien durante el juego. En este tutorial, cubriremos los aspectos básicos de la máscara de bits de mosaico mientras trabajamos hacia implementaciones más complicadas que utilizan mosaicos de esquina y múltiples tipos de terreno.

Cómo funciona Tile Bitmasking

Visión general

El enmascaramiento de mosaicos se trata de calcular un valor numérico y asignar un sprite específico basado en ese valor. Cada mosaico mira sus fichas vecinas para determinar qué sprite del conjunto se asigna a sí mismo.

Cada sprite en un conjunto de fichas está numerado, y el proceso de enmascaramiento de bits devuelve un número correspondiente a la posición de un sprite en el conjunto de fichas. En tiempo de ejecución, se lleva a cabo el procedimiento de enmascaramiento de bit, y cada tesela se actualiza con el sprite apropiado.

Example terrain sprite sheet for tile bitmaskingExample terrain sprite sheet for tile bitmaskingExample terrain sprite sheet for tile bitmasking

La hoja de sprites anterior consiste en fichas de terreno con todas las posibles configuraciones de borde. Los números en cada tesela representan el valor de enmascaramiento de bits, que aprenderemos a calcular en la siguiente sección. Por ahora, es importante entender cómo se relaciona el valor de la máscara de bits con el conjunto de fichas del terreno. Los sprites se ordenan secuencialmente de modo que un valor de máscara de bits de 0 devuelve el primer sprite, hasta llegar a un valor de 15 que devuelve el 16to sprite.

Cálculo del valor de enmascaramiento de bits

Calcular este valor es relativamente simple. En este ejemplo, asumimos un solo tipo de terreno sin piezas de esquina.

Cada tesela comprueba la existencia de teselas en el norte, oeste, este y sur, y cada comprobación arroja un valor booleano, donde 0 representa un espacio vacío y 1 indica la presencia de otro mosaico de terreno.

Este resultado booleano se multiplica por el valor direccional binario y se suma al total acumulado del valor de máscara de bits; es más fácil de entender con algunos ejemplos:

Valores direccionales de 4 bits

  • Norte = 20 = 1
  • Oeste = 21 = 2
  • Este = 22 = 4
  • Sur = 23 = 8
Tile bitmasking exampleTile bitmasking exampleTile bitmasking example

El cuadrado verde en la figura de arriba representa el mosaico de terreno que estamos calculando. Comenzaremos por buscar un mosaico en el norte. No hay ninguna ficha al norte, por lo que la verificación booleana devuelve un valor de 0. Multiplicamos 0 por el valor direccional para Norte, 20 = 1, lo que nos da 1 * 0 = 0.

Para un mosaico de terreno rodeado completamente por espacio vacío, cada comprobación booleana devuelve 0, lo que da como resultado el número binario de 4 bits 0000 o 1 * 0 + 2 * 0 + 4 * 0 + 8 * 0 = 0. Hay 16 combinaciones posibles en total , de 0 a 15, por lo que el 1er sprite en el conjunto de fichas se usará para representar este tipo de mosaico de terreno con un valor de 0.

Tile bitmasking exampleTile bitmasking exampleTile bitmasking example
Un mosaico de terreno bordeado por una sola loseta hacia el norte devuelve un valor binario de 0001, o 1 * 1 + 2 * 0 + 4 * 0 + 8 * 0 = 1. El 2do sprite en el conjunto de fichas se usará para representar este tipo de terreno con un valor de 1.
Tile bitmasking exampleTile bitmasking exampleTile bitmasking example

Un mosaico de terreno bordeado por un azulejo al norte y un azulejo al este devuelve un valor binario de 0101 o 1 * 1 + 2 * 0 + 4 * 1 + 8 * 0 = 5. El sexto sprite en el juego de fichas será usado para representar este tipo de terreno con un valor de 5.

Tile bitmasking exampleTile bitmasking exampleTile bitmasking example

Un mosaico de terreno bordeado por un azulejo al este y un azulejo al oeste devuelve un valor binario de 0110, o 1 * 0 + 2 * 1 + 4 * 1 + 8 * 0 = 6. El séptimo sprite en el juego de fichas será usado para representar este tipo de terreno con un valor de 6.

Asignación de Sprites a Mosaicos

Después de calcular el valor de enmascaramiento de una ficha, asignamos el sprite apropiado del conjunto de fichas. Este paso final se puede realizar en tiempo real a medida que se carga el mapa, o el resultado se puede guardar y cargar en el editor de mosaico de su elección para su posterior edición.

Tile bitmasking how tiles are assigned based on the terrains shapeTile bitmasking how tiles are assigned based on the terrains shapeTile bitmasking how tiles are assigned based on the terrains shape

La figura de la izquierda representa un conjunto de mosaicos de un solo terreno de 4 bits, ya que aparecería secuencialmente en una hoja de mosaico. La figura de la derecha muestra cómo se ven las fichas en el juego una vez que se han colocado usando el procedimiento de enmascaramiento de bits. Cada mosaico está marcado con su valor de máscara de bits para mostrar la relación entre el orden de un mosaico en la hoja de mosaico y su posición en el juego.

Como ejemplo, examinemos el mosaico en la esquina superior derecha de la figura de la derecha. Este azulejo está bordeado por azulejos al oeste y sur. La verificación booleana devuelve un valor binario de 1010, o 1 * 0 + 2 * 1 + 4 * 0 + 8 * 1 = 10. Este valor corresponde al 11mo sprite en la hoja de mosaico.

Complejidad de fichas

La cantidad de verificaciones booleanas direccionales requeridas depende de la complejidad prevista de su conjunto de fichas. Al ignorar las piezas de esquina, puede usar esta solución simplificada de 4 bits que solo requiere cuatro comprobaciones binarias direccionales.

¿Pero qué sucede cuando quieres crear un terreno más atractivo visualmente? Tendrá que lidiar con la existencia de los mosaicos de esquina, lo que aumenta la cantidad de sprites de 16 a 48. El siguiente ejemplo de máscara de bits de 8 bits requiere ocho comprobaciones direccionales booleanas por tesela.

8 bits Bitmasking con mosaicos de esquina

Para este ejemplo, estamos creando un juego de fichas de arriba hacia abajo que representa el terreno cubierto de hierba cerca del océano. En este caso, nuestro océano existe en una capa debajo de las fichas del terreno. Esto nos permite utilizar una solución de un solo terreno, manteniendo la ilusión de que dos tipos de terreno están colisionando.

Una vez que el juego se está ejecutando y el procedimiento de enmascaramiento de bits está completo, los sprites nunca cambiarán. Esta es una implementación inamovible y estática de la máscara de bits donde todo tiene lugar antes de que el jugador vea las fichas.

Presentando mosaicos de esquina

Queremos que el terreno sea más visualmente interesante que la solución anterior de 4 bits, por lo que se requieren piezas de esquina. Esta complejidad visual adicional requiere una cantidad exponencial de trabajo adicional para el artista, el programador y el juego en sí. Al ampliar lo que aprendimos de la solución de 4 bits, podemos comprender rápidamente cómo abordar la solución de 8 bits.

A sprite sheet of an example tilesetA sprite sheet of an example tilesetA sprite sheet of an example tileset

Aquí está la hoja de sprites completa para nuestros mosaicos del lado del océano. ¿Notaste algo peculiar sobre la cantidad de fichas? El ejemplo de 4 bits de antes dio como resultado 24 = 16 teselas, por lo que este ejemplo de 8 bits seguramente debería dar como resultado 28 = 256 teselas, aunque hay claramente menos que eso allí.

Si bien es cierto que este procedimiento de enmascaramiento de bits de 8 bits da como resultado 256 valores binarios posibles, no todas las combinaciones requieren un mosaico completamente único. El siguiente ejemplo ayudará a explicar cómo se pueden representar 256 combinaciones con solo 48 mosaicos.

Valores direccionales de 8 bits

  • Noroeste = 20 = 1
  • Norte = 21 = 2
  • Nordeste = 22 = 4
  • Oeste = 23 = 8
  • Este = 24 = 16
  • Suroeste = 25 = 32
  • Sur = 26 = 64
  • Sureste = 27 = 128
Tile bitmasking 8-bit exampleTile bitmasking 8-bit exampleTile bitmasking 8-bit example

Ahora estamos haciendo ocho controles direccionales booleanos. El mosaico central de arriba está bordeado por mosaicos al norte, noreste y este, por lo que esta comprobación booleana devuelve un valor binario de 00010110 o 1 * 0 + 2 * 1 + 4 * 1 + 8 * 0 + 16 * 1 + 32 * 0 + 64 * 0 + 128 * 0 = 22.

Tile bitmasking 8-bit exampleTile bitmasking 8-bit exampleTile bitmasking 8-bit example

El mosaico de la izquierda de arriba es similar al mosaico anterior, pero ahora también está bordeado por mosaicos al suroeste y sureste. Esta verificación direccional Booleana debería devolver un valor binario de 10110110, o 1 * 0 + 2 * 1 + 4 * 1 + 8 * 0 + 16 * 1 + 32 * 1 + 64 * 0 + 128 * 1 = 182.

Este valor es diferente del mosaico anterior, pero ambos mosaicos serían visualmente idénticos, por lo que se vuelve redundante.

Para eliminar las redundancias, agregamos una condición adicional a nuestra verificación direccional booleana: cuando verifiquemos la presencia de fichas de esquina aledañas, también debemos verificar las fichas vecinas en los cuatro puntos cardinales (directamente al norte, este, sur u oeste) .

Por ejemplo, la ficha al noreste está rodeada por fichas existentes, mientras que las fichas al sudoeste y sudeste no lo están. Esto significa que las fichas Suroeste y Sureste no están incluidas en el cálculo de la máscara de bits.

Con esta nueva condición, esta comprobación booleana devuelve un valor binario de 00010110 o 1 * 0 + 2 * 1 + 4 * 1 + 8 * 0 + 16 * 1 + 32 * 0 + 64 * 0 + 128 * 0 = 22 antes de. Ahora puede ver cómo las 256 combinaciones se pueden representar con solo 48 mosaicos.

Orden de baldosas

Otro problema que puede notar es que los valores calculados por el procedimiento de enmascaramiento de bits de 8 bits ya no se correlacionan con el orden secuencial de los mosaicos en la hoja de sprites. Solo hay 48 teselas, pero nuestros posibles valores calculados van de 0 a 255, por lo que ya no podemos utilizar el valor calculado como referencia directa cuando tomamos el sprite apropiado.

Lo que necesitamos, por lo tanto, es una estructura de datos para contener la lista de valores calculados y sus valores de mosaicos correspondientes. La forma en que desee implementar esto depende de usted, pero recuerde que el orden en el que verifica las fichas circundantes dicta el orden en que las fichas deben colocarse en la hoja de sprites.

Para este ejemplo, verificamos los mosaicos adyacentes en el siguiente orden: Noroeste, Norte, Noreste, Oeste, Este, Sudoeste, Sur, Sudeste.

A continuación se muestra el conjunto completo de valores de enmascaramiento de bits que se relacionan con las posiciones de los mosaicos en nuestra hoja de sprites (no dude en utilizar estos valores en su proyecto para ahorrar tiempo):

1
{ 2 = 1, 8 = 2, 10 = 3, 11 = 4, 16 = 5, 18 = 6, 22 = 7, 24 = 8, 26 = 9, 27 = 10, 30 = 11, 31 = 12, 64 = 13, 66 = 14, 72 = 15, 74 = 16, 75 = 17, 80 = 18, 82 = 19, 86 = 20, 88 = 21, 90 = 22, 91 = 23, 94 = 24, 95 = 25, 104 = 26, 106 = 27, 107 = 28, 120 = 29, 122 = 30, 123 = 31, 126 = 32, 127 = 33, 208 = 34, 210 = 35, 214 = 36, 216 = 37, 218 = 38, 219 = 39, 222 = 40, 223 = 41, 248 = 42, 250 = 43, 251 = 44, 254 = 45, 255 = 46, 0 = 47 }

Múltiples tipos de terreno

Todos nuestros ejemplos anteriores asumen un solo tipo de terreno, pero ¿y si introducimos un segundo terreno en la ecuación? Necesitamos una solución de enmascaramiento de bits de 5 bits, y tenemos que definir nuestros dos tipos de terreno. También debemos asignar un valor al mosaico central que solo se cuenta bajo condiciones específicas. Recuerde que ya no contabilizamos el "espacio vacío" como en los ejemplos anteriores; las fichas ahora deben estar rodeadas por otra ficha en todos los lados.

Tile bitmasking 8-bit example with multiple terrain typesTile bitmasking 8-bit example with multiple terrain typesTile bitmasking 8-bit example with multiple terrain types

La figura anterior muestra un ejemplo con dos tipos de terreno y sin azulejos de esquina. Tipo 1 siempre devuelve un valor de 0 siempre que se detecte durante la verificación direccional; el valor del mosaico central se calcula y usa solo si es tipo de terreno 2.

El mosaico central del ejemplo anterior está rodeado por el tipo de terreno 2 al norte, oeste y este, y por tipo de terreno 1 al sur. El mosaico central es del tipo de terreno 1, por lo que no se cuenta. Esta comprobación booleana devuelve un valor binario de 00111 o 1 * 1 + 2 * 1 + 4 * 1 + 8 * 0 + 16 * 0 = 7.

Tile bitmasking 8-bit example with multiple terrain typesTile bitmasking 8-bit example with multiple terrain typesTile bitmasking 8-bit example with multiple terrain types

En este ejemplo, nuestro mosaico central es tipo de terreno 2, por lo que se contará en el cálculo. La losa central está rodeada por el terreno tipo 2 al norte y al oeste. También está rodeado por el terreno tipo 1 hacia el este y el sur. Esta comprobación booleana devuelve un valor binario de 10011 o 1 * 1 + 2 * 1 + 4 * 0 + 8 * 0 + 16 * 1 = 19.

Implementación dinámica

El cálculo de la máscara de bits también se puede realizar durante el juego, lo que permite cambios en tiempo real en la colocación y apariencia del azulejo. Esto es útil para terrenos destructibles y juegos que permiten la creación y construcción. El procedimiento de enmascaramiento de bits inicial es obligatorio para todas las fichas, pero cualquier cálculo dinámico adicional solo debe realizarse cuando sea absolutamente necesario. Por ejemplo, un mosaico de terreno destruido activaría el cálculo de la máscara de bits solo para los mosaicos circundantes.

Conclusión

Tile bitmasking es el ejemplo perfecto de cómo construir un sistema que funcione para ayudarte en el desarrollo de juegos. No es algo que tenga un impacto directo en la experiencia del jugador; en cambio, este método de automatizar una porción de diseño de nivel que consume mucho tiempo proporciona un beneficio valioso para el desarrollador. En pocas palabras: el enmascaramiento de fichas es una manera rápida de hacer que el juego haga su trabajo sucio, permitiéndole concentrarse en tareas más importantes.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Game Development tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.