Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Programming

Codificación de terreno de píxeles destructible: cómo hacer que todo explote

by
Read Time:11 minsLanguages:

Spanish (Español) translation by Juan Pablo Diaz Cuartas (you can also view the original English article)

En este tutorial, implementaremos un terreno de píxeles totalmente destruible, al estilo de juegos como Cortex Command y Worms. Aprenderá cómo hacer que el mundo explote donde sea que lo fotografíe, y cómo hacer que el "polvo" se asiente en el suelo para crear nuevas tierras.

Nota: Aunque este tutorial está escrito en Procesamiento y compilado con Java, debería ser capaz de utilizar las mismas técnicas y conceptos en casi cualquier entorno de desarrollo de juegos.


Vista previa del resultado final

Usted también puede jugar la demostración. WASD para moverse, haga clic izquierdo para disparar balas explosivas, haga clic derecho para rociar píxeles.


Paso 1: el terreno

En nuestra caja de arena de desplazamiento lateral, el terreno será la mecánica principal de nuestro juego. Algoritmos similares a menudo tienen una imagen para la textura del terreno, y otra como una máscara en blanco y negro para definir qué píxeles son sólidos. En esta demostración, el terreno y su textura son todos una imagen, y los píxeles son sólidos en función de si son transparentes o no. El enfoque de la máscara sería más apropiado si desea definir las propiedades de cada píxel, como la probabilidad de que se desaloje o el rebote del píxel.

Para representar el terreno, el arenero dibuja los píxeles estáticos primero, luego los píxeles dinámicos con todo lo demás en la parte superior

El terreno también tiene métodos para averiguar si un píxel estático en una ubicación es sólido o no, y métodos para eliminar y agregar píxeles. Probablemente la forma más efectiva de almacenar la imagen es como una matriz de 1 dimensión. Obtener un índice 1D a partir de una coordenada 2D es bastante simple:

Para que los píxeles dinámicos reboten, tendremos que ser capaces de descubrir la superficie normal en cualquier punto. Haz un bucle a través de un área cuadrada alrededor del punto deseado, busca todos los píxeles sólidos cercanos y promedia su posición. Tome un vector desde esa posición hasta el punto deseado, inviértalo y normalícelo. ¡Es tu normalidad!

Las líneas negras representan las normales al terreno en varios puntos.

Así es como se ve en el código:


Paso 2: el píxel dinámico y la física

El "Terreno" en sí mismo almacena todos los píxeles estáticos no móviles. Los píxeles dinámicos son píxeles actualmente en movimiento y se almacenan por separado de los píxeles estáticos. A medida que el terreno explota y se asienta, los píxeles cambian entre estados estáticos y dinámicos a medida que se desalojan y colisionan. Cada píxel se define por una serie de propiedades:

  • Posición y velocidad (requerida para que la física funcione).
  • No solo la ubicación, sino también la ubicación previa del píxel. (Podemos escanear entre los dos puntos para detectar colisiones).
  • Otras propiedades incluyen el color del píxel, la pegajosidad y el rebote.

Para que el píxel se mueva, su posición debe reenviarse con su velocidad. La integración de Euler, aunque es inexacta para simulaciones complejas, es lo suficientemente simple como para que podamos mover nuestras partículas de manera eficiente:

El tiempo transcurrido es la cantidad de tiempo transcurrido desde la última actualización. La precisión de cualquier simulación puede romperse por completo si el tiempo transcurrido es demasiado variable o demasiado grande. Esto no es un gran problema para los píxeles dinámicos, pero lo será para otros esquemas de detección de colisión.

Utilizaremos tiempos predeterminados de tamaño fijo, tomando el tiempo transcurrido y dividiéndolo en trozos de tamaño constante. Cada fragmento es una "actualización" completa de la física, y todo sobrante se envía al siguiente fotograma.


Paso 3: Detección de colisión

La detección de colisiones para nuestros píxeles voladores es tan simple como dibujar algunas líneas.

El algoritmo de línea de Bresenham fue desarrollado en 1962 por un caballero llamado Jack E. Bresenham. Hasta el día de hoy, se ha utilizado para dibujar líneas alias simplificadas de manera eficiente. El algoritmo se adhiere estrictamente a los enteros y usa principalmente sumas y restas para trazar líneas con eficacia. Hoy lo usaremos para un propósito diferente: detección de colisión.

Estoy usando un código tomado de un artículo en gamedev.net. Si bien la mayoría de las implementaciones del algoritmo de línea de Bresenham reordena el orden de dibujo, este en particular nos permite escanear siempre de principio a fin. El orden es importante para la detección de colisiones; de lo contrario, detectaremos colisiones en el extremo equivocado de la ruta del píxel.

La pendiente es una parte esencial del algoritmo de línea de Bresenham. El algoritmo funciona dividiendo la pendiente en sus componentes "subir" y "ejecutar". Si, por ejemplo, la pendiente de la línea fuera 1/2, podemos trazar la línea colocando dos puntos horizontalmente, subiendo (y a la derecha) uno, y luego dos más.

El algoritmo que estoy mostrando aquí da cuenta de todos los escenarios, si las líneas tienen una pendiente positiva o negativa o si es vertical. El autor explica cómo lo deriva en gamedev.net.


Paso 4: Manejo de colisiones

