Tutorial: Desenvolvendo um Jogo de Sinuca em Cocos2d-x: Parte 2 – Criando os objetos rígidos

Hoje, iniciamos a implementação de outro jogo.

Até agora criamos o projeto Cocos2d-x e já vimos a tela de gameplay.

Continuando, vamos começar a trabalhar na simulação física.

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

Criamos no último tutorial o projeto Cocos2d-x do nosso jogo de sinuca. Também implementamos a tela de gameplay e vimos como ficará o jogo. Nesse tutorial, nós adicionaremos a simulação física no aplicativo e criaremos os objetos rígidos da cena do jogo. Deixaremos o ambiente do jogo pronto para, futuramente, incluirmos a simulação da tacada e do atrito das bolas com a mesa.

 

Simulação física e força da gravidade

gravidadeAntes de criarmos os objetos rígidos, que é a proposta do tutorial de hoje, precisamos incluir a simulação física no aplicativo. Para fazer isso, basta realizar uma pequena modificação em uma linha de código do arquivo “HelloWorldScene.cpp”. Apenas substitua a seguinte linha de código:

auto scene = Scene::create();

por essa:

auto scene = Scene::createWithPhysics();

Pronto, acabamos de adicionar simulação física no nosso jogo. Porém, o ambiente físico não condiz com o que precisamos especificamente no jogo de sinuca. Quando adicionamos a simulação física, nós criamos o ambiente físico padrão do Cocos2d-x. Esse ambiente possui a força de gravidade que atrai os corpos rígidos para baixo. Como o jogo tem câmera superior da mesa de bilhar, a força da gravidade, na verdade está “entrando” na tela do aparelho em vez de ter o direcionamento para baixo. Assim, precisamos retirar a força de gravidade padrão. Para isso, no arquivo “HelloWorldScene.cpp”, adicione a seguinte linha de código:

scene->getPhysicsWorld()->setGravity(Vec2(0.0,0.0));

logo abaixo dessa:

auto scene = Scene::createWithPhysics();

Agora deixamos o ambiente físico propício para a simulação física do nosso jogo de sinuca. Daremos continuidade ao tutorial criando os objetos rígidos da simulação.

 

Criando os objetos rígidos

GameplayOs objetos rígidos da simulação física nada mais são do que as três bolas e as paredes da mesa, estes mostrados na tela de gameplay. O resultado são estes quatro objetos rígidos que teremos que manipular durante a execução do jogo. Assim, precisamos criar um atributo na classe “HelloWorld” para cada um desses objetos rígidos. Para tal, abra o arquivo “HelloWorldScene.h”, e adicione as seguintes linhas de código:

cocos2d::PhysicsBody* bolaBrancaCorpo;

cocos2d::PhysicsBody* bolaVermelhaCorpo;

cocos2d::PhysicsBody* bolaAmarelaCorpo;

cocos2d::PhysicsBody* mesaCorpo;

logo abaixo dessa:

cocos2d::Sprite* bolaAmarela;

Criaremos, primeiramente, os objetos rígidos referentes as bolas de bilhar existentes na tela de gameplay. Esses objetos rígidos têm a geometria de círculo com raio igual à metade da largura do sprite e possuem coeficiente de restituição igual a 1. Isso faz com que não haja amortecimento no impacto da colisão entre eles. Para criar estes objetos, abra o arquivo “HelloWorldScene.cpp” e adicione as seguintes linhas de código:

HelloWorld::bolaBrancaCorpo = PhysicsBody::createCircle(

  HelloWorld::bolaBranca->getContentSize().width/2,PhysicsMaterial(1.0,1.0,0.0));

HelloWorld::bolaBranca->addComponent(HelloWorld::bolaBrancaCorpo);

HelloWorld::bolaVermelhaCorpo = PhysicsBody::createCircle(

  HelloWorld::bolaVermelha->getContentSize().width/2,PhysicsMaterial(1.0,1.0,0.0));

HelloWorld::bolaVermelha->addComponent(HelloWorld::bolaVermelhaCorpo);

HelloWorld::bolaAmarelaCorpo = PhysicsBody::createCircle(

  HelloWorld::bolaAmarela->getContentSize().width/2,PhysicsMaterial(1.0,1.0,0.0));

HelloWorld::bolaAmarela->addComponent(HelloWorld::bolaAmarelaCorpo);

logo abaixo dessa:

addChild(HelloWorld::bolaAmarela);

geometryAgora precisamos criar o objeto rígido referente a mesa de bilhar. Este é um pouco diferente dos outros criados para as bolas. Ele possui a geometria composta por seis segmentos de reta que representam as paredes existentes entre as bocas da mesa de bilhar. Além disso, esse objeto rígido não sofre movimentação durante a simulação física, ou seja, ele é um objeto estático. Dessa forma, criaremos seis segmentos de reta e definiremos o objeto rígido da mesa como sendo a junção desses segmentos. Por último, faremos com que o objeto rígido da mesa seja estático. Para fazer tudo isso, adicione as seguintes linhas de código logo abaixo do código adicionado anteriormente.

HelloWorld::mesaCorpo = PhysicsBody::create();

