martes, 5 de agosto de 2014

Como crear Vida y puntaje en Phaser "Invader Reborn"



En este ocasion vamos agregar los últimos detalles para nuestra versión del Space Invaders como es de esperar cada vez que seamos impactados nuestra vida sera reducida, si logramos dar en el objetivo(Aliens) estos serán destruidos.

Entonces solo necesitamos activar la colision entre ambos objetos cuya reaccion seria en caso de el heroe una vida menos, para los Aliens seria su fin y ademas nuestro puntaje seria aumentado. 



Comenzemos: 

Si bien podemos hacer el puntaje y vidas en texto plano pero con unas imagenes para adornar el resultado seria mejor, cargamos las imagenes necesarias:

 game.load.image("_TITULO","titulo.png");
    game.load.image("_puntaje","puntaje.png"); 
    game.load.image("_vidas","vidas.png"); 

Agregamos las nuevas variables:

var 
puntaje=0,
puntajeTexto,
vidas,
textoEstado;

En la funcion create tenemos:

function create() {
   game.physics.startSystem(Phaser.Physics.ARCADE);
game.add.image(0,0,"_FONDO");
inicioFrase= game.add.image(90,200,"_TITULO");
 
 //cargamento de nuestra Nave
    municion = game.add.group();
    municion.enableBody = true;
    municion.physicsBodyType = Phaser.Physics.ARCADE;
    municion.createMultiple(30, 'balaHEROE');
    municion.setAll('anchor.x', 0.5);
    municion.setAll('anchor.y', 1);
    municion.setAll('outOfBoundsKill', true);

 //los enemigos tambien tienen municion
    municionEnemigo = game.add.group();
    municionEnemigo.enableBody = true;
    municionEnemigo.physicsBodyType = Phaser.Physics.ARCADE;
    municionEnemigo.createMultiple(30, 'balaALIEN');
    municionEnemigo.setAll('anchor.x', 0.5);
    municionEnemigo.setAll('anchor.y', 1);
    municionEnemigo.setAll('outOfBoundsKill', true);

    // Los invasores
    navesEnemigas = game.add.group();
    navesEnemigas.enableBody = true;
    navesEnemigas.physicsBodyType = Phaser.Physics.ARCADE;

    
    //Nuestro posibles resultado(pierdes,ganas)
    textoEstado = game.add.text(game.world.centerX,game.world.centerY,' ', { font: '50px Arial', fill: '#99f' });
    textoEstado.anchor.setTo(0.5, 0.5);
    textoEstado.visible = false;

    //Nuestro centro de mando
    teclas = game.input.keyboard.createCursorKeys();
    teclaDisparo = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);
    
 //solo se puede presionar una sola vez el click
 var una = game.input.onDown.add(comienza,this);
 una._isOnce=true;
};

Aqui vemos el codigo nuevo agregado, al iniciar el juego vemos un frase (El Titulo del Juego) esto lo agregamos :
inicioFrase= game.add.image(90,200,"_TITULO"); 

El metodo ya visto add.image(x,y,Nombre Clave), tambien en el juego ya sea cuando perdemos o ganamos nos aparece un mensaje indicandonos tal accion para esto agregamos un texto normal: 

 textoEstado = game.add.text(game.world.centerX,game.world.centerY,' ', { font: '50px Arial', fill: '#99f' }); 

textoEstado.anchor.setTo(0.5, 0.5);

 textoEstado.visible = false; 

Nada nuevo colocamos un texto que va aparecer centrado pero ademas no es visible(visible=false) porque aun no sabemos si perdimos o ganamos. 

Ahora para empezar el juego es necesario presionar click pero solo una vez no queremos que cada vez que realize un evento del mouse el juego sea reiniciado para usamos 

 var una = game.input.onDown.add(comienza,this); 
una._isOnce=true; 


Ya sabemos para crear un evento que se dispare cuando presionemos click usamos el método onDown si recuerdas que esto es una Señal, el resultado lo almacenamos en la variable "una" esto corresponde a una SignalBinding no es mas que es la unión entre la señal y la función a la que llama en este caso la función comienza.

 Ahora dentro de esta varible podemos acceder a la propiedad isOnce que no sirve para controlar que el evento sea ejecutado solo una vez es decir solo cuando iniciemos por primera vez el juego.

 Despues de hacer presionado click nuestra función comienza sera llamada:


function comienza (){
creadorDeAliens();
crearJugador();
crearTexto();
inicioFrase.kill();
empieza=true;
};

Cuando iniciemos el juego debemos quitar el titulo para eso usamos el metodo kill() (Destruir) de los sprites. Ahora desde la funcion comienza tambien es llamada la nueva funcion crearTexto() como su nombre lo indica la usaremos para crear el puntaje y las vidas correspondientes.

function crearTexto(){
    //Nuestro puntaje
    puntajeTexto = game.add.text(135,0, ":" + puntaje, { font: '50px Arial', fill: '#fea' });
    game.add.image(10,10,"_puntaje")
    // Nuestra valiosa vida
    vidas = game.add.group();
    game.add.image(680,10,"_vidas")

 for (var i = 0; i < 3; i++) 
    {
        var local = vidas.create(game.world.width - 130 + (50 * i), 80, 'HEROE');
        local.anchor.setTo(0.5, 0.5);
        local.angle = 45;
        local.alpha = 0.4;
    }
};

Primero agregamos el texto correspodiente al puntaje(valor) y le pasamos la variable puntaje la cual inicialmente equivale a cero. 

 puntajeTexto = game.add.text(135,0, ":" + puntaje, { font: '50px Arial', fill: '#fea' }); 