El píxel dinámico puede hacer una de dos cosas durante una colisión.

  • Si se mueve lo suficientemente lento, el píxel dinámico se elimina y se agrega uno estático al terreno donde colisionó. Apegarse sería nuestra solución más simple. En el algoritmo de línea de Bresenham, es mejor hacer un seguimiento de un punto anterior y un punto actual. Cuando se detecta una colisión, el "punto actual" será el primer píxel sólido que golpea el rayo, mientras que el "punto anterior" es el espacio vacío justo antes de este. El punto anterior es exactamente la ubicación donde necesitamos pegar el píxel.
  • Si se mueve demasiado rápido, lo rebotamos fuera del terreno. ¡Aquí es donde entra nuestro algoritmo de superficie normal! Refleja la velocidad inicial de la bola sobre la normal para rebotarla.
  • El ángulo a cada lado de lo normal es el mismo.


Paso 5: balas y explosiones!

Las viñetas actúan exactamente como los píxeles dinámicos. El movimiento está integrado de la misma manera, y la detección de colisiones utiliza el mismo algoritmo. Nuestra única diferencia es el manejo de colisiones

Después de que se detecta una colisión, las balas explotan al eliminar todos los píxeles estáticos dentro de un radio, y luego colocar píxeles dinámicos en su lugar con sus velocidades apuntando hacia afuera. Utilizo una función para escanear un área cuadrada alrededor del radio de una explosión para descubrir qué píxeles desalojar. Luego, la distancia del píxel desde el centro se usa para establecer una velocidad.


Paso 6: El jugador

El jugador no es una parte central de la mecánica del terreno destructible, pero implica una detección de colisión que será definitivamente relevante para los problemas que llegarán en el futuro. Explicaré cómo se detecta y maneja la colisión en la demostración para el jugador.

  1. Para cada borde, bucle de una esquina a la siguiente, comprobando cada píxel.
  2. Si el píxel es sólido, comience en el centro del jugador y escanee hacia ese píxel para golpear un píxel sólido.
  3. Mueva el reproductor lejos del primer píxel sólido que golpee.

Paso 7: Optimizar

Miles de píxeles se están manejando a la vez, lo que provoca un gran esfuerzo en el motor de física. Al igual que cualquier otra cosa, para hacer esto rápido, recomendaría usar un lenguaje que sea razonablemente rápido. La demostración está compilada en Java.

También puedes hacer cosas para optimizar en el nivel del algoritmo. Por ejemplo, la cantidad de partículas de explosiones puede reducirse al disminuir la resolución de destrucción. Normalmente encontramos cada píxel y lo convertimos en un píxel dinámico de 1x1. En su lugar, escanee cada 2x2 píxeles, o 3x3, y ejecute un píxel dinámico de ese tamaño. En la demostración, usamos 2x2 píxeles.

Si está utilizando Java, la recolección de basura será un problema. La JVM encontrará periódicamente objetos en la memoria que ya no se utilizan, como los píxeles dinámicos que se descartan a cambio de píxeles estáticos, y trata de deshacerse de ellos para dejar espacio para más objetos. Sin embargo, eliminar objetos, toneladas de objetos requiere tiempo, y cada vez que la JVM realiza una limpieza, nuestro juego se congela brevemente.

Una posible solución es usar un caché de algún tipo. En lugar de crear / destruir objetos todo el tiempo, simplemente puede contener objetos muertos (como píxeles dinámicos) para reutilizarlos más tarde.

Use primitivas siempre que sea posible. Por ejemplo, usar objetos para posiciones y velocidades va a hacer las cosas un poco más difíciles para la recolección de basura. Sería aún mejor si pudieras almacenar todo como primitivos en matrices unidimensionales.


Paso 8: Hágalo usted mismo

Hay muchas direcciones diferentes que puedes tomar con esta mecánica de juego. Las características se pueden agregar y personalizar para combinar con cualquier estilo de juego que desee.

Por ejemplo, las colisiones entre píxeles dinámicos y estáticos se pueden manejar de manera diferente. Una máscara de colisión bajo el terreno se puede usar para definir la adherencia, el rebote y la fuerza de cada píxel estático, o la probabilidad de ser desplazado por una explosión.

Hay una variedad de cosas diferentes que puedes hacer con las armas también. Las balas pueden tener una "profundidad de penetración" para permitir que se mueva a través de tantos píxeles antes de explotar. La mecánica tradicional de armas también se puede aplicar, como una variada cadencia de fuego o, como una escopeta, se pueden disparar múltiples balas a la vez. Incluso puede, como en el caso de las partículas hinchables, que las balas reboten en los píxeles metálicos.


Conclusión

La destrucción 2D del terreno no es completamente única. Por ejemplo, los clásicos Gusanos y tanques eliminan partes del terreno en explosiones. Cortex Command utiliza partículas animosas similares que usamos aquí. Otros juegos también podrían, pero aún no he oído hablar de ellos. Espero con ansias ver lo que otros desarrolladores harán con esta mecánica.

La mayor parte de lo que he explicado aquí está completamente implementado en la demostración. Por favor, eche un vistazo a su fuente si algo parece ambiguo o confuso. He agregado comentarios a la fuente para hacerlo lo más claro posible. ¡Gracias por leer!

Advertisement
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.