Anuncios

Bienvenidos sean a este post, hoy nos centraremos en la creacion de la clase que actuara como una camara para nuestro nivel y seguir a nuestro jugador.

Anuncios
Anuncios

Si bien este va a ser un concepto innovador, inclusive para mi, con respecto a lo visto hasta ahora en proyectos anteriores de este curso como de otros que he realizado no deja de ser muy interesante porque todos los objetos de nuestro niveles van a tener una posicion y tamaño virtual, esto provocara que la deteccion de colision quede vinculada a estos parametros virtuales, como podran darse cuenta estos parametros no tienen relacion con lo que veremos en pantalla porque no todos los objetos se veran en pantalla por cada frame, es mas los objetos no seran visibles la mayoria de los frames y como esta pantalla conoce la resolucion de la pantalla se encargara de convertir estos parametros virtuales en las coordenadas de pixeles.

Anuncios

Comencemos creando la clase con las siguientes caracteristicas:

  • Nombre: Camara
  • Tipo: Class
Anuncios

Nuestro siguiente paso sera modificar el codigo generado con el siguiente:

package org.example.pepeaventura;

import android.graphics.PointF;
import android.graphics.Rect;

class Camara {
    private PointF mCamaraActualCentroMundo;
    private Rect mRectConvertido;
    private int mPixelsPorMetro;
    private int mCentroPantallaX;
    private int mCentroPantallaY;

    Camara(int resolucionPantallaX, int resolucionPantallaY){
        mCentroPantallaX = resolucionPantallaX / 2;
        mCentroPantallaY = resolucionPantallaY / 2;

        final int pixelsPorMetroAradioResolucion = 48;
        mPixelsPorMetro = resolucionPantallaX /
                pixelsPorMetroAradioResolucion;

        mRectConvertido = new Rect();
        mCamaraActualCentroMundo = new PointF();
    }
}
Anuncios

Para esta clase primero declararemos cinco variables:

  • mCamaraActualCentroMundo, sera la encargada de contener el centro de la camara con los parametros virtuales
  • mRectConvertido, este contendra los cuatro puntos convertidos de los parametros virtuales a coordenadas de pixeles
  • mPixelsPorMetro, el numero de pixeles que representa a un metro virtual
  • mCentroPantallaX, es la coordenada del pixel central en el eje horizontal
  • mCentroPantallaY, idem al anterior pero en el eje vertical
Anuncios
Anuncios

Luego tenemos a nuestro constructor, el cual recibira dos atributos que van a ser el ancho y alto de la pantalla, lo primero que haremos es tomar los valores recibidos y dividirlos a la mitad y asignarlos a los ejes correspondientes, con esto ya tendriamos los centros asignados, despues tenemos una constante que usaremos para decir cuantos metros mostraremos en el ancho de la pantalla, variando este valor podemos hacer un ZOOM IN o ZOOM OUT pero para ello deberia dejar de ser constante, luego definiremos el valor de mPixelsPorMetro que sera la division entre resolucionPantallaX y la constante antes comentada, por ultimo crearemos las variables/objetos encargadas de los objetos en pantalla, para nuestro siguiente paso sera agregar los metodos setter and getter:

    int getmPixelsPorMetroY(){
        return mPixelsPorMetro;
    }

    int getCentro(){
        return mCentroPantallaY;
    }

    float getCentroMundoCamaraY(){
        return mCamaraActualCentroMundo.y;
    }

    void setCentroMundo(PointF centroMundo){
        mCamaraActualCentroMundo.x = centroMundo.x;
        mCamaraActualCentroMundo.y = centroMundo.y;
    }

    int getPixelsPorMetro(){
        return mPixelsPorMetro;
    }e
Anuncios

Si observan vamos a tener dos metodos que devuelven el mismo valor, este es mPixelsPorMetro, despues tenemos uno que devuelve el centro de la pantalla en base al eje Y, otro que devuelve el centro de la camara tambien en base al eje Y por ultimo tenemos el metodo encargado de setear el centro del mundo es decir que setea la camara sobre el jugador y sera llamada por cada cuadro dando esa sensacion, por ultimo tenemos el metodo que realiza la verdadera magia:

    Rect mundoApantalla(float objetoX,
                        float objetoY,
                        float objetoAncho,
                        float objetoAlto) {

        int izquierda = (int) (mCentroPantallaX
                - ((mCamaraActualCentroMundo.x - objetoX)
                * mPixelsPorMetro));

        int arriba = (int) (mCentroPantallaY
                - ((mCamaraActualCentroMundo.y - objetoY)
                * mPixelsPorMetro));

        int derecha = (int) (izquierda
                + (objetoAncho * mPixelsPorMetro));

        int abajo = (int) (arriba
                + (objetoAlto * mPixelsPorMetro));

        mRectConvertido.set(izquierda, arriba, derecha, abajo);

        return mRectConvertido;
    }
Anuncios

Este metodo se encargara de devolver las coordenadas de la pantalla relativas a una ubicacion del mundo o nivel, en este metodo recibiremos cuatro parametros:

  • objetoX, sera el valor del eje X del objeto
  • objetoY, el valor del eje Y del objeto
  • objetoAncho, el valor del ancho del objeto
  • objetoAlto, el valor de altura del objeto
Anuncios

Despues crearemos cuatro variables para generar los valores para el objeto Rect que devolveremos, analicemos primero el valor de izquierda:

        int izquierda = (int) (mCentroPantallaX
                - (mCamaraActualCentroMundo.x - objetoX)
                * mPixelsPorMetro);
