Tutorial: Desenvolvendo um shoot em up game: Parte 2 – Aparecendo novos inimigos

PwnedDemos início ao desenvolvimento de mais um game para a nossa lista.

Implementaremos um jogo de nave que atira em inimigos.

Hoje faremos os inimigos aparecerem de forma dinâmica na tela.

 

Todos os tutoriais da sequência
Parte 1 – Parte 2 – Parte 3Parte 4Parte 5Parte 6

No último tutorial, vimos como funciona a mecânica de um jogo shoot em up. Criamos o projeto no Cocos2d-x e programamos a tela de gameplay para termos uma noção de como o jogo ficaria.

Veremos nesse tutorial como funcionará o aparecimento de inimigos na tela. Apesar do jogo ainda não ter interação com o usuário, já podemos implementar desde já essa funcionalidade. Então … bora.

Antes de partirmos para a implementação da funcionalidade que nos interessa hoje, excluiremos um trecho de código que se tornou inútil. Abra o arquivo “HelloWorldScene.cpp” e apague as seguintes linhas de código:

HelloWorld::inimigos[0]->setPosition(ccp(size.width/2,0.9*size.height));

HelloWorld::inimigos[0]->setVisible(true);

HelloWorld::sombraInimigos[0]->setPosition(ccp(size.width/2+0.15*size.width,0.9*size.height-0.07*size.width));

HelloWorld::sombraInimigos[0]->setVisible(true);

Note que, nesse código, nós apenas incluíamos um inimigo no cenário para termos a ideia do gameplay. Agora faremos com que os inimigos sigam uma lógica para aparecer e desaparecer da tela. Mas, como funciona essa lógica?

 

Movimentação dos helicópteros

Os helicópteros aparecerão no cenário iniciando a sua movimentação fora da tela do aparelho. Isso faz com que jogo tenha um efeito de entrada dos helicópteros no cenário. Eles não se movimentarão durante o jogo, apenas atirarão. Vale lembrar que a implementação da funcionalidade de tiros dos helicópteros será implementada em outro tutorial.

Figura 1 - Aparecimento e desaparecimento dos inimigos
Figura 1 – Aparecimento e desaparecimento dos inimigos

Após decorrer cinco segundos da entada dos helicópteros, independente se houve alguns deles abatidos, todos sairão por onde entraram e uma nova leva de inimigos aparece. Ela aparecerá exatamente como a leva anterior. A Figura 1 mostra como eles sairão e aparecerão no cenário.

Bora implementar isso.

 

Implementação dos movimentos

Não precisaremos programar muito para fazermos eles se movimentarem desse jeito. Implementaremos dois métodos, um que fará a animação dos helicópteros entrando e outro que fará a animação deles saindo. Dessa forma, precisaremos prototipá-los na classe “HelloWorld”. Assim sendo, abra o arquivo “HelloWorldScene.h” e adicione as seguintes linhas de código:

void entraInimigos();

void saiInimigos();

logo abaixo dessa:

cocos2d::CCSprite* sombraInimigos[6];

Salve esse arquivo. Agora abra o arquivo “HelloWorldScene.cpp” e adicione no final dele as seguintes linhas de código:

void HelloWorld::entraInimigos() {

    int i;

    float al = CCDirector::sharedDirector()->getWinSize().height;

    float la = CCDirector::sharedDirector()->getWinSize().width;

    float posInicial[6][2] = {

        {(1*la)/7-0.4*la,0.9*al+0.3*la},

        {(2*la)/7-0.5*la,0.8*al},

        {(3*la)/7-0.3*la,0.9*al+0.4*la},

        {(4*la)/7+0.3*la,0.9*al+0.4*la},

        {(5*la)/7+0.5*la,0.8*al},

        {(6*la)/7+0.4*la,0.9*al+0.3*la}};

    float posFinal[6][2] = {

        {(1*la)/7,0.9*al},

        {(2*la)/7,0.8*al},

        {(3*la)/7,0.9*al},

        {(4*la)/7,0.9*al},

        {(5*la)/7,0.8*al},

        {(6*la)/7,0.9*al}};

    for(i=0;i<6;i++) {

        HelloWorld::inimigos[i]->setPosition(ccp(posInicial[i][0],posInicial[i][1]));

        HelloWorld::inimigos[i]->setVisible(true);

        HelloWorld::inimigos[i]->runAction(CCMoveTo::create(0.5,ccp(posFinal[i][0],posFinal[i][1])));

        HelloWorld::sombraInimigos[i]->setPosition(ccp(posInicial[i][0]+0.15*la,posInicial[i][1]-0.07*la));

        HelloWorld::sombraInimigos[i]->setVisible(true);

        HelloWorld::sombraInimigos[i]->runAction(CCMoveTo::create(0.5,ccp(posFinal[i][0]+0.15*la,posFinal[i][1]-0.07*la)));

    }

    unschedule(schedule_selector(HelloWorld::entraInimigos));

    schedule(schedule_selector(HelloWorld::saiInimigos),5);

}

