Tutorial: Desenvolvimento de Jogos para Android com Cocos2d-x – Parte 7

Muitos jogos possuem botões na tela de toque para que o jogador possa realizar comandos como chamar menus, pausar jogos, comandar os personagens e por aí vai.

Vimos antes como usar a tela do dispositivo a nosso favor, mas como reconhecemos cliques em botões pertencentes às HUDs? É difícil fazer isso, Santy?

Veremos que é mais simples do que vocês imaginam.

No último tutorial eu falei sobre como reconhecemos toques na tela do celular. Apresentei alguns conceitos como: o que são classes, objetos e herança em linguagens de programação orientadas a objeto. Aprendemos muitas coisas desde o início dos tutoriais, não? ;D

Nesse tutorial daremos continuidade ao uso do toque na tela, porém agora vamos focar mais em interação com botões. Bora fazer o nosso MegaMan (créditos a Capcom) andar quando clicamos nos botões de seta? Go, go, go …

 

Inclusão dos botões na tela

Vamos por partes. Primeiramente colocaremos os botões na tela do celular. Obviamente, quando terminarmos essa primeira etapa, os botões ainda não farão nada. Daremos início ao tutorial abrindo o código do tutorial passado, mais especificamente os arquivos “HelloWorldScene.cpp”. Nesse arquivo, logo abaixo da seguinte linha de código

addChild(sprite);

adicione essas linhas de código:

CCSprite* setaEsquerda = CCSprite::createWithSpriteFrameName(“Seta.png”);

setaEsquerda->setPosition(ccp(setaEsquerda->boundingBox().size.width/2,size.height-setaEsquerda->boundingBox().size.height/2-50));

setaEsquerda->setTag(2);

addChild(setaEsquerda);

CCSprite* setaDireita = CCSprite::createWithSpriteFrameName(“Seta.png”);

setaDireita->setTag(3);

setaDireita->setFlipX(true);

setaDireita->setPosition(ccp(size.width-setaDireita->boundingBox().size.width/2,size.height-setaDireita->boundingBox().size.height/2-50));

addChild(setaDireita);

O que fizemos agora? Incluímos dois novos Sprites que representam os botões de interação “seta para a esquerda” e “seta para a direita”. Esses Sprites foram adicionados como nós filhos do objeto HelloWorld. Caso você não sabe do que eu esteja falando ou não se lembra, entenda como Sprites funcionam lendo esse tutorial e sobre a hierarquia de objetos do Cocos2d-x lendo esse tutorial.

Vocês perceberam algo errado? Incluímos os botões como filhos da classe HelloWorld e não como filhos da classe camadaHUD, essa responsável pelos elementos de HUD. Deixo esse “conserto” em suas mãos, como um exercício. ;D

Logo após criarmos os botões, nós adicionamos uma tag a cada um deles, sendo 2 o valor pertencente ao botão “seta para a esquerda”, e 3 o valor pertencente ao botão “seta para a direita”. Vocês podem ver também que o botão “seta para a direita” utiliza o mesmo sprite frame do botão “seta para a esquerda”, porém o botão “seta para a direita” é graficamente invertido. Finalmente, nós posicionamos ambos os botões nos cantos direito e esquerdo da parte superior da tela. Simples (vírgula) não?

Se vocês forem compilar o código atual, o jogo dará erro porque não existe nenhum sprite frame com o nome “Seta.png”. Como estamos utilizando o mesmo sprite sheet desse tutorial, o jogo não encontra a o sprite frame que define a imagem do botão. Troque os arquivos “Megaman.plist” e “Megaman.png”, esses localizados na pasta “HelloResources”, pelos arquivos existentes “nesse arquivo compactado”: Com a substituição do sprite sheet, o jogo executará, porém os botões não farão nada se o usuário clicar neles. Precisamos incluir as funcionalidades nesses botões.

 

Funcionalidades dos botões

Para incluirmos as funcionalidades nos botões, ou seja, fazermos o MegaMan andar para a esquerda se a “seta para a esquerda” for pressionada e andar para a direita se a “seta para a direita” for pressionada, no mesmo arquivo “HelloWorldScene.cpp”, substitua as seguintes linhas de código:

void HelloWorld::ccTouchesEnded(CCSet *pTouches,CCEvent *pEvent) {

CCPoint p = (static_cast<CCTouch*>(pTouches->anyObject()))->getLocationInView();

p.y = CCDirector::sharedDirector()->getWinSize().height – p.y;

getChildByTag(1)->setPosition(p);

}

por essas linhas:

void HelloWorld::ccTouchesEnded(CCSet *pTouches,CCEvent *pEvent) {

unscheduleAllSelectors();

}