Anuncios
Anuncios

Lo primero que hacemos es especificar el tipo que queremos devolver y como el lenguaje es safe-type debemos convertirlo al mismo formato y como ambos son de tipo numerico no vamos a tener inconvenientes, en este caso tomaremos el valor del centro del eje X de la pantalla, y le sustraeremos la ubicacion actual donde esta ubicada nuestra camara, como podran ver es la diferencia entre el centro de la camara y el valor del eje X del objeto y a su vez multiplicada por mPixelPorMetro que nos convertira las medidas virtuales en coordenadas en pixeles, esto que realizamos es para el eje X u horizontal de los objetos, en el caso de la variable arriba hacemos exactamente lo mismo pero el eje vertical de los objetos, vamos a tomar el caso de la variable derecha:

        int derecha = (int) (izquierda
                + (objetoAncho * mPixelsPorMetro));
Anuncios

En este caso volvemos a indicar que lo convierta en int pero despues tomaremos el valor de izquierda y lo incrementaremos con el valor del ancho del objeto multiplicado por la escala, para mantener la proporcion, esto determina el limite del eje horizontal de los objetos y con abajo usamos lo mismo pero en lugar de izquierda usamos arriba y lo incrementamos con objetoAlto, con esto ya tenemos los cuatro puntos de referencia para mandar a nuestro objeto Rect, para eso usamos a mRectConvertido y por medio de set le pasamos los cuatro parametros si se lo preguntan equivale a lo siguiente:

  • izquierda = left
  • arriba = top
  • derecha = right
  • abajo = bottom
Anuncios

Como pueden darse cuenta basicamente las variables son los nombres traducidos, despues de haberlo establecido por medio de set y por ultimo devolvemos el objeto creado, con esto ya tenemos nuestra clase terminada pero vamos a suponer un par de ejemplos para entender el concepto de como trabaja nuestra camara.

Anuncios

Vamos a tomar como ejemplo la formula de calculo del valor para izquierda, en este caso seria algo asi:

centropantallaX - ((centrocamaraX - ejexobjeto) * escala)
Nota: Recuerden que para la eje vertical reemplazamos el eje X por el Y.
Anuncios

Si le asignaramos un valor seria algo asi:

960 - ((120 - 120) * 48)
960 - (0 * 48)
960
Anuncios

Si aplicamos valores a la variable arriba se vera algo asi:

540 - ((90 - 90) * 48)
540 - ( 0 * 48)
540
Anuncios

Recordemos la ecuacion para obtener el valor de derecha:

izquierda + (anchoobjeto * escala)
Anuncios

Vamos a asignarle valores:

960 + (1 * 48)
960 + 48
1048
Anuncios

Lo mismo vamos a hacer para la variable abajo:

540 + (2 * 48)
540 + 96
636
Anuncios

Con esto ya tenemos los cuatro valores establecidos para el rectangulo donde estara nuestro objeto, si lo pasamos al set se vera asi:

mRectConvertido.set(960, 540, 1048, 636);
Anuncios

Todas estas operaciones la hara por cada uno de los objetos permitiendo a los mismos en sus respectivos lugares al momento de pasar el jugador, en realidad la camara, por el lugar del mundo o nivel, con esto hemos concluido la clase veamos el codigo final:

Camara.java

package org.example.pepeaventura;

import android.graphics.PointF;
import android.graphics.Rect;

class Camara {
    private PointF mCamaraActualCentroMundo;
    private Rect mRectConvertido;
    private int mPixelsPorMetro;
    private int mCentroPantallaX;
    private int mCentroPantallaY;

    Camara(int resolucionPantallaX, int resolucionPantallaY){
        mCentroPantallaX = resolucionPantallaX / 2;
        mCentroPantallaY = resolucionPantallaY / 2;

        final int pixelsPorMetroAradioResolucion = 48;
        mPixelsPorMetro = resolucionPantallaX /
                pixelsPorMetroAradioResolucion;

        mRectConvertido = new Rect();
        mCamaraActualCentroMundo = new PointF();
    }

    int getmPixelsPorMetroY(){
        return mPixelsPorMetro;
    }

    int getCentro(){
        return mCentroPantallaY;
    }

    float getCentroMundoCamaraY(){
        return mCamaraActualCentroMundo.y;
    }

    void setCentroMundo(PointF centroMundo){
        mCamaraActualCentroMundo.x = centroMundo.x;
        mCamaraActualCentroMundo.y = centroMundo.y;
    }

    int getPixelsPorMetro(){
        return mPixelsPorMetro;
    }

    Rect mundoApantalla(float objetoX,
                        float objetoY,
                        float objetoAncho,
                        float objetoAlto) {

        int izquierda = (int) (mCentroPantallaX
                - ((mCamaraActualCentroMundo.x - objetoX)
                * mPixelsPorMetro));

        int arriba = (int) (mCentroPantallaY
                - ((mCamaraActualCentroMundo.y - objetoY)
                * mPixelsPorMetro));

        int derecha = (int) (izquierda
                + (objetoAncho * mPixelsPorMetro));

        int abajo = (int) (arriba
                + (objetoAlto * mPixelsPorMetro));

        mRectConvertido.set(izquierda, arriba, derecha, abajo);

        return mRectConvertido;
    }
}
Anuncios

En resumen, hoy hemos visto una clase realmente magica, esta nos permitira crear la sensacion de una camara para poder seguir a nuestro jugador en el nivel, tambien nos permitira escalarlos de manera dinamica y trabajarlo para el resto 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