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

Simule telas desechables y ragdolls con una integración simple de Verlet

by
Read Time:12 minsLanguages:

Spanish (Español) translation by Elías Nicolás (you can also view the original English article)

La dinámica del cuerpo suave consiste en simular objetos deformables realistas. Lo utilizaremos aquí para simular una cortina de tela desgarrable y un conjunto de ragdolls con los que puede interactuar y arrojar alrededor de la pantalla. Será rápido, estable y lo suficientemente simple como para hacerlo con las matemáticas de nivel secundario.

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


Vista previa del resultado final

En esta demostración, puedes ver una gran cortina (mostrando la simulación de la tela), y una serie de pequeños stickmen (mostrando la simulación de ragdoll):

También puedes probar la demo. Haga clic y arrastre para interactuar, presione 'R' para restablecer, y presione 'G' para alternar la gravedad.


Paso 1: Un punto y su movimiento

Los bloques de construcción de nuestro juego con ser el punto. Para evitar la ambigüedad, lo llamaremos PointMass. Los detalles están en el nombre: es un punto en el espacio y representa una cantidad de masa.

La forma más básica de implementar la física para este punto es "reenviar" su velocidad de alguna manera.


Paso 2: Pasos de tiempo

No podemos asumir que nuestro juego se ejecutará a la misma velocidad todo el tiempo. Puede funcionar a 15 cuadros por segundo para algunos usuarios, pero a 60 para otros. Es mejor tener en cuenta las tasas de fotogramas de todos los rangos, lo que se puede hacer usando un paso de tiempo.

De esta manera, si un cuadro tardara más en transcurrir para una persona que para otra, el juego seguiría funcionando a la misma velocidad. Para un motor de física, sin embargo, esto es increíblemente inestable.

Imagina si tu juego se congela por un segundo o dos. El motor compensaría en exceso eso, y movería la PointMass más allá de varias paredes y objetos con los que, de otro modo, habría detectado una colisión. Por lo tanto, no solo se vería afectada la detección de colisiones, sino también el método de resolución de restricciones que utilizaremos.

¿Cómo podemos tener la estabilidad de la primera ecuación, x = x + velX, con la consistencia de la segunda ecuación, x = x + velX * timeElapsed? ¿Y si, tal vez, pudiéramos combinar los dos?

Eso es exactamente lo que haremos. Imagine que nuestro timeElapsed fue 30. Podríamos hacer exactamente lo mismo que la última ecuación, pero con una mayor precisión y resolución, llamando x = x + (velX * 5) seis veces.

El algoritmo aquí utiliza un paso de tiempo fijo mayor que uno. Encuentra el tiempo transcurrido, lo divide en "trozos" de tamaño fijo y empuja la cantidad restante de tiempo al siguiente fotograma. Ejecutamos la simulación poco a poco para cada parte en la que se divide nuestro tiempo transcurrido.

Escogí 16 para el tamaño del paso del tiempo, para simular la física como si estuviera funcionando a aproximadamente 60 cuadros por segundo. La conversión de elapsedTime a cuadros por segundo se puede hacer con algunas matemáticas: 1 second / elapsedTimeInSeconds.

1s / (16ms/1000s) = 62.5fps, por lo que un paso de tiempo de 16ms es equivalente a 62.5 cuadros por segundo.


Paso 3: Restricciones

Las restricciones son restricciones y reglas agregadas a la simulación, que guían dónde PointMasses puede y no puede ir.

Pueden ser simples como esta restricción de límite, para evitar que las PointMass se muevan fuera del borde izquierdo de la pantalla:

La adición de la restricción para el borde derecho de la pantalla se realiza de manera similar:

Hacer esto para el eje y es una cuestión de cambiar cada x a una y.

Tener el tipo correcto de restricciones puede resultar en interacciones muy hermosas y cautivadoras. Las restricciones también pueden llegar a ser extremadamente complejas. Intenta imaginarte simulando una canasta vibrante de granos con ninguno de los granos que se intersecan, o un brazo robótico de 100 articulaciones, o incluso algo tan simple como una pila de cajas. El proceso típico consiste en encontrar puntos de colisión, encontrar la hora exacta de colisión y luego encontrar la fuerza o el impulso adecuado para aplicar a cada cuerpo para evitar esa colisión.

Comprender la cantidad de complejidad que puede tener un conjunto de restricciones puede ser difícil, y luego resolver esas restricciones en tiempo real es aún más difícil. Lo que haremos es simplificar la resolución de restricciones significativamente.


Paso 4: Integración de Verlet

Un matemático y programador llamado Thomas Jakobsen exploró algunas formas de simular la física de los personajes para los juegos. Él propuso que la precisión no es tan importante como la credibilidad y el rendimiento. El corazón de todo su algoritmo fue un método utilizado desde los años 60 para modelar dinámicas moleculares, llamado Integración de Verlet. Puede que estés familiarizado con el juego Hitman: Codename 47. Fue uno de los primeros juegos en usar la física de ragdoll, y usa los algoritmos desarrollados por Jakobsen.

La integración de Verlet es el método que utilizaremos para reenviar la posición de nuestro PointMass. Lo que hicimos antes, x = x + velX, es un método llamado Integración de Euler (que también usé en Codificación del terreno de píxeles destructibles).

La principal diferencia entre Euler y Verlet Integration es cómo se implementa la velocidad. Usando Euler, se almacena una velocidad con el objeto y se agrega a la posición del objeto en cada cuadro. Sin embargo, el uso de Verlet aplica la inercia utilizando la posición anterior y actual. Tome la diferencia en las dos posiciones y agréguela a la última posición para aplicar la inercia.

