viernes, 8 de mayo de 2009

Las colisiones

Quizás es uno de los temas más importantes de nuestro juego: no demos salirnos de nuestro mundo, ni atravesar las paredes. La intención de este post es de dotar a las librerías que estamos creando, y de paso al NSMB, de esta cualidad tan necesaria.

Vamos a ver cosas que hemos tenido en cuenta a la hora de programar el tema de las colisiones:

  1. Veamos cómo está definido Koopa, nuestro héroe:

    Está dentro de un array de 4x4, pero en el fondo sólo ocupa 2x4 (2 columnas y 4 filas). Es decir, una colisión se dará en el caso en que un objeto entrase en las coordenadas (x+1, y) o (x+1, y+1) o (x+1, y+2) o (x+1, y+3) o (x+2, y) o (x+2, y+1) o (x+2, y+2) o (x+2, y+3). El resto de coordenadas no causan colisión.


  2. Otro tema a tener en cuenta. Nuestro juego es de plataformas y Koopa está siempre en las mismas coordenadas, son las plataformas las que se mueven, por lo que habrá que calcular en que casillas del mapa está nuestra tortuga.

    En el código que tenemos hecho hasta la fecha estamos trabajando con formas de 16x16 pixeles,

    y esto nos va a dar problemas. Hay que cambiar las cosas, tenemos que pasar a que nuestro mapa vuelva a ser de 8x8. Dejaremos las funciones de 16x16 por si otro proyecto las necesitase.

  3. El mapa de colisiones, es decir un array parecido al que define la forma de nuestro mundo pero de colisiones.



En definitiva hemos añadido el siguiente código:


  • Se ha creado una función que nos permite asignar un array donde definir los obstáculos de nuestro mundo:
    void ScreenManager::SetCollisionMap8x8(void *collisionMap, unsigned int cols, unsigned int rows).

  • Y una que nos permita preguntar por una posible colisión:
    int ScreenManager::IsCollision(Sprite *sprite, int x, int y). Ambas funciones se han implementado en la clase ScreenManager.

  • En la clase Sprite se han definido las siguientes funciones:
    void SetCollisionMap(void *collisionMap, unsigned int cols, unsigned int rows);
    void *GetCollisionMap();
    unsigned int GetCollisionCols();
    unsigned int GetCollisionRows();
    Que son las que sirven para definir el mapa de colisiones del Sprite.

  • En NSMB.cpp hemos añadido el control de colisiones. Para hacer pruebas hemos dejado el código de subir y bajar, que no son del juego de NSMB, pero nos sirven, en este momento, para probar la funcionalidad. Este control lo encontraréis en la función int NSMB::avanzar() que es invocada desde HeldRight y HeldLeft.

  • El editor de pantallas tiene nuevas opciones como son la de grabar mapas de 8x8 y uno de colisiones.



Para ver la versión que corresponde a este post pinchar aquí.
La nueva versión del editor de mapas está aquí.

Esto empieza a tener algo de forma. Nos falta que nuestro héroe, que tiene que ser Mario y no koopa, empiece a saltar. Lo dejaremos para próximos post. Y las monedas, tenemos que llenar nuestro mundo de monedas!!!

Nos vemos en los comentarios.

Saludos

2 comentarios:

David Martínez Martínez dijo...

Hola Íñigo, me parece interesante la forma en la que tratas las colisiones, ¿pero por qué no las haces por tiles en vez de especificarle tu a mano cuales son atravesables y cuales no?

Me refiero a que lo hagas como el juego Pokemon, que tenias otro mapa con los sitios que se podían atravesar y los que no. Podrías hacer que el editor, cuando creas un mapa, el solo te creara un segundo mapa donde salen estas zonas atravesables y las que no.

Te lo digo, porque poner a mano todas las zonas donde nuestro héroe se puede chocar, es un verdadero tostón.

¡Sigue así! Saludos y cuídate.

Inigo dijo...

Tienes razón.

Estoy cambiando el programa de Java (el de crear los mapas) para que me cree el mapa de colisiones, y poder crear los cuatro niveles de fondos que se pueden tener en la DS.

Saludos