[XNA] Detección de colisiones entre una Cámara y un Terreno

En mi anterior blog escribí un artículo en el que se explicaba como generar un terreno en XNA a partir de un mapa de alturas (catalán). Vamos a partir de ese ejemplo para este nuevo artículo.

Una problematica común en un juego es que movamos directamente la cámara (en primera persona) sin «atravesar las paredes». Sería el caso típico de juegos como Quake, Unreal, y también de coches, entre otros. Aquí vemos un ejemplo de juego con la cámara en primera persona:

Normalmente las colisiones entre modelos 3D dentro del juego se detectarían mediante BoundingSpheres, lo cual de entrada tiene que ser relativamente fácil. Es fácil porque de entrada todos los modelos tienen o pueden tener un BoundingSphere que los «rodee», como se puede ver en la imagen siguiente. Posteriormente utilizando el método «Intersects» de una instancia de la clase BoundingSphere de XNA podemos saber si hay colisión o no entre estos dos objetos…

Con el terreno generado mediante un mapa de alturas el problema hay que afrontarlo de otro modo… no se puede utilizar la clase BoundingSphere ni BoundingBox por motivos evidentes: la detección de colisiones sería enormemente imprecisa. Por lo tanto esta solución es difícil que nos sirva para los terrenos. ¿Qué hacemos entonces? En internet se pueden encontrar multitud de aproximaciones/soluciones. A mi lo que me parece más sencillo es lo siguiente: en el momento de generar el terreno a partir del mapa de alturas, estamos creando vértices para nuestro nuevo modelo 3D. Miremos de almacenar esa información de forma fácilmente accesible, por ejemplo en una lista de vértices. Cuando movamos la cámara… sólo deberemos buscar el valor de Y para el terreno, en relación a la posición Y del vector posición de la cámara. Miremos de ilustrarlo con un fantástico dibujo para que se entienda mejor… :

La idea es simplemente que al desplazar la cámara por cualquiera de sus ejes, se compruebe el elemento Y del vértice del terreno más cercano para la posición X-Z de la cámara. Si el usuario mueve la cámara a una posición en la que hay colisión, incrementamos la posición de la camara para evitar la misma. De este modo obtenemos la sensación de que la cámara «camina» por encima del terreno generado. El resultado es el siguiente:

Os dejo además el enlace al código, para que podáis probarlo. Recordad que para ejecutarlo es necesario tener instalado el XNA Framework Redistributable 3.0 o superior.

6 comentarios sobre “[XNA] Detección de colisiones entre una Cámara y un Terreno”

  1. uf! mas trabajo? jejeje Lo «malo» es que tendría que traducirlos. Cuando pueda moveré alguno que me parezca más interesante.

    Moltes gracies! 🙂

  2. Aunque el tema sea de colisiones sobre terreno, a ver si podeis aclararme un tema sobre los BoundingBox.
    A modo de ejemplo en un espacio 3D pongo un modelo/columna centrada en las coordenadas del grid (0,0,0).
    Esa columna tiene un radio de 5 unidades i altura de 20 unidades.
    He intentado crearle un BoundingBox y lo mas que he conseguido mas que una colision de una columna es una colisión de un muro del centro al infinito del grid.
    ¿Que valores deberian tener los dos Vector3 de BoundingBox?
    He probado diferentes posibilidades si exito, entiendo que esto no es correcto:
    (-5,0,-5) (5,20,5)

    Gracias de antemano

  3. Torpe de mi en el BoudingBox del objecto en movimiento tenia el valor de X en vez de Z.
    Que burro!!!
    La clase que muestra en xnawiki, perfecta, la he acomodado a mi proyecto i feten!!! altamente recomendable y sencilla de implementar.
    Lástima no poder mandar una captura en mi proyecto 🙂

    Y ahora me respondo:
    (-5,0,-5) (5,20,5) es correcto para el ejemplo que plantaba, el error estaba en los vector3 del otro objeto.

    Gracias!!

  4. Hola como va estuve probando el código y en la linea :

    terreny = Content.Load(«terreny»);

    Me da el siguiente error:

    This device does not support 32-bit indices. Use IndexElementSize.SixteenBits or a type that has a size of two bytes.

    ¿Alguna idea de lo que puede ser?

    Gracias

Responder a anonymous Cancelar respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *