Tutorial: Jogos em HTML5 – Parte 5: Adicionando Outros Elementos

No último tutorial, aprendemos a fazer o tratamento de colisão entre a bola e a raquete e também fizemos com que a bola não saia da área de jogo, a não ser pela parte inferior. Caso isto ocorra, o jogador perde o jogo.

Legal, agora falta só mais uma coisa: como o jogador ganha? Para isso, vamos aprender hoje a criar novos elementos de jogo, neste caso, os tijolos do Breakout. A função deles é serem destruídos pelo jogador e, quando todos os tijolos forem destruídos, o jogador vence.

Para podermos criar esse elemento, vamos utilizar todos os conhecimentos que nós vimos até agora.

 

Criando a Classe Tijolo

Vamos iniciar já definindo a classe Tijolo, que é bem semelhante a classe Raquete:

Classe Tijolo:
01 function Tijolo(x,y,largura,altura){
02   this.x = x;
03   this.y = y;
04   this.largura = largura;
05   this.altura = altura;
06 }

Os tijolos são retângulos que nem a raquete. Se o Javascript fosse uma linguagem Orientada a Objeto, poderíamos criar uma superclasse retângulo. Dessa forma, faríamos que as classes Tijolo e Raquete herdassem as características desta retângulo. Mas como não é, vamos repetir o código.

Agora, vamos definir a aparência dos tijolos: como o estilo da arte do jogo é algo mais preto e branco, vamos definir que os retângulos são pretos com a borda acizentada. Então, criaremos o método pintar para a nossa classe Tijolo:

Classe Tijolo:
01 function Tijolo(x,y,largura,altura){
02   this.x = x;
03   this.y = y;
04   this.largura = largura;
05   this.altura = altura;
06
07   this.pintar = function(){
08     contexto.fillRect(this.x,this.y,this.largura,this.altura);
09     contexto.fillStyle=”#555555″;
10     contexto.strokeRect(this.x,this.y,this.largura,this.altura);
11     contexto.fillStyle=”#000000″;
12   }
13
14 }

No código, desenhamos primeiro um retângulo totalmente cheio usando os atributos da classe (posição x, posição y, largura e altura). Depois, avisamos para mudar para a cor de código #555555 que é um cinza não tão claro, mas também não tão escuro  e, com esta cor, desenhamos um retângulo só com bordas. Isso gerará um retângulo preto com bordas cinzas. Para evitar que tudo vire cinza, fechamos o código retornando para a cor preta.

Vamos preparar para testar o nosso código. Primeiro, vamos adicionar nas definições globais, um vetor que guardará todos os tijolos. O código vai ficar assim:

Definições Globais:
01 var tijolos = new Array();
02 tijolos.push(new Tijolo(10,10,50,10));
03 tijolos.push(new Tijolo(62,10,50,10));
04 tijolos.push(new Tijolo(114,10,50,10));
05 tijolos.push(new Tijolo(166,10,50,10));
06 tijolos.push(new Tijolo(30,22,50,10));
07 tijolos.push(new Tijolo(82,22,50,10));
08 tijolos.push(new Tijolo(134,22,50,10));
09 tijolos.push(new Tijolo(186,22,50,10));

Aqui criamos a variável “tijolos” e criamos um vetor. Então, instanciamos oito tijolos no vetor. Cada tijolo, posicionado em uma posição (x,y) tendo a mesma largura (50) e altura (10). A quantidade de tijolos, posições e tamanho fica ao cargo do Level Designer, ou seja, você mudará apenas os parâmetros para refletir a disposição desejada.

Agora, antes de fechar, precisamos chamar o método pintar de cada tijolo. Nós definimos anteriormente que haveria uma função responsável para isso, que é a função pintar():

Função Pintar:
01 function pintar(){
02   contexto.clearRect(0,0,400,600);
03   jogador.pintar();
04   bola.pintar();
05
06   for(t in tijolos){
07     tijolos[t].pintar();
08   }
09
10 }

Aqui, a adição ocorre a partir da linha 6, onde usamos a forma alternativa do for do Javascript específico para vetores. É o equivalente ao “foreach“ de diversas outras linguagens. Então, esse trecho diz que para cada t (que é o índice do vetor) em tijolos, pinte na tela o que tiver na posição t de tijolos. Ou seja, ele executará o método pintar() para cada tijolo dentro do vetor. Se usou a mesma configuração dos tijolos, a imagem deve ficar semelhante a isto:

Tratamento de Colisão
Temos nossos tijolos, mas a bolinha ainda está passando direto por eles, sem reação nenhuma. Agora vem o que aprendemos no tutorial passado, sobre tratamento de colisão.

