Bienvenidos sean a este post, hoy nos centraremos en como detectar las colisiones si bien no lo hicimos hasta ahora fue porque es mucho mas complejo que lo visto anteriormente.
Para comenzar debemos volver a nuestra clase EngineFisicas, mas exactamente al metodo detectarColisiones y lo modificaremos de la siguiente manera:
private void detectarColisiones(GameState gs,
ArrayList<GameObjeto> objetos){
boolean colisionDetectada = false;
Transformar jugadorTransformar = objetos.get(
ManagerNivel.JUGADOR_INDICE).getTransformar();
JugadorTransformar jugadorJugadorTransformar =
(JugadorTransformar) jugadorTransformar;
ArrayList<RectF> chocadorJugador =
jugadorJugadorTransformar.getChocadores();
PointF ubicacionJugador = jugadorTransformar.getUbicacion();
for(GameObjeto go : objetos){
if (go.chekaActivo()){
if (RectF.intersects(
go.getTransformar().getChocador(),
jugadorTransformar.getChocador())){
colisionDetectada = true;
Transformar pruebaTransformar =
go.getTransformar();
PointF pruebaUbicacion =
pruebaTransformar.getUbicacion();
if (objetos.indexOf(go) !=
ManagerNivel.JUGADOR_INDICE){
for(int i = 0; i < chocadorJugador.size(); i++){
}
}
}
}
}
if (!colisionDetectada){
jugadorJugadorTransformar.noEnTierra();
}
}
En este metodo lo primero que haremos sera crear una variable para detectar la colision, despues crearemos dos nuevas referencias donde la primera sera de tipo Transformar para iniciar el Transformar del jugador, la segunda es de tipo JugadorTransformar donde lo iniciaremos con lo obtenido en la referencia anterior, con estas dos variables luego creamos un nuevo ArrayList con todos los chocadores del jugador, nuestra ultima variable sera para almacenar la posicion del jugador, nuestro primer paso luego de creadas las variables sera un bucle for para pasar por todos los objetos, en el bloque lo primero que chequearemos es si el objeto obtenido esta activo, en caso de que el objeto este activo vamos a chequear por medio de intersects si el objeto contenido en go se se cruza con el del jugador, ambos datos los sacamos por medio de getChocadores de cada uno de los objetos.
En caso de ser verdadero lo primero que haremos es pasar a verdadero a colisionDetectada, es decir que se detecto una colision, y una vez modificada crearemos una variable de tipo Transformar para el objeto que estamos trabajando en el bucle y otra de tipo PointF para saber su ubicacion, estas dos variables seran para hacer las pruebas aunque si bien podemos hacer estas acciones directamente trabajando de esta forma nos ayudara a entender mejor el codigo y puede que sea un poco mas rapido, veamos la siguiente condicion:
if (objetos.indexOf(go) !=
ManagerNivel.JUGADOR_INDICE){
for(int i = 0; i < chocadorJugador.size(); i++){
}
}
En este caso obtendremos el objeto en base al indice obtenido por el bucle y compararemos si este es distinto al indice del jugador, siempre que sea distinto del jugador y con este verificamos donde se golpeo al jugador, por ahora lo dejaremos en blanco y pronto lo completaremos, por ultimo por fuera de esto tenemos un condicional donde verificamos si no se detecto colision, en caso de estar en estado false se considera que el jugador no colisiono o no esta en el suelo, por ende lo seteamos como que no esta en tierra.
Con lo anterior concluimos gran parte del metodo ahora solo nos falta el bucle for que dejamos en blanco al cual le pondremos el siguiente codigo:
for(int i = 0; i < chocadorJugador.size(); i++){
if (RectF.intersects(
pruebaTransformar.getChocador(),
chocadorJugador.get(i))){
switch (go.getTag() + " con " + i){
case "plataforma movible con 3":
jugadorJugadorTransformar.enTierra();
ubicacionJugador.y = (pruebaTransformar
.getUbicacion().y
- jugadorTransformar
.getTamano().y );
break;
case "muerte con 3":
gs.muerte();
break;
case "objeto inerte con 3":
jugadorJugadorTransformar.enTierra();
ubicacionJugador.y = (pruebaTransformar
.getUbicacion().y
- jugadorTransformar
.getTamano().y );
break;
case "objeto inerte con 0":
ubicacionJugador.y = pruebaUbicacion.y
+ pruebaTransformar.getTamano().y;
jugadorJugadorTransformar.disparaCabezaGolpeada();
break;
case "coleccionable con 1":
SoundEngine.playMonedaRecogida();
go.setInactivo();
gs.monedasRecogidas();
break;
case "coleccionable con 2":
SoundEngine.playMonedaRecogida();
go.setInactivo();
gs.monedasRecogidas();
break;
case "objeto inerte con 1":
jugadorTransformar.detenerMovDerecha();
ubicacionJugador.x = (pruebaTransformar
.getUbicacion().x
- jugadorTransformar
.getTamano().x);
break;
case "objeto inerte con 2":
jugadorTransformar.detenerMovIzquierda();
ubicacionJugador.x = (pruebaTransformar
.getUbicacion().x
+ jugadorTransformar
.getTamano().x);
break;
case "objeto objetivo con 3":
SoundEngine.playLogrado();
gs.objetivoAlcanzado();
break;
default:
break;
}
}
}
El bucle for pasara por todos los objetos de tipo «chocador» de nuestro jugador, luego usaremos un intersects para verificar si entre el objeto chocador de nuestro objeto de prueba y el objeto cargado en chocadorJugador que lo obtendremos con el get y el valor de i del bucle se cruzan, despues en el bloque del if tenemos un switch al igual que en el proyecto anterior usaremos el tag concatenado con la palabra con y el indice del chocador de nuestro jugador, luego en los case usaremos esa concatenacion para ver que se cumpla la condicion, veamos un case:
case "plataforma movible con 3":
jugadorJugadorTransformar.enTierra();
ubicacionJugador.y = (pruebaTransformar
.getUbicacion().y
- jugadorTransformar
.getTamano().y );
break;
Veamos este ejemplo, en este caso el tag va a ser «plataforma movible» se concatena con la palabra «con» mas un espacio adelante y otro atras, por ultimo tambien concatenaremos el valor del indice correspondiente de la parte que usamos como chocador o colisionador, en este caso tenemos el caso de cuando los pies estan arriba de una plataforma movil, en caso de cumplirse procede a actualizar la posicion del eje Y por medio de la ubicacion del eje Y del transformar de prueba y el valor del eje Y del tamaño de nuestro jugador, analicemos el siguiente case:
case "muerte con 3":
gs.muerte();
break;
En este case veremos el caso de cuando nuestro pie toca alguno de los elementos marcados como muerte, llama al metodo de muerte de GameState y sale del juego volviendo al menu principal, veamos el siguiente case:
case "objeto inerte con 3":
jugadorJugadorTransformar.enTierra();
ubicacionJugador.y = (pruebaTransformar
.getUbicacion().y
- jugadorTransformar
.getTamano().y );
break;
Este es el case mas importante porque sera el que detecte cuando nuestros pies esten en contacto con una plataforma, hace exactamente lo mismo que en el primer case pero para las plataformas fijas, veamos el siguiente case:
case "objeto inerte con 0":
ubicacionJugador.y = pruebaUbicacion.y
+ pruebaTransformar.getTamano().y;
break;
Este sera el case que se encargara de monitorear si nuestra cabeza golpea con la plataforma o un objeto inerte, y establecera el limite de nuestro salto, pasemos al siguiente case:
case "coleccionable con 1":
SoundEngine.playMonedaRecogida();
go.setInactivo();
gs.monedasRecogidas();
break;
En este case veremos como manejar la colision con un coleccionable y el lado derecho, recuerden que el coleccionable son las monedas, donde procede a llamar a los tres metodos para reproducir el sonido de recoleccion de moneda, desaparecerla y sumarla, lo mismo hace el siguiente case pero para el lado izquierdo, veamos el siguiente case a estos dos:
case "objeto inerte con 1":
jugadorTransformar.detenerMovDerecha();
ubicacionJugador.x = (pruebaTransformar
.getUbicacion().x
- jugadorTransformar
.getTamano().x);
break;
Para este case monitoreamos cuando un objeto inerte (la pila de piedras por ejemplo) se nos pone adelante o de nuestro lado derecho y no nos permite avanzar, por ende llamamos a detener el movimiento horizontal derecho y la ubicacion de nuestro jugador sera a la izquierda del objeto inerte, el siguiente case hace exactamente lo mismo pero con el lado izquierdo y ubica a nuestro jugador en el lado derecho del objeto, veamos el ultimo case:
case "objeto objetivo con 3":
SoundEngine.playLogrado();
gs.objetivoAlcanzado();
break;
Este es el case encargado de chequear la llegada al objetivo o la salida del nivel, siempre y cuando el pie toque el mismo, en caso de cumplirse procede a reproducir el sonido de salida y llama al metodo que se encarga de salir del nivel y colocar el nuevo record en caso de que sea asi, con esto ya tenemos nuestro juego completo y podemos probarlo como se ve en el siguiente video
En el video podemos ver un par de niveles pero solo como se mueve porque via emulador no podemos presionar dos botones con el cursor pero es que para que tengan la impresion de como queda nuestro juego, les recomiendo jugarlo en un movil para vivir toda la experiencia.
En resumen, hoy hemos llegado al final de nuestro juego podemos ver como tenemos un juego de plataforma muy completo, con las reglas basicas de uno, en el proximo post veremos todos los codigos para generar el juego al igual que hicimos con los proyectos anteriores, espero les haya gustado sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.
Tengo un Patreon donde podes acceder de manera exclusiva a material para este blog antes de ser publicado, sigue los pasos del link para saber como.


Donación
Es para mantenimento del sitio, gracias!
$1.00