Agregamos aceleración allí para la gravedad. Aparte de eso, accX y accY no serán necesarios para resolver colisiones. Con la integración de Verlet, ya no necesitamos hacer ningún tipo de impulso o fuerza para resolver colisiones. Cambiar la posición solo será suficiente para tener una simulación estable, realista y rápida. Lo que Jakobsen desarrolló es un sustituto lineal de algo que de otra manera no sería lineal.


Paso 5: Restricciones de enlace

Los beneficios de la integración de Verlet se pueden mostrar mejor a través del ejemplo. En un motor de tela, no solo tendremos PointMasses, sino también enlaces entre ellos. Nuestros "enlaces" serán una restricción de distancia entre dos PointMasses. Idealmente, queremos que dos PointMasses con esta restricción estén siempre a cierta distancia.

Cada vez que resolvemos esta restricción, la Integración de Verlet debería mantener a estos puntos en movimiento. Por ejemplo, si un extremo se moviera rápidamente hacia abajo, el otro extremo debería seguirlo como un látigo a través de la inercia.

Solo necesitaremos un enlace para cada par de PointMasses que se adjunten entre sí. Todos los datos que necesitará en el enlace son las PointMasses y las distancias de descanso. Opcionalmente, puede tener rigidez, por más de una restricción de resorte. En nuestra demostración también tenemos una "sensibilidad al desgarro", que es la distancia a la que se eliminará el enlace.

Aquí solo explicaré RestanceDistance, pero la distancia al rasgado y la rigidez están implementadas en la demostración y en el código fuente.

Puedes usar el álgebra lineal para resolver la restricción. Encuentre las distancias entre los dos, determine qué tan lejos están restingDistance, luego tradúzcalas en base a eso y sus diferencias.

En la demostración, también tenemos en cuenta la masa y la rigidez. Hay algunos problemas para resolver esta restricción. Cuando hay más de dos o tres PointMasses vinculadas entre sí, resolver algunas de estas restricciones puede violar otras restricciones previamente resueltas.

Thomas Jakobsen también tuvo este problema. Al principio, uno podría crear un sistema de ecuaciones y resolver todas las restricciones a la vez. Sin embargo, esta complejidad aumentaría rápidamente y sería difícil agregar más que solo unos pocos enlaces al sistema.

Jakobsen desarrolló un método que podría parecer tonto e ingenuo al principio. Él creó un método llamado "relajación", donde en lugar de resolver la restricción una vez, lo resolvemos varias veces. Cada vez que reiteramos y resolvemos los vínculos, el conjunto de vínculos se acerca cada vez más a todos los que se resuelven.

Paso 6: Juntarlo

Para resumir, aquí está cómo funciona nuestro motor en pseudocódigo. Para un ejemplo más específico, echa un vistazo al código fuente de la demostración.


Paso 7: Añadir una tela

Ahora podemos construir el propio tejido. Crear los enlaces debe ser bastante simple: enlace a la izquierda cuando PointMass no es el primero en su fila, y enlace cuando no es el primero en su columna.

La demostración utiliza una lista unidimensional para almacenar PointMasses, y encuentra puntos para enlazar utilizando x + y * width.

Puede notar en el código que también tenemos "pin PM". Si no queremos que caiga nuestra cortina, podemos bloquear la fila superior de PointMasses en sus posiciones iniciales. Para programar una restricción de pines, agregue algunas variables para realizar un seguimiento de la ubicación de los pines, y luego mueva el PointMass a esa posición después de cada resolución de la restricción.


Paso 8: Añadir algunos Ragdolls

Los Ragdolls fueron las intenciones originales de Jakobsen detrás de su uso de Verlet Integration. Primero empezaremos con las cabezas. Crearemos una restricción de círculo que solo interactuará con el límite.

A continuación podemos crear el cuerpo. Agregué cada parte del cuerpo para que coincida con cierta precisión con las proporciones de masa y longitud de un cuerpo humano normal. Echa un vistazo a Body.pde en los archivos de origen para obtener todos los detalles. Hacer esto nos llevará a otro tema: el cuerpo se contorsionará fácilmente en formas incómodas y parecerá muy poco realista.

Hay varias maneras de solucionar esto. En la demostración, utilizamos enlaces invisibles y muy rígidos desde los pies hasta el hombro y la pelvis hasta la cabeza para empujar naturalmente el cuerpo a una posición de descanso menos incómoda.

También puede crear restricciones de ángulo falso utilizando enlaces. Digamos que tenemos tres PointMasses, con dos vinculados a uno en el medio. Puede encontrar una longitud entre los extremos para satisfacer cualquier ángulo elegido. Para encontrar esa longitud, puedes usar la Ley de los cosenos.

Modifique el enlace para que esta restricción solo se aplique cuando la distancia sea menor que la distancia de reposo o, si es mayor que. Esto evitará que el ángulo en el punto central esté demasiado cerca o demasiado lejos, según lo que necesite.


Paso 9: ¡Más dimensiones!

Una de las grandes cosas de tener un motor de física completamente lineal es el hecho de que puede ser cualquier dimensión que desee. Todo lo que se hizo con x también se hizo con un valor de y, y la fuerza de trabajo puede extenderse a tres o incluso cuatro dimensiones (aunque no estoy seguro de cómo se representaría eso).

Por ejemplo, aquí hay una restricción de enlace para la simulación en 3D:


Conclusión

¡Gracias por leer! Gran parte de la simulación se basa en gran medida en el artículo de Thomas Jakobsen Advanced Character Physics de GDC 2001. Hice todo lo posible para eliminar la mayoría de las cosas complicadas y simplificar hasta el punto que la mayoría de los programadores entenderán. Si necesita ayuda o tiene algún comentario, no dude en publicar a continuación.

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.