Anuncios

Bienvenidos sean a este post, si bien nosotros tenemos una clase encargada de transformar a nuestros objetos para el caso de Pepe vamos a necesitar una clase diferente para poder trabajar mejor sobre él.

Anuncios

Como pueden imaginarse a diferencia de proyectos anteriores ahora no solamente necesitamos que nuestro personaje tenga contacto con los bordes, una bala, una manzana, un laser o un limite superior o inferior, sino que tambien deberemos hacer susceptible que distinta partes de su cuerpo detecten un contacto, por este motivo debemos crear una clase nueva pero que se dedique pura y exclusivamente al jugador y para ello vamos a crear la nueva clase con las siguientes caracteristicas:

  • Nombre: JugadorTransformar
  • Tipo: Class
Anuncios

Una vez creada la nueva clase modificaremos su codigo con el siguiente:

package org.example.pepeaventura;

import android.graphics.PointF;
import android.graphics.RectF;

import java.util.ArrayList;

class JugadorTransformar extends Transformar {

    private ArrayList<RectF> mChocadores;

    private final float DECIMO = .1f;
    private final float MITAD = .5f;
    private final float TERCIO = .3f;
    private final float QUINTO = .2f;
    private final float PIES_SALIENTE = 1.2f;

    private RectF mCabezaRectF = new RectF();
    private RectF mDerechaRectF = new RectF();
    private RectF mIzquierdaRectF = new RectF();
    private RectF mPiesRectF = new RectF();

    private boolean mSaltoIniciado = false;
    private boolean mCabezaGolpeadaIniciada = false;
    private boolean mEnTierra;

    JugadorTransformar(float velocidad,
                       float anchoObjeto,
                       float altoObjeto,
                       PointF ubicacionInicial){

        super(velocidad,
                anchoObjeto,
                altoObjeto,
                ubicacionInicial);

        mChocadores = new ArrayList<>();
        mChocadores.add(mCabezaRectF);
        mChocadores.add(mDerechaRectF);
        mChocadores.add(mIzquierdaRectF);
        mChocadores.add(mPiesRectF);
    }
}
Anuncios
Anuncios

En esta nueva clase la primera rareza que tendremos es el ArrayList para RectF al cual llamaremos mChocadores, porque como mencionamos al principio ahora no solamente necesitamos detectar las colisiones sino tambien debemos detectar el tipo de colision, de esto hablaremos mas adelante, y como deben ser varios tipos de colisiones lo haremos de esta forma, las siguientes cinco variables seran usadas mas que nada para cuando veamos el tema de las colisiones, las siguientes cuatro variables seran las rectangulos que usaremos para detectar las cuatro posiciones de nuestro sprite, es decir arriba (cabeza), abajo (pies), lado izquierdo y lado derecho, despues tenemos tres variables que las usaremos principalmente para detectar si esta saltando (mSaltoIniciado), si chocamos contra una plataforma superior (mCabezaGolpeadaIniciada) y por ultimo para saber si estamos sobre una plataforma (mEnTierra).

Anuncios

El siguiente paso sera el constructor donde recibiremos cuatro atributos, los cuales seran la velocidad, la altura, el ancho y la posicion inicial del sprite de nuestro jugador, como nosotros hicimos a esta clase heredera de Transformar necesitamos enviar estos datos al constructor de esta clase por medio de super, con esto ya tenemos solucionado el inconveniente de la herencia o extension (como quieran llamarlo), lo siguiente sera definir el espacio en memoria del ArrayList llamado mChocadores, despues por medio de add agregaremos cada uno de los elementos que usaremos para detectar las colisiones, con esto ya tenemos el constructor concluido pasemos a agregar el siguiente metodo:

    public ArrayList<RectF> getChocadores(){
        actualizaChocadores();
        return mChocadores;
    }
Anuncios

