Tutorial: Desenvolvendo um jogo ao estilo Duck Hunt: Parte 3 – Estourando os balões

Olá pessoal, lembram do ultimo tutorial? Os balões já se movimentam na tela de forma aleatória.

No entanto, clicar neles ainda não adianta de nada.

Vamos fazer os balões estourarem quando o jogador clicar sobre eles? Vamos lá!

Parte 1Parte 2 – Parte 3 – Parte 4

Vimos no tutorial passado como fazer balões entrar e sair da tela de forma aleatória. Fizemos dois procedimentos principais: um que cria balão e outro que destrói o sprite de balões que saem da tela. Fizemos o procedimento de criar balão ser executado a cada meio segundo, de forma que balões apareçam na tela constantemente.

Nesse tutorial, nós implementaremos o estouro dos balões que são clicados pelo jogador. Para que possamos identificar qual sprite é clicado pelo jogador, nós precisaremos criar uma lista que armazena os sprites de todos os balões criados e ainda não destruídos. Essa será a nossa primeira preocupação de hoje.

 

Gerenciando a lista de balões

CasaVoandoPrecisamos gerenciar com inteligência os sprites dos balões mostrados ao jogador. Toda vez que um balão é criado, ele precisa ser adicionado em uma lista de sprites de balões. Da mesma forma, toda vez que um sprite de balão sai da tela, ele precisa ser removido dessa lista.

Para que tenhamos em mãos a lista de sprites em qualquer momento, nós precisamos incluí-la como um atributo da classe “HelloWorld”. Assim, abra o arquivo “HelloWorldScene.h” e adicione a seguinte linha de código:

std::list<cocos2d::Sprite*> baloes;

logo abaixo dessa:

virtual bool init();

Com a lista devidamente criada, podemos incluir nela a referência dos sprites dos balões recém-criados. Para fazer isso, abra o arquivo “HelloWorldScene.cpp” e adicione a seguinte linha de código:

HelloWorld::baloes.push_back(balao);

logo abaixo dessa:

balao->runAction(Sequence::create(mov,dst,NULL));

Note que o sprite foi adicionado no final do método “entraNovoBalao”. Agora, para que o jogo fique consistente, os balões que saem da tela precisam ser removidos dessa lista. No tutorial passado, não existia essa lista de sprites. Precisávamos apenas retirar o sprite dos balões da tela. Agora, nós precisamos, além de retirar os sprites da tela, remover os sprites da lista de sprites.

Para tal, vamos criar um método que trata todos os procedimentos necessários quando um balão sai da tela. Utilizaremos o método “destroiSprite” em outro momento. Chamaremos esse novo método de “saiBalao”. Nesse método, nós removeremos da lista de sprites a referência do sprite do balão que saiu da tela e o destruiremos da memória. Para declarar o protótipo do método na classe “HelloWorld”, abra o arquivo “HelloWorldScene.h” e adicione a seguinte linha de código:

static void saiBalao(Node *n);

logo abaixo dessa:

std::list<cocos2d::Sprite*> baloes;

BalaoPerdidoAgora, implementaremos o método “saiBalao”. Abra o arquivo “HelloWorldScene.cpp” e adicione as seguintes linhas de código no final do arquivo.

void HelloWorld::saiBalao(Node *n) {

    HelloWorld* h = static_cast<HelloWorld*>(n->getParent());

    h->baloes.remove(static_cast<Sprite*>(n));

    n->removeFromParentAndCleanup(true);

}

Como resolvemos deixar o método “destroiSprite” somente com a função de destruir sprites da memória, deveremos mudar a linha de código que programa a sua execução. Antes, nós chamávamos o método “destroiSprite” para destruir um sprite de balão quando ele saía da tela. Agora, faremos com que o método “saiBalao” seja executado em seu lugar. Para isso, modifique a seguinte linha de código:

CallFuncN *dst = CallFuncN::create(HelloWorld::destroiSprite);

de forma que ela fique assim:

CallFuncN *dst = CallFuncN::create(HelloWorld::saiBalao);

Agora sim, quando um balão é incluso na tela, o seu sprite é adicionado na lista de sprites de balões. Quando um balão sai da tela, a referência de seu sprite é removida da lista de sprites e o sprite em si é destruído.

Agora implementaremos os estouros dos balões clicados pelo jogador.

 

Detecção e resposta de toque na tela

