Anuncios

Bienvenidos sean a este post, hoy crearemos la clase encargada de los distintos estados del juego.

Anuncios

Esta va a trabajar de forma muy similar al proyecto anterior, aunque se podran imaginar que los estados de este juego van a ser un poco diferentes, ya que en lugar de estar enfocado en los aliens, puntajes o lasers tiene que estar supervisando el tiempo, monitorear otros tiempos (como las plataformas), el nivel que esta jugando, asi como tambien conocer y compartir los estados de pausado, jugando, dibujando, corriendo, etc.

Anuncios

Para comenzar vamos a crear una nueva clase con las siguientes caracteristicas:

  • Nombre: GameState
  • Tipo: Class
Anuncios

Una vez creada la nueva clase vamos a modificar el codigo generado con el siguiente:

package org.example.pepeaventura;

import android.content.Context;
import android.content.SharedPreferences;

final class GameState {
    private static volatile boolean mThreadCorriendo = false;
    private static volatile boolean mPausado = true;
    private static volatile boolean mGameOver = true;
    private static volatile boolean mDibujando = false;
    private ControladorEngine controladorEngine;
    private int mCuevaMasRapida;
    private int mMontanaMasRapida;
    private int mCiudadMasRapida;
    private long tiempoInicialEnMilis;
    private int mMonedasDisponibles;
    private int monedasRecogidas;
    private SharedPreferences.Editor editor;
    private String nivelActual;

    GameState(ControladorEngine gs, Context contexto){
        controladorEngine = gs;
        SharedPreferences prefs = contexto.getSharedPreferences(
                "Record",
                Context.MODE_PRIVATE);
        editor = prefs.edit();
        mCuevaMasRapida = prefs.getInt(
                "tiempo_cueva_masrapido",1000);
        mMontanaMasRapida = prefs.getInt(
                "tiempo_montana_masrapido",1000);
        mCiudadMasRapida = prefs.getInt(
                "tiempo_ciudad_masrapido",1000);
    }

    void monedasRecogidas(){
        monedasRecogidas++;
    }

    int getMonedasRestantes(){
        return mMonedasDisponibles - monedasRecogidas;
    }

    void monedasAgregadasAlNivel(){
        mMonedasDisponibles++;
    }

    void reseteoMonedas(){
        mMonedasDisponibles = 0;
        monedasRecogidas = 0;
    }

    void setNivelActual(String nivel){
        nivelActual = nivel;
    }

    String getNivelActual(){
        return nivelActual;
    }

    void objetivoAlcanzado(){
        finalJuego();
    }

    int getCuevaMasRapida(){
        return mCuevaMasRapida;
    }
    
    int getMontanaMasRapida(){
        return mMontanaMasRapida;
    }
    
    int getCiudadMasRapida(){
        return mCiudadMasRapida;
    }
}
Anuncios

Vamos a analizar este codigo, primero tendremos estas variables:

  • mThreadCorriendo, se encargara de decir cuando esta activo el thread principal
  • mPausado, indica si el juego esta pausado o no
  • mGameOver, indica si el juego se termino o no
  • mDibujando, indica si esta dibujando o no
Anuncios
Anuncios

Con estas variables sabremos como es el estado de nuestro juego, ya sea desde que esta corriendo hasta el juego terminado tambien estas variables son de tipo static para que sean accesibles para todas las clases y volatile para poder manipular a traves de nuestro thread, veamos las siguientes variables:

  • controladorEngine, este sera una referencia para manipular el juego/nivel directamente
  • mCuevaMasRapida, sera para almacenar el mejor puntaje en la cueva
  • mMontanaMasRapida, idem al anterior pero en la montaña
  • mCiudadMasRapida, idem al anterior pero en la ciudad
  • tiempoInicialEnMilis, se iniciara con cada nivel para averiguar cuando se tardo en superar el nivel
  • mMonedasDisponibles, indica el total de monedas en el nivel
  • monedasRecogidas, cuantas monedas recogimos
  • editor, sera para escribir el nuevo “record”
  • nivelActual, indicara cual es el nivel que estamos jugando
Anuncios

Con estos ya tenemos nuestras variables cubiertas, el siguiente bloque es el constructor de la clase, en este definiremos a controladorEngine, despues crearemos una variable de tipo SharedPreferences para poder obtener los mejores puntajes, definimos a editor y por ultimo obtenemos los puntajes de cada nivel con sus respectivos identificadores y el valor predeterminado en caso de no tenerlo es 1000, despues tendremos metodos de tipo getter and setter y algunas funciones extras, las funciones setter son:

  • setNivelActual, establece en que nivel estamos
Anuncios

Las funciones getter son:

  • getMonedasRestantes, nos devuelve la diferencia entre las monedas del nivel y las monedas recogidas
  • getNivelActual, devuelve el valor del nivel actual
  • getCuevaMasRapida, devuelve el mejor tiempo de la cueva
  • getMontanaMasRapida, devuelve el mejor tiempo de la montaña
  • getCiudadMasRapida, devuelve el mejor tiempo de la ciudad