A principio, a detecção tem a mesma lógica que usamos para a colisão Raquete x Bola. Então, adicionaremos o seguinte método na classe Tijolo:

Classe Tijolo:
01 function Tijolo(x,y,largura,altura){
02   this.x = x;
03   this.y = y;
04   this.largura = largura;
05   this.altura = altura;
06
07   this.pintar = function(){
08  …
12   }
13
14   this.detectarColisaoTijoloxBola = function(){
15     var xMaisProximo = clamp(bola.x, this.x, (this.x+this.largura));
16     var yMaisProximo = clamp(bola.y, this.y, (this.y+this.altura));
17     var distanciaX = bola.x – xMaisProximo;
18     var distanciaY = bola.y – yMaisProximo;
19     var distancia = (distanciaX*distanciaX)+(distanciaY*distanciaY);
20     if (distancia < (bola.raio*bola.raio)){
21       if(bola.x>this.x && bola.x<(this.x+this.largura)){
22         bola.inverterY();
23       }else if(bola.y>this.y && bola.y<(this.y+this.altura)){
24         bola.inverterX();
25       }else{
26         bola.inverterY();
27         bola.inverterX();
28       }
29       return true;
30     }
31     return false;
32   }
33
34 }

Da linha 15 até 19, a lógica é a mesma usada na detecção Raquete x Bola, mudando apenas o que era raquete para tijolo (neste caso, representado pela palavra-chave “this”). Na Linha 20, temos a detecção, só que em vez de retornar, vamos aplicar a resposta aqui dentro. Na linha 21, vemos se a bola atingiu as partes inferiores ou superiores do tijolo. Se atingiu, o sentido Y da trajetória da bola será invertido. Na linha 23 fazemos a mesma verificação, só que para as laterais esquerda e direita, invertendo o sentido X da bola. Caso não bateu na parte de baixo, ou nas laterais, significa que bateu em um canto, cujo efeito é o sentido em que a bola está se invertendo completamente (mudança de direção tanto no eixo X quanto no eixo Y). Apesar de modificarmos aqui a parte física da bola, o método retorna o resultado da detecção, que é necessária para a nossa próxima parte.

Agora, basta nós adicionarmos a verificação no mainloop() e, caso ocorreu uma colisão, remover o tijolo da lista.

Função mainloop:
01 function mainloop(){
02   …
15
16
17   for(t in tijolos){
18      if(tijolos[t].detectarColisaoTijoloxBola()){
19        tijolos.splice(t,1);
20        if(tijolos.length==0){
21          estado=3;
22        }
23      }
24    }
25
26   pintar();
27 }

Aqui vamos utilizar a outra forma do “for” para percorrer o vetor tijolo. Para cada tijolo, será verificado se ocorreu uma colisão. Caso afirmativo, o tijolo em questão será excluído do vetor de tijolos (linha 19). O método utilizado é o splice(), que recebe como parâmetro o índice a ser excluído (índice t) e a quantidade de itens a serem excluídos a partir do índice (1 item). Uma curiosidade é que neste método de exclusão, quando um elemento é destruído, torna o jogo mais eficiente conforme o usuário vai avançando no jogo. Isso gerou um bug no jogo Space Invaders, que acabou se tornando um mecanismo padrão do jogo: a das naves em jogo que aceleram o movimento a medida em que elas fossem destruídas.

Continuando, se houver exclusão de tijolos, então testamos a condição de vitória que é a seguinte: se a quantidade de tijolos for igual a 0, então o jogo entra no estado de vitória. Agora, vocês podem testar jogo e quando a bola bater nos tijolos, eles devem desaparecer.

Considerações Finais
Este tutorial teve como objetivo principal revisar e mostrar tudo que foi ensinado até agora através da adição do elemento final do jogo: os tijolos. Vimos também algumas funções que podem ser utilizadas pelo Javascript para percorrer os vetores, assim como podemos instanciar a mesma classe diversas vezes.

Nos próximos tutoriais, vamos fazer o acabamento do jogo, adicionando outros elementos que não são vitais ao jogo, mas que podem torná-lo mais interessantes. Portanto, não percam o nosso próximo tutorial.

Thalisson Christiano de Almeida

Thalisson Christiano de Almeida

Formado em Ciência da Computação (UDESC). Foi Programador da Céu Games e professor do Técnico em Informática do SENAI-SC. Atualmente, trabalha na empresa By Seven. Já foi jogador de xadrez e praticou kung-fu, ambos por 4 anos. Hoje é praticante do Jiu-jitsu, esperando que não fique nos 4 anos. Não tem preferência de tipos de jogos em especifico, variando desde jogos casuais de Facebook até jogos mais hardcore.

Send this to a friend