Bienvenidos sean a este post, hoy nos centraremos en completar los componentes para el alien Chaser y el disparo de los lasers de los aliens.
Si bien en este post creamos las especificaciones para todos nuestros objetos, incluidos todos los enemigos, y en este otro post hemos creado las clases para los componentes del jugador y el fondo, lo que haremos hoy es algo similar a este ultimo post porque crearemos las clases para manejar algunos de los componentes del primer post mencionado, para este caso sera el de Chaser, si bien ya tenemos uno de los componentes cubierto como es ComponentesGraficosStd y para el laser de los Alien es muy similar al del jugador pero como vimos en el primer post tienen su propia interfaz para tener su propia identificacion, procedamos a completar la primera clase y para ello vamos a crear una nueva con el nombre ComponenteAlienChaserMovimiento y modificaremos el codigo generado por el siguiente:
package org.example.invasores;
import java.util.Random;
class ComponenteAlienChaserMovimiento implements ComponenteMovimiento {
private Random mDisparoAlazar = new Random();
private GeneradorLaserAlien generadorLaserAlien;
ComponenteAlienChaserMovimiento (GeneradorLaserAlien gla){
generadorLaserAlien = gla;
}
}
Primero crearemos una variable que contendra un numero al azar para los disparos del Alien, luego crearemos un objeto de una clase que todavia no existe pero que proximamente la generaremos, luego tenemos el constructor donde recibiremos un dato del tipo de esta clase inexistente y la asignaremos al objeto antes mencionado, para nuestro siguiente paso sera agregar el metodo mover dentro de la clase:
@Override
public boolean mover(long fps, Transformar t,
Transformar jugadorTransformar){
final int TOMAR_DISPARO = 0;
final int CHANCE_DISPARO = 100;
float anchoPantalla = t.getTamanoPantalla().x;
PointF ubicacionJugador = jugadorTransformar.getPosicion();
float altura = t.getObjetoAltura();
boolean mirandoDerecha = t.getMirandoDerecha();
float mDistanciaPersecucion = t.getTamanoPantalla().x / 3f;
float mDistanciaVision = t.getTamanoPantalla().x / 1.5f;
PointF ubicacion = t.getPosicion();
float velocidad = t.getVelocidad();
float diferenciaVelocidadVertical = .3f;
float reduccionRelativaAlJugador = 1.8f;
float reboteBusquedaVertical = 20f;
if (Math.abs(ubicacion.x - ubicacionJugador.x)
> mDistanciaPersecucion){
if (ubicacion.x < ubicacionJugador.x){
t.apuntarDerecha();
}
else if (ubicacion.x > ubicacionJugador.x) {
t.apuntarIzquierda();
}
}
if (Math.abs(ubicacion.x - ubicacionJugador.x)
<= mDistanciaVision){
if ((int) ubicacion.y - ubicacionJugador.y
< -reboteBusquedaVertical){
t.apuntarAbajo();
}
else if ((int) ubicacion.y - ubicacionJugador.y
> reboteBusquedaVertical){
t.apuntarArriba();
}
if (!jugadorTransformar.getMirandoDerecha()) {
ubicacion.x += velocidad * reduccionRelativaAlJugador/fps;
} else {
ubicacion.x -= velocidad * reduccionRelativaAlJugador/fps;
}
} else {
t.pararVertical();
}
if (t.apuntandoAbajo()){
ubicacion.y += velocidad * diferenciaVelocidadVertical / fps;
}
else if (t.apuntandoArriba()) {
ubicacion.y -= velocidad * diferenciaVelocidadVertical / fps;
}
if (t.apuntandoIzquierda())
ubicacion.x -= (velocidad) / fps;
if (t.apuntandoDerecha())
ubicacion.x += (velocidad) / fps;
t.actualizaColision();
if (mDisparoAlazar.nextInt(CHANCE_DISPARO) == TOMAR_DISPARO ){
if (Math.abs(ubicacionJugador.y - ubicacion.y) < altura){
if ((mirandoDerecha && ubicacionJugador.x > ubicacion.x
|| !mirandoDerecha && ubicacionJugador.x < ubicacion.x)
&& Math.abs(ubicacionJugador.x - ubicacion.x)
< anchoPantalla){
generadorLaserAlien.generaLaserAlien(t);
}
}
}
return true;
}
Lo primero que haremos sera crear dos constantes, las cuales estaran involucradas al disparar o no de los Aliens pero de estas hablaremos un poco mas adelante, despues tendremos esta serie de variables:
- anchoPantalla, almacena el ancho de la pantalla
- ubicacionJugador, almacena donde esta el jugador
- altura, almacena la altura de la nave
- mirandoDerecha, almacena si esta mirando a la derecha
- mDistanciaPersecucion, calcula y almacena cuan lejos esta con respecto a la nave antes de perseguirla
- mDistanciaVision, calcula y almacena cuan lejos puede ver la nave
- ubicacion, almacena la ubicacion de la nave
- velocidad, almacena la velocidad de la nave
- diferenciaVelocidadVertical, almacena la diferencia de velocidad relativa con el jugador
- reduccionRelativaAlJugador, almacena la reduccion de velocidad relativa al jugador
- reboteBusquedaVertical, almacena un valor que nos ayuda a evitar un excedente de precision
Vamos a pasar a analizar el primer bloque condicional:
if (Math.abs(ubicacion.x - ubicacionJugador.x)
> mDistanciaPersecucion){
if (ubicacion.x < ubicacionJugador.x){
t.apuntarDerecha();
}
else if (ubicacion.x > ubicacionJugador.x) {
t.apuntarIzquierda();
}
}
Este condicional se encarga de mover al Alien en la direccion del jugador pero relativa a la direccion de viaje del jugador, primero compararemos al valor absoluto de la diferencia entre la ubicacion de nuestro alien contra la ubicacion del jugador con respecto a la distancia de persecucion, si es mayor ejecutara el bloque, despues tenemos un condicional donde verifica si el eje X de ubicacion es menor al eje X de la ubicacion del jugador y en caso de ser verdadero apunta a la derecha, de lo contrario ( en caso que el eje X del alien sea mayor al jugador) apunta a la izquierda, veamos el siguiente condicional:
if (Math.abs(ubicacion.x - ubicacionJugador.x)
<= mDistanciaVision){
if ((int) ubicacion.y - ubicacionJugador.y
< -reboteBusquedaVertical){
t.apuntarAbajo();
}
else if ((int) ubicacion.y - ubicacionJugador.y
> reboteBusquedaVertical){
t.apuntarArriba();
}
if (!jugadorTransformar.getMirandoDerecha()) {
ubicacion.x += velocidad * reduccionRelativaAlJugador/fps;
} else {
ubicacion.x -= velocidad * reduccionRelativaAlJugador/fps;
}
} else {
t.pararVertical();
}
Este condicional verifica si el alien puede ver al jugador, volvemos a usar el valor absoluto de la diferencia entre la ubicacion del alien y el jugador para ver si es menor o igual al rango de vision del alien, en caso de ser verdadero usara el bloque, de lo contrario llama a pararVertical para detener al alien, en caso de estar dentro del rango de vision utiliza otra condicional donde verifica si la diferencia entre el eje Y del alien con el eje Y del jugador es menor al valor negativo de reboteBusquedaVertical y en caso de ser cierto apunta hacia abajo, en caso contrario usamos otro condicional donde verifica que esa diferencia sea mayor al valor anterior y en caso de ser verdadero apunta hacia arriba.
El ultimo condicional es el que configura el movimiento de nuestro alien, donde en caso de que el jugador no esta mirando a la derecha incrementa el valor del eje X del Alien en base a la velocidad multiplicado por la division entre reduccionRelativaAlJugador y los fps, en caso contrario (es decir esta mirando a la derecha) hace la misma operacion pero en lugar de incrementar hace la sustraccion del eje X del alien, despues tendremos los siguientes condicionales:
if (t.apuntandoAbajo()){
ubicacion.y += velocidad * diferenciaVelocidadVertical / fps;
}
else if (t.apuntandoArriba()) {
ubicacion.y -= velocidad * diferenciaVelocidadVertical / fps;
}
if (t.apuntandoIzquierda())
ubicacion.x -= (velocidad) / fps;
if (t.apuntandoDerecha())
ubicacion.x += (velocidad) / fps;
t.actualizaColision();
El primer condicional verifica si el alien esta apuntando hacia abajo, en caso de ser verdadero incrementa el valor del eje Y del alien, de lo contrario decrementa el valor del eje Y del alien, el siguiente condicional verifica si esta apuntando a la izquierda y en caso de ser verdadero disminuye el valor del eje X del alien, el siguiente verifica si mira a la derecha y en caso de ser cierto incrementa el valor del eje X del alien, por ultimo actualizamos al metodo encargado de detectar las colisiones, con estos condicionales tenemos controlado el movimiento de nuestro alien en pantalla cualquiera sea el lugar donde este apuntando, por ultimo tenemos este bloque:
if (mDisparoAlazar.nextInt(CHANCE_DISPARO) == TOMAR_DISPARO ){
if (Math.abs(ubicacionJugador.y - ubicacion.y) < altura){
if ((mirandoDerecha && ubicacionJugador.x > ubicacion.x
|| !mirandoDerecha && ubicacionJugador.x < ubicacion.x)
&& Math.abs(ubicacionJugador.x - ubicacion.x)
< anchoPantalla){
generadorLaserAlien.generaLaserAlien(t);
}
}
}
Este sera el encargado de disparar los lasers del alien, para esto entran en accion las constantes que hicimos al principio de todo, donde CHANCE_DISPARO sera el encargado de setear el rango de valores que usara para generar al azar, tambien aca verifica si el valor al azar es igual a TOMAR_DISPARO y en caso de ser verdadero verifica si la diferencia entre el eje Y del jugador y el alien es menor a la altura del alien, en caso de ser verdadero verifica si esta mirando a la derecha y el eje X es mayor al eje X del alien o (o logico) si no esta mirando a la derecha y el eje X del jugador es menor al eje X del alien, y a su vez que el valor absoluto de la diferencia entre el eje X del jugador y el alien sea menor al ancho de la pantalla, en caso de ser todo cierto dispara el laser pero esto todavia no va a funcionar porque no existe la clase y obviamente el metodo, por ultimo devuelve un true para que esto exista, con esto ya tenemos a nuestra nave Chaser detras de nosotros, pasemos a la siguiente clase.
Vamos a crear una nueva clase con los siguientes parametros:
- Nombre: GeneradorLaserAlien
- Tipo: Interface
Como pueden ver generamos una interfaz y no una clase, nuestro siguiente paso sera modificar el codigo generado automaticamente por el siguiente:
package org.example.invasores;
interface GeneradorLaserAlien {
void generaLaserAlien(Transformar transformar);
}
Para esta clase simplemente creamos el prototipo del metodo de nuestra clase anterior y si bien esto soluciono los inconvenientes, si se fijan ahora no tendran notificaciones de errores, todavia nos falta la implementacion y para ello usaremos al GameEngine, para esto vamos a modificar el comienzo de la clase:
class GameEngine extends SurfaceView implements Runnable,
Iniciador,
GameEngineBroadcaster,
GeneradorLaserJugador{
De la siguiente manera:
class GameEngine extends SurfaceView implements Runnable,
Iniciador,
GameEngineBroadcaster,
GeneradorLaserJugador,
GeneradorLaserAlien{
El siguiente paso sera definir al metodo de esta interfaz, para ello agregaremos el siguiente bloque dentro de la clase GameEngine:
public void generaLaserAlien(Transformar transformar){
ArrayList<GameObjeto> objetos = mNivel.getObjetos();
if (objetos.get(Nivel.mProximoLaserAlien).generar(transformar)){
Nivel.mProximoLaserAlien++;
mSoundEngine.repDisparar();
if (Nivel.mProximoLaserAlien >= Nivel.ULTIMO_LASER_ALIEN)
Nivel.mProximoLaserAlien = Nivel.PRIMER_LASER_ALIEN;
}
}
En este caso es muy similar a cuando hablamos de como generar el laser del jugador, primero obtenemos todos los objetos del nivel, luego usaremos un condicional donde verifica que se haya generado el laser del alien y en caso de ser verdadero incrementa el valor del proximo laser del alien, luego reproduce el sonido del disparo, por ultimo tenemos un condicional donde verifica si el proximo laser alien es mayor o igual al valor de la constante que almacena el ultimo laser alien, en caso de ser verdadero le asigna el valor del primer laser al proximo laser, con esto ya cubrimos como generar los lasers de los aliens, en el proximo post veremos como implementar los movimientos de los aliens faltantes.
En resumen, hoy hemos creado la clase de los movimientos de nuestro alien Chaser, que tendra la particularidad de estar persiguiendo a nuestro jugador, tambien tendra un campo visual y si nuestro jugador no esta dentro del mismo hara que este se detenga, tambien le dimos la posibilidad de dispararnos, hemos creado la interfaz encargada de disparar y la hemos implementado en la GameEngine, 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.

Tambien podes donar
Es para mantenimiento del sitio, gracias!
$1.00