full screen background image

Desenvolvendo um Jogo Digital do Zero: Parte 24 – Implementação do menu principal

Desenvolvendo um Jogo Digital do Zero: Parte 24 – Implementação do menu principal

Continuaremos essa saga com a implementação do menu.

Não basta projetar e fazer o design visual, também precisamos incluir essa tela no jogo.

Veremos como implementar o menu e como o interligar com o início do jogo.

 

No último artigo da saga “Desenvolvendo um Jogo Digital do Zero”, vocês viram com o Filipe como ficaram as telas do menu principal, sobre e término do jogo. Obviamente, para que o trabalho realizado seja devidamente aplicado, precisaremos implementar as funcionalidades dessas telas no Shark Pong.

Hoje vamos programar a tela de menu principal e a funcionalidade que inicia o jogo quando o jogador clica na opção de início de jogo. Deixaremos para o próximo artigo a implementação da tela de sobre e das funcionalidades dos botões que abrem essa tela e que fecha o jogo.

MenuAntes de tudo, precisamos atualizar os arquivos de sprite sheet para que possamos implementar a tela do menu principal. Para isso, baixe esse arquivo e o descompacte na pasta “Resources”. Substitua os arquivos já existentes pelos dois arquivos descompactados. Neles, adicionamos alguns sprite frames para a implementação das funcionalidades advindas pela implementação do menu.

É interessante sabermos como funciona o fluxo do jogo para que o possamos implementar da forma correta. Quando abrimos o aplicativo, ele, primeiramente, abre o menu principal na tela. Somente após o jogador clicar na opção correta que o jogo iniciará. Eu me refiro aqui ao game implementado em todos os outros artigos de programação. Pensando dessa forma, precisaremos implementar dois métodos: um responsável em pôr na tela o menu principal; outro para pôr o jogo na tela e iniciá-lo. Vamos começar implementando o método que inicia o jogo.

 

Iniciando o jogo

InicioAté agora, implementamos o Shark Pong para que ele seja iniciado logo quando o aplicativo é aberto. Assim, existem algumas inicializações já realizadas em outros artigos que precisam ser reposicionadas. Aproveitaremos essas inicializações no início do artigo de hoje e, por isso, vamos começar implementando o método que inicia a execução do jogo.

Para incluir o protótipo do método que inicia o jogo, adicione a seguinte linha de código no arquivo “HelloWorldScene.h”:

void animacaoInicialTubarao();

logo abaixo dessa:

float posicaoInicialTubarao[2];

Como vocês podem ver, o nome do método recém-adicionado é “animacaoInicialTubarao”. Isso porque o jogo é iniciado com a animação do tubarão emergindo do mar. Tanto essa animação como a própria tela de gameplay são inicializadas logo quando o aplicativo é iniciado. Parte dessa inicialização será feita, a partir de agora, dentro do método “animacaoInicialTubarao”. Assim, precisaremos remover parte do código de inicialização. Para isso, apague todo esse bloco de código existente no arquivo “HelloWorldScene.cpp”:

CCArray* surfJog = CCArray::create();

surfJog->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“SurfistaJogador2.png”));

surfJog->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“SurfistaJogador1.png”));

surfJog->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“SurfistaJogador2.png”));

surfJog->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“SurfistaJogador3.png”));

HelloWorld::paJogador->runAction(CCRepeatForever::create(

  CCAnimate::create(CCAnimation::createWithSpriteFrames(surfJog,0.15))));

CCArray* surfIA = CCArray::create();

surfIA->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“SurfistaIA2.png”));

surfIA->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“SurfistaIA1.png”));

surfIA->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“SurfistaIA2.png”));

surfIA->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“SurfistaIA3.png”));

HelloWorld::paIA->runAction(CCRepeatForever::create(

  CCAnimate::create(CCAnimation::createWithSpriteFrames(surfIA,0.15))));

CCArray* tub = CCArray::create();

tub->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“Tubarao2.png”));

tub->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“Tubarao3.png”));

tub->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“Tubarao4.png”));

tub->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“Tubarao5.png”));

tub->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“Tubarao1.png”));

HelloWorld::tubarao->runAction(CCAnimate::create(CCAnimation::createWithSpriteFrames(tub,0.15)));