Este metodo se encargara de devolvernos a mChocadores pero antes actualizara los mismos por medio del metodo actualizaChocadores, el cual agregaremos a continuacion:

    public void actualizaChocadores(){
        PointF ubicacion = getUbicacion();
        float alturaObjeto = getTamano().y;
        float anchoObjeto = getTamano().x;

        mChocadores.get(0).left = ubicacion.x
                + ((anchoObjeto * TERCIO));
        mChocadores.get(0).top = ubicacion.y;
        mChocadores.get(0).right = ubicacion.x
                + anchoObjeto - (anchoObjeto * TERCIO);
        mChocadores.get(0).right = ubicacion.y
                + (alturaObjeto * DECIMO);

        mChocadores.get(1).left = ubicacion.x
                + anchoObjeto - (anchoObjeto * DECIMO);
        mChocadores.get(1).top = ubicacion.y
                + (alturaObjeto * TERCIO);
        mChocadores.get(1).right = ubicacion.x
                + anchoObjeto;
        mChocadores.get(1).bottom = ubicacion.y
                + (alturaObjeto -(alturaObjeto * MITAD));

        mChocadores.get(2).left = ubicacion.x;
        mChocadores.get(2).top = ubicacion.y
                + (alturaObjeto * QUINTO);
        mChocadores.get(2).right = ubicacion.x
                + (anchoObjeto * DECIMO);
        mChocadores.get(2).bottom = ubicacion.y
                + (alturaObjeto - (alturaObjeto * QUINTO));

        mChocadores.get(3).left = ubicacion.x
                + (anchoObjeto * TERCIO);
        mChocadores.get(3).top = ubicacion.y
                + alturaObjeto - (alturaObjeto * DECIMO);
        mChocadores.get(3).right = ubicacion.x
                + anchoObjeto - (anchoObjeto * TERCIO);
        mChocadores.get(3).bottom = ubicacion.y
                + alturaObjeto + (alturaObjeto * PIES_SALIENTE);

    }
Anuncios

En esta ocasion vamos a sacar ventaja de la herencia porque al prinicipio tendremos tres variables y las definiremos gracias a los metodos de la clase maestra (Transformar), veamos para que son:

  • ubicacion, sera para la ubicacion de nuestro sprite en los ejes X e Y y gracias al metodo getUbicacion
  • alturaObjeto, sera la altura del objeto y gracias al valor del eje Y devuelto por getTamano
  • anchoObjeto, es el ancho del objeto y este es por el valor de X de la devolucion de getTamano
Anuncios

Con estos tres datos mas las constantes podremos definir las cuatro coordenadas del objeto RectF que esta dentro del ArrayList, vamos a tomar uno de ejemplo:

        mChocadores.get(0).right = ubicacion.x
                + anchoObjeto - (anchoObjeto * TERCIO);
Anuncios

En este caso vamos a tomar el caso del seteo de la coordenada right, para ello primero pasaramos al eje X de ubicacion y la sumaremos la diferencia entre el ancho del objeto y el ancho del objeto por el valor en TERCIO, salvo en casos especificos donde pasaremos uno solo de los ejes de ubicacion el resto sera incrementado por el ancho o la altura y en algunos casos como este seran afectados por una de las constantes definidas al principio, vamos a indicar que hace cada bloque de reasignacion de coordenadas:

        mChocadores.get(0).left = ubicacion.x
                + ((anchoObjeto * TERCIO));
        mChocadores.get(0).top = ubicacion.y;
        mChocadores.get(0).right = ubicacion.x
                + anchoObjeto - (anchoObjeto * TERCIO);
        mChocadores.get(0).right = ubicacion.y
                + (alturaObjeto * DECIMO);
Anuncios

Este sera para detectar lo que este por arriba de la cabeza, veamos el siguiente bloque:

        mChocadores.get(1).left = ubicacion.x
                + anchoObjeto - (anchoObjeto * DECIMO);
        mChocadores.get(1).top = ubicacion.y
                + (alturaObjeto * TERCIO);
        mChocadores.get(1).right = ubicacion.x
                + anchoObjeto;
        mChocadores.get(1).bottom = ubicacion.y
                + (alturaObjeto -(alturaObjeto * MITAD));