void HelloWorld::saiInimigos() {

    int i;

    float al = CCDirector::sharedDirector()->getWinSize().height;

    float la = CCDirector::sharedDirector()->getWinSize().width;

    float posFinal[6][2] = {

        {(1*la)/7-0.4*la,0.9*al+0.3*la},

        {(2*la)/7-0.5*la,0.8*al},

        {(3*la)/7-0.3*la,0.9*al+0.4*la},

        {(4*la)/7+0.3*la,0.9*al+0.4*la},

        {(5*la)/7+0.5*la,0.8*al},

        {(6*la)/7+0.4*la,0.9*al+0.3*la}};

    for(i=0;i<6;i++) {

        HelloWorld::inimigos[i]->runAction(CCMoveTo::create(0.5,ccp(posFinal[i][0],posFinal[i][1])));

        HelloWorld::sombraInimigos[i]->runAction(CCMoveTo::create(0.5,ccp(posFinal[i][0]+0.15*la,posFinal[i][1]-0.07*la)));

    }

    unschedule(schedule_selector(HelloWorld::saiInimigos));

    schedule(schedule_selector(HelloWorld::entraInimigos),0.8);

}

HelicopteroO trecho de código é um pouco longo, mas é tranquilo para entender. No método “entraInimigos”, nós criamos duas matrizes que armazenam as posições iniciais e finais de todos os helicópteros. Logo após, nós ajustamos os helicópteros e suas sombras nessas posições. Notem que nós deixamos os sprites visíveis. Isso porque, futuramente, nós os deixaremos invisíveis após o jogador acertá-los com um tiro. Para finalizar, nós iniciamos as animações dos helicópteros, fazendo-os entrar no cenário e programamos a execução do método “saiInimigos” para após o decorrer de cinco segundos.

No método “saiInimigos”, nós criamos uma matriz que armazena as posições finais dos helicópteros e iniciamos a animação deles saindo do cenário. Por fim, é programada a execução do método “entraInimigos” para o decorrer de 0,8 segundos.

Essa implementação fará com que uma leva de helicópteros entre no cenário, fique nele por cinco segundos e saia dele para que uma nova leva entre depois. Porém, se você compilar o código, perceberá que nenhum helicóptero entrará no cenário. Isso porque não chamamos nenhuma vez esses métodos. Para que essa animação em loop seja iniciada, basta chamarmos o método “entraInimigos” logo no início do jogo. Para isso, adicione a seguinte linha de código:

HelloWorld::entraInimigos();

logo abaixo dessas:

    addChild(HelloWorld::sombraInimigos[i],1);

}

Agora siiim … compile o código e execute o jogo. Você verá algo como o que é mostrado na animação a seguir.

JogoExecutando

Vimos nesse tutorial como funcionará a entrada e saída de inimigos no cenário do nosso game shoot em up. Implementamos essa funcionalidade por meio de dois métodos: um que realiza a animação de entrada dos helicópteros e outro que realiza a animação de saída deles. Para que o sistema funcionasse de forma constante, nós fizemos com que um método chamasse o outro após um período de tempo.

No próximo tutorial nós implementaremos os botões do jogo e a funcionalidade deles. Ou seja, faremos o jogador ter o controle da sua nave, tanto para movê-la como para atirar. =]

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.