Capítulo 6 - Colisiones

En este capítulo haremos que las balas creadas en el capítulo 5 sepan algo acerca de los enemigos para permitirles colisionar con estos y destruirlos, en otras palabras haremos explotar cosas.

Capítulo 6.1 - Enemigos & Colisiones

En este punto tanto los enemigos como el jugador disparan pero qué más da que disparen si no explota nada. A continuación veremos cómo tratar colisiones simples entre sprites en Cocos2d-x.

Para comenzar crearemos un pool de enemigos y añadiremos un par de enemigos a la escena pues un solo enemigo no es suficiente. Lo haremos de la misma forma que hacemos el pool de balas.

Ahora vamos a extender nuestra clase Bullet, de forma que cada bala sepa acerca de su objetivo, es decir cada bala almacena una referencia a su objetivo para ver si colisiona con este.

Bullet.h

Bullet.cpp

Si la bala es del jugador almacenará un pool de enemigos (todos los posibles en la escena) y en cada frame, verificará si está colisionando con un enemigo. En caso de ser así lo destruirá y la bala pasará a estar deshabilitada. Lo mismo sucede si la bala pertenece a un enemigo, sin embargo sólo almacenará referencia al Player.

Echemos también un ojo al método setCurrentAnimation de la clase Player por ejemplo. El resto de los cambios los veremos más adelante.

Cuando se ejecute este método (llamado en el update de la clase Bullet cuando pertenece a un enemigo), al colisionar un bala con el jugador se producirá un error (error mencionado en el capítulo 4) pues el objeto _explosionAnimation ya no existirá. Esto es debido a que como dicho objeto no se utilizó nunca, cocos lo eliminó gracias a que es un release object. Para mantener ese objeto en memoria hasta que destruyamos el objeto Player, debemos llamar al método retain() y posteriormente será eliminado al eliminar el objeto Player.

Veamos cómo queda nuestra clase Player al completo.

Player.h

Player.cpp

Como vemos ahora llamamos al método retain() al crear las animaciones. También hemos añadido unas líneas al método update justo al inicio del mismo donde miramos sí la nave está explotando, de ser así, hacemos que la nave no se pueda controlar y que deje de disparar. Una vez termine de explotar, hacemos que deje de ser visible.

Otro método importante es setTargets donde actualizamos con el listado de enemigos todas las balas del jugador.

Ya tenemos la clase Player lista, la clase BasicEnemy es muy similar solo que obviamente con un comportamiento distinto en el update, y además solo almacenará una referencia al player en lugar de un pool de objetos. Además en el init() de BasicEnemy hacemos una llamada al método scheduleUpdate() que equivale a schedule(schedule_selector(BasicEnemy::update)) la razón por la que hacemos esto es para que en cada frame se llame al método update sin necesidad de hacer un loop en el GameLayer que llame al update de cada enemigo. Veamos ahora GameLayer para analizar su comportamiento.

En nuestra escena principal generaremos enemigos que aparecerán en posiciones aleatorias y gestionaremos colisiones entre los enemigos y el jugador.

GameLayer.h

GameLayer.cpp

Como vemos usamos una técnica para generar enemigos muy similar a como gestionamos los disparos del jugador y los enemigos, usando una secuencia de cocos. Solo que ahora se generan desde la parte superior de la pantalla y se deshabilitan al ser destruidos o llegar al final de la pantalla para poder ser rehabilitados de nuevo.

En el método update tan solo miramos si el jugador está chocando con algún enemigo, en cuyo caso destruimos a ambos. En caso de que el jugador sea destruido, es decir _player->isVisible()==false hacemos que el fondo deje de moverse pues el jugador ya no está avanzando. En Capítulos siguientes añadiremos mecanismo para volver a comenzar el juego y mostrar alguna información en pantalla.

Descarga la carpeta Classes del proyecto hasta el momento aquí.


Capítulo anterior | Capítulo siguiente