HelloWorld::tubarao->runAction(CCMoveTo::create(0.75,ccp(size.width/2,size.height/2)));

CCSequence* seq = CCSequence::create(CCDelayTime::create(0.75),

  CCCallFunc::create(this,callfunc_selector(HelloWorld::iniciaJogo)),NULL);

runAction(seq);

CocosDenshion::SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(0.2);

CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic(“Background.mp3”,true);

botao-na-camisaUma linha de código apagada precisa ser mantida e outras duas linhas precisam ser adicionadas para que a nova inicialização do jogo aconteça corretamente. Como o aplicativo é iniciado com o menu principal e não mais com o jogo, precisamos deixar os botões de interação invisíveis ao jogador no início. Assim, no mesmo lugar onde foi excluído o código anterior, adicione as seguintes linhas de código:

HelloWorld::botaoDescer->setVisible(false);

HelloWorld::botaoSubir->setVisible(false);

CocosDenshion::SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(0.2);

Agora implementaremos o método “animacaoInicialTubarao”. Nele, conterá o código de inicialização removido anteriormente e mais algumas linhas que reposicionam os sprites existentes no jogo para que um novo início do game aconteça. Estamos pensando em reinício de jogo pelo fato de que um novo jogo pode ser iniciado após o término do anterior. Não implementaremos essa funcionalidade no artigo de hoje, mas parte dela já está implementada desde já. Adicione as seguintes linhas de código no final do arquivo “HelloWorldScene.cpp”.

void HelloWorld::animacaoInicialTubarao() {

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

    setTouchEnabled(false);

    HelloWorld::tubarao->setPosition(ccp(0.78*size.width,size.height/2));

    HelloWorld::tubarao->setRotation(0.0);

    HelloWorld::tubarao->setVisible(true);

    HelloWorld::paJogador->setPosition(ccp(0.1*size.width,size.height/2));

    HelloWorld::paJogador->setFlipY(false);

    HelloWorld::paJogador->setVisible(true);

    HelloWorld::paIA->setPosition(ccp(0.9*size.width,size.height/2));

    HelloWorld::paIA->setFlipY(true);

    HelloWorld::paIA->setVisible(true);

    HelloWorld::polvo->setVisible(false);

    HelloWorld::botaoDescer->setVisible(true);

    HelloWorld::botaoSubir->setVisible(true);

    CCArray* tub = CCArray::create();

    CCArray* surfJog = CCArray::create();

    surfJog->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“SurfistaJogador2.png”));

    surfJog->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“SurfistaJogador1.png”));

    surfJog->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“SurfistaJogador2.png”));

    surfJog->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“SurfistaJogador3.png”));

    HelloWorld::paJogador->runAction(CCRepeatForever::create(

      CCAnimate::create(CCAnimation::createWithSpriteFrames(surfJog,0.15))));

    CCArray* surfIA = CCArray::create();

    surfIA->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“SurfistaIA2.png”));

    surfIA->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“SurfistaIA1.png”));

    surfIA->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“SurfistaIA2.png”));

    surfIA->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“SurfistaIA3.png”));

    HelloWorld::paIA->runAction(CCRepeatForever::create(

      CCAnimate::create(CCAnimation::createWithSpriteFrames(surfIA,0.15))));

    tub->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“Tubarao2.png”));

    tub->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“Tubarao3.png”));

    tub->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“Tubarao4.png”));

    tub->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“Tubarao5.png”));

    tub->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“Tubarao1.png”));

    HelloWorld::tubarao->runAction(CCAnimate::create(CCAnimation::createWithSpriteFrames(tub,0.15)));

    HelloWorld::tubarao->runAction(CCMoveTo::create(0.75,ccp(size.width/2,size.height/2)));

    CCSequence* seq = CCSequence::create(CCDelayTime::create(0.75),

      CCCallFunc::create(this,callfunc_selector(HelloWorld::iniciaJogo)),NULL);

    runAction(seq);

    CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic(“Background.mp3”,true);

}

joiaO método de início de jogo já está devidamente implementado e pronto para ser utilizado.

 

Abrindo o menu principal

