Tutorial: Desenvolvendo um jogo ao estilo Duck Hunt: Parte 2 – Movimentando os balões

Continuamos o desenvolvimento de mais um game.

Já sabemos como ficará o gameplay do nosso jogo ao estilo Duck Hunt.

E hoje, nós implementaremos a funcionalidade de entrada e saída dos balões.

Parte 1 – Parte 2 – Parte 3Parte 4

No último tutorial, nós vimos como funciona o mecanismo do Duck Hunt, criamos o projeto do jogo em Cocos2d-x e, por último, programamos a tela de gameplay. Vimos como ficaria o jogo com a temática de explodir balões, em vez de atirar em patos. Nesse tutorial, nós programaremos a entrada e a saída dos balões da tela do jogo. Então, mão na massa!

Como dito, nós implementamos a tela de gameplay. Com isso, nós adicionamos alguns sprites de balões com o objetivo de teste. Obviamente, como vamos implementar a entrada de novos balões, os sprites adicionados anteriormente precisam ser excluídos da tela de gameplay. Para excluir esses objetos gráficos, abra o arquivo “HelloWorldScene.cpp” e remova todo o código existente entre essa linha (inclusive):

Sprite *balao1 = Sprite::createWithSpriteFrameName(“Balao1.png”);

e essa (inclusive):

addChild(balao3);

BexigaCom isso, o jogador só enxerga o fundo, que foi o que sobrou. Primeiramente, vamos entender como funcionará o sistema de entrada e saída de balões. O sistema funcionará por meio de dois métodos: um que cria um novo balão e o movimenta pela tela e outro que destrói o sprite de um balão que sai da tela. Nomearemos esses métodos, respectivamente, como “entraNovoBalao” e “destroiSprite”. Com isso, já podemos fazer as modificações necessárias na classe “HelloWorld”. Abra o arquivo “HelloWorldScene.h” e adicione as seguintes linhas de código:

void entraNovoBalao(float dt);

static void destroiSprite(Node *n);

logo abaixo dessa:

virtual bool init();

O método “entraNovoBalao” é iniciado com a criação de um sprite de balão cheio. Logo após, é sorteado um valor aleatório entre 0 e 3 que determina em qual dos quatro cantos da tela o balão aparecerá. Também é sorteado um novo valor aleatório que determina a posição do canto sorteado em que o balão aparecerá. Sabendo o canto sorteado e a posição do canto, o sprite recém-criado é posicionado no lugar correto. Da mesma forma, são sorteados dois novos valores que determinam onde o balão finaliza a sua movimentação. Por último, o sprite é adicionado na tela e é dado início à movimentação do balão. Adicione as seguintes linhas de código no final do arquivo “HelloWorldScene.cpp”.

void HelloWorld::entraNovoBalao(float dt) {

    static long r = time(NULL);

    int v1,v2;

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

    Sprite *balao = Sprite::createWithSpriteFrameName(“Balao1.png”);

    balao->setScale(0.15*size.height/balao->getBoundingBox().size.height);

    MoveTo *mov;

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

    srand(r);

    r = rand();

    v1 = r%4;

    srand(r);

    r = rand();

    if(v1==0) {

        v2 = (((float)r)/RAND_MAX)*size.width;

        balao->setPosition(Vec2(v2,-balao->getBoundingBox().size.height/2));

    }else if(v1==1) {

        v2 = (((float)r)/RAND_MAX)*size.width;

        balao->setPosition(Vec2(v2,size.height+ balao->getBoundingBox().size.height/2));

    }else if(v1==2) {

        v2 = (((float)r)/RAND_MAX)*size.height;

        balao->setPosition(Vec2(-balao->getBoundingBox().size.width/2,v2));

    }else {

        v2 = (((float)r)/RAND_MAX)*size.height;

        balao->setPosition(Vec2(size.width+ balao->getBoundingBox().size.width/2,v2));

    }

    srand(r);

    r = rand();

    v1 = r%4;

    srand(r);

    r = rand();

    if(v1==0) {

        v2 = (((float)r)/RAND_MAX)*size.width;

        mov = MoveTo::create(4,Vec2(v2,-balao->getBoundingBox().size.height/2));

    }else if(v1==1) {

        v2 = (((float)r)/RAND_MAX)*size.width;

        mov = MoveTo::create(4,Vec2(v2,size.height+ balao->getBoundingBox().size.height/2));

    }else if(v1==2) {

        v2 = (((float)r)/RAND_MAX)*size.height;

        mov = MoveTo::create(4,Vec2(-balao->getBoundingBox().size.width/2,v2));

    }else {

        v2 = (((float)r)/RAND_MAX)*size.height;

        mov = MoveTo::create(4,Vec2(size.width+ balao->getBoundingBox().size.width/2,v2));

    }

    addChild(balao);

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

}

ExplosionBalloonAgora só falta adicionar o método “destroiSprite” para que o sistema esteja devidamente implementado. Este método apenas destrói o sprite que saiu da tela. Adicione as seguintes linhas de código no final do arquivo.

void HelloWorld::destroiSprite(Node *n) {

    n->removeFromParentAndCleanup(true);

}

O sistema de inclusão e exclusão de balões já está devidamente implementado. Porém, ele ainda não foi invocado. Para fazer com que os balões comecem a entrar na tela, teremos que executar o método “entraNovoBalao” constantemente. Faremos com que um balão seja incluso na tela a cada meio segundo. Isso deixará o jogo com um desafio legal. Para isso, adicione a seguinte linha de código:

schedule(schedule_selector(HelloWorld::entraNovoBalao),0.5);

logo abaixo dessa:

addChild(fundo);

Agora siiim. Basta compilar o código e executar o jogo. Você verá que novos balões entram na tela constantemente com movimentações variadas e aleatórias. Veja o resultado do tutorial de hoje da Figura 1.

Figura 1 - Jogo executando
Figura 1 – Jogo executando

Vimos nesse tutorial como funciona o sistema de entrada e saída de balões. Implementamos um método que cria um balão e o movimenta na tela e outro que destrói o sprite dos balões que saem da tela. Por último, nós fizemos com que o método de criar balões seja executado a cada meio segundo.

Programaremos no próximo tutorial a detecção e resposta de toque na tela. Faremos com que os balões estourem caso o jogador clique sobre eles.

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.