Tutorial: Desenvolvendo um jogo de guiar bolinha em labirinto – Parte 2: Bolinha andando

Começamos a criar um jogo ao estilo do aTilt.

Porém, não fizemos nada mais do que apenas preparar o código para a implementação em si.

Que tal fazermos a bolinha de aço andar na tela conforme a angulação do aparelho?

No tutorial passado eu mostrei a vocês um game bastante baixado há uma época atrás. Mostrei alguns conceitos físicos por trás do jogo e iniciamos a implementação dele. Não chegamos a implementar algo, mas limpamos o código para podermos criar o jogo praticamente do zero. Nesse tutorial nós implementaremos a principal funcionalidade do game: a movimentação da bolinha. Bora lá?

Configurando o debug draw

Primeiramente, vamos configurar o debug draw para que possamos visualizar os objetos rígidos que criaremos no mundo físico do Box2D. Para isso, precisamos baixar alguns arquivos com código pré-implementado capaz de mostrar os corpos rígidos na tela do aparelho. Baixe todos os arquivos desse site com extensão “.h” e “.cpp” e copie-os para a pasta “Classes”, do projeto criado no último tutorial.

O simples fato de copiar os arquivos para a pasta certa não fará com que eles sejam compilados junto ao seu jogo. Para incluí-los na compilação, primeiramente abra o arquivo “Android.mk”, localizado na pasta “proj.androidjni”. Logo após, modifique a seguinte linha de código desse arquivo:

../../Classes/HelloWorldScene.cpp

para essas linhas:

../../Classes/HelloWorldScene.cpp

../../Classes/B2DebugDrawLayer.cpp

../../Classes/GLES-Render.cpp

Nesse momento os arquivos baixados foram adicionados para compilação. Eles estão compilados, mas ainda não são utilizados no jogo. Para que possamos enxergar os corpos rígidos é necessário adicionar a funcionalidade do debug draw. Para isso precisamos adicionar alguns códigos nos arquivos “HelloWorldScene.h” e “HelloWorldScene.cpp”. Primeiramente abra o arquivo “HelloWorldScene.h” e adicione as seguintes linhas de código:

#include “Box2D/Box2D.h”

#include “B2DebugDrawLayer.h”

#define PTM_RATIO 40

logo abaixo dessa linha:

#define __HELLOWORLD_SCENE_H__

Não obstante, no mesmo arquivo, adicione essas linhas:

B2DebugDrawLayer* debugDrawLayer;

virtual void draw();

b2World* mundo;

abaixo dessa:

CREATE_FUNC(HelloWorld);

A edição do arquivo “HelloWorldScene.h”, por enquanto, é essa. Agora, abra o arquivo “HelloWorldScene.cpp” e adicione as seguintes linhas de código:

HelloWorld::mundo = new b2World(b2Vec2(0,0));

HelloWorld::debugDrawLayer = B2DebugDrawLayer::create(HelloWorld::mundo,PTM_RATIO);

addChild(HelloWorld::debugDrawLayer,9999);

logo abaixo dessa:

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

Ainda no mesmo arquivo, adicione ao final dele as seguintes linhas de código:

void HelloWorld::draw() {

    CCLayer::draw();

    ccGLEnableVertexAttribs(kCCVertexAttribFlag_Position);

    kmGLPushMatrix();

    HelloWorld::mundo->DrawDebugData();

    kmGLPopMatrix();

}

Pronto. Acabamos de adicionar o debug draw para que possamos visualizar os objetos rígidos inclusos no mundo do Box2D. Apresentei uma explicação mais detalhada sobre o debug draw nesse tutorial. Se você não se lembra como ele funciona, dê uma olhada lá.

 

Adicionando a movimentação na bolinha de aço

Agora vamos adicionar uma bolinha como um objeto rígido no Box2D e vamos fazê-la andar na tela conforme a angulação do aparelho. No tutorial passado eu expliquei como funciona a física por trás dessa movimentação. Se você não lembra, aqui vem uma recapitulação.

Estamos simulando a presença da bolinha na superfície da tela do aparelho. Na primeira parte da Figura 1, temos uma certa angulação do aparelho em relação ao chão, que nesse caso é igual a 30 graus. Na segunda parte, foi adicionada a bolinha (verde) sobre o aparelho. Na terceira parte, foi decomposta a força de gravidade que é exercida sobre a bolinha de aço em outras duas forças: uma paralela (verde) e outra perpendicular (laranja) à superfície do celular. A força laranja é desconsiderada, pois não ocasiona movimentação alguma na bolinha de aço, somente a força verde é que gera a movimentação na bolinha. Essa força pode ser calculada pela fórmula mostrada na quarta parte da Figura 1.

Figura 1 - Força aplicada na bolinha de aço

Figura 1 – Força aplicada na bolinha de aço

A força verde é calculada e aplicada sobre o corpo rígido que representa a bolinha de aço, esse existente no mundo do Box2D. Dando continuidade a edição do código, abra o arquivo “HelloWorldScene.h” e adicione as seguintes linhas de código:

b2Body* bolinha;

virtual void didAccelerate(cocos2d::CCAcceleration *pAccelerationValue);

void atualiza(float dt);

logo abaixo dessa (adicionada anteriormente nesse tutorial):

b2World* mundo;

Já fizemos todas as modificações necessárias nesse arquivo. Agora abra o aquivo “HelloWorldScene.cpp” e adicione as seguintes linhas de código:

b2BodyDef definicaoBolinha;

definicaoBolinha.type = b2_dynamicBody;

definicaoBolinha.position.Set((size.width/2)/PTM_RATIO,(size.height/2)/PTM_RATIO);

HelloWorld::bolinha = HelloWorld::mundo->CreateBody(&definicaoBolinha);

b2CircleShape geometriaBolinha;

geometriaBolinha.m_radius = 0.5;

b2FixtureDef cascaBolinha;

cascaBolinha.shape = &geometriaBolinha;

cascaBolinha.density = 1.0;

HelloWorld::bolinha->CreateFixture(&cascaBolinha);

setAccelerometerEnabled(true);

schedule(schedule_selector(HelloWorld::atualiza));

abaixo dessa (adicionada anteriormente nesse tutorial):

addChild(HelloWorld::debugDrawLayer,9999);

Ainda no mesmo arquivo, adicione ao final as seguintes linhas de código:

void HelloWorld::didAccelerate(CCAcceleration *pAccelerationValue) {

    float g = 9.78*HelloWorld::bolinha->GetMass();

    b2Vec2 f;

    f.Set(g*cos((M_PI/2)*(1 – pAccelerationValue->x)),g*cos((M_PI/2)*(1 – pAccelerationValue->y)));

    HelloWorld::bolinha->ApplyForceToCenter(f);

}

void HelloWorld::atualiza(float dt) {

    HelloWorld::mundo->Step(dt,3,2);

}

Agora a funcionalidade de movimentação da bolinha já está implementada. Mas … o que fizemos no código acima? Primeiramente adicionamos um objeto rígido circular exatamente no centro da tela do aparelho. Esse objeto representa a bolinha de aço que andará pela tela do celular de acordo com a angulação do aparelho em relação ao chão. Além disso, fizemos com que o método “atualiza” seja chamado constantemente para atualizar a posição da bolinha na tela. Para finalizar, acionamos os acelerômetros do celular e fizemos a bolinha andar na tela. Vimos melhor como utilizar os acelerômetros do celular nesse tutorial.

A cada mudança de angulação do aparelho, o método “didAccelerate” é chamado. Isso significa que, a cada mudança de angulação, nós calculamos a força “f” no eixo X e no eixo Y. Perceba no mesmo método que inicialmente é calculada a força “g”, ilustrada também na Figura 1. Logo após, calculamos “f” para X e “f” para Y por meio da multiplicação pelo cosseno do ângulo, esse também mostrado na Figura 1. Porém, o ângulo dado pelo acelerômetro varia de +1 até -1, ao invés de variar de 90 até -90 graus. Por isso existe a multiplicação pelo valor da metade do número PI (o cosseno é calculado com base em ângulos descritos em radianos). Utilizando um pouco de matemática vocês podem perceber que a fórmula mostrada na Figura 1 está perfeitamente aplicada no código. Após calcularmos “f” para X e para Y, nós aplicamos a força calculada exatamente no centro do corpo rígido que representa a bolinha de aço. Isso faz com que ela ande de acordo com a angulação do aparelho em relação ao chão. A Figura 2 mostra o objeto que representa a bolinha de aço sendo equilibrado no centro da tela. Legal, né? =]

Figura 2 - Bolinha sendo equilibrada

Figura 2 – Bolinha sendo equilibrada

Vimos nesse tutorial como adicionar a funcionalidade de movimentação na bolinha de aço. Apresentei para vocês a física por trás da movimentação, baseada na angulação do aparelho, e como utilizar os acelerômetros para isso. No próximo tutorial iniciaremos a parte de desenho do mundo, ou seja, vamos fazer um labirinto para o jogo.
Por hoje é isso pessoal, um grande abraço. []

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