Anuncios

Bienvenidos sean a este post, hoy crearemos a nuestra clase GameState la cual nos traera muchas facilidades a la hora de manejar a todos los objetos del juego.

Anuncios
Anuncios

Pero porque debemos manejarlo con una clase y no como antes? La respuesta es simple, para este juego vamos a necesitar en algunos momentos que una de las clases sepa lo que sucede en las otras porque al momento de ensamblar nuestro juego principal necesitaremos que todas las variables esten en el mismo rango.

Anuncios
Anuncios

Si bien podemos disponer de muchas soluciones para el inconveniente antes mencionado pero nosotros implementaremos una clase (GameState) donde contendra los distintos estados (juego pausado, game over, perder una vida, etc) y estos los compartira por dentro de los metodos de las otras clases, entre las opciones que dispondremos sera la posibilidad de pasar a GameState por medio de GameEngine, en este caso GameEngine podra tener acceso a todos los objetos e inclusive a GameState pero esta ultima clase tendra acceso a toda la informacion que se debe utilizar cuando sea necesario, pero como podemos dar acceso parcial a una clase?

Anuncios
Anuncios

La solucion es una interfaz, de la cual hablamos en este post, porque si bien nosotros podemos pasar una referencia de la GameEngine desde la misma clase a GameState esto no es justamente lo que deseamos porque queremos que GameState tengo un control directo pero limitado porque si GameState tiene demasiado acceso a GameEngine que sucederia si esta decide pausar el juego en un momento incorrecto?

Anuncios
Anuncios

Las interfaces como vimos anteriormente son clases que unicamente poseen las declaraciones o prototipos de metodos, sin ningun tipo de definicion de los mismos, en el caso de que necesitemos implementar una interfaz la clase que lo hace debe definir el o los metodos de la interfaz y a su vez se convierte en un objeto de ese tipo, esto nos da la posibilidad de usarlo polimorficamente como ese tipo, aqui podemos ver algunos ejemplos:

mThread = new Thread(this);
Anuncios
Anuncios

Cuando vimos en los proyectos anteriores a la hora de definir nuestro thread y cuando nosotros enviamos a this como argumento le decimos a este objeto que implemente la interfaz Runnable porque esto es lo que requiere la clase Thread, otro ejemplo de los que vinimos usando es onTouchEvent, si bien nosotros no implementamos esta interfaz directamente si lo hicimos por medio de SurfaceView la cual tambien extiende a View la cual si implementa a un interfaz que nos permite sobreescribir (override) al metodo onTouchListener.

Anuncios

Pasemos a crear nuestra interfaz y para ello debemos hacer click con el boton derecho sobre el contenedor donde estan nuestras otras clases y seleccionaremos New -> Java Class, nos aparecera un nuevo cuadro donde completaremos los siguiente campos:

  • Nombre: Iniciador
  • Tipo: Interface
Anuncios

Con esto solo bastara para poder trabajar con la nueva interfaz, una vez generada reemplazaremos el codigo por el siguiente:

package org.example.invasores;

interface Iniciador {

    public void desapareceReaparece();
}
Anuncios

Como mencionamos anteriormente lo bueno de las interfaces es que solamente debemos declarar el metodo, para implementarlo debemos modificar el comienzo de la clase:

class GameEngine extends SurfaceView implements Runnable
Anuncios

De la siguiente manera:

class GameEngine extends SurfaceView implements Runnable, Iniciador
Anuncios

Si recuerdan hace un tiempo mencionamos que la herencia no podia ser multiple pero si la implementacion de las interfaces por eso es valido agregarlo con una coma despues de Runnable, si bien nos quedo con un error para solucionarlo debemos definir la clase de la interfaz y para ello agregaremos el siguiente bloque dentro de la clase GameEngine:

    public void desapareceReaparece(){
        
    }
Anuncios

Como pueden ver con solo agregarla vacia pero respetando la misma estructura que en la interfaz se soluciono nuestro problema, por el momento no hara nada pero ya existe.

Anuncios
Nota: Recuerden que para poder implementar una interfaz deben al menos definir uno de los metodos de la misma en la clase a implementar.
Anuncios

Con esto podemos pasar a nuestra clase y para ello debemos de vuelta hacer click con el boton derecho sobre el contenedor, seleccionar New -> Java class y completaremos los siguientes campos:

  • Nombre: GameState
  • Tipo: Class
Anuncios

Con nuestra nueva clase generada podemos pasar a modificar el codigo de la clase creada con el siguiente:

package org.example.invasores;

import android.content.SharedPreferences;

final class GameState {
    private static volatile boolean mThredCorriendo = false;
    private static volatile boolean mPaused = true;
    private static volatile boolean mGameOver = true;
    private static volatile boolean mDibujando = false;

    private Iniciador mIniciador;

    private int mPuntaje;
    private int mPuntajeAlto;
    private int mNumNaves;

    private SharedPreferences.Editor mEditor;
}
Anuncios
Anuncios

La primera curiosidad que tenemos en esta clase es la palabra final lo cual hace que nuestra clase no puede ser heredera o como se usa en Java no puede extender a ninguna clase maestra, despues tendremos cuatros variables de tipo boolean que seran estaticas y volatiles, la primera palabra que podran existir en todas las clases del juego y la segunda como vinimos hasta ahora que pueden ser accedidas por todos los threads, pero estas representaran cuatro estados de nuestro juego:

  • mThreadCorriendo, sera para indicar que el juego esta iniciado y funcionando por eso esta en false
  • mPaused, para indicar que el juego se pauso y no solamente que haya salido del enfoque de Android por eso esta en true
  • mGameOver, para indicar que el juego termino por eso esta en true
  • mDibujando, para indicar que se estan manejando los objetos en pantalla, por eso esta en false
Anuncios

Nuestro siguiente objeto sera de la interfaz Iniciador la cual nos permitira tener acceso al metodo desapareceReaparece en GameEngine una vez que es inicializado, despues tendremos tres variables para controlar:

  • mPuntaje, el puntaje en el juego
  • mPuntajeAlto, para almacenar el mejor puntaje
  • mNumNaves, para almacenar el numero de naves (vidas)
Anuncios

Por ultimo pero no menos importante tenemos un objeto de tipo SharedPreferences, es el mismo tema que vimos en el primer proyecto en este post, pero todavia no diremos para que lo usaremos.

Anuncios

Con esto ya tenemos la base de nuestra clase GameState, la cual por ahora como vimos nos permite manejar cuatro estados de nuestro juego, no nuestro thread como hasta ahora, los cuales son:

  • Iniciado
  • Pausado
  • Finalizado
  • Jugando (o dibujando)
Anuncios

Tambien hemos implementado una interfaz que nos permitira pasar una referencia de GameEngine desde GameEngine pero invoca a la interfaz dentro de la clase (GameState) que lo necesita, y por ultimo nos permite llamar metodos de GameEngine a traves de GameState por medio de la interfaz.

Anuncios

En resumen, hoy hemos visto como trabajaremos con este proyecto para manejar a nuestros objetos, hemos explicado porque debemos implementar una interfaz, para que nos sirve, como nos ayuda, despues creamos la clase GameState y hemos creado las variables y/u objetos necesarios para nuestra clase, 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