Anuncios

Bienvenidos sean a este post, en el post de hoy vamos a finalizar nuestro proyecto mediante la implementacion de la clase anterior en nuestro game engine.

Anuncios

Para ello debemos ir a nuestra clase SnakeJuego, al constructor de la misma y agregar el siguiente bloque justo despues del constructor de la manzana:

        mSnake = new Snake(contexto,
                new Point(ANCHO_NUM_BLOQUES,
                        mNumeroBloquesAlto), 
                tamanoBloque);
Anuncios

En este caso creamos a nuestra «serpiente», para ello enviamos el contexto, luego por medio de Point enviaremos dos datos para la creacion del tamaño de nuestra grilla y por ultimo el tamaño del segmento para la imagen, con esto iniciamos el objeto y nuestro siguiente paso sera agregar la siguiente linea en el metodo que inicia el juego:

        mSnake.reset(ANCHO_NUM_BLOQUES,mNumeroBloquesAlto);
Anuncios

Esta linea ira dentro del metodo nuevoJuego y sera encargada de resetear el cuerpo de nuestra serpiente, nuestro siguiente cambio sera la implementacion del metodo actualizar, para ello agregaremos el siguiente codigo:

    public void actualizar(){
        mSnake.mover();
        if (mSnake.chekaCena(mManzana.getUbicacion())){
            mManzana.generar();
            mPuntaje++;
            mSP.play(mComer_ID,1,1,0,0,1);
        }
        if (mSnake.detectarMuerte()){
            mSP.play(mMordida_ID,1,1,0,0,1);
            mPausado = true;
        }
    }
Anuncios
Anuncios

Hasta antes de esta modificacion nuestro metodo simplemente estaba en blanco pero ahora lo primero que hace es mover a la serpiente y el primer condicional chequea si comimos la manzana a traves del metodo chekaCena al cual le informamos la ubicacion de la manzana por medio de getUbicacion, en caso de ser cierto procede a generar una nueva en pantalla, incrementa el puntaje y reproduce el sonido de comerlo.

El siguiente condicional verifica si morimos, es decir si nos mordimos o nos salimos de la pantalla, en cualquier caso procede a reproducir el sonido de la falla y establece a mPausado como true para detener el juego, con esto ya tenemos cubierto el metodo actualizar, nuestra siguiente modificacion sera en el metodo dibujar de esta clase donde agregaremos la siguiente linea justo despues de dibujar la manzana y antes del condicional donde chequea si esta pausado:

mSnake.dibujar(mCanvas,mPincel);
Anuncios

En esta linea simplemente vamos a dibujar a la serpiente mediante el canvas y pincel de nuestro game engine, la ultima modificacion sera para cuando tocamos la pantalla y para ello agregaremos una linea dentro del case de ACTION_UP despues del condicional donde verifica a mPausado:

mSnake.cambiarDireccion(evento);
Anuncios

Con esto cambia la direccion de nuestra cabeza dependiendo de que lado de la pantalla toquemos y con esto ya finalizamos los cambios en nuestro juego y ya tenemos todo implementado, veamos el codigo final de nuestro game engine:

SnakeJuego.js

package org.example.snake;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.io.IOException;

class SnakeJuego extends SurfaceView implements Runnable {

    private Thread mThread = null;
    private long mProxTiempoCuadro;
    private volatile boolean mPausado = true;
    private volatile boolean mJugando = false;
    private SoundPool mSP;
    private int mComer_ID = -1;
    private int mMordida_ID = -1;
    private final int ANCHO_NUM_BLOQUES = 30;
    private int mNumeroBloquesAlto;
    private int mPuntaje;
    private Canvas mCanvas;
    private SurfaceHolder mSurfaceHolder;
    private Paint mPincel;
    private Snake mSnake;
    private Manzana mManzana;