Anuncios

Por ultimo tendremos estas funciones:

  • monedasRecogidas, incrementa el valor de monedasRecogidas
  • monedasAgregadasAlNivel, incrementa el valor de mMonedasDisponibles
  • reseteoMonedas, resetea las variables de las monedas
  • objetivoAlcanzado, sera para finalizar el juego/nivel
Anuncios

Con esto ya tenemos algunos aspectos cubiertos pero todavia nos faltan otros metodos para los estados faltantes del juego y/u objetos, para ello agregaremos los siguientes metodos:

    void iniciaNuevoJuego(){
        detenTodo();
        controladorEngine.iniciaNuevoNivel();
        iniciaTodo();
        tiempoInicialEnMilis = System.currentTimeMillis();
    }

    int getTiempoActual(){
        long MILES_EN_SEGUNDOS = 1000;
        return (int) ((System.currentTimeMillis()
                - tiempoInicialEnMilis) / MILES_EN_SEGUNDOS);
    }

    void muerte(){
        detenTodo();
        SoundEngine.playJugadorQuemar();
    }

    private void finalJuego(){
        detenTodo();
        int tiempoTotal = ((mMonedasDisponibles - monedasRecogidas) * 10) 
                + getTiempoActual();

        switch (nivelActual){
            case "cueva":
                if (tiempoTotal < mCuevaMasRapida){
                    mCuevaMasRapida = tiempoTotal;
                    editor.putInt("tiempo_cueva_masrapido", mCuevaMasRapida);
                    editor.commit();
                }
                break;
            case "montana":
                if (tiempoTotal < mMontanaMasRapida){
                    mMontanaMasRapida = tiempoTotal;
                    editor.putInt("tiempo_montana_masrapido", mMontanaMasRapida);
                    editor.commit();
                }
                break;
            case "ciudad":
                if (tiempoTotal < mCiudadMasRapida){
                    mCiudadMasRapida = tiempoTotal;
                    editor.putInt("tiempo_ciudad_masrapido", mCiudadMasRapida);
                    editor.commit();
                }
                break;
        }
    }
Anuncios
Anuncios

El primer metodo iniciara un nuevo juego, en este caso detiene todo (proximamente agregaremos este metodo), luego iniciaremos un nuevo nivel, usaremos un metodo para iniciar todo (tambien lo agregaremos a continuacion), por ultimo reiniciaremos el valor tiempoInicialEnMilis pasemos al siguiente metodo, este nos devolvera el tiempo actual del juego, para ello establecemos un valor de tipo long, luego devolvemos la diferencia entre el tiempo actual y el valor establecido de tiempoInicialEnMilis y a esta diferencia la dividiremos por la variable anterior, el siguiente metodo se encarga de la muerte del jugador y para ello llama a detenTodo y reproducira un sonido pero como hicimos en el proyecto anterior a traves de una clase pero la crearemos mas adelante.

El siguiente metodo es el encargado de finalizar el juego, en este caso es llamado cuando se alcanza el objetivo o la meta, primero creara una variablle llamada tiempoTotal la cual almacenara la diferencia entre las monedas del nivel y las recogidas y la multiplicara por diez, a este total le sumara el valor obtenido por getTiempoActual, despues tendremos un switch donde verifica el nivel actual, los tres case son iguales pero cada case representa cada uno de los niveles, vamos a tomar uno de ejemplo:

            case "cueva":
                if (tiempoTotal < mCuevaMasRapida){
                    mCuevaMasRapida = tiempoTotal;
                    editor.putInt("tiempo_cueva_masrapido", mCuevaMasRapida);
                    editor.commit();
                }
Anuncios

En este caso si el nivel es de la cueva, verifica si tiempoTotal es menor mCuevaMasRapida, en caso de ser verdadero procede a reemplazar el valor de mCuevaMasRapida con tiempoTotal, despues usamos a editor para escribir este valor en las preferencias con la clave “tiempo_cueva_masrapido“, la siguiente linea sube los cambios al archivo, los otros case son lo mismo pero para la montaña y la ciudad, vamos a agregar los ultimos metodos que nos faltan:

    void detenTodo(){
        mPausado = true;
        mGameOver = true;
        mDibujando = false;
    }

    void iniciaTodo(){
        mPausado = false;
        mGameOver = false;
        mDibujando = true;
    }

    void detenThread(){
        mThreadCorriendo = false;
    }

    void iniciaThread(){
        mThreadCorriendo = true;
    }

    boolean getThreadCorriendo(){
        return mThreadCorriendo;
    }

    boolean getDibujando(){
        return mDibujando;
    }

    boolean getPausado(){
        return mPausado;
    }
    
    boolean getGameOver(){
        return mGameOver;
    }
Anuncios
Anuncios