Pero esto no es una imagen ya que de ser asi seria estatica y no se veria reflejado nuestro puntaje, para usar imagenes Texto en Phaser se puede hacer con Bitmap Font pero en esta oportunidad no hablaremos de el. 

 Agregamos la imagen correspondiente al texto "PUNTAJE": game.add.image(10,10,"_puntaje"); 

Para nuestras vidas crearemos un grupo el cual tiene 3 objetos(vidas):
 vidas = game.add.group();

Agregamos la imagen con el texto "Vidas": 
 game.add.image(680,10,"_vidas"); 

Ahora creamos un for para crear las tres naves simbolizando nuestras vidas ademas los objetos tienen un pequeña inclinacion(angulo) y su propiedad alpha es disminuida haciendo que se vea casi transparante.

 for (var i = 0; i < 3; i++) { 
 var local = vidas.create(game.world.width - 130 + (50 * i), 80, 'HEROE');
 local.anchor.setTo(0.5, 0.5);
 local.angle = 45; local.alpha = 0.4; }

 El funcion Update:

    game.physics.arcade.overlap(municion, navesEnemigas, unoMenos, null, this);
    game.physics.arcade.overlap(municionEnemigo, jugador, unaVidaMenos, null, this);

Creamos la colsion entre los objetos usando el metodo overlap que se dispara cuando dos objetos colisionan. Al producirse la colision llamamos a las funciones correspondientes (municion-navesEnemigas===unoMenos) y (municionEnemigo-jugador===unaVidaMenos).

 Veamos la funcion unoMenos:


function unoMenos (bala, enemigo) {
    bala.kill();
    enemigo.kill();
    puntaje += 20;
    puntajeTexto.text = ":" + puntaje;
    if (navesEnemigas.countLiving() == 0)
    {
//con semejante logro ps mayor la bonificacion
        puntaje += 1000;
        puntajeTexto.text = ":" + puntaje;
        municionEnemigo.forEach(function(a){a.kill();},this);
     //nuestra frase de victoria
        textoEstado.text = "  Has salvado el planeta \n Presiona click para repetir";
//lo hacemos visible para que todos lo puedan ver
        textoEstado.visible = true;
//claro tienes derecho a repetir
        game.input.onTap.addOnce(repetir,this);
    }
};

Como han chocado las eliminamos a ambas, aumentamos el puntaje al mismo tiempo actualizamos la etiqueta que muestra el valor del puntaje mediante la propiedad de la clase texto .text:
puntajeTexto.text = ":" + puntaje; 

Ademas comprobamos si aun existen naves enemigas de no ser asi significa que hemos salido victoriosos, entonces aumentamos nuestro puntaje un poco mas , destruimos alguna bala enemigo que quede por el aire, actualizamos nuestra variable textoEstado que en este caso correponde a la frase de victoria y la hacemos visible. 

Por si alguna razón quieres jugar de nuevo agregamos una señal
onTap(En computador es lo mismo que un click) y que solo se ejecute una sola vez addOnce(callback,contexto) para llamar a la funcion repetir

 Ahora es el turno de la funcion unaVidaMenos:

function unaVidaMenos (pj,bala) {
    bala.kill();
    vida = vidas.getFirstAlive();
    if (vida)
    {
        vida.kill();
    }
    //Hemos fracasado en nuestra mision
    if (vidas.countLiving() < 1)
    {
        jugador.kill();
        textoEstado.text="    Nuestro hogar ha sido destruido \n       Presiona click para empezar";
        textoEstado.visible = true;
        //tienes otra oportunidad
        game.input.onTap.addOnce(repetir,this);
    }
};

En esta funcion destruimos a la bala que nos impacta, comprobamos si aun tenemos vidas es decir nuestras vidas son menor que 1 ,de ser asi destruimos a nuestro heroe actualizamos nuestro textoEstado esta vez con un frase de revancha y lo hacemos visibles, como queremos venganza tambien podemos tener otra oportunidad llamando a la funcion repetir.

 Y para terminar tenemos la funcion repetir:

function repetir () {
    puntaje=0;
    puntajeTexto.text=":"+puntaje;
//recuperamos todas nuestras vidas
    vidas.callAll('revive');
//los enemigo tienen maquinas para resucitar:(
    navesEnemigas.removeAll();
    creadorDeAliens();
//pero nosotros tenemos las esferas del dragon:)
    jugador.revive();
//no hay texto que mostrar
    textoEstado.visible = false;
};

Reiniciamos nuestro puntaje a cero y actualizamos ese valor en la etiqueta puntajeTexto usamos el metodo callAll() de la clase grupos para llamar el metodo revive() de lo sprites para restaurar todas nuestras vidas.

 Eliminamos todos los Aliens que existan con el metodo de los grupos .removeAll()(remover todo),e inmediatamente llamamos a la funcion creadorDeAliens() para traer a la vida a los enemigos.

 Nuestro heroe tambien es resucitado y como estamos como al principio no hay ningun textoEstado que mostrar.

 Con esto ya tenemos una version jugable claro con un monton de cosas que podemos agregar pero ya eso lo pueden hacer hacer a su gusto:

 Agregar una explosion cuando se produzca una colision. 

Agregar Items que produzcan alguna mejora en nuestro armamento. 

Agregar un jefe Final. 

Agregar movimiento aleatorios entre los Aliens. 

Agregar niveles y naves mas poderosas.

 Hasta la proxima.

No hay comentarios:

Publicar un comentario