Agora implementaremos o menu principal. A Figura 1 mostra a proposta de menu principal desenvolvida pelo designer visual Filipe. Note que nela, têm elementos gráficos que já existem no jogo e elementos gráficos que precisam ser criados. Alguns elementos já criados são: o tubarão, o polvo e os surfistas. Os elementos gráficos que precisamos criar são: a logo do jogo, as três opções do menu e o link do blog Fábrica de Jogos. Assim, precisamos criar um total de cinco sprites para podermos mostrar o menu principal ao jogador. Além disso, precisamos adicionar na classe “HelloWorld” o protótipo do método que mostra o menu, esse nomeado como “abreMenu”. Para adicionar os sprites e o protótipo do método na classe “HelloWorld”, abra o arquivo “HelloWorldScene.h” e adicione as seguintes linhas de código:

cocos2d::CCSprite* logo;

cocos2d::CCSprite* botaoNovoJogo;

cocos2d::CCSprite* botaoSobre;

cocos2d::CCSprite* botaoSair;

cocos2d::CCSprite* link;

void abreMenu();

logo abaixo dessa:

float posicaoInicialTubarao[2];

Figura 1 - Proposta de menu

Figura 1 – Proposta de menu

Declaradas as variáveis que armazenam as referências dos elementos gráficos, agora podemos inicializá-las. Para isso, abra o arquivo “HelloWorldScene.cpp”, adicione as seguintes linhas de código:

HelloWorld::logo = CCSprite::createWithSpriteFrameName(“Logo.png”);

HelloWorld::logo->setScale((0.35*size.height)/HelloWorld::logo->boundingBox().size.height);

HelloWorld::logo->setPosition(ccp(size.width/2,0.78*size.height));

addChild(HelloWorld::logo);

HelloWorld::botaoNovoJogo = CCSprite::createWithSpriteFrameName(“BotaoNovoJogo.png”);

HelloWorld::botaoNovoJogo->setScale((0.08*size.height)/HelloWorld::botaoNovoJogo->boundingBox().size.height);

HelloWorld::botaoNovoJogo->setPosition(ccp(size.width/2,0.45*size.height));

addChild(HelloWorld::botaoNovoJogo);

HelloWorld::botaoSobre = CCSprite::createWithSpriteFrameName(“BotaoSobre.png”);

HelloWorld::botaoSobre->setScale((0.08*size.height)/HelloWorld::botaoSobre->boundingBox().size.height);

HelloWorld::botaoSobre->setPosition(ccp(size.width/2,0.32*size.height));

addChild(HelloWorld::botaoSobre);

HelloWorld::botaoSair = CCSprite::createWithSpriteFrameName(“BotaoSair.png”);

HelloWorld::botaoSair->setScale((0.08*size.height)/HelloWorld::botaoSair->boundingBox().size.height);

HelloWorld::botaoSair->setPosition(ccp(size.width/2,0.18*size.height));

addChild(HelloWorld::botaoSair);

HelloWorld::link = CCSprite::createWithSpriteFrameName(“AnoLink.png”);

HelloWorld::link->setScale((0.04*size.height)/HelloWorld::link->boundingBox().size.height);

HelloWorld::link->setPosition(ccp(size.width/2,0.03*size.height));

addChild(HelloWorld::link);

logo abaixo dessa:

addChild(HelloWorld::botaoSubir);

Não há nada de tão complexo no código adicionado. Perceba que apenas foram instanciados os objetos referentes aos elementos gráficos criados. Agora, implementaremos o método “abreMenu”. Adicione as seguintes linhas de código no final do arquivo “HelloWorldScene.cpp”.

void HelloWorld::abreMenu() {

    HelloWorld::tubarao->setVisible(false);

    HelloWorld::polvo->setVisible(false);

    HelloWorld::logo->setVisible(true);

    HelloWorld::botaoNovoJogo->setVisible(true);

    HelloWorld::botaoSobre->setVisible(true);

    HelloWorld::botaoSair->setVisible(true);

    HelloWorld::link->setVisible(true);

}

NerdProgramadores mais experientes notarão que a inclusão dos novos elementos gráficos do menu influenciam diretamente no jogo que vinha funcionando até então. Tais elementos são pertencentes ao menu principal e precisam estar invisíveis durante a execução do jogo. Dessa forma, é necessário incluir mais linhas de código no método “animacaoInicialTubarao”. Adicione as seguintes linhas de código:

