parte 10 – Gerenciando vida do personagem

O que veremos aqui?

Neste post, veremos como gerenciar a vida do personagem, permitindo que encoste uma vez no monstro e não morra imediatamente, caso esteja com uma vida sobrando.

Gerenciamento de vidas

Uma vida no jogo nada mais é que uma flag, que definirá o status do jogador, essa flag indicará o tamanho do jogador, que se estiver grande e encostar em um inimigo irá ficar pequeno. Se estiver pequeno e encostar, então irá morrer, simples assim!

Como no Super Mario ou Donkey Kong, faremos 2 níveis de vida, onde o jogador começa pequeno e quando pega a vida ele cresce. Caso esteja grande e encoste num inimigo ou em algo que o mate, ele irá diminuir de tamanho e ficar imune por uns 5 segundos. Depois, caso encoste novamente em algo irá morrer definitivamente.

Definindo tamanhos do jogador

O primeiro passo, será definirmos dois tamanhos para o jogador: pequeno e grande, onde o primeiro é o tamanho natural dele e o segundo será ativo quando ele pegar algum recurso no jogo que lhe dê uma energia adicional.

Crie então estas funções no jogo:

/**
 *  Define o tamanho do jogador pequeno
 */
function defineJogadorPequeno(){
    tamanhoJogador = 'pequeno';
    jogador.scale.setTo(0.8,0.8);
}

/**
 *  Define o tamanho do jogador como grande
 */
function defineJogadorGrande(){
    tamanhoJogador = 'grande';
    jogador.scale.setTo(1,1);
}

Agora dentro da função que cria o jogador, após criá-lo, chame a função que define o tamanho dele como pequeno:

function criaJogador(){
     // demais código aqui...
     defineJogadorPequeno();
}

O próximo passo será gerenciar a morte ou não do jogador. Nesse jogo ele poderá ter uma única vida adicional, ou seja, os bônus não serão acumulativos.

Controlando tamanho do jogador

Para controlar a vida adicional do jogador, vamos criar uma flag que define o tamanho dele. Crie esta flag (variável bandeira) logo abaixo do contador de moedas do jogo, ou seja, no início do código:

    var contadorMoedas = 0;

    // Define tamanho do jogador. No início do jogo é pequeno
    var tamanhoJogador = 'pequeno';

Essa variável flag criada é usada nas funções defineJogadorPequeno e defineJogadorGrande, entre outras partes do jogo que veremos a seguir.

O próximo passo é modificar a função encostou inimigo, fazendo com que ao encostar em um inimigo seja chamada uma função que gerencia coisas mortíferas ao em vez de chamar diretamente a função fimDoJogo. Por isso, deixe a função encostou inimigo assim:


function encostouInimigo (jogador, inimigo) {
    // Verifica se pulou em cima do inimigo
    if (jogador.body.touching.down && inimigo.body.touching.up){
        // Mata inimigo
        inimigo.kill();
        // Faz jogador pular
        jogador.body.velocity.y = -650;
        // Executa música de pulo em algo
        musicaKick.play('', 0, 1, false);
    }else{
        // Em vez de terminar o jogo, chama função que gerencia "coisas mortíferas"
        encostouEmAlgoMortifero();
    }
}

Veja que mudamos apenas uma linha da função. Agora crie esta nova função encostouEmAlgoMortifero como segue abaixo:

/**
 *  Toda vez que jogador encosta em algo mortífero,
 *  chama esta função
 */
function encostouEmAlgoMortifero(){
    // Se o jogador está imune, sai da função
    if (jogadorImune){
        return false;
    }

    if (tamanhoJogador == 'grande'){
        // Pisca jogador
        fadeJogador();
        // Define seu novo tamanho
        defineJogadorPequeno();
    }else{
        // Se jogador já está pequeno e encostou em algo mortífero, então termina o jogo
        fimDoJogo();
    }
}

Veja que esta função verifica logo no início se o jogador está imune, através da flag jogadorImune. Crie então esta flag no início do código, logo abaixo da flag que gerencia o tamanhoDoJogador:

    var tamanhoJogador = 'pequeno';
    // Flag (variável bandeira) que controla imunidade do jogador
    var jogadorImune = false;

Depois de verificar se o jogador está imune, a função verifica seu tamanho, e caso ele esteja grande, ela faz um fade no jogador chamando a função fadeJogador.

A função fadeJogador irá fazer o jogador piscar, informando ao usuário que ele foi atingido. Crie essa nova função com o seguinte código fonte:

/** 
 *  Faz jogador piscar e ficar imune enquanto isso
 */
function fadeJogador(){
    var numeroPiscadas = 5;
    var intervaloPiscadas = 200;

    // Cria objeto tween para controle do jogador
    var tween = game.add.tween(jogador);

    // Define propriedades do evento atuando no jogador
    tween.to( 
        { alpha: 0 }, 
        intervaloPiscadas, 
        Phaser.Easing.Linear.None, 
        false, 
        0, 
        numeroPiscadas, 
        false
    );

    // Cria um sinalizador interno no sistema
    var signal = new Phaser.Signal();

    // Quando terminar o processo, chama esta função anônima
    signal.add(function(){
        // Exibe jogador
        jogador.alpha = 1;
        // Deixa-o imune
        jogadorImune = false;
    });

    // Ao completar evento, chama sinal criado acima
    tween.onComplete = signal;

    //  Inicia todo o processo
    tween.start();

    // Define se o jogador está imune aos inimigos
    jogadorImune = true;
}

O último passo é garantir que o jogador não sofra colisões dos inimigos enquanto estiver imune. Para isso, na função atualizaJogo, ao chamar a função verificaSeEncostouInimigo que faz a checagem de colisão entre inimigos e o jogador, crie a condição if, deixando-a assim:

function atualizaJogo() {
    game.physics.arcade.collide(jogador, layer);
    game.physics.arcade.collide(inimigos, layer, inimigoColidiuTile);

    movimentaJogador();

    // Se o jogador NÃO estiver imune, verifica colisões com inimigo
    if (jogadorImune == false){
        verificaSeEncostouInimigo();
    }
    
    verificaSeEncostouMoedas();
    verificaEscada();
}

Desafio

Fizemos até agora tudo para gerenciar a vida adicional do jogador. Se você chamar manualmente, no console F12, a função pegouEnergia(), verá que o jogador irá crescer e então tudo que fizemos irá funcionar.

O desafio agora é criar pontos no jogo que quando o jogador alcançar, seja inserida energia nele. Ou seja, quando o jogador encostar em um cogumelo ou algo do tipo, o jogo deve chamar a função pegouEnergia que irá fazer o jogador crescer.

Dica 1: o funcionamento disso é muito similar a colisão entre o jogador e as moedas.
Dica 2: Você pode fazer com que um número x de moedas forneça uma vida energia ao jogador!

Bons estudos :)

Jogo em ação

Aqui você pode ver o código que implementamos funcionando. Neste link você pode baixar esta versão do jogo:

O que vem por aí?

No próximo post veremos como fazer o jogador morrer se acabar o tempo da fase.

Até breve!

4 Comments

  1. Paulo então estudo no colegio cotemig e um dos meus projetos e desenvolver um jogo de duas fazer utilizando a base do phaser e queria sua ajuda para desenvolver uma das minhas fases igual a sua

Leave a Reply