2011-01-14 13 views
6

Estoy intentando diseñar un algoritmo de detección de colisiones para un cliente personalizado de Minecraft que estoy creando. Básicamente, todo el mundo está formado por cubos, y el jugador (o cámara) debe poder pararse y moverse contra estos cubos. El resultado que quiero se ilustra en esta imagen: imageDetección de colisiones deslizando contra un plano en XNA

La línea verde es el vector de movimiento del jugador. Cuando el jugador está cepillando contra un plano de uno de los cubos, quiero que el vector cambie a uno que sea perpendicular al plano. El vector debería, sin embargo, mantener toda su velocidad en la dirección del avión, pero perder toda la velocidad hacia el plano.

Espero haber aclarado mi pregunta. ¿Cuál es la mejor y más eficiente forma de implementar un sistema de detección de colisión como este? Además, ¿un sistema como este permitirá un simple componente de gravedad?

EDITAR: Olvidé mencionar que los cubos se almacenan en una matriz tridimensional, [x, y, z].

+0

Me encanta esta pregunta. Sugiero que también publiques en gamedev.stackexchange.com. Me imagino que este es un problema común en el desarrollo de juegos. –

+0

@BigDave - Oh, no sabía que había un sitio específicamente para el desarrollo de juegos. Stack Exchange realmente está creciendo. – Bevin

Respuesta

1

Un enfoque simple para implementar esto sería detectar la colisión de la pelota y el avión. Calcule la profundidad de penetración, esto es hasta qué punto la pelota realmente ha pasado el avión, y empuje la pelota hacia atrás en la dirección de la normal del avión.

Esto tendrá el efecto de poner la pelota en la superficie del avión. Si haces esto para cada cuadro, la pelota se deslizará efectivamente a lo largo del plano, asumiendo por supuesto que el vector de velocidad de la pelota no es paralelo a la normal del avión.

El campo de detección de colisión es grande y complejo, y dependiendo de su juego, debe determinar qué es suficiente para sus necesidades en términos del nivel de realismo que necesita y los requisitos de rendimiento. Siempre debe buscar la solución más simple que brinde una retroalimentación lo suficientemente realista, dependiendo del juego, a menudo no tiene que ser perfecto.

Básicamente debe romper su detección de colisión en 2 fases, generalmente conocidas como fase amplia y fase estrecha.

La fase amplia podría ser tan simple como realizar una verificación de caja rápida para determinar posibles colisiones y luego enviar esa colisión potencial a la detección de colisión de fase estrecha para realizar comprobaciones más detalladas donde determinar si realmente hubo una colisión y la profundidad de la colisión Si tiene muchos objetos, la fase amplia puede usar algún tipo de indexación de quadtree para seleccionar solo los bloques cercanos a su objeto para realizar la detección de colisión.

+0

@Chris Taylor - Sí, pensé que podría ser algo tan simple como eso. ¿Cómo crees que debería ir a calcularlo? ¿Debería iterar a través de un subconjunto de cubos y verificar si el jugador se está cruzando con uno de ellos? – Bevin

+0

@Bevin, mi respuesta a su pregunta adicional fue un poco larga, así que simplemente actualicé la respuesta con un poco más de información. Espero que esto ayude. –

+0

@Chris Taylor - Bueno, sé el tamaño del jugador, por lo que podría simplemente iterar sobre los cubos que están, por ejemplo, a lo sumo a 4 cuadras de distancia. Eso debería dar suficiente espacio para la detección. ¿Cómo puedo detectar qué tan lejos se ha cruzado el jugador, y cuánto empujarlo fuera del bloque? – Bevin

0

En un mundo de cubos Axis Alineados, esto es realmente fácil. Es fácil pensar que necesitas algo complicado, pero en realidad es muy simple. Esto es por experiencia después de escribir mi propio clon de Minecraft.

Así es como:

position.X += velocity.X; 
if(colliding()) 
    position.X -= velocity.X; 

position.Y += velocity.Y; 
if(colliding()) 
    position.Y -= velocity.Y; 

position.Z += velocity.Z; 
if(colliding()) 
    position.Z -= velocity.Z; 

Aquí está el código para saber si está o no en colisión:

bool colliding() 
{ 
    int minX = Position.X - size.X/2; 
    int minY = Position.Y - size.Y/2; 
    int minZ = Position.Z - size.Z/2; 

    int maxX = Position.X + size.X/2; 
    int maxY = Position.Y + size.Y/2; 
    int maxZ = Position.Z + size.Z/2; 

    for (int x = minX; x <= maxX; x++) 
    for (int y = minY; y <= maxY; y++) 
     for (int z = minZ; z <= maxZ; z++) 
     { 
     if(blockType[x, y, z] != 0) 
      return true; 
     } 

    return false; 
} 
+0

Esto no funcionará si el jugador no está alineado. ¿Qué pasa si el jugador solo intersecta ligeramente uno de los aviones? Entonces será empujado más allá de lo necesario. – Bevin

+0

El jugador puede tratarse como un cuadro alineado sin eje de rotación para evitar una colisión. Funciona bien. Sé lo que quieres decir, pero el jugador no lo notifica. Animaría al OP a intentarlo. – Hannesh

Cuestiones relacionadas