HelloWorld::logo->setVisible(false);

HelloWorld::botaoNovoJogo->setVisible(false);

HelloWorld::botaoSobre->setVisible(false);

HelloWorld::botaoSair->setVisible(false);

HelloWorld::link->setVisible(false);

logo abaixo dessa:

HelloWorld::botaoSubir->setVisible(true);

Agora precisamos arrumar as transições entre o término de um jogo e o menu. Quando um jogo é finalizado, os botões de interação com o jogo precisam ficar invisíveis e as animações dos surfistas precisam ser finalizadas. Isso deve acontecer quando acabar a animação do tubarão comendo um dos surfistas. Dessa forma, adicione as seguintes linhas de código:

HelloWorld::paJogador->cleanup();

HelloWorld::paIA->cleanup();

HelloWorld::botaoDescer->setVisible(false);

HelloWorld::botaoSubir->setVisible(false);

logo abaixo dessa:

HelloWorld::paJogador->setVisible(false);

SelecionandoOs métodos que mostra o menu principal ao jogador e que dá início ao jogo já foram devidamente implementados. Porém, precisamos chamar o método que mostra o menu principal logo quando a aplicação é iniciada. Além disso, precisamos acionar a tela de toque para que o jogador possa escolher uma das opções do menu. Para isso, adicione as seguintes linhas de código:

HelloWorld::abreMenu();

setTouchEnabled(true);

logo abaixo dessa:

CocosDenshion::SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(0.2);

Agora o menu é iniciado antes jogo, mas ainda não foi implementada a funcionalidade do botão “Novo Jogo”. Finalizaremos o artigo de hoje fazendo isso. Nossa… esse artigo está longo, hein!? Mas falta pouco. =]

 

Incluindo a funcionalidade do botão “Novo Jogo”

JogadorNovamente nos deparamos com o problema de gerenciamento de elementos gráficos existentes em diferentes telas. Notem que, quando o menu está sendo apresentado ao jogador, os botões de interação com o jogo devem ser desconsiderados na tela de toque. Para que isso aconteça, precisamos modificar duas linhas de código já existentes. Mude a seguinte linha:

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

de forma que ela fique assim:

if(HelloWorld::botaoDescer->isVisible()&&HelloWorld::botaoDescer->boundingBox().containsPoint(ponto)) {

e a seguinte linha:

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

de forma que ela fique assim:

} else if(HelloWorld::botaoSubir->isVisible()&&HelloWorld::botaoSubir->boundingBox().containsPoint(ponto)) {

Agora os botões de interação somente funcionarão enquanto o jogo estiver executando. Para finalizar (Uufffaaa…), vamos incluir a funcionalidade no botão “Novo Jogo”. Adicione ao final do método “ccTouchesBegan” as seguintes linhas de código.

else if(HelloWorld::botaoNovoJogo->isVisible()&&HelloWorld::botaoNovoJogo->boundingBox().containsPoint(ponto)) {

    HelloWorld::animacaoInicialTubarao();

}

Agora sim … o menu será mostrado ao jogador quando o aplicativo iniciar e o jogo será iniciado quando o botão “Novo Jogo” for clicado. Para os curiosos de plantão, a Figura 2 ilustra o menu sendo mostrado, mas agora pelo próprio jogo. Vale lembrar que as funcionalidades dos botões “Sobre” e “Sair” serão implementadas no próximo artigo.

Figura 2 - Menu sendo mostrado pelo jogo

Figura 2 – Menu sendo mostrado pelo jogo

 

Relembrando, implementamos nesse artigo a tela do menu principal e a funcionalidade do botão “Novo Jogo”. Para isso, precisamos criar cinco novos elementos gráficos por meio de sprites e precisamos implementar o fluxo entre o menu e o início do jogo.

Veremos no próximo artigo como serão implementadas a tela “Sobre” e as funcionalidades dos botões “Sobre” e “Sair”. Além disso, também implementaremos as telas de término 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). Atualmente é programador da Céu Games (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.


Show Buttons
Hide Buttons