É muito legal ver quando nosso jogo começa a criar corpo.
Mas ainda falta deixá-lo parecido com os objetos existentes no mundo real.
Hoje, colocaremos imagens nos objetos rígidos, deixando o nosso jogo como um labirinto feito de madeira.
Go go go …
No tutorial passado nós incluímos as paredes no nosso jogo de guiar a bolinha no labirinto. Estamos nos aproximando do fim desse game, estão percebendo? Nesse tutorial eu adicionarei as “figurinhas” sobre os objetos rígidos no Box2D, fazendo com que o cenário feito de caixas tenha o aspecto de um labirinto feito de madeira. Além disso, colocaremos um Sprite de bola de aço que acompanha o objeto rígido pertencente à bola.
Dando início ao tutorial, baixe esse arquivo: Texturas para o game. Depois, descompacte-o na pasta “Resources”, existente no projeto criado no Cocos2d-x. Eu criei um sprite sheet que contém arquivos de imagens para o fundo do labirinto, para as paredes e para a bolinha de aço. Caso você não saiba para que servem os arquivos de sprite sheet contidos no arquivo compactado ou não lembre como criá-los, dê uma olhada nesse tutorial. Após a descompactação na pasta correta, você já pode usar o sprite sheet para criar os Sprites que servirão como texturas para os objetos rígidos existentes no mundo do Box2D.
Agora vamos incluir o código responsável por adicionar os Sprites no mundo do Cocos2d-x. Como de praxe, modificaremos a versão do código obtida após o término do último tutorial. Caso você não o fez, clique aqui e o faça para que possamos dar continuidade nesse tutorial. Primeiramente abra o arquivo “HelloWorldScene.h” e adicione a seguinte linha de código:
cocos2d::CCSprite* bolinhaSprite;
logo abaixo desse linha, essa adicionada no último tutorial:
b2Body* bolinha;
Agora abra o arquivo “HelloWorldScene.cpp” e adicione o seguinte código:
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile(“spriteSheet.plist”);
CCSprite* fundoSprite = CCSprite::createWithSpriteFrameName(“Fundo.png”);
fundoSprite->setPosition(ccp(size.width/2,size.height/2));
addChild(fundoSprite);
CCSprite* caixasSprite[6];
caixasSprite[0] = CCSprite::createWithSpriteFrameName(“Parede.png”);
caixasSprite[0]->setScaleX(288.0/caixasSprite[0]->boundingBox().size.width);
caixasSprite[0]->setScaleY(32.0/caixasSprite[0]->boundingBox().size.height);
caixasSprite[0]->setPosition(ccp(caixas[0]->GetPosition().x*PTM_RATIO,caixas[0]->GetPosition().y*PTM_RATIO));
addChild(caixasSprite[0]);
caixasSprite[1] = CCSprite::createWithSpriteFrameName(“Parede.png”);
caixasSprite[1]->setScaleX(288.0/caixasSprite[1]->boundingBox().size.width);
caixasSprite[1]->setScaleY(32.0/caixasSprite[1]->boundingBox().size.height);
caixasSprite[1]->setPosition(ccp(caixas[1]->GetPosition().x*PTM_RATIO,caixas[1]->GetPosition().y*PTM_RATIO));
addChild(caixasSprite[1]);
caixasSprite[2] = CCSprite::createWithSpriteFrameName(“Parede.png”);
caixasSprite[2]->setScaleX(128.0/caixasSprite[2]->boundingBox().size.width);
caixasSprite[2]->setScaleY(32.0/caixasSprite[2]->boundingBox().size.height);
caixasSprite[2]->setRotation(90);
caixasSprite[2]->setPosition(ccp(caixas[2]->GetPosition().x*PTM_RATIO,caixas[2]->GetPosition().y*PTM_RATIO));
addChild(caixasSprite[2]);
caixasSprite[3] = CCSprite::createWithSpriteFrameName(“Parede.png”);
caixasSprite[3]->setScaleX(64.0/caixasSprite[3]->boundingBox().size.width);
caixasSprite[3]->setScaleY(32.0/caixasSprite[3]->boundingBox().size.height);
caixasSprite[3]->setRotation(90);
caixasSprite[3]->setPosition(ccp(caixas[3]->GetPosition().x*PTM_RATIO,caixas[3]->GetPosition().y*PTM_RATIO));
addChild(caixasSprite[3]);
caixasSprite[4] = CCSprite::createWithSpriteFrameName(“Parede.png”);
caixasSprite[4]->setScaleX(64.0/caixasSprite[4]->boundingBox().size.width);
caixasSprite[4]->setScaleY(32.0/caixasSprite[4]->boundingBox().size.height);
caixasSprite[4]->setRotation(90);
caixasSprite[4]->setPosition(ccp(caixas[4]->GetPosition().x*PTM_RATIO,caixas[4]->GetPosition().y*PTM_RATIO));
addChild(caixasSprite[4]);
caixasSprite[5] = CCSprite::createWithSpriteFrameName(“Parede.png”);
caixasSprite[5]->setScaleX(64.0/caixasSprite[5]->boundingBox().size.width);
caixasSprite[5]->setScaleY(32.0/caixasSprite[5]->boundingBox().size.height);
caixasSprite[5]->setRotation(90);
caixasSprite[5]->setPosition(ccp(caixas[5]->GetPosition().x*PTM_RATIO,caixas[5]->GetPosition().y*PTM_RATIO));
addChild(caixasSprite[5]);
HelloWorld::bolinhaSprite = CCSprite::createWithSpriteFrameName(“Bolinha.png”);
HelloWorld::bolinhaSprite->setPosition(ccp(HelloWorld::bolinha->GetPosition().x*PTM_RATIO,HelloWorld::bolinha->GetPosition().y*PTM_RATIO));
addChild(HelloWorld::bolinhaSprite);
logo abaixo dessa linha, também adicionada no tutorial anterior:
caixas[5]->CreateFixture(&cascaCaixas5);
O que fizemos acima? Antes de tudo, eu abri o sprite sheet para que pudéssemos criar e incluir Sprites no mundo do Cocos2d-x. Logo após, eu criei, posicionei e adicionei um Sprite que representa o fundo do labirinto no mundo do Cocos2d-x. Continuando, eu criei e escalei (mudei o tamanho) dos Sprites que representam duas paredes na horizontal e os adicionei ao jogo. Para terminar de criar as paredes, adicionei mais quatro delas na vertical, o que necessitou que eu rotacionasse os Sprites em 90 graus, para deixá-los em pé. Finalizando, eu incluí um Sprite que representa a bolinha de aço.
Notem que eu apenas adicionei esse Sprite no ambiente, mas não o fiz seguir o objeto rígido que representa a bolinha de aço. Para que o Sprite acompanhe corretamente esse objeto rígido, é necessário que, a cada atualização do mundo do Box2D, você atualize também a nova posição do Sprite. Isso fará com que a cada movimentação que aconteça no objeto rígido que representa a bolinha de aço, a posição do Sprite seja atualizada, fazendo com que ele se movimente também. Para isso, adicione a seguinte linha de código:
HelloWorld::bolinhaSprite->setPosition(ccp(HelloWorld::bolinha->GetPosition().x*PTM_RATIO,HelloWorld::bolinha->GetPosition().y*PTM_RATIO));
logo abaixo dessa:
HelloWorld::mundo->Step(dt,3,2);
Compile o código e execute o jogo. Perceba que, agora, todos os objetos rígidos do jogo tem um Sprite que os representam no mundo do Cocos2d-x. Isso fez com que cada parede tenha a sua respectiva imagem de madeira, o fundo tenha uma imagem de uma madeira ou pouco mais clara e a bolinha tenha uma imagem de uma bolinha de aço. Note que, mesmo após adicionarmos os Sprites, o debug draw continua sendo mostrado na tela. Se você quiser ver como fica o resultado sem ele, comente essa linha de código (adicione duas barras “//” no começo da linha):
addChild(HelloWorld::debugDrawLayer,9999);
Isso fará com que o jogo seja executado sem o debug draw, ou seja, como ele realmente deve aparecer na tela do aparelho. Se você não lembra muito bem sobre o que é e para que serve o debug draw, veja esse tutorial. A Figura 1 mostra o jogo sendo executado sem o debug draw.
Figura 1 – Jogo executando sem o debug draw
Nesse tutorial nós vimos como adicionar Sprites que representam cada objeto rígido existente no mundo do Box2D. Vimos que, para que o Sprite da bolinha de aço ande conforme o objeto rígido que a representa no mundo do Box2D, é necessário atualizar a posição do Sprite a cada mudança no mundo do Box2D. Ao final nós retiramos temporariamente o debug draw para que pudéssemos visualizar como estava o jogo. Não esqueça de “descomentar” a linha de código que comentamos por último. O debug draw ainda será importante nos próximos tutoriais.
No próximo tutorial nós adicionaremos as bocas que a bolinha não poderá entrar e a boca que a bolinha deverá ser colocada. Para isso, precisaremos programar as bocas, as suas funcionalidades e adicionar um Sprite que representa cada uma delas no mundo do Cocos2d-x. Mas isso não é tema desse tutorial.
Um grande abraço e nos vemos adiante. []