Anuncios

Este estara a la derecha de nuestro sprite, pasemos al siguiente bloque:

        mChocadores.get(2).left = ubicacion.x;
        mChocadores.get(2).top = ubicacion.y
                + (alturaObjeto * QUINTO);
        mChocadores.get(2).right = ubicacion.x
                + (anchoObjeto * DECIMO);
        mChocadores.get(2).bottom = ubicacion.y
                + (alturaObjeto - (alturaObjeto * QUINTO));
Anuncios

Este va a ser para el lado izquierdo de nuestro sprite, veamos el ultimo bloque:

        mChocadores.get(3).left = ubicacion.x
                + (anchoObjeto * TERCIO);
        mChocadores.get(3).top = ubicacion.y
                + alturaObjeto - (alturaObjeto * DECIMO);
        mChocadores.get(3).right = ubicacion.x
                + anchoObjeto - (anchoObjeto * TERCIO);
        mChocadores.get(3).bottom = ubicacion.y
                + alturaObjeto + (alturaObjeto * PIES_SALIENTE);
Anuncios

Este va a corresponder a los pies de nuestro sprite, como pueden ver usamos la constante PIES_SALIENTE para la coordenada bottom, es decir para detectar cuando esta en el piso o no, con esto ya tenemos lo basico si lo tuvieramos que graficar sera algo semejante a esto

Anuncios

Donde las lineas rojas representan los RectF que acabamos de definir, como les dije antes esto nos dara la posibilidad de poder trabajar de mejor forma para interpretar cuando el personaje se cae, esta en una plataforma o simplemente tiene una obstruccion adelante que debe saltar, para ir finalizando vamos a agregar los siguientes metodos getter and setter:

    void iniciaSalto(){
        mSaltoIniciado = true;
    }

    void manejandoSalto(){
        mSaltoIniciado = false;
    }

    boolean saltoIniciado(){
        return mSaltoIniciado;
    }

    void setNoEnTierra(){
        mEnTierra = false;
    }

    void disparaCabezaGolpeada(){
        mCabezaGolpeadaIniciada = true;
    }

    void manejandoCabezaGolpeada(){
        mCabezaGolpeadaIniciada = false;
    }

    boolean cabezaGolpeada(){
        return mCabezaGolpeadaIniciada;
    }

    void noEnTierra(){
        mEnTierra = false;
    }

    void enTierra(){
        mEnTierra = true;
    }

    boolean estaEnTierra(){
        return mEnTierra;
    }
Anuncios

Estos metodos se encargaran de setear y devolver algunas de las variables de esta clase, veamos el detalle:

Anuncios
  • iniciaSalto, sirve para indicar que se inicio el salto
  • manejandoSalto, nos sirve para pasar a false el salto y comenzar la caida
  • saltoIniciado, sirve para devolver el estado de si esta saltando o no
  • setNoEnTierra, informa que no esta sobre tierra o una plataforma
  • disparaCabezaGolpeada, seteara que el jugador choco con una plataforma superior
  • manejandoCabezaGolpeada, setea en false la variable y comienza la caida
  • cabezaGolpeada, nos devuelve el valor de la variable que maneja el golpe en la cabeza
  • noEnTierra, setea que no esta en tierra o en una plataforma
  • enTierra, setea que esta en tierra o en una plataforma
  • estaEnTierra, devuelve el valor de la variable que maneja el estar sobre la tierra o plataforma
Anuncios

En realidad todos estos metodos los usaremos cuando actualicemos la clase encargada de manejar las fisicas y con los componentes que agregaremos en el siguiente post, con esto ya podemos dar por terminada la clase y podemos pasar a ver como quedo nuestro codigo final:

JugadorTransformar.java

package org.example.pepeaventura;

import android.graphics.PointF;
import android.graphics.RectF;

import java.util.ArrayList;

class JugadorTransformar extends Transformar {

    private ArrayList<RectF> mChocadores;

