Anuncios

Bienvenidos sean a este post, hoy hablaremos sobre el patron observador que nos servira para varias cosas.

Anuncios
Anuncios

Mas adelante agregaremos dos clases que se encargaran por un lado de controlar la interfaz del usuario y otra para controlar al jugador y por medio de GameEngine controlaremos los toques de la pantalla para enviar una informacion para una clase u otra, si miramos con retrospectiva nuestros proyectos anteriores cada vez que controlabamos los toques en pantalla lo haciamos por medio de la clase que hace de Game Engine con excepcion del proyecto anterior donde el toque de pantalla era manejado por la clase propia, es decir Snake, pero esto no deberiamos manejarlo de esta forma porque si bien en ese juego tenemos dos clases solamente y no nos estorba pero imaginense un codigo donde tengamos cientos de objetos, nos volveriamos locos para manejar todo eso.

Por este motivo crearemos un mecanismo que se encargue de que los objetos decidan por si mismos mientras el juego esta corriendo y que cada uno reciba los datos del toque para que despues la GameEngine se encargue de contactarlos cada vez que un nuevo dato es recibido, es decir que el GameEngine se encargara de transmitir los datos de toque cuando los reciba y estas dos clases las reciban.

Anuncios

Con el mecanismo explicado vamos a comenzar la implementacion del mismo y para ello lo primero que haremos es crear una nueva interfaz.

Anuncios
Nota: Recordemos que GameEngine sera la encargada de transmitir (Broadcaster) y tendremos dos clases que seran las observadoras.
Anuncios

Al igual que hicimos antes debemos hacer click con el boton derecho sobre la carpeta donde estan nuestras otras clases de Java y seleccionar New -> Java class cuando aparezca el nuevo cuadro completaremos los datos de esta forma:

  • Nombre: GameEngineBroadcaster
  • Tipo: Interface
Anuncios

Una vez creada la interfaz debemos modificar el codigo generado automaticamente por el siguiente:

package org.example.invasores;

interface GameEngineBroadcaster {
    void addObservador(InputObservador o);
}
Anuncios

En este caso hicimos a la interfaz privada y agregamos un prototipo que recibe un tipo de clase que aun no existe, nuestro siguiente paso sera agregar a este tipo que tambien es una interfaz, para ello volvemos a hacer lo anterior con estos datos:

  • Nombre: InputObservador
  • Tipo: Interface
Anuncios

Al igual que en el caso anterior reemplazamos el codigo generado automaticamente con el siguiente:

package org.example.invasores;

import android.graphics.Rect;
import android.view.MotionEvent;

import java.util.ArrayList;

interface InputObservador {
    void handleInput(MotionEvent evento, 
                     GameState gs, 
                     ArrayList<Rect> controles);
}
Anuncios

En esta interfaz solamente agregamos un prototipo que recibira tres datos:

  • Uno de tipo MotionEvent (para los toques en pantalla)
  • GameState para recibir el estado del juego
  • ArrayList para los distintos controles en la pantalla
Anuncios

Con estas dos interfaces creadas procedamos a transformar a nuestro GameEngine en “Broadcaster”, y para ello volveremos a la clase GameEngine y modificaremos esta linea:

class GameEngine extends SurfaceView implements Runnable, Iniciador {
Anuncios

De la siguiente manera:

class GameEngine extends SurfaceView implements Runnable,
        Iniciador, GameEngineBroadcaster {
Anuncios

Como pueden ver lo unico que hicimos fue implementar la ultima interfaz que agregamos aunque nos quede con error no se preocupen porque ahora lo comenzaremos a solucionar y para ello agregaremos primero un objeto de tipo ArrayList junto a las variables que declaramos en el comienzo:

    private ArrayList<InputObservador> inputObservadores = 
            new ArrayList<>();
Anuncios

Con esto simplemente creamos un ArrayList para los observadores de las entradas o lo mismo que decir a cada vez que tocamos la pantalla, lo siguiente es implementar el metodo de la interfaz GameEngineBroadcaster y para ello agregaremos el siguiente bloque y puede ser despues del constructor de esta clase:

    public void addObservador(InputObservador o){
        inputObservadores.add(o);
    }
Anuncios

En este caso recibe un dato de tipo InputObservador para luego tomar ese atributo y agregarlo en el ArrayList llamado inputObservadores, nuestra ultima modificacion sera en el metodo onTouchEvent donde reemplazaremos el bloque actual por el siguiente:

    @Override
    public boolean onTouchEvent(MotionEvent evento){
        for(InputObservador o : inputObservadores){
            o.handleInput(evento,mGameState,mHud.getControles());
        }
        return true;
    }
Anuncios
Anuncios

Como pueden ver reemplazamos la llamada a un sonido por un bucle mejorado que nos garantiza que pasaremos por todos los objetos que contenga inputObservadores esto lo enviara a handleInput con los tres datos, esto como dijimos nos garantiza que los objetos sean 0 o 1000 sean manipulados por nuestra funcion que aun no existe pero de eso hablaremos en el proximo post pero antes de despedirnos veamos como esta quedando el codigo de nuestro GameEngine:

GameEngine.java

package org.example.invasores;

import android.content.Context;
import android.graphics.Point;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceView;

import java.util.ArrayList;

class GameEngine extends SurfaceView implements Runnable,
        Iniciador, GameEngineBroadcaster {
    private Thread mThread = null;
    private long mFPS;

    private ArrayList<InputObservador> inputObservadores =
            new ArrayList<>();

    private GameState mGameState;
    private SoundEngine mSoundEngine;

    HUD mHud;
    Renderer mRenderer;

    public GameEngine(Context contexto, Point tamano){
        super(contexto);
        mGameState = new GameState(this, contexto);
        mSoundEngine = new SoundEngine(contexto);
        mHud = new HUD(tamano);
        mRenderer = new Renderer(this);
    }

    public void addObservador(InputObservador o){
        inputObservadores.add(o);
    }

    @Override
    public void run(){
        while(mGameState.getThreadCorriendo()){
            long frameInicio = System.currentTimeMillis();
            if (!mGameState.getPausado()){

            }
            mRenderer.dibujar(mGameState,mHud);
            long frameActual = System.currentTimeMillis() - frameInicio;
            if (frameActual >= 1){
                final int MILISEGUNDOS = 1000;
                mFPS = MILISEGUNDOS / frameActual;
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent evento){
        for(InputObservador o : inputObservadores){
            o.handleInput(evento,mGameState,mHud.getControles());
        }
        return true;
    }

    public void stopThread(){
        mGameState.detenerTodo();

        try{
            mThread.join();
        } catch (InterruptedException e){
            Log.e("Exception","stopThread" +
                    e.getMessage());
        }
    }

    public void startThread(){
        mGameState.startThread();
        mThread = new Thread(this);
        mThread.start();
    }

    public void desapareceReaparece(){

    }
}
Anuncios

En resumen, hoy hemos visto el concepto del patron Observador, hemos visto como es su teoria, como nos puede ayudar con respecto a lo visto anteriormente, hemos implementado un par de interfaces para generar nuestro “broadcaster”, tambien hemos modificado nuestro game engine para que trabaje de esta forma, 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.

Anuncios

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