    public SnakeJuego(Context contexto, Point tamano) {
        super(contexto);

        int tamanoBloque = tamano.x / ANCHO_NUM_BLOQUES;
        mNumeroBloquesAlto = tamano.y / tamanoBloque;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
            AudioAttributes atributos = new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                    .build();
            mSP = new SoundPool.Builder()
                    .setAudioAttributes(atributos)
                    .setMaxStreams(5)
                    .build();
        } else {
            mSP = new SoundPool(5, AudioManager.STREAM_MUSIC,0);
        }
        try {
            mComer_ID = mSP.load(contexto,R.raw.apple,0);
            mMordida_ID = mSP.load(contexto,R.raw.bitten,0);
        } catch (Exception e){
            Log.e("Error","Ha ocurrido un error con la carga de los archivos");
        }
        mSurfaceHolder=getHolder();
        mPincel = new Paint();

        mManzana = new Manzana(contexto,
                new Point(ANCHO_NUM_BLOQUES,
                        mNumeroBloquesAlto),
                tamanoBloque);
        mSnake = new Snake(contexto,
                new Point(ANCHO_NUM_BLOQUES,
                        mNumeroBloquesAlto),
                tamanoBloque);
    }

    @Override
    public void run(){
        while(mJugando){
            if(!mPausado){
                if(requiereActualizar()){
                    actualizar();
                }
            }
            dibujar();
        }
    }

    public boolean requiereActualizar(){
        final long BLANCO_FPS = 10;
        final long MILES_POR_SEGUNDO = 1000;
        if(mProxTiempoCuadro<=System.currentTimeMillis()){
            mProxTiempoCuadro=System.currentTimeMillis()
                    + MILES_POR_SEGUNDO / BLANCO_FPS;
            return true;
        }
        return false;
    }

    public void actualizar(){
        mSnake.mover();
        if (mSnake.chekaCena(mManzana.getUbicacion())){
            mManzana.generar();
            mPuntaje++;
            mSP.play(mComer_ID,1,1,0,0,1);
        }
        if (mSnake.detectarMuerte()){
            mSP.play(mMordida_ID,1,1,0,0,1);
            mPausado = true;
        }
    }

    public void dibujar(){
        if(mSurfaceHolder.getSurface().isValid()){
            mCanvas = mSurfaceHolder.lockCanvas();
            mCanvas.drawColor(Color.argb(255,26,128,182));
            mPincel.setColor(Color.argb(255,255,255,255));
            mPincel.setTextSize(120);
            mCanvas.drawText("" + mPuntaje,20,120,mPincel);
            mManzana.dibujar(mCanvas,mPincel);
            mSnake.dibujar(mCanvas,mPincel);
            if (mPausado){
                mPincel.setColor(Color.argb(255,255,255,255));
                mPincel.setTextSize(100);
                mCanvas.drawText(getResources().getString(R.string.inicioTexto),
                        20,300,mPincel);
            }
            mSurfaceHolder.unlockCanvasAndPost(mCanvas);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent evento){
        switch (evento.getAction() & MotionEvent.ACTION_MASK){
            case MotionEvent.ACTION_UP:
                if (mPausado){
                    mPausado = false;
                    nuevoJuego();
                    return true;
                }
                mSnake.cambiarDireccion(evento);
                break;
            default:
                break;
        }
        return true;
    }

    public void nuevoJuego(){
        mSnake.reset(ANCHO_NUM_BLOQUES,mNumeroBloquesAlto);
        mManzana.generar();
        mPuntaje = 0;
        mProxTiempoCuadro = System.currentTimeMillis();
    }

    public void pausar(){
        mJugando=false;
        try{
            mThread.join();
        } catch (InterruptedException e){
            Log.e("Error", "no se pudo detener el thread.");
        }
    }

    public void retomar(){
        mJugando=true;
        mThread = new Thread(this);
        mThread.start();
    }
}
Anuncios

Con esto ya podemos probar nuestro juego para ello vamos a compilarlo y probarlo tal como se ve en el siguiente video

En el video podemos ver como funciona nuestro juego terminado, vemos como crece la serpiente a medida que come mas manzana y como se genera de forma aleatoria.

Anuncios

En resumen, hoy hemos terminado el juego se puede ver como quedo completo, como se implemento la clase vista en el post anterior, como se maneja de correcta y como cambia la direccion dependiendo de que lado de la pantalla estemos tocando, 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

Anuncio publicitario