    private final float DECIMO = .1f;
    private final float MITAD = .5f;
    private final float TERCIO = .3f;
    private final float QUINTO = .2f;
    private final float PIES_SALIENTE = 1.2f;

    private RectF mCabezaRectF = new RectF();
    private RectF mDerechaRectF = new RectF();
    private RectF mIzquierdaRectF = new RectF();
    private RectF mPiesRectF = new RectF();

    private boolean mSaltoIniciado = false;
    private boolean mCabezaGolpeadaIniciada = false;
    private boolean mEnTierra;

    JugadorTransformar(float velocidad,
                       float anchoObjeto,
                       float altoObjeto,
                       PointF ubicacionInicial){

        super(velocidad,
                anchoObjeto,
                altoObjeto,
                ubicacionInicial);

        mChocadores = new ArrayList<>();
        mChocadores.add(mCabezaRectF);
        mChocadores.add(mDerechaRectF);
        mChocadores.add(mIzquierdaRectF);
        mChocadores.add(mPiesRectF);
    }

    public ArrayList<RectF> getChocadores(){
        actualizaChocadores();
        return mChocadores;
    }


    public void actualizaChocadores() {
    PointF ubicacion = getUbicacion();
    float alturaObjeto = getTamano().y;
    float anchoObjeto = getTamano().x;

    mChocadores.get(0).left = ubicacion.x
            + ((anchoObjeto * TERCIO));
    mChocadores.get(0).top = ubicacion.y;
    mChocadores.get(0).right = ubicacion.x
            + anchoObjeto - (anchoObjeto * TERCIO);
    mChocadores.get(0).right = ubicacion.y
            + (alturaObjeto * DECIMO);

    mChocadores.get(1).left = ubicacion.x
            + anchoObjeto - (anchoObjeto * DECIMO);
    mChocadores.get(1).top = ubicacion.y
            + (alturaObjeto * TERCIO);
    mChocadores.get(1).right = ubicacion.x
            + anchoObjeto;
    mChocadores.get(1).bottom = ubicacion.y
            + (alturaObjeto - (alturaObjeto * MITAD));

    mChocadores.get(2).left = ubicacion.x;
    mChocadores.get(2).top = ubicacion.y
            + (alturaObjeto * QUINTO);
    mChocadores.get(2).right = ubicacion.x
            + (anchoObjeto * DECIMO);
    mChocadores.get(2).bottom = ubicacion.y
            + (alturaObjeto - (alturaObjeto * QUINTO));

    mChocadores.get(3).left = ubicacion.x
            + (anchoObjeto * TERCIO);
    mChocadores.get(3).top = ubicacion.y
            + alturaObjeto - (alturaObjeto * DECIMO);
    mChocadores.get(3).right = ubicacion.x
            + anchoObjeto - (anchoObjeto * TERCIO);
    mChocadores.get(3).bottom = ubicacion.y
            + alturaObjeto + (alturaObjeto * PIES_SALIENTE);
    }

    void iniciaSalto(){
        mSaltoIniciado = true;
    }

    void manejandoSalto(){
        mSaltoIniciado = false;
    }

    boolean saltoIniciado(){
        return mSaltoIniciado;
    }

    void setNoEnTierra(){
        mEnTierra = false;
    }

    void disparaCabezaGolpeada(){
        mCabezaGolpeadaIniciada = true;
    }

    void manejandoCabezaGolpeada(){
        mCabezaGolpeadaIniciada = false;
    }

    boolean cabezaGolpeada(){
        return mCabezaGolpeadaIniciada;
    }

    void noEnTierra(){
        mEnTierra = false;
    }

    void enTierra(){
        mEnTierra = true;
    }

    boolean estaEnTierra(){
        return mEnTierra;
    }
}
Anuncios

En resumen, hoy hemos creado los distintos objetos que se encargaran de las detecciones de colisiones, a diferencia de los otros proyectos no tratamos al jugador como un rectangulo sino que debemos encerrarlo entre distintos rectangulos para poder detectar cual es la situacion de colision y poder trabajar al respecto, 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