pedrocacique

Colisões - parte 2

27 de maio de 2016

Olá pessoas!

Na Parte 1 deste tutorial, começamos a desenvolver a lógica para um jogo simples de plataforma, para que possamos estudar as colisões entre objetos.

Nosso intuito é desenvolver um pequeno game como este:

See the Pen Platform Player Movement by Pedro Cacique (@phcacique) on CodePen.

Até este ponto, temos o movimento do personagem e a ação da gravidade sendo parada apenas ao chegar na parte inferior do canvas.

Colisão da base

O primeiro passo é criarmos um método que detecta a colisão entre dois objetos. Considere os seguintes atributos:

Um método simples para detecção de colisão entre dois objetos é verificar se eles estão em uma mesma área do espaço na tela. Na imagem acima, o objeto vermelho está na mesma região horizontal que o objeto cinza (ambos estão entre as linhas a e b). Entretanto, não há colisão entre eles, pois não estão na mesma área vertical (um está acima da linha c e o outro está abaixo).

Para detectar a colisão, vamos considerar os três pontos destacados no objeto vermelho. Vamos verificar se ao menos um dos três pontos está na região exata do segundo objeto. Assim, saberemos se há colisão.

Para a colisão com a plataforma, precisamos comparar apenas se a base do player (pontos B e C) estão na região desejada. Sabe-se que o ponto A é equivalente à origem do objeto, logo: A = (player.x, player.y). O ponto B tem a mesma coordenada X, mas deslocado em Y em uma distância equivalente à altura do player, logo: B = (player.x, player.y+player.height)

De forma análoga, temos que C = (player.x+player.width, player.y+player.height)

Para a colisão da base do jogador com a plataforma, precisamos verificar se:

  • No eixo vertical, a coordenada Y do ponto B (ou C) está entre as linhas c e d;
  • No eixo horizontal, a coordenada X do ponto B (ou C) está entre as linhas a e b;

Caso ocorra um desses casos, consideramos que há colisão da base do player com a plataforma. Criamos então uma função chamada detectBaseCollision(obj1, obj2), que recebe dois objetos e verifica se há colisão entre eles.

Criamos um array chamado platform, que conterá todas as plataformas do jogo. No método onload, inicializamos este vetor com todas as plataformas que queremos. Neste caso, coloquei apenas o piso, logo abaixo. Criamos o objeto e adicionamos ao vetor.

no método de update, verificamos se há colisão. Caso haja, dizemos que a posição y do player é igual ao valor imediatamente acima da plataforma. Caso contrário, a gravidade pode agir normalmente. Criamos ainda uma variável booleana chamada isOnGround, para nos ajudar mais adiante no método de pulo.

See the Pen Platform mechanics - part4 by Pedro Cacique (@phcacique) on CodePen.

Observe que colocamos a plataforma em um array, e o percorremos no método update para verificar a colisão e depois novamente no método draw, para desenhar as plataformas.

Para considerar a colisão completa do objeto, devemos levar em consideração não apenas os pontos B e C, mas também o ponto A. Veja como pode ficar um segundo método que detecta a colisão completa:

Este método pode ser usado, por exemplo, para verificar a colisão com outros objetos, como coleta de itens para incremento dos pontos do jogador, ou ainda com inimigos, para que haja dano. O processo é semelhante ao da verificação com a plataforma: cria-se um vetor de itens coletáveis e faz-se a verificação com todos eles no método update.

Pulo

Para a lógica do pulo, vamos alterar os métodos de evento do teclado, para identificarmos quando uma determinada tecla é pressionada. Aqui usaremos a tecla SHIFT, de código 16, para determinar quando pular. Sempre que a tecla for pressionada, a variável isShift receberá o valor true.

No método update, vamos verificar o seu valor. Caso seja verdadeiro, chamaremos o método jump(), que criaremos a seguir. Também verificamos se o player não está na colidindo com a plataforma. Caso isso ocorra (pulando ou caindo), atribuímos o valor true à variável isJumping (que será o controle do pulo).

O próximo passo é estabelecer o método do pulo, que deverá aplicar uma força contrária à gravidade até que uma altura máxima seja atingida.

No método jump(), o primeiro teste que fazemos é se o player não está pulando atualmente. Caso não esteja, acrescentamos à posição Y do jogador, o valor negativo da máxima altura permitida para o pulo (negativo, pois o eixo Y aumenta para baixo).

A partir daí, a gravidade voltará a fazer efeito. Caso ela seja menor que zero, vamos aumentar gradativamente o seu valor, até que normalize (linhas 9 a 18).

Por fim, transferimos para este ponto a verificação da colisão com as plataformas (linhas 20 a 28).

Veja como ficou o código até este ponto:

See the Pen Platform game mechanics by Pedro Cacique (@phcacique) on CodePen.

Dica: Na janela acima, clique em JS para ver o código.

Agora você!

Crie os elementos coletáveis para o nosso jogo e mais plataformas no espaço. A seguir, a minha implementação desta tarefa, para que compare com a sua solução:

See the Pen Platform Player Movement by Pedro Cacique (@phcacique) on CodePen.

Espero que tenham aproeitado o tutorial e que tenha sido claro o suficiente. Caso ainda tenha dúvidas, não hesite em entrar em contato.

Até a próxima!