ToqueNaTelaA implementação dessa funcionalidade será separada em duas partes: uma que identifica qual sprite o jogador clicou e outra que faz as sub-rotinas de tratamento do sprite que foi clicado. Vamos começar nos preocupando com as sub-rotinas de tratamento do sprite clicado. Criaremos um método que dá início à animação de estouro de balão e destrói o sprite após a animação. Vamos adicionar o protótipo do método “estouraBalao” na classe “HelloWorld”. Abra o arquivo “HelloWorldScene.h” e adicione a seguinte linha de código:

void estouraBalao(cocos2d::Sprite* s);

logo abaixo dessa:

std::list<cocos2d::Sprite*> baloes;

Agora, implementaremos o método “estouraBalao”. Adicione as seguintes linhas de código no final do arquivo “HelloWorldScene.cpp”.

void HelloWorld::estouraBalao(Sprite* s) {

    Vector<SpriteFrame*> frames;

    CallFuncN *dst = CallFuncN::create(HelloWorld::destroiSprite);

    HelloWorld::baloes.remove(s);

    frames.reserve(3);

    frames.pushBack(SpriteFrameCache::getInstance()->

      getSpriteFrameByName(“Balao2.png”));

    frames.pushBack(SpriteFrameCache::getInstance()->

      getSpriteFrameByName(“Balao3.png”));

    frames.pushBack(SpriteFrameCache::getInstance()->

      getSpriteFrameByName(“Balao4.png”));

    Animation* animation = Animation::createWithSpriteFrames(frames,0.075f);

    Animate* anim = Animate::create(animation);

    s->cleanup();

    s->runAction(Sequence::create(anim,dst,NULL));

}

Note que, no método recém-implementado, nós referenciamos o método “destroiSprite”, criado no último tutorial. Ele é chamado logo após a animação de estouro do balão. Além disso, antes da animação iniciar, a referência do sprite estourado é retirada da lista de sprites de balão.

Agora que temos um método próprio para tratamento de estouro de balões, basta detectar quando o jogador clica sobre um balão e identificar o seu sprite. Novamente implementaremos funções de tela de toque. Como de praxe, precisaremos implementar um dos métodos reservados unicamente para isso, nesse caso o “onTouchBegan”. Assim, vamos incluir o seu protótipo na classe “HelloWorld”. Abra o arquivo “HelloWorldScene.h” e adicione a seguinte linha de código:

virtual bool onTouchBegan(cocos2d::Touch *touch,cocos2d::Event *unused_event);

logo abaixo dessa:

std::list<cocos2d::Sprite*> baloes;

Inclua a implementação desse método no arquivo “HelloWorldScene.cpp”. Adicione as seguintes linhas de código no final do arquivo.

bool HelloWorld::onTouchBegan(Touch *touch,Event *unused_event) {

    std::list<Sprite*>::iterator i;

    Size visibleSize = Director::getInstance()->getVisibleSize();

    Vec2 p = touch->getLocationInView();

    p.y = visibleSize.height – p.y;

    for(i=HelloWorld::baloes.begin();i!=HelloWorld::baloes.end();i++) {

        Sprite* s = static_cast<Sprite*>(*i);

        if(s->getBoundingBox().containsPoint(p)) {

            HelloWorld::estouraBalao(s);

            break;

        }

    }

    return true;

}

No método “onTouchBegan”, nós verificamos se o jogador está clicando em algum dos sprites de balões existentes na lista de sprites. Caso seja identificado algum sprite que o jogador esteja clicando sobre, o método “estouraBalao” é chamado.

OuvintePorém, ainda não terminamos a implementação do tutorial de hoje. Agora, basta instanciarmos um objeto ouvinte de interação com a tela de toque. Nessa nova versão do Cocos2d-x, nós precisamos instanciar um objeto ouvinte para que o método “onTouchBegan” seja chamado corretamente. Para isso, adicione as seguintes linhas de código:

EventListenerTouchOneByOne* listener = EventListenerTouchOneByOne::create();

listener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan,this);

Director::getInstance()->getEventDispatcher()->

  addEventListenerWithSceneGraphPriority(listener,this);

logo abaixo dessa:

addChild(fundo);

Agora sim … você pode compilar o código e executar o jogo. Note que, quando o jogador clica sobre um balão, esse balão é estourado.

Então pessoal, vimos no tutorial de hoje como adicionar a funcionalidade de estourar os balões que são clicados pelo jogador. Foi preciso criar uma lista de sprites de balões existentes na tela para verificar se o jogador está clicando sobre um deles. Caso o jogador clique sobre um deles, é disparada uma animação de estouro e o sprite é retirado na tela.

No próximo tutorial, nós implementaremos alguns objetos de HUD para mostrar ao jogador quantas tentativas erradas ele teve e quantas ele acertou nos balões.

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

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.