Tutorial: Desenvolvendo um jogo de memorização de sinais: Parte 5 – HUDs, pontuação e término

Já implementamos praticamente todas as funcionalidades do nosso jogo de memorização.

Está faltando apenas lapidar o jogo com a inserção de elementos de HUD.

Hoje finalizaremos o desenvolvimento de mais um game.

 

Parte 1Parte 2Parte 3Parte 4 – Parte 5

Vimos no último tutorial como funciona o fluxo do jogo de memorização de sequência de sinais. No fluxo, existe um momento que o computador mostra a sequência ao jogador e existe um momento em que o jogador apresenta a sequência ao jogo.

Nesse tutorial, nós finalizaremos a implementação do nosso jogo de memorização de sequência de sinais incluindo alguns elementos de HUD. Para deixarmos o jogo completo, adicionaremos um cronômetro regressivo para a apresentação da primeira sequência, e a apresentação da quantidade máxima de sinais que o jogador conseguiu decorar quando o jogo terminar. Bora lá.

Contagem regressiva

contagem_regressivaÉ fácil ver a necessidade da existência de um elemento de HUD para que possamos incluir na tela um cronômetro para o início do jogo. Esse cronômetro será simulado por uma etiqueta que inicia a contagem em 3 e a finaliza em 1. Como incluiremos um novo elemento de HUD no início do jogo, precisaremos modificar o código que dá início ao jogo.

Vínhamos iniciando o jogo requisitando ao computador apresentar o primeiro sinal da sequência. Isto, porém, pode sacanear o jogador se ele não estiver concentrado. Assim, existe a necessidade de criação de uma etiqueta para uma contagem regressiva e de um método que modifica os procedimentos de início do jogo.

Como normalmente acontece, um cronômetro modifica o número apresentado a cada segundo. Essa modificação textual será realizada por um método. Esse método apenas modifica o número apresentado pela etiqueta recém-criada. Assim, precisamos declarar essa etiqueta e esses dois métodos na classe “HelloWorld”. Para isso, abra o arquivo “HelloWorldScene.h” e adicione as seguintes linhas de código:

cocos2d::CCLabelTTF* msg1;

void decrementaTempoInicial();

void inicioDeJogo();

logo abaixo dessa:

int conta;

Eu nomeei a variável que armazena a etiqueta como “msg1”, o método que inicia o jogo como “inicioDeJogo” e o método que modifica o número do cronômetro como “decrementaTempoInicial”. Vamos inicializar a etiqueta para que possamos usá-la. Abra o arquivo “HelloWorldScene.cpp” e adicione as seguintes linhas de código:

HelloWorld::msg1 = CCLabelTTF::create(“3″,””,60);

HelloWorld::msg1->setAnchorPoint(ccp(0.5,0.0));

HelloWorld::msg1->setPosition(ccp(size.width/2,size.height/2));

addChild(HelloWorld::msg1);

logo abaixo dessa:

HelloWorld::sequencia->retain();

cronometroCom isso, nós acabamos de incluir o número 3 no meio da tela do jogo. Se deixarmos assim, esse número ficará lá desde o início até o fim do jogo. Note que precisamos decrementar o texto a cada segundo e que precisamos deixar essa etiqueta invisível quando a contagem regressiva acabar. Vamos, primeiramente, implementar o método que decrementa o número do cronômetro. Adicione as seguintes linhas de código no final do arquivo “HelloWorldScene.cpp”:

void HelloWorld::decrementaTempoInicial() {

    char segundo[2];

    strcpy(segundo,HelloWorld::msg1->getString());

    segundo[0]–;

    HelloWorld::msg1->setString(segundo);

}

Agora implementaremos o método “inicioDeJogo”. Nele, nós especificaremos ao motor do Cocos2d-x para realizar a seguinte sequência de eventos: esperar um segundo, decrementar o número do cronômetro (de 3 para 2), esperar mais um segundo, decrementar o número do cronômetro (de 2 para 1), esperar mais um segundo, iniciar o jogo (chamando o método já implementado “vezDoComputador”). Adicione as seguintes linhas de código no final do arquivo:

void HelloWorld::inicioDeJogo() {

    CCDelayTime* tempo1Segundo = CCDelayTime::create(1.0);

    CCCallFunc* decrementaTempo = CCCallFunc::create(

      this,callfunc_selector(HelloWorld::decrementaTempoInicial));

    CCCallFunc* iniciaSequencia = CCCallFunc::create(

      this,callfunc_selector(HelloWorld::vezDoComputador));

    CCSequence* seq = CCSequence::create(

      tempo1Segundo->clone(),decrementaTempo->clone(),

      tempo1Segundo->clone(),decrementaTempo,

      tempo1Segundo,iniciaSequencia,NULL);

    runAction(seq);

}

Ainda não finalizamos a implementação do cronômetro. É necessário deixar a etiqueta invisível quando o jogo inicia. Para isso, basta adicionar a seguinte linha de código:

HelloWorld::msg1->setVisible(false);

logo abaixo dessa:

