Tutorial: Desenvolvendo um Jogo de Batalha Naval em Cocos2d-x: Parte 1 – Projeto e Tela de Gameplay

Iniciaremos a implementação de mais um jogo para a nossa lista.

Dessa vez, construiremos um jogo de batalha naval.

Então, vamos ao nosso próximo desafio.

Parte 1 – Parte 2Parte 3Parte 4

Finalizamos no último tutorial a implementação de um jogo de sinuca. Fechamos com a programação dos elementos de HUD e término do jogo.

Nesse tutorial, nós daremos início à programação de um jogo de batalha naval. Primeiramente, nós criaremos e prepararemos o projeto Cocos2d-x. Logo após, nós criaremos os objetos gráficos do jogo. Por último, nós implementaremos uma tela de gameplay. Partiu.

 

Criando e preparando o projeto

Abra o terminal e acesse a pasta onde você deseja criar o projeto do jogo de batalha naval. Certifique-se de que não há espaços em branco no caminho até essa pasta. Digite “cocos new BatalhaNaval -p com.Santy.BatalhaNaval -l cpp” e aperte “Enter”. Será criado um projeto Cocos2d-x com o nome “BatalhaNaval” e com pacote “com.Santy.BatalhaNaval”. Caso você não consiga criar o projeto, veja como fazer isso nesse tutorial. A Figura 1 mostra eu criando o projeto no terminal.

Figura 1 - Criando o projeto Cocos2d-x
Figura 1 – Criando o projeto Cocos2d-x

Se você compilar o código do projeto recém-criado e executar o aplicativo, será mostrada na tela do aparelho a imagem padrão do Cocos2d-x. Porém, essa imagem é meramente ilustrativa e não serve de nada para o nosso jogo. Para apagá-la, acesse a pasta “Resources”, existente dentro da pasta do projeto criado, e apague o arquivo “HelloWorld.png”. Descompacte nessa mesma pasta esse arquivo compactado. Nele, estão compactados os dois arquivos de sprite sheet que utilizaremos na programação do jogo. Eu mesmo criei esses arquivos de sprite sheet com base nos arquivos de sprite desse site. Caso você não saiba o que é um sprite sheet e nem como fazer um, veja esse tutorial.

Antes de começarmos a programar o jogo, vamos remover o código desnecessário referente ao “Hello World” padrão do Cocos2d-x. Abra o arquivo “HelloWorldScene.cpp” e apague todas as linhas de código existentes entre essas (inclusive):

/////////////////////////////

// 3. add your codes below…

e essa (inclusive):

this->addChild(sprite, 0);

Agora podemos começar a escrever códigos referente à programação do jogo.

 

Instanciando os elementos gráficos

PortaAvioesNesse jogo, teremos cinco tipos diferentes de elementos gráficos. Um corresponde à superfície de mar, outro corresponde aos indicadores de onde ainda é possível atirar e os outros correspondem aos navios grandes, médios e pequenos. Existirá apenas um objeto gráfico referente à superfície do mar e esse objeto não será modificado em momento algum no decorrer do jogo. Assim sendo, precisaremos criar na classe “HelloWorld” apenas os atributos referentes aos indicadores de opção de tiro e os atributos referentes aos navios. Para isso, abra o arquivo “HelloWorldScene.h” e adicione as seguintes linhas de código:

cocos2d::Sprite *grade[6][10];

cocos2d::Sprite *naviosG[2];

cocos2d::Sprite *naviosM[4];

cocos2d::Sprite *naviosP[6];

logo abaixo dessa:

virtual bool init();

Salve esse arquivo e o feche, pois não faremos mais modificações nele. Agora, instanciaremos os objetos referentes a esses elementos gráficos. Abra o arquivo “HelloWorldScene.cpp” e adicione as seguintes linhas de código:

int i,j;

CCSpriteFrameCache::getInstance()->addSpriteFramesWithFile(“SpriteSheet.plist”);

Sprite *fundo = Sprite::createWithSpriteFrameName(“Fundo.png”);

if(visibleSize.width/visibleSize.height>fundo->getContentSize().width/fundo->getContentSize().height)

    fundo->setScale(visibleSize.width/fundo->getContentSize().width);

else

    fundo->setScale(visibleSize.height/fundo->getContentSize().height);

fundo->setPosition(Vec2(visibleSize.width/2,visibleSize.height/2));

