Bienvenidos sean a este post, hoy llego el gran dia porque hasta ahora creamos todo lo necesario desde los componentes hasta el nivel donde contiene todo pero hoy veremos como implementarlo en nuestro juego.
Para comenzar debemos ir a nuestra clase GameEngine en donde estan todas las declaraciones de las variables/objetos agregaremos la siguiente linea:
Nivel mNivel;
Con esto declaramos a nuestro nuevo objeto, el siguiente paso sera definirlo en el constructor de la clase, para ello agregaremos el siguiente bloque:
mNivel = new Nivel(contexto,
new PointF(tamano.x,tamano.y),
this);
En este caso simplemente creamos el nivel en memoria, el contexto, el tamaño de la pantalla y el GameEngine que en este caso lo hacemos a traves del this, nuestra siguiente modificacion sera en el metodo desapareceReaparece, el cual sera llamado por GameState cuando necesite aparecer o desaparecer los objetos en el nivel, veamos como debemos modificarlo:
public void desapareceReaparece(){
ArrayList<GameObjeto> objetos = mNivel.getObjetos();
for(GameObjeto o : objetos){
o.setInactivo();
}
objetos.get(Nivel.INDICE_JUGADOR)
.generar(objetos.get(Nivel.INDICE_JUGADOR)
.getTransformar());
objetos.get(Nivel.INDICE_FONDO)
.generar(objetos.get(Nivel.INDICE_FONDO)
.getTransformar());
}
Este metodo sera el encargado de aparecer y desaparecer todos los objetos en nuestro nivel, para ello crearemos un nuevo objeto llamado objetos donde estaran todos los GameObjeto de nivel, despues a traves de un for mejorado setearemos a todos como inactivos, luego le diremos que por medio de get obtenga al objeto que sera el jugador, lo genera y por ultimo obtiene el objeto Transformar del jugador, lo mismo hacemos para el fondo, en este caso solo obtendremos dos objetos pero proximamente agregaremos los restantes, pasemos a modificar el siguiente metodo:
@Override
public boolean generaLaserJugador(Transformar transformar){
ArrayList<GameObjeto> objetos = mNivel.getObjetos();
if (objetos.get(Nivel.mProximoLaserJugador)
.generar(transformar)){
Nivel.mProximoLaserJugador++;
mSoundEngine.repDisparar();
if (Nivel.mProximoLaserJugador >= Nivel.ULTIMO_LASER_JUGADOR){
Nivel.mProximoLaserJugador = Nivel.PRIMER_LASER_JUGADOR;
}
}
return true;
}
Este sera el metodo encargado de generar los lasers del jugador, al igual que el caso anterior crearemos un objeto para almacenar los objetos del nivel, luego usaremos un condicional donde genera al «laser», en caso de ser verdadero incrementa el valor de mProximoLaserJugador, luego reproduce el sonido del disparo, despues verifica si mProximoLaserJugador es mayor o igual a ULTIMO_LASER_JUGADOR y en caso de ser verdadero establece el valor del proximo laser con el primer laser del jugador, por ultimo devuelve un true, nuestro siguiente paso sera modificar el metodo run de la siguiente forma:
@Override
public void run(){
while(mGameState.getThreadCorriendo()){
long frameInicio = System.currentTimeMillis();
ArrayList<GameObjeto> objetos = mNivel.getObjetos();
if (!mGameState.getPausado()){
if (mFisicasEngine.actualizar(mFPS,objetos,mGameState,
mSoundEngine,mSistemaParticula))
desapareceReaparece();
}
mRenderer.dibujar(objetos,mGameState,mHud,mSistemaParticula);
long frameActual = System.currentTimeMillis() - frameInicio;
if (frameActual >= 1){
final int MILISEGUNDOS = 1000;
mFPS = MILISEGUNDOS / frameActual;
}
}
}
En este metodo hicimos sutiles diferencias, la primera fue agregar esta linea:
ArrayList<GameObjeto> objetos = mNivel.getObjetos();
Hace exactamente lo mismo que estuvimos viendo hasta ahora, la siguiente modificacion fue en este bloque:
if (mFisicasEngine.actualizar(mFPS,objetos,mGameState,
mSoundEngine,mSistemaParticula))
desapareceReaparece();
Donde modificamos los argumentos de dos a cinco argumentos, esto ocasionara que nos genere un error momentaneamente, y este se encargara de desaparecer o reaparecer los objetos que reciban un impacto, la siguiente modificacion es este bloque:
mRenderer.dibujar(objetos,mGameState,mHud,mGameState);
Este en lugar de recibir los tres argumentos que esperaba recibe cuatro, en ambos casos entre otras cosas le enviamos a objetos, con esto terminamos las modificaciones en la clase GameEngine solo nos resta solucionar los dos problemas que nos aparecieron con estas ultimas modificaciones, vamos a arreglar la primera yendo a la clase FisicasEngine y modificaremos esta linea:
boolean actualizar(long fps, SistemaParticula sp){
De la siguiente forma:
boolean actualizar(long fps,
ArrayList<GameObjeto> objetos,
GameState gs,
SoundEngine se,
SistemaParticula sp){
Con esto podremos recibir todos los datos que decidimos enviarle desde el GameEngine, el siguiente paso es agregar las siguientes lineas dentro del bloque del metodo:
for(GameObjeto objeto : objetos){
if (objeto.chekaActivo()){
objeto.actualizar(fps,
objetos.get(Nivel.INDICE_JUGADOR)
.getTransformar());
}
}
En este caso pasamos por todos los objetos informados, luego usamos a chekaActivo para saber si esta activo o no, en caso de ser verdadero procede a actualizar el objeto con el valor de Transformar, el codigo queda de la siguiente manera:
FisicasEngine.java
package org.example.invasores;
import java.util.ArrayList;
class FisicasEngine {
boolean actualizar(long fps,
ArrayList<GameObjeto> objetos,
GameState gs,
SoundEngine se,
SistemaParticula sp){
for(GameObjeto objeto : objetos){
if (objeto.chekaActivo()){
objeto.actualizar(fps,
objetos.get(Nivel.INDICE_JUGADOR)
.getTransformar());
}
}
if (sp.mEstaCorriendo)
sp.actualizar(fps);
return false;
}
}
Lo siguiente sera la modificacion de la clase Renderer donde primero modificaremos esta linea:
void dibujar(GameState gs, HUD hud, SistemaParticula sp){
De la siguiente manera:
void dibujar(ArrayList<GameObjeto> objetos, GameState gs,
HUD hud, SistemaParticula sp){
Como podemos ver ahora tenemos los cuatro atributos que nos envia GameEngine, la siguiente modificacion sera en el condicional que verifica si se esta dibujando, el cual actualmente esta vacio y lo completaremos de la siguiente manera:
if (gs.getDibujando()){
for(GameObjeto objeto : objetos){
if (objeto.chekaActivo())
objeto.dibujar(mCanvas,pincel);
}
}
En este caso cada vez que este dibujando ejecutara un bucle que pasara por todos los objetos donde chequea objeto por objeto si esta activo y en caso de ser verdadero procede a dibujarlo, nuestra siguiente modificacion sera en el condicional donde verifica si se termino el juego, el cual al igual que en el caso anterior esta en blanco pero lo modificaremos de la siguiente manera:
if (gs.getGameOver()){
objetos.get(Nivel.INDICE_FONDO).dibujar(mCanvas,pincel);
}
En este caso hacemos que dibuje el fondo de pantalla, por ahora, con esto ya tenemos todas las modificaciones realizadas pasemos a ver el codigo de nuestra clase hasta ahora:
Renderer.java
package org.example.invasores;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.util.ArrayList;
class Renderer {
private Canvas mCanvas;
private SurfaceHolder mSurfaceHolder;
private Paint pincel;
Renderer(SurfaceView sv){
mSurfaceHolder = sv.getHolder();
pincel = new Paint();
}
void dibujar(ArrayList<GameObjeto> objetos, GameState gs,
HUD hud, SistemaParticula sp){
if (mSurfaceHolder.getSurface().isValid()){
mCanvas = mSurfaceHolder.lockCanvas();
mCanvas.drawColor(Color.argb(255,0,0,0));
if (gs.getDibujando()){
for(GameObjeto objeto : objetos){
if (objeto.chekaActivo())
objeto.dibujar(mCanvas,pincel);
}
}
if (gs.getGameOver()){
objetos.get(Nivel.INDICE_FONDO).dibujar(mCanvas,pincel);
}
if (sp.mEstaCorriendo)
sp.dibujar(mCanvas,pincel);
hud.dibujar(mCanvas,pincel,gs);
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
}
}
}
Con todo esto ya tenemos nuestro juego bastante avanzado y podemos probarlo, compilemos como funciona hasta ahora en el siguiente video
Como pueden ver funciona de diez, solo me falto probar como sube y baja pero les aseguro que funciona tambien, con esto ya tenemos cubierto como mover el fondo, el disparo, el sonido del disparo y el volteo, nuestro siguiente paso seran los enemigos pero este tema sera un tema arduo y complejo que lo veremos en diferentes posts.
En resumen, hoy hemos implementado todo lo visto en los posts anteriores, hemos visto como implementarlo en el GameEngine, las modificaciones que se deben realizar, por ultimo lo hemos probado y comprobado como esta funcionando con nuestro GameObjetos, 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