void HelloWorld::ccTouchesBegan(CCSet *pTouches,CCEvent *pEvent) {

CCPoint p = (static_cast<CCTouch*>(pTouches->anyObject()))->getLocationInView();

p.y = CCDirector::sharedDirector()->getWinSize().height – p.y;

if(getChildByTag(2)->boundingBox().containsPoint(p))

schedule(schedule_selector(HelloWorld::andaEsquerda));

else if(getChildByTag(3)->boundingBox().containsPoint(p))

schedule(schedule_selector(HelloWorld::andaDireita));

}

void HelloWorld::andaEsquerda(double dt) {

getChildByTag(1)->setPositionX(getChildByTag(1)->getPositionX()-2);

}

void HelloWorld::andaDireita(double dt) {

getChildByTag(1)->setPositionX(getChildByTag(1)->getPositionX()+2);

}

Não obstante, abra o arquivo “HelloWorldScene.h”, e adicione essas linhas:

virtual void ccTouchesBegan(cocos2d::CCSet *pTouches,cocos2d::CCEvent *pEvent);

void andaEsquerda(double dt);

void andaDireita(double dt);

logo abaixo dessa linha de código:

virtual void ccTouchesEnded(cocos2d::CCSet *pTouches,cocos2d::CCEvent *pEvent);

Após essa mudança, se você compilar o código, o MegaMan andará para a esquerda se você pressionar o botão “seta para a esquerda” e andará para a direita se você pressionar o botão “seta para a direita”. O que fizemos no código para incluir essas funcionalidades nos botões?

Se vocês forem reparar, incluímos dois métodos responsáveis por capturar interação com a tela e dois métodos que criamos por conta própria. Os métodos “ccTouchesEnded” e “ccTouchesBegan” são responsáveis pela interação com a tela. Eles fazem parte da classe CCLayer e identificam toques na tela quando o usuário tira o dedo e quando ele põe o dedo na tela, respectivamente.

Logo, quando o usuário encosta o dedo na tela, o método “ccTouchesBegan” é chamado. Nesse momento, ele identifica em qual parte da tela houve o toque e verifica se esse toque está ocorrendo sobre algum dos dois botões. Caso o toque seja realizado sobre o botão “seta para a esquerda”, o método “andaEsquerda” é chamado constantemente.  O mesmo acontece com o botão “seta para a direita”. Se o toque não acontecer sobre botão algum, então o jogo não faz nada, obviamente. Vale lembrar que isso sempre acontece somente quando o usuário inicia um clique na tela.

Quando o usuário tira o dedo da tela, então o método “ccTouchesEnded” é chamado. Nesse momento o jogo para de chamar consecutivamente qualquer um dos métodos “andaEsquerda” e “andaDireita”. Então o MegaMan para de andar. O Sprite do MegaMan anda porque esses dois métodos são chamados constantemente. A cada intervalo de alguns milissegundos esses métodos são chamados e eles modificam duas unidades de posição horizontal. No caso do “andaDireita”, o Sprite é reposicionado subtraindo duas unidades de sua posição horizontal e, no caso do “andaEsquerda”, o Sprite é reposicionado somando duas unidades. Como isso ocorre em um intervalo de tempo muito pequeno e como os valores adicionados são relativamente pequenos (duas unidades), então o MegaMan anda com o passar do tempo. Simples, não? =]

Figura 1 - Jogo executando com botões

Figura 1 – Jogo executando com botões

Ainda tem alguns pontos para melhorar, como, por exemplo, o Sprite do MegaMan ser invertido se a tecla “para a esquerda” for pressionada. Também podemos fazer a animação do personagem por troca de frames acontecer somente quando um botão é pressionado e fazer a troca de frames parar se o usuário tirar o dedo da tela. Outro ponto interessante é que se o jogador clica e deixa o dedo pressionado por muito tempo, o MegaMan sai da tela. Seria interessante adicionar uma parede lógica nos limites da tela. Deixo essas dicas para vocês implementarem.

Para os curiosos de plantão, a Figura 1 mostra o resultado da tela com os botões de HUD.

Vimos nesse tutorial como incluir botões para interagirmos com os personagens nos nossos games. Não mostrei sobre botões que chamam menus ou coisas do tipo, mas isso funciona praticamente da mesma forma. Ainda não mostrei como incluir cenários e inimigos, mas veja a Figura 1 e analise se já não está com uma carinha de jogo. =]

O próximo tutorial será um pouco diferente. Vou quebrar um pouco essa sequência que estou fazendo e mostrar como podemos incluir cenários em nossos jogos. Mas isso é outra história e renderá mais alguns tutoriais. Prontos para continuar?

Então é isso pessoal, nos vemos mais para frente.

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.