85
4.4. Controle o herói pelo teclado e veja sua animação
Casa do Código
No próximo capítulo, falarei sobre detecção de colisões, um aspecto fun-
damental da grande maioria dos jogos. Seja para golpear um inimigo, ou para coletar argolas, a interação do sprite do personagem com os outros (inimigos, blocos, plataformas) se dará através da colisão entre as áreas que ocupam na tela.
Figura 4.5: Sprite controlado pelo teclado
86
Capítulo 5
Detecção de colisões
Chegou a hora de detectarmos colisões, ou seja, saber quando um elemento
toca outro na tela. Isso tornará possível saber quando um inimigo atacou o herói ou foi atingido, ou quando o herói coletou um item. A partir de colisões, disparamos inúmeros acontecimentos que são a base dos jogos, em especial
os de aventura e ação.
5.1
Colisão entre retângulos
Um dos métodos mais simples para detectar colisões é criar uma caixa delim-itadora (bounding box) ao redor de cada sprite e verificar a intersecção entre os retângulos:
5.1. Colisão entre retângulos
Casa do Código
Figura 5.1: Sprites colidindo: retângulos (bounding boxes) apresentam intersecção
Figura 5.2: Sem intersecção, não há colisão
Mas, quem dera que tudo fosse perfeito! Isso pode nos trazer alguns prob-
lemas devido às áreas vazias dos sprites:
88
Casa do Código
Capítulo 5. Detecção de colisões
Figura 5.3: Retângulos intersectando sem haver a colisão real desejada. O
dragão colide com uma área vazia do sprite do herói.
A abordagem que adotaremos para resolver este problema é a seguinte:
cada sprite poderá ter vários retângulos de colisão, demarcando suas principais áreas:
Figura 5.4: Definindo vários bounding boxes para objetos irregulares
Nosso controle agora ficará muito mais preciso e com qualidade bastante
satisfatória
para a maioria dos casos. Colisão em pequenas áreas vazias serão imperceptíveis devido à velocidade com que ocorrem as animações (e sempre poderemos definir mais um retângulo onde acharmos necessário).
Ganhamos também um bônus: na figura 5.4, temos uma ação de ataque (o
herói tentando socar o dragão). Podemos diferenciar quem conseguiu atacar quem através de qual retângulo do herói colidiu com o retângulo do dragão.
89
5.2. Teste da classe Colisor
Casa do Código
Interseção de retângulos
Figura 5.5: Intersecção de retângulos
Pela geometria, dois retângulos se intersectam se:
(x1 + largura1) > x2 E
x1 < (x2 + largura2) E
(y1 + altura1) > y2 E
y1 < (y2 + altura2)
No próximo tópico, iniciaremos o desenvolvimento de uma classe que
aplica essas fórmulas para detectar colisões entre sprites.
5.2
Teste da classe Colisor
Iniciaremos o desenvolvimento da classe responsável por colidir objetos.
Como de costume, iniciaremos por um pequeno aplicativo de teste onde
definimos como queremos interagir com a classe.
90
Casa do Código
Capítulo 5. Detecção de colisões
Criaremos uma classe para essa nova funcionalidade. Começaremos
criando o aplicativo de teste, onde definimos de que forma queremos interagir com a classe Colisor:
rq tstst
P t
t
tttçã sõstt
srt srsrssrt
srt srssrt
s ss t t
s
srt
s s é qr trã s s trs
srt
t
No JavaScript, obtemos o canvas e seu context, e criamos algumas bolin-
has:
r s tttss
r tt sttt
r tt
r
r
r tt
91
5.2. Teste da classe Colisor
Casa do Código
r r
r
O próximo passo é criar o objeto Colisor e colocar nele os sprites:
r sr sr
srrt
srrt
Agora, façamos o loop de animação. Por enquanto, este loop será uma
simples função. Perceba que, a cada ciclo, apenas realizamos as tarefas que nossos loops já fazem e, em seguida, mandamos o colisor realizar seu processamento. O colisor se encarregará de enviar mensagens aos objetos que
colidirem.
rqsttrr
t r
t
ttrt st st
t s srts
tr
tr
s
sr
sr
Prssr sõs
srrssr
rqsttrr
92
Casa do Código
Capítulo 5. Detecção de colisões
5.3
A classe Colisor
A classe Colisor, como definimos antes, terá inicialmente 2 métodos:
novoSprite e processar. Manteremos um array de sprites, da mesma
forma que a classe Animacao:
t sr
tssrts
srrtt
rt tsrt
tssrtsssrt
rssr t
q rs rçã sã
O coração da classe é o método processar. Aqui, precisamos testar
quais sprites estão colidindo entre si. Faremos um algoritmo do tipo todos contra todos no array de sprites, usando dois loops for aninhados. Para
cada elemento no array (primeiro loop), é testada sua colisão contra todos os outros (segundo loop). Note que ainda estamos abstraindo a lógica de cálculo da colisão:
rssr t
r r tssrts
r r tssrts
ã r srt s
t
strr sã
tststrstssrts tssrts
O novo método testarColisao irá fazer mais um todos contra to-
dos, agora entre os retângulos do primeiro sprite e os do segundo. Lembre-se de que cada sprite poderá definir mais de um retângulo (figura 5.4). Dessa 93
5.3. A classe Colisor
Casa do Código
forma, criamos um label colisoes para podermos parar os dois loops logo
na primeira colisão entre retângulos detectada:
tstrs tsrt srt
tr s rtâs sã srt
r rts srtrtss
r rts srtrtss