addChild(fundo);

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

    for(j=0;j<10;j++) {

        HelloWorld::grade[i][j] = Sprite::createWithSpriteFrameName(“Opcao.png”);

        HelloWorld::grade[i][j]->setScaleX((visibleSize.width/10.0)/HelloWorld::grade[i][j]->getContentSize().width);

        HelloWorld::grade[i][j]->setScaleY((visibleSize.height/6.0)/HelloWorld::grade[i][j]->getContentSize().height);

        HelloWorld::grade[i][j]->setPosition(Vec2(((2*j+1)*HelloWorld::grade[i][j]->getBoundingBox().size.width)/2.0,

          visibleSize.height – ((2*i+1)*HelloWorld::grade[i][j]->getBoundingBox().size.height)/2.0));

        addChild(HelloWorld::grade[i][j]);

    }

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

    HelloWorld::naviosG[i] = Sprite::createWithSpriteFrameName(“NavioG.png”);

    HelloWorld::naviosG[i]->setScaleX((visibleSize.width/10.0)/HelloWorld::naviosG[i]->getContentSize().width);

    HelloWorld::naviosG[i]->setScaleY((visibleSize.height/2.0)/HelloWorld::naviosG[i]->getContentSize().height);

    HelloWorld::naviosG[i]->setVisible(false);

    addChild(HelloWorld::naviosG[i]);

}

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

    HelloWorld::naviosM[i] = Sprite::createWithSpriteFrameName(“NavioM.png”);

    HelloWorld::naviosM[i]->setScaleX((visibleSize.width/10.0)/HelloWorld::naviosM[i]->getContentSize().width);

    HelloWorld::naviosM[i]->setScaleY((visibleSize.height/3.0)/HelloWorld::naviosM[i]->getContentSize().height);

    HelloWorld::naviosM[i]->setVisible(false);

    addChild(HelloWorld::naviosM[i]);

}

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

    HelloWorld::naviosP[i] = Sprite::createWithSpriteFrameName(“NavioP.png”);

    HelloWorld::naviosP[i]->setScaleX((visibleSize.width/10.0)/HelloWorld::naviosP[i]->getContentSize().width);

    HelloWorld::naviosP[i]->setScaleY((visibleSize.height/6.0)/HelloWorld::naviosP[i]->getContentSize().height);

    HelloWorld::naviosP[i]->setVisible(false);

    addChild(HelloWorld::naviosP[i]);

}

logo abaixo dessa:

this->addChild(menu, 1);

CobrindoAté agora, primeiramente, nós abrimos os arquivos de sprite sheet para que pudéssemos criar os sprites do jogo. Logo após, nós criamos um sprite para o fundo do jogo, o redimensionamos e o posicionamos de forma que ele cubra toda a tela do aparelho. Em seguida, nós criamos e posicionamos todos os sprites que indicam as opções de lugares onde o jogador ainda pode atirar. Por último, nós criamos todos os navios e os deixamos invisíveis com o objetivo de preparar o início do jogo.

Vamos à tela de gameplay.

 

Programando a tela de Gameplay

Se você compilar o código atual e executar o jogo, será mostrada a tela inicial com somente o mar e as opções de lugares para atirar. Isso não nos mostra muita coisa sobre a tela de gameplay. Vamos deixar a tela um pouco mais incrementada adicionando três navios e dois tiros falhos. Para fazer isso, adicione as seguintes linhas de código:

HelloWorld::grade[1][4]->setVisible(false);

HelloWorld::grade[2][4]->setVisible(false);

HelloWorld::grade[3][4]->setVisible(false);

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

HelloWorld::naviosG[0]->setPosition(Vec2(HelloWorld::grade[2][4]->getPositionX(),HelloWorld::grade[2][4]->getPositionY()));

HelloWorld::grade[4][6]->setVisible(false);

HelloWorld::grade[4][7]->setVisible(false);

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

HelloWorld::naviosM[0]->setRotation(90.0);

HelloWorld::naviosM[0]->setPosition(Vec2(7*HelloWorld::grade[0][0]->getBoundingBox().size.width,

  visibleSize.height-(9*HelloWorld::grade[0][0]->getBoundingBox().size.height)/2.0));

HelloWorld::grade[1][1]->setVisible(false);

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

HelloWorld::naviosP[0]->setRotation(180.0);

HelloWorld::naviosP[0]->setPosition(Vec2(HelloWorld::grade[1][1]->getPositionX(),HelloWorld::grade[1][1]->getPositionY()));

HelloWorld::grade[2][6]->setSpriteFrame(“Erro.png”);

HelloWorld::grade[4][2]->setSpriteFrame(“Erro.png”);

logo abaixo dessas:

    addChild(HelloWorld::naviosP[i]);

}

Note que deixamos invisíveis alguns sprites que indicam opções de lugares para atirar. Nesses mesmos lugares, nós posicionamos três navios. Nós também substituímos outros dois indicadores por tiros falhos. Com isso, temos uma tela de gameplay melhor. Basta compilar o código e executar o jogo para ver o resultado. Para os curiosos de plantão, a tela é mostrada na Figura 2.Você verá a tela com várias opções de onde ainda falta atirar, três barcos já abatidos e dois tiros falhos.

Figura 2 - Tela de gameplay
Figura 2 – Tela de gameplay

Criamos o projeto do nosso próximo jogo no tutorial de hoje. Esse será um jogo de batalha naval e já sabemos mais ou menos como será o gameplay.

No próximo tutorial, nós implementaremos o sistema que distribui aleatoriamente todos os barcos no cenário.

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