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

Entendiendo los Comportamientos del Volante: Evitando Colisiones

by
Read Time:8 minsLanguages:
This post is part of a series called Understanding Steering Behaviors.
Understanding Steering Behaviors: Movement Manager
Understanding Steering Behaviors: Path Following

Spanish (Español) translation by Ricardo Mayén (you can also view the original English article)

La navegacion decente de NPCs (Personajes no Jugables) frecuentemente requiere la habilidad de evitar obstáculos. Este tutorial cubre el comportamiento del volante para evitar colisiones, lo cual permite a los personajes esquivar con gracia cualquier número de obstáculos en el ambiente.

Aunque este tutorial se ha escrito usando AS3 y Flash, deberías ser capaz de usar las mismas técnicas y conceptos en casi cualquier ambiente de desarrollo de juegos. Debes tener un entendimiento básico de vectores matemáticos.


Introducción

La idea básica detrás de evitar la colisión es generar una fuerza de dirección para evitar obstáculos cada vez que uno está lo suficientemente cerca para bloquear el paso. Aún si el ambiente tiene varios obstáculos, este comportamiento usará uno de ellos a la vez para calcular la fuerza de evasión.

Sólo los obstáculos enfrente del personaje son analizados: el más cercano, el cual se considera más amenazante, se selecciona para evaluación. Como resultado, el personaje es capaz de esquivar todos los obstáculos en el área, haciendo la transición de uno a otro elegante e impecablemente.


Los obstáculos frente al personaje son analizados y el más cercano (el más amenazador) se selecciona.

El comportamiento de evasión no es un algoritmo para encontrar un camino. Hará que los personajes se muevan a través del ambiente, evitando obstáculos, eventualmente encontrando una ruta la cual tomar para atravesar los bloques - pero no funciona muy bien con obstáculos "L" o "T", por ejemplo.

Tip: Este comportamiento de evasión de colisión puede sonar parecido al comportamiento de huida, pero hay una diferencia importante entre ellos. Un personaje que se mueve cerca de una pared la evitará sólo si está bloqueando el camino, pero el comportamiento de huida siempre presionará al personaje a alejarse de la pared.

Viendo al frente

El primer paso para evitar obstáculos en el ambiente es percibirlos. Los únicos obstáculos de los cuales el personaje se tiene que preocupar son los que están frente a él y que bloquean la ruta directamente.

Cómo se explicó antes, el vector de velocidad describe la dirección del personaje. Se usará para producir un nuevo vector llamado ahead, el cual es una copía del vector de velocidad, pero con una extensión diferente.


El vector ahead es la línea de visión del personaje.

Este vector se calcula de la siguiente manera:

El largo del vector ahead (ajustado con MAX_SEE_AHEAD) define cuan lejos el personaje "verá".

A mayor MAX_SEE_AHEAD, más rápido el personaje comenzará a actuar para evadir un obstáculo porque se percibirá como una amenaza aunque se encuentre lejos:


Mientras más grande sea la distancia al frente, más antes el personaje comenzará a actuar para evadir un obstáculo.

Verificando si hay Riesgo de Colisión

Para verificar si hay riesgos de colisión, cada obstáculo (o su caja limitante) debe ser descrita como una forma geométrica. Usar una esfera (un círculo en dos dimensiones) da el mejor resultado, asi que cada obstáculo en el ambiente será descrito como tal.

Una solución posible para ver si hay riesgo de colisión esla intersección línea-esfera – la línea es el vector ahead y la esfera es el obstáculo. Ese planteamiento funciona, pero voy a usar una simplificación de él, lo cual es más fácil de entender y tiene resultados similares (a veces aúnmejores).

El vector ahead se usará para producir otro vector con la mitad de su longitud.


La misma dirección, la mitad de la longitud.

El vector ahead2 se calcula exáctamente como ahead, pero su longitud se corta a la mitad.

Queremos llevar a cabo una revisión de colisión para probar si alguno de esos dos vectores se encuentran dentro de la esfera obstáculo. Eso se logra fácilmente al comparar la distancia entre el final del vector y el centro de la esfera.

Si la distancia es menor o igual al radio de la esfera, entonces el vector está dentro de la esfera y se encontró una colisión:


El vector ahead está interceptando el obstáculo si d < r. El vector ahead2 fue omitido para claridad.

Si cualquiera de los dos vectores ahead están dentro de la esfera del obstáculo entonces ese obstáculo está bloqueando el camino. La distancia Euclideana entre dos puntos puede ser usada:

Si más de un obstáculo bloquea el camino, entonces el más cercano (el "más amenazador") se selecciona para hacer el cálculo:


