¿Cómo represento proyectiles en un videojuego?

14

Estoy haciendo un juego de disparos fijo simple, similar a "Galaga" ,) como parte de una presentación que estoy haciendo. Me pregunto qué estrategias y estructuras de datos usarían las personas para rastrear proyectiles, como los láseres disparados desde la nave espacial. Una implementación súper simple que he usado, antes, es representar cada proyectil como un punto y verificar las colisiones con todos los objetos en la escena.

Sin embargo, esto parece costoso, en escenas grandes con muchos proyectiles; Me pregunto qué otros tipos de estrategias o implementaciones se utilizan para este tipo de casos de uso. ¿Qué usan los juegos como FPS para rastrear proyectiles (balas, proyectiles, etc.)?

Polaris878
fuente
55
Muchos juegos de FPS suponen que las balas son instantáneas, pero existen aquellas que calculan las trayectorias y el tiempo de viaje.
John McDonald
2
+1 esta es una gran pregunta, y tampoco la limitaría a 3d necesariamente.
cenizas999

Respuestas:

8

Para proyectiles muy rápidos (como láser o balas), puede usar un Ray .

Un rayo tiene un punto de inicio y un punto final. Una estructura de datos (muy mínima) para un rayo es:

struct Ray
{
  Vector3f start, end ;
} ;

Se ve como esto:

ingrese la descripción de la imagen aquí

(También puede almacenar en caché el vector de dirección y la longitud, pero usé una definición muy simple arriba).

Si el rayo es un rayo láser que viaja a la velocidad de la luz, simplemente persistiría el rayo (como comenzando en la boquilla de la pistola y terminando en una pared en algún lugar) durante un par de cuadros. Cualquier cosa que se cruce con el rayo de cada cuadro recibe daño.

Si el rayo es un proyectil más lento (como una bala, por ejemplo), el rayo modela la distancia que recorrió la bala en un paso de tiempo. El punto de inicio es donde está el rayo al comienzo del cuadro, y el punto final es donde estará el rayo después de terminar el cuadro. Cualquier cosa en el camino del rayo de bala es dañada por la bala.

Los rayos pueden colisionar eficientemente con esferas, aabbs, cascos convexos, etc. Vea mi proyecto Hullinator para un programa real en ejecución (CTRL + Clic para disparar rayos)

bobobobo
fuente
1
Un rayo no funciona muy bien para muchos proyectiles. Por ejemplo, cualquier proyectil que se pueda lanzar, como proyectiles de tanques. Sin embargo, los rayos son excelentes para proyectiles de tiro recto.
MichaelHouse
Bueno, si el caparazón se mueve extremadamente lento (en comparación con una bala o un láser), entonces sí, lo
modelaría
77
Técnicamente, un rayo es un punto de partida y una dirección. Esto se puede determinar CON un punto de inicio y otro punto, pero esto no es parte de su definición. Por definición, los rayos son infinitos y no tienen un punto final.
Casey Kuball
1
Tienes razón, lo que he descrito es en realidad un segmento de línea , pero la mayoría de las personas los llaman rayos cuando hablan de detección de colisión.
bobobobo
3

El uso de un rayo funciona bien para proyectiles que viajan instantáneamente, como las balas. Para los proyectiles que tienen una velocidad más lenta, como el tipo que utilizará para su juego espacial, tiene sentido simplemente rastrear su posición en el mundo del juego como lo haría con cualquier otra entidad. Lo que a menudo hago es tener una clase base llamada Entidad que contiene propiedades de cualquier objeto duradero del juego: posición, rotación, cuadro de colisión, etc. Mi jugador manejado y proyectiles heredan de esto y mi mundo del juego solo necesita saber cómo lidiar la Entidad de superclase, no cada tipo individual de entidad.

Para aumentar el rendimiento, es muy común mantener un grupo alrededor de los objetos que creará y destruirá con frecuencia. Cuando necesite un nuevo proyectil que extraería de este grupo, modifique el nuevo proyectil según sea necesario y devuélvalo al grupo cuando haya caducado.

JPRO
fuente
2

Cuando desee optimizar para la detección de colisiones, puede almacenar todos los objetos del juego en un árbol de dos o tres dimensiones . Esta estructura de datos hace que sea muy eficiente recuperar todos los objetos en un área determinada.

Sin embargo, los árboles binarios tienen la desventaja de que se degeneran fácilmente cuando se agregan, eliminan y cambian sus posiciones, por lo que deberá equilibrarlos automáticamente .

Un compromiso que sería más fácil de implementar pero no tan eficiente sería utilizar un enfoque basado en fragmentos. Divide el campo de juego en cubos y realiza un seguimiento de los objetos que tocan cada cubo. Cuando verifica las colisiones con un objeto, solo necesita verificarlo contra las listas de objetos de los cubos que está tocando (reemplace "cubo" con "rectángulo" para un 2d-juego).

Philipp
fuente