El primer metodo se encarga de detener todos los procesos, excepto el Thread, setea como true a mPausado y mGameOver y como false a mDibujando, el siguiente metodo se encarga de iniciar todos los procesos y hace todo lo contrario al primero pero tampoco inicia al Thread, los siguientes metodos si se encargaran de detener e iniciar el thread del juego respectivamente, los ultimos cuatro metodos son de tipo getter para devolver los valores mThreadCorriendo, mDibujando, mPausado y mGameOver en ese orden, con esto tenemos nuestra clase terminada (salvo por el detalle del SoundEngine) pero como pueden ver se manejan varios de los estados del juego y tambien el mejor puntaje de cada uno de los niveles, veamos como quedo su codigo hasta ahora:

GameState.java

package org.example.pepeaventura;

import android.content.Context;
import android.content.SharedPreferences;

final class GameState {
    private static volatile boolean mThreadCorriendo = false;
    private static volatile boolean mPausado = true;
    private static volatile boolean mGameOver = true;
    private static volatile boolean mDibujando = false;
    private ControladorEngine controladorEngine;
    private int mCuevaMasRapida;
    private int mMontanaMasRapida;
    private int mCiudadMasRapida;
    private long tiempoInicialEnMilis;
    private int mMonedasDisponibles;
    private int monedasRecogidas;
    private SharedPreferences.Editor editor;
    private String nivelActual;

    GameState(ControladorEngine gs, Context contexto){
        controladorEngine = gs;
        SharedPreferences prefs = contexto.getSharedPreferences(
                "Record",
                Context.MODE_PRIVATE);
        editor = prefs.edit();
        mCuevaMasRapida = prefs.getInt(
                "tiempo_cueva_masrapido",1000);
        mMontanaMasRapida = prefs.getInt(
                "tiempo_montana_masrapido",1000);
        mCiudadMasRapida = prefs.getInt(
                "tiempo_ciudad_masrapido",1000);
    }

    void monedasRecogidas(){
        monedasRecogidas++;
    }

    int getMonedasRestantes(){
        return mMonedasDisponibles - monedasRecogidas;
    }

    void monedasAgregadasAlNivel(){
        mMonedasDisponibles++;
    }

    void reseteoMonedas(){
        mMonedasDisponibles = 0;
        monedasRecogidas = 0;
    }

    void setNivelActual(String nivel){
        nivelActual = nivel;
    }

    String getNivelActual(){
        return nivelActual;
    }

    void objetivoAlcanzado(){
        finalJuego();
    }

    int getCuevaMasRapida(){
        return mCuevaMasRapida;
    }

    int getMontanaMasRapida(){
        return mMontanaMasRapida;
    }

    int getCiudadMasRapida(){
        return mCiudadMasRapida;
    }

    void iniciaNuevoJuego(){
        detenTodo();
        controladorEngine.iniciaNuevoNivel();
        iniciaTodo();
        tiempoInicialEnMilis = System.currentTimeMillis();
    }

    int getTiempoActual(){
        long MILES_EN_SEGUNDOS = 1000;
        return (int) ((System.currentTimeMillis()
                - tiempoInicialEnMilis) / MILES_EN_SEGUNDOS);
    }

    void muerte(){
        detenTodo();
        SoundEngine.playJugadorQuemar();
    }

    private void finalJuego(){
        detenTodo();
        int tiempoTotal = ((mMonedasDisponibles - monedasRecogidas) * 10)
                + getTiempoActual();

        switch (nivelActual){
            case "cueva":
                if (tiempoTotal < mCuevaMasRapida){
                    mCuevaMasRapida = tiempoTotal;
                    editor.putInt("tiempo_cueva_masrapido", mCuevaMasRapida);
                    editor.commit();
                }
                break;
            case "montana":
                if (tiempoTotal < mMontanaMasRapida){
                    mMontanaMasRapida = tiempoTotal;
                    editor.putInt("tiempo_montana_masrapido", mMontanaMasRapida);
                    editor.commit();
                }
                break;
            case "ciudad":
                if (tiempoTotal < mCiudadMasRapida){
                    mCiudadMasRapida = tiempoTotal;
                    editor.putInt("tiempo_ciudad_masrapido", mCiudadMasRapida);
                    editor.commit();
                }
                break;
        }
    }

    void detenTodo(){
        mPausado = true;
        mGameOver = true;
        mDibujando = false;
    }

    void iniciaTodo(){
        mPausado = false;
        mGameOver = false;
        mDibujando = true;
    }

    void detenThread(){
        mThreadCorriendo = false;
    }

    void iniciaThread(){
        mThreadCorriendo = true;
    }

    boolean getThreadCorriendo(){
        return mThreadCorriendo;
    }

    boolean getDibujando(){
        return mDibujando;
    }

    boolean getPausado(){
        return mPausado;
    }

    boolean getGameOver(){
        return mGameOver;
    }
}
Anuncios

En resumen, hoy hemos creado la clase encargada de manejar la mayor cantidad de estados del juego, hemos visto como se maneja los mejores puntajes de cada nivel, a traves de las preferencias de Android, hemos visto como controlar los distintos estados del juego, ya sea desde iniciar el Thread hasta el game over del juego, 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.

Donación

Es para mantenimento del sitio, gracias!

$1.00