Colisões entre círculos
Neste post vamos investigar o conceito de colisões. Para visualizar o que vamos implementar, utilizarei o Pyxel.
Colisão
No contexto de jogos digitais, as regras de colisão definem os limites dos mapas, por onde os personagens podem se mover (plataformas, paredes, etc.). Se o jogo possuir o ideia de tiro, é necessário também detectar quando personagens e o terreno são atingidos pelos tiros.
Nesse sentido, o controle de colisão tem um papel muito importante dentro de um jogo. A maioria dos engines possuem funcionalidades especificas para o tratamento de colisões, facilitando a vida do programador. No caso do Pyxel não temos tais facilidades, temos que implementar todo o código responsável por detectar as colisões entre os elementos do jogo.
Colisão entre círculos
A colisão entre círculos é a mais simples, pois um círculo é uma figura uniforme, tendo uma distância única em relação ao centro, o raio. Desta forma, para detectar se dois círculos colidiram basta medir a distância entre os dois elementos para os quais desejamos saber se houve colisão e comparar com a soma de seus raios. Se essa distância é menor que a soma dos raios das duas figuras temos uma colisão. Vamos ver como podermos implementar isso usando Pyxel. Ele não trás nenhuma funcionalidade para ajudar nessa tarefa, vamos usá-lo apenas para ter algo visual para observar.
O código
O código abaixo implementa a detecção de colisão entre dois círculos. Neste exemplo, um dos círculos está fixo e o usuário pode mover um segundo círculo com o mouse.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import pyxel
import math
class Circulos:
def __init__(self):
pyxel.init(200, 200)
self.x = 50
self.y = 50
self.raio1 = 20
self.raio2 = 10
self.colidiu = False
pyxel.run(self.update, self.draw)
def update(self):
self.colidiu = self.detectar_colisao(self.x, self.y, self.raio1, pyxel.mouse_x, pyxel.mouse_y, self.raio2)
def draw(self):
pyxel.cls(6)
pyxel.circ(self.x, self.y, self.raio1, 5)
cor = 15
if self.colidiu:
cor = 8
pyxel.circ(pyxel.mouse_x, pyxel.mouse_y, self.raio2, cor)
def detectar_colisao(self, x1, y1, r1, x2, y2, r2):
distancia = math.sqrt((x1 - x2)**2 + (y1 - y2)**2)
if distancia <= r1 + r2:
return True
else:
return False
Circulos()
No construtor da classe Circulos
temos a definição dos atributos x
e y
, que compõem a coordenada do círculo estático mencionado anteriormente. O atributo raio1
é o raio deste círculo estático, e raio2
é o raio do círculo que você pode mover pela tela. Criamos mais um atributo para armazenar a informação e que os dois elementos estão em situação de colisão entre si. Essa não é a melhor estratégia se você tiver vários elementos para verificar a colisão, mas como temos apenas dois elementos é suficiente.
A função draw
vai pintar o círculo menor com uma cor diferente caso eles estejam em situação de colisão. A linha 19 pinta o círculo estático. Define-se a cor 15 de antemão, e caso exista a colisão ela é alterada para 8. A linha 25 pinta o círculo com a cor correta de acordo com o estado do elemento.
A função update
faz apenas delegar a detecção da colisão para a função detectar_colisao
, que como o próprio nome diz, fará o cálculo da distância entre os dois centros dos círculos. A função precisa saber onde está o primeiro círculo (self.x
e self.y
) e seu raio (self.raio1
), bem como a posição do mouse (pyxel.mouse_x
e pyxel.mouse_y
) e o raio do círculo móvel (self.raio2
). O cálculo é feito utilizando-se o Teorema de Pitágoras, onde a distância entre os dois pontos é hipotenusa (linha 29). Se a distância for menor ou igual à soma dos raios, as figuras colidiram (linha 30).
Leave a comment