El obstáculo más cercano (el más amenazador) se selecciona para hacer el cálculo:

Calculando la Fuerza de Evasión

La fuerza de evasión debe presionar al personaje lejos del obstáculo, permitiendole esquivar la esfera. Se puede hacer usando un vector formado al usar el centro de la esfera (el cual es un vector de posición) y el vector ahead. Calculamos esta fuerza de evasión de la siguiente manera:

Después que la avoidance_force es calculada, se normaliza y se escala por MAX_AVOID_FORCE, el cual es un número usado para definir la longitud de la avoidance_force. A mayor MAX_AVOID_FORCE, más fuerte presiona la fuerza de evasión al personaje lejos del obstáculo.


Cálculo de fuerza de evasión. La línea anaranjada punteada muestra la trayectoria que el personaje tomará para evitar el obstáculo.
Tip: La posición de cualquier entidad puede ser descrita como un vector, de manera que puedan usarse en cálculos con otros vectores y fuerzas.

Evitando el Obstáculo

La implementación final para el método collisionAvoidance( ), el cual regresa la fuerza de evasión, es:

La fuerza de evasión debe ser agregada a la velocidad del vector del personaje. Como se explicó previamente, todas las fuerzas de dirección pueden ser combinadas en una, produciendo una fuerza que representa todo el comportamiento activo en el personaje.

Dependiendo del ángulo de la fuerza de evasión y la dirección, no interrumpirá otras fuerzas de dirección, tales como buscar y alejarse. La fuerza de evasión es agregada a la velocidad del jugador como es usual:

Ya que todos los comportamientos de manejo son recalculados en cada actualización del juego, la fuerza de evasión se mantendrá activa siempre y cuando el obstáculo bloquee el camino.

Tan pronto como el obstáculo no intercepte la línea del vector ahead, la fuerza de evasión se volverá nula (sin efecto) o se recalculará para evitar el nuevo obstáculo amenazante. El resultado es un personaje que es capaz de evitar los obstáculos.


Mueve el cursor del ratón. Haz clic para ver las fuerzas.

Mejorando la Detección de Colisión

La implementación actual tiene dos problemas, ambos relacionados a la detección de colisión. El primero sucede cuando los vectores ahead están fuera de la esfera obstáculo, pero el personaje está demasiado cerca (o dentro) del obstáculo.

Si eso sucede, el personaje tocará (o entrará) al obstáculo, saltandose el proceso de evasión porque no se detectó una colisión.


A veces los vectores ahead están fuera del obstáculo, pero el personaje está dentro.

El problema se puede corregir al agregar un tercer vector al control de colisión: el vector de posición del personaje. El uso de tres vectores mejora ampliamente la detección de colisión.

El segundo problema sucede cuando el personaje se encuentra cerca del obstáculo, alejandose de él. A veces maniobrar causará una colisión, aunque el personaje solamente está rotando para ver en otra dirección.


El maniobrar podría causar una colisión aunque el personaje solamente esté rotando.

Ese problema puede ser arreglado al llevar a escala los vectores aheadde acuerdo a la velocidad actual del personaje. El código para calcular el vector ahead, por ejemplo, se cambia a:

La variable dynamic_length variará de 0 a 1. Cuando el personaje se mueve a velocidad máxima, la dynamic_length es 1; cuando el personaje está disminuyendo la velocidad o acelerando, la dynamic_length is 0 o mayor (por ejemplo 0.5)

Como consecuencia, si el personaje está simplemente maniobrando sin moverse, la dynamic_length tiende a zero, produciendo un vector ahead nulo, el cual no tiene colisiones.

Abajo está el resultado con estas mejoras:


Mueve el cursor del ratón. Haz clic para ver las fuerzas.

Demo: ¡Es Hora de los Zombies!

Para mostrar el comportamiento de evasión de colisión en acción, creo que una horda de zombies es el ejemplo perfecto. Abajo hay un demo que muestra varios zombies (con velocidades diferentes) buscando el cursor del ratón. El arte es de SpicyPixel y Clint Bellanger, de OpenGameArt.


Mueve el cursor del ratón. Haz clic para ver las fuerzas.

Conclusión

El comportamiento de evasión de colisión le permite a cualquier personaje esquivar obstáculos en el ambiente. Ya que todas las fuerzas de conducción son recalculadas en cada actualización del juego, los personajes interactuan implecablemente con cada obstáculo, siempre analizando los más amenazadores (los más cercanos).

Aunque este comportamiento no es un algoritmo para encontrar el camino, los resultados alcanzados son bastante convincentes para mapas abarrotados.

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.