Tutorial: Desenvolvendo um jogo de memorização de sinais: Parte 3 – Interação com o jogo

Já implementamos a geração aleatória de sequência de sinais e a apresentação da sequência ao jogador.

Hoje programaremos a funcionalidade que propicia a interação com o jogo.

Faremos com que os botões possam ser apertados pelo jogador.

 

Parte 1Parte 2 – Parte 3 – Parte 4Parte 5

Vimos no último tutorial como funciona a geração e o aumento aleatorizado da sequência de sinais. Para isso, nós implementamos um método que sorteia um valor numérico inteiro aleatório de 0 a 3 e o adiciona ao final da sequência. Esse valor determina qual das quatro lâmpadas acenderá por último. Também implementamos um método que apresenta a sequência ao jogador, acendendo as lâmpadas conforme uma lista criada unicamente para esse propósito. Ao final, nós testamos os dois métodos com a adição de algumas linhas de código a mais.

Nesse tutorial, nós implementaremos o sistema de interação com o jogo. Acionaremos a tela de toque e distinguiremos qual botão o jogador está apertando, isto com base na posição que ele encostou o dedo na tela. Faremos com que a lâmpada, ligada ao botão que o jogador está apertando, acenda enquanto ele está com o dedo encostado na tela e se apague quando desencostado.

 

Eliminando código desnecessário

JogandoNoLixoAntes de tudo, vamos excluir o código adicionado no último tutorial para testar os métodos implementados. Abra o arquivo “HelloWorldScene.cpp” e apague as seguintes linhas de código:

schedule(schedule_selector(HelloWorld::aumentaSequencia),1.5);

schedule(schedule_selector(HelloWorld::mostraSequencia),2);

e as seguintes linhas de código:

schedule(schedule_selector(HelloWorld::aumentaSequencia),0.6*i + 1.5);

schedule(schedule_selector(HelloWorld::mostraSequencia),0.6*i + 2);

Como foi dito, essas linhas foram adicionadas com o intuito único de testar os métodos implementados no tutorial passado. Como hoje implementaremos a interação com o jogo, essas linhas não se fazem mais necessárias. Isso não significa que a implementação dos métodos foi inútil. Utilizaremos tais métodos em tutoriais posteriores.

Agora, vamos implementar a funcionalidade nos botões.

 

Adicionando a interação com o jogo

pensadorAntes de sairmos codificando, precisamos pensar um pouco no problema que precisamos resolver. Note que existem quatro botões diferentes e que eles estão em lugares distintos na tela. Por isso, é necessário pensar na possibilidade do jogador clicar em mais de um ao mesmo tempo. Na verdade, precisamos limitar isso, fazendo com que os outros botões não sejam acionados caso um botão já esteja sendo apertado no momento. Para que isso seja possível, é necessário criar uma variável que armazena o número identificador do toque na tela. Ela basicamente identificará se algum botão já está sendo apertado pelo jogador.

Além disso, precisamos implementar dois métodos específicos que possuem a função de gerenciar toques na tela. Esses métodos são o “ccTouchesBegan” e o “ccTouchesEnded”, sendo o primeiro chamado quando um toque é iniciado; o outro quando finalizado. Assim, precisamos declarar esses métodos e uma variável que armazena um valor numérico inteiro para gerenciar os toques nos botões do jogo. Para isso, abra o arquivo “HelloWorldScene.h” e adicione as seguintes linhas de código:

int idToque;

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

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

logo abaixo dessa:

cocos2d::CCArray* sequencia;

Agora implementaremos os métodos declarados na classe “HelloWorld”. Adicione as seguintes linhas de código no final do arquivo “HelloWorldScene.cpp”.

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

    if(HelloWorld::idToque==-1) {

        CCSize size = CCDirector::sharedDirector()->getWinSize();

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

        ponto.y = size.height – ponto.y;

        if(HelloWorld::botaoSup->boundingBox().containsPoint(ponto)) {

            HelloWorld::lampSup->setDisplayFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“LuzAcesa.png”));

            HelloWorld::idToque = (static_cast<CCTouch*>(pTouches->anyObject()))->getID();

        } else if(HelloWorld::botaoInf->boundingBox().containsPoint(ponto)) {

            HelloWorld::lampInf->setDisplayFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“LuzAcesa.png”));

            HelloWorld::idToque = (static_cast<CCTouch*>(pTouches->anyObject()))->getID();

        } else if(HelloWorld::botaoEsq->boundingBox().containsPoint(ponto)) {

            HelloWorld::lampEsq->setDisplayFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“LuzAcesa.png”));

            HelloWorld::idToque = (static_cast<CCTouch*>(pTouches->anyObject()))->getID();

        } else if(HelloWorld::botaoDir->boundingBox().containsPoint(ponto)) {

            HelloWorld::lampDir->setDisplayFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“LuzAcesa.png”));

            HelloWorld::idToque = (static_cast<CCTouch*>(pTouches->anyObject()))->getID();

        }

    }

}

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

    if(HelloWorld::idToque==(static_cast<CCTouch*>(pTouches->anyObject()))->getID()) {

        HelloWorld::lampSup->setDisplayFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“LuzApagada.png”));

        HelloWorld::lampInf->setDisplayFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“LuzApagada.png”));

        HelloWorld::lampEsq->setDisplayFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“LuzApagada.png”));

        HelloWorld::lampDir->setDisplayFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“LuzApagada.png”));

        HelloWorld::idToque = -1;

    }

}

apertarbotaoNo método “ccTouchesBegan” um toque na tela somente é analisado se não existe outro toque acontecendo no momento. Caso seja um toque único na tela, é identificado em qual parte dela o jogador está encostando. Se for sobre o botão superior, por exemplo, o sprite que representa a lâmpada superior é modificado de forma que a lâmpada fique acesa. Além disso, a variável gerenciadora de toque na tela passa a armazenar o número identificador do toque. Isso evitará que outro botão seja acionado, caso o jogador ainda esteja com o dedo sobre um dos botões.

Quando o jogador tira o dedo da tela, o método “ccTouchesEnded” é chamado e, caso o toque que o jogador acabou de finalizar seja o mesmo de um botão que ele apertou, todas as lâmpadas passam a ficar apagadas. O funcionamento conjunto dos métodos faz com que somente um botão seja acionado e faz com que a lâmpada fique acesa enquanto o jogador estiver com o dedo sobre o botão.

Nesse momento, faltam apenas duas linhas de código para que a interação com o jogo esteja completamente funcionando: inicializar a variável “idToque” e acionar a tela de toque. Para isso, adicione as seguintes linhas de código:

HelloWorld::idToque = -1;

setTouchEnabled(true);

logo abaixo dessa:

HelloWorld::sequencia->retain();

Pronto. Se você compilar o código e executar o jogo perceberá que somente um botão pode ser acionado de cada vez. Além disso, a lâmpada logo ao lado do botão que o jogador está apertando acende. A Figura 1 ilustra o jogo executando, sendo que o jogador está apertando o botão azul no momento da captura da tela.

Figura 1 - Momento quando o jogador aperta o botão azul
Figura 1 – Momento em que o jogador aperta o botão azul

Implementamos nesse tutorial o sistema de interação com o jogo de memorização de sinais. Criamos uma variável gerenciadora de toques sobre os botões e implementamos dois métodos de toque na tela. Não implementamos o jogo por completo ainda, mas notem que já temos três funcionalidades importantes implementadas: a geração aleatória da sequência, a apresentação dela ao jogador e a interação com o jogo.

No próximo tutorial, nós juntaremos essas funcionalidades implementando o fluxo principal do jogo.

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.

Send this to a friend