void HelloWorld::vezDoComputador() {

Fizemos quase tudo para que tenhamos o cronômetro no início do jogo. Agora só falta chamarmos o método “inicioDeJogo” em vez de chamar o método “vezDoComputador” quando o aplicativo inicia. Assim, no lugar onde tem essas duas linhas de código:

HelloWorld::idToque = -1;

HelloWorld::vezDoComputador();

substitua essa:

HelloWorld::vezDoComputador();

por essa:

HelloWorld::inicioDeJogo();

Pronto. Agora já temos o cronômetro regressivo antes de iniciar o jogo. Vamos adicionar as mensagens de término de jogo.

Contagem de pontos e término do jogo

alturaUm dos problemas que ainda temos na versão atual do jogo é do jogador não saber a pontuação dele quando acaba o jogo. A pontuação, nada mais é, do que o tamanho da sequência de sinais que ele conseguiu decorar até errar. Um ponto interessante é que não precisamos armazenar qualquer informação sobre tamanho da sequência. Isso porque nós já temos em mãos essa informação. Podemos saber o tamanho da sequência atual pelo tamanho do vetor que armazena a sequência. Isso nos livra de uma preocupação que normalmente temos quando chega na parte de contagem de pontos, que é o armazenamento deles em alguma variável.

Dessa forma, em se tratando de pontuação, precisamos apenas nos preocupar em criar a etiqueta que mostra a pontuação (o tamanho da última sequência) ao jogador quando o jogo é finalizado. Além da declaração dessa etiqueta, precisamos também declarar um método responsável por executar todos os procedimentos realizados quando o jogador erra.

Até esse momento, nós fechamos o jogo quando o jogador erra um sinal. Isso não deve ocorrer. Primeiro porque o jogador fica sem informação sobre o desempenho dele no jogo e, segundo, porque o jogo fecha muito bruscamente. Dessa forma, vamos declarar na classe “HelloWorld” uma variável que armazena a etiqueta que informa a pontuação ao jogador e o método que realiza as sub-rotinas de término de jogo. Abra o arquivo “HelloWorldScene.h” e adicione as seguintes linhas de código:

cocos2d::CCLabelTTF* msg2;

void terminoDeJogo();

logo abaixo dessa:

cocos2d::CCLabelTTF* msg1;

Como de praxe, precisamos inicializar a etiqueta para a utilizarmos. No arquivo “HelloWorldScene.cpp”, adicione as seguintes linhas de código:

HelloWorld::msg2 = CCLabelTTF::create(“”,””,45);

HelloWorld::msg2->setAnchorPoint(ccp(0.5,1.0));

HelloWorld::msg2->setPosition(ccp(size.width/2,size.height/2));

HelloWorld::msg2->setVisible(false);

addChild(HelloWorld::msg2);

logo baixo dessa:

addChild(HelloWorld::msg1);

Perceba que apenas inicializamos a etiqueta sem qualquer texto e invisível. Isso porque saberemos o seu texto somente após o jogador errar uma sequência. Além disso, ela fica oculta durante toda a execução do jogo, só aparecendo no final, quando ela realmente é necessária.

FimdalinhaVamos implementar agora o método que realiza todos os procedimentos para finalizar um jogo. Quando o jogador clica em um botão referente a um sinal que não é o exato, o jogo precisa desligar a tela de toque e apresentar as etiquetas informando o término do jogo e a pontuação do jogador. Isso tudo é feito no método “terminoDeJogo”. Adicione as seguintes linhas de código no final do arquivo “HelloWorldScene.cpp”:

void HelloWorld::terminoDeJogo() {

    char msg[25];

    setTouchEnabled(false);

    HelloWorld::msg1->setString(“Termino do Jogo”);

    sprintf(msg,”Sequencia de %i sinais”,

      HelloWorld::sequencia->count()-1);

    HelloWorld::msg2->setString(msg);

    HelloWorld::msg1->setVisible(true);

    HelloWorld::msg2->setVisible(true);

}

Perceba que reutilizamos a etiqueta do cronômetro para apresentar a mensagem de término de jogo e utilizamos a etiqueta recém-criada para apresentar a pontuação do jogador. Perceba também que a pontuação do jogador é igual ao tamanho da sequência atual subtraído de 1. Isso porque ele conseguiu decorar sem errar somente até a sequência anterior.

Para finalizar, basta chamarmos o método “terminoDeJogo” quando o jogador erra uma sequência. Para isso, em todo o arquivo “HelloWorldScene.cpp”, substitua as linhas de código que são assim:

HelloWorld::menuCloseCallback(this);

por essa:

HelloWorld::terminoDeJogo();

Prooonto. Agora sim o jogo foi finalizado. Se você compilar o código e executar o jogo, perceberá que agora ele tem um cronômetro inicial. Além disso, quando o jogador erra uma sequência, o jogo mostra na tela uma mensagem de término e a pontuação do jogador. Para os curiosos de plantão, o vídeo a seguir mostra como ficou o nosso game.

Adicionamos, nesse tutorial, alguns elementos de HUD. Mostramos um cronômetro regressivo no início para que o jogador não seja pegado de surpresa quando o jogo apresentar o primeiro sinal. Além disso, criamos uma mensagem de término de jogo que é mostrada quando o jogador erra uma sequência. Também é mostrado o tamanho da última sequência que o jogador conseguiu decorar.

Então é isso, pessoal. Esse é o último tutorial que eu escreverei nesse ano. Assim sendo, eu desejo a todos vocês fiéis leitores ótimas festas. Nós nos vemos no próximo ano.

Um grande abraço e até mais. []

Santiago Viertel

Santiago Viertel

Formado em Bacharelado em Ciência da Computação (UDESC), mestre e doutorando em Análise de Algoritmos (UFPR). Foi programador da Céu Games por 8 anos. Possui a preferência por jogos de estratégia e de tiro em primeira pessoa. Jogando bastante DotA 2, Left 4 Dead 2 e Age of Empires II HD.

Send this to a friend