HelloWorld::mesaCorpo->addShape(PhysicsShapeEdgeSegment::create(

  Vec2(-(319.0/800.0)*HelloWorld::mesa->getContentSize().width,-(174.0/454.0)*HelloWorld::mesa->getContentSize().height),

  Vec2(-(27.0/800.0)*HelloWorld::mesa->getContentSize().width,-(174.0/454.0)*HelloWorld::mesa->getContentSize().height),

  PhysicsMaterial(1.0,1.0,0.0)));

HelloWorld::mesaCorpo->addShape(PhysicsShapeEdgeSegment::create(

  Vec2(-(319.0/800.0)*HelloWorld::mesa->getContentSize().width,(174.0/454.0)*HelloWorld::mesa->getContentSize().height),

  Vec2(-(27.0/800.0)*HelloWorld::mesa->getContentSize().width,(174.0/454.0)*HelloWorld::mesa->getContentSize().height),

  PhysicsMaterial(1.0,1.0,0.0)));

HelloWorld::mesaCorpo->addShape(PhysicsShapeEdgeSegment::create(

  Vec2((319.0/800.0)*HelloWorld::mesa->getContentSize().width,-(174.0/454.0)*HelloWorld::mesa->getContentSize().height),

  Vec2((27.0/800.0)*HelloWorld::mesa->getContentSize().width,-(174.0/454.0)*HelloWorld::mesa->getContentSize().height),

  PhysicsMaterial(1.0,1.0,0.0)));

HelloWorld::mesaCorpo->addShape(PhysicsShapeEdgeSegment::create(

  Vec2((319.0/800.0)*HelloWorld::mesa->getContentSize().width,(174.0/454.0)*HelloWorld::mesa->getContentSize().height),

  Vec2((27.0/800.0)*HelloWorld::mesa->getContentSize().width,(174.0/454.0)*HelloWorld::mesa->getContentSize().height),

  PhysicsMaterial(1.0,1.0,0.0)));

HelloWorld::mesaCorpo->addShape(PhysicsShapeEdgeSegment::create(

  Vec2(-(348.0/800.0)*HelloWorld::mesa->getContentSize().width,-(145.0/454.0)*HelloWorld::mesa->getContentSize().height),

  Vec2(-(348.0/800.0)*HelloWorld::mesa->getContentSize().width,(145.0/454.0)*HelloWorld::mesa->getContentSize().height),

  PhysicsMaterial(1.0,1.0,0.0)));

HelloWorld::mesaCorpo->addShape(PhysicsShapeEdgeSegment::create(

  Vec2((348.0/800.0)*HelloWorld::mesa->getContentSize().width,-(145.0/454.0)*HelloWorld::mesa->getContentSize().height),

  Vec2((348.0/800.0)*HelloWorld::mesa->getContentSize().width,(145.0/454.0)*HelloWorld::mesa->getContentSize().height),

  PhysicsMaterial(1.0,1.0,0.0)));

HelloWorld::mesaCorpo->setDynamic(false);

HelloWorld::mesa->addComponent(HelloWorld::mesaCorpo);

Com isso nós finalizamos a criação dos objetos rígidos pertencentes a cena do jogo. Apesar de você não ver os objetos rígidos, eles estão lá. O que você acha de os vermos para fins de teste?

 

Debug draw

drawA criação de objetos rígidos em simulações físicas é muitas vezes abstrata ao programador. Durante vários momentos fica difícil de os visualizar mentalmente. Existe a possibilidade de ver os objetos rígidos na tela para se ter uma ideia do que está definitivamente sendo simulado. O processo de mostrar na tela as informações da simulação física, como geometria dos objetos rígidos, por exemplo, é chamado informalmente como debug draw.

Antigamente, os desenvolvedores precisavam programar todo o processo de debug draw. Atualmente, a biblioteca Cocos2d-x já tem essa funcionalidade pré implementada. O objeto do Cocos2d-x “PhysicsWorld”, existente nas novas versões da biblioteca, dá esse suporte ao desenvolvedor. Esse é mais um ponto positivo da integração da biblioteca Cocos2d-x com o motor físico Chipmunk.

Para você ver os objetos rígidos simulados, no arquivo “HelloWorldScene.cpp”, adicione a seguinte linha de código:

scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);

logo abaixo dessa:

scene->getPhysicsWorld()->setGravity(Vec2(0.0,0.0));

Se você compilar o código e executar o jogo, você verá em vermelho os segmentos de reta que formam as paredes da mesa e as circunferências que representam os objetos rígidos das bolas de bilhar, essas também em vermelho. A Figura 1 mostra a tela de gameplay com os objetos rígidos.

Figura 1 - Objetos rígidos do gameplay
Figura 1 – Objetos rígidos do gameplay

Incluímos nesse tutorial a simulação física no nosso jogo de sinuca. Retiramos a força da gravidade, pelo fato do jogo ter câmera superior, e criamos os objetos rígidos referentes as bolas e as paredes da mesa de bilhar. Por último, nós executamos o debug draw para visualizarmos os objetos rígidos existentes na simulação.

Se realizarmos uma tacada no mundo físico atual, as bolas nunca pararão de andar porque ainda não existe a ação de forças de atrito entre as bolas e a mesa. Infelizmente, não tem como utilizarmos a biblioteca física a nosso favor para calcular e aplicar tais forças. Isso deverá ser implementado por nós mesmos, no próximo tutorial. =]

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