Tutorial: Criando um jogo ao estilo Arkanoid – Parte 4: A bola rebatendo na pá

A principal funcionalidade do jogo Arkanoid é a propriedade que a pá tem de rebater a bola.

Por enquanto, temos apenas a bola andando e colidindo com os lados da tela do aparelho.

No final desse tutorial, teremos a primeira versão jogável do nosso game, com a pá rebatendo a bola de fogo.

No tutorial anterior eu mostrei a vocês como adicionar a movimentação na bola de fogo. Vimos que foi necessário criar um vetor que aponta a direção em que a bola está andando e a fizemos andar com a aplicação do conceito da física do movimento retilíneo uniforme. Nesse tutorial eu mostrarei a vocês como pode ser implementada a principal funcionalidade do jogo Arkanoid que o deixa tão viciante: a propriedade de parede que a pá tem.

Iniciaremos a implementação modificando uma parte do que programamos no último tutorial. Caso você não o fez, acesse aqui e o finalize para darmos continuidade. Tiraremos agora a propriedade de parede da parte inferior do aparelho. A partir de agora ali será um buraco que a bola de fogo não poderá cair. Para isso, apague as seguintes linhas de código do arquivo “HelloWorldScene.cpp”:

if((HelloWorld::bola->getPositionY()+HelloWorld::bola->boundingBox().size.height/2>=size.height&&HelloWorld::vetorDirecao[1]>0) ||

  (HelloWorld::bola->getPositionY()-HelloWorld::bola->boundingBox().size.height/2<=0&&HelloWorld::vetorDirecao[1]<0))

Nesse mesmo lugar, onde foram excluídas as linhas de código, adicione a seguinte linha de código:

if((HelloWorld::bola->getPositionY()+HelloWorld::bola->boundingBox().size.height/2>=size.height&&HelloWorld::vetorDirecao[1]>0))

Essa mudança faz com que a bola rebata apenas nas laterais e na parte superior da tela. A partir de agora, a parte inferior da tela não rebate mais a bola de fogo.

Agora, adicione as seguintes linhas de código:

if(HelloWorld::bola->getPositionY()-HelloWorld::bola->boundingBox().size.height/2<=0&&HelloWorld::vetorDirecao[1]<0) {

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

    HelloWorld::vetorDirecao[0] = sqrt(2)/2;

    HelloWorld::vetorDirecao[1] = sqrt(2)/2;

}

if(HelloWorld::pa->boundingBox().intersectsRect(HelloWorld::bola->boundingBox())) {

    float tamanho;

    HelloWorld::vetorDirecao[0] = HelloWorld::bola->getPositionX() – HelloWorld::pa->getPositionX();

    HelloWorld::vetorDirecao[1] = HelloWorld::bola->getPositionY() – HelloWorld::pa->getPositionY();

    tamanho = sqrt(HelloWorld::vetorDirecao[0]*HelloWorld::vetorDirecao[0] + HelloWorld::vetorDirecao[1]*HelloWorld::vetorDirecao[1]);

    HelloWorld::vetorDirecao[0] = HelloWorld::vetorDirecao[0]/tamanho;

    HelloWorld::vetorDirecao[1] = HelloWorld::vetorDirecao[1]/tamanho;

}

logo abaixo dessas linhas (após a modificação já realizada):

if((HelloWorld::bola->getPositionY()+HelloWorld::bola->boundingBox().size.height/2>=size.height&&HelloWorld::vetorDirecao[1]>0))

    HelloWorld::vetorDirecao[1] = -HelloWorld::vetorDirecao[1];

O que fizemos? Note que essas linhas de código foram adicionadas dentro do método “moveBola”. Dessa forma, a cada quadro mostrado na tela, é verificado se a bola não saiu dela pela parte inferior. Caso isso aconteça, o jogo reposiciona a bola no centro e a faz andar na direção diagonal superior direita. Isso foi feito para que o jogo seja reiniciado após a bola de fogo sair da tela. Percebam também que essas últimas linhas de código implementam a funcionalidade que tanto queremos nesse tutorial. Caso haja intersecção entre a bola e a pá, então há colisão. Havendo colisão, é calculado o novo vetor direção e a bola passa a seguir um novo caminho. Esse vetor aponta na direção formada entre o centro da pá e o centro da bola. Calcular essa direção sempre foi o padrão de jogos ao estilo Arkanoid porque é a única forma do jogador poder mudar a direção inicial da bola.

Figura 1 - Vetor direção recalculado

Figura 1 – Vetor direção recalculado

Matematicamente, o vetor direção é encontrado subtraindo os valores de coordenadas x e y do centro da bola de fogo dos valores de coordenadas x e y do centro da pá. Fazendo isso, teremos o vetor mostrado na Figura 1. Porém, como precisamos que esse vetor tenha o tamanho igual a 1, então dividimos cada coordenada pelo seu tamanho atual, esse último calculado pela raiz quadrada dos quadrados de suas coordenadas. Assim, temos um vetor de tamanho igual a 1 e que aponta para o centro da bola de fogo.

Vimos nesse tutorial como implementar a funcionalidade de parede na pá. Para isso, fizemos com que o jogo reinicie caso a bola de fogo saia pela parte inferior da tela e fizemos com que a pá rebatesse a bola de fogo. Para isso, toda vez que a bola colide com a pá é recalculado o vetor direção da bola. Apresentei como esse vetor é recalculado matematicamente. No próximo tutorial adicionaremos várias caixas amarelas e incluiremos o objetivo principal do jogo: destruir essas caixas.

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.