[XNA] Detección de colisiones en un mundo 3D – (Episode II)

En el episodio anterior comencé a introducir el tema de la detección de colisiones en juegos 3D, aplicándo el concepto a un posible nivel de un videojuego. En este episodio seguiré desarrollado este “nivel” del videojuego, en concreto diseñaré una pantalla muy simple, pero lo más importante: intentaré simplificar el trabajo que supondría añadir más niveles a un juego y gestionar su información. Así pues esta parte del tutorial podría considerarse prácticamente más afín a las estructuras de datos que no a la detección de colisiones (tema al que volveremos en el episodio III).

Lo primero va a ser disponer de 1 o N modelos que conformen nuestro mundo. En este momento pondré un modelo que se compondrá de distintos objetos, no obstante, lo ideal es que existan N objetos formando nuestro “mundo”, y que renderizemos sólo aquellos que son visibles por el jugador (los que están en el frustum de la cámara). Pero por ahora no nos compliquemos la vida… un mundo con un solo modelo. En mi caso lo he hecho en MAX, pero hay un montón de aplicaciones de modelado 3D gratuitas, posteriormente habrá que exportar el modelo a FBX.

Como podéis comprobar ni siquiera aplico texturas al modelo… en este caso se trata de una simple prueba de concepto que iremos perfeccionando.

 

 

Al final el resultado será este (otra vez estoy utilizando el robot modelado por Jordi Gimenez):

Así pues vayamos a ver qué aproximación he utilizado para implementar un gestor de niveles… he creado una clase ManagerNiveles, que gestiona y contiene un “almacén de datos” al que le he llamado “Nivel”.

Nivel podría contener cualquier nivel de nuestro videojuego, mientras la definición del mismo exista en el fichero XML correspondiente (nivelN.xml), y es que basándome en el artículo anterior, ManagerNiveles carga toda la información desde un fichero externo para hacer más fácil de gestionar N niveles en un videojuego. Este XML contiene información de los boundingbox y boundingspheres que se utilizarán en la siguiente parte del tutorial.

clases

Esta clase ManagerNiveles es muy interesante porque encapsula la información del nivel y el método necesario para pintarlo, así como la referencia a todos sus modelos y sus objetos bounding. Así pues, en la clase Game, tendremos un código muy simple, comenzando obviamente por una instancia a la clase:

   1: ManagerNiveles managerNivel;

Después sólo tendremos que hacer un new de la instancia y inicializar el nivel que queramos, en nuestro caso el 1:

   1: // Inicializo el nivel

   2: managerNivel.IniciarNivel(1);

Y para renderizar el nivel, el método Draw de la clase game hará simplemente lo siguiente:

   1: // Pintamos el nivel

   2: managerNivel.Draw(gameTime, camara.Vista, camara.Proyeccion);

Sencillo, verdad? Ahora veamos el método IniciarNivel de la clase ManagerNiveles.

   1: // Deserializamos los datos desde el XML y establecemos los mismos en la clase colisionesMundo

   2: nivel = new Nivel();

   3:  

   4: XmlSerializer ser = new XmlSerializer(typeof(Nivel));

   5:  

   6: TextReader lector = new StreamReader(

   7:     string.Format(@"{0}ContentNivelesNivel{1}.xml", Environment.CurrentDirectory, numeroNivel));

   8: nivel = (Nivel)ser.Deserialize(lector);

   9: lector.Close();

  10:  

  11: // Inicializamos los objetos del mundo

  12: foreach (DatosModelo objeto in nivel.objetosMundo)

  13: {

  14:     nivel.modelosMundo.Add(new ObjetoInerte(objeto.nombreModelo, content));

  15:     nivel.modelosMundo[nivel.modelosMundo.Count - 1].transformacionRaiz.Escala *= Matrix.CreateScale(objeto.Escala);

  16: }

Ese lo que hace es deserializar la información del XML en un objeto de tipo Nivel. Posteriormente carga en memoria todos los modelos que contiene el nivel.

El dibujado, al que hemos llamado antes desde la clase game, simplemente recorre los modelos y los pinta uno a uno (aquí es donde tendremos que utilizar más tarde un frustum culling para pintar sólo los modelos que se encuentran dentro del frustum de la cámara):

   1: public void Draw(GameTime gameTime, Matrix vista, Matrix proyeccion) 

   2: {

   3:     foreach (ObjetoInerte modelo in nivel.modelosMundo)

   4:     {

   5:         modelo.Draw(gameTime, vista, proyeccion);

   6:     }

   7: }

 Y nada más por hoy! En el próximo episodio veremos como el robot tiene detección de colisiones, que le impide atravesar las paredes, como podéis observar que ahora oucrre en el vídeo.

2 comentarios en “[XNA] Detección de colisiones en un mundo 3D – (Episode II)”

Deja un comentario

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