Como calcular colisão entre círculos

Ultimamente eu tenho trabalhado num joguinho de tiro top down em rede, em que os personagens são nada mais nada menos que círculos. Como não tenho muito tempo livre, e o pouco tempo que tenho divido entre vários projetos malucos diferentes (quem sabe um dia falo deles aqui), este provavelmente vai demorar muito tempo pra ficar pronto.

Jogo de tiro topdown multiplayer sem nome, com gráficos hiper-realistas.

A moral da história é que pra implementar a parte do tiro no jogo (lembrando que a bala é uma bola, assim como o jogador), precisei descobrir como detectar a colisão entre dois círculos. Depois de quebrar a cabeça por algum tempo, resolvi dar uma pesquisada na internet e fiquei impressionado com a simplicidade da solução.

Vejamos o exemplos abaixo:

Dois círculos parcialmente sobrepostos em um plano cartesiano.

Aqui temos dois círculos num plano bidimensional. Lembrando que a coordenada y costuma “subir pra baixo” em sistemas de coordenadas de engines de jogos, canvas, etc. Ou seja, quanto maior o valor y, mais para baixo na tela o elemento fica posicionado, o que é o oposto do que acontece no plano cartesiano que utilizamos para desenhar gráficos de funções.

O centro do círculo 1 está na posição (3,3) do plano, e seu raio é igual a 2. O centro do círculo 2 está na posição (6,5) e seu raio é igual 3. Mesmo nessa imagem torta é possível perceber que elas estão colidindo (leia-se, se sobrepondo), agora precisamos fazer com que o computador saiba disso também.

Calculando as distâncias vertical e horizontal

O primeiro passo para detectar esse tipo de colisão é calcular a distância entre os centros dos dois círculos. Para isso, primeiro precisamos calcular a distância horizontal (dh) e vertical (dv) entre os centros deles. Isso é muito simples:

dh = x2-x1
dv = y2-y1

A distância horizontal é a diferença entre a coordenada x dos centros de cada círculo. Já a distância vertical é a diferença entre a coordenada y dos mesmos. No nosso caso, dh = 6 -3 = 3, e dv = 5-3 = 2.

Talvez você tenha percebido que é possível que dh ou dv sejam números negativos, dependendo da posição dos círculos, e não faz muito sentido falar em distâncias negativas, então o mais apropriado seria calcular o módulo (o valor absoluto) da subtração de uma coordenada pela outra. Mas para os nossos objetivos, isso não é necessário, e você verá o motivo daqui há pouco.

Gráfico demonstrando a colisão entre dois círculos.

Perceba que fazendo um tracejado com o valor das distâncias vertical e horizontal a partir dos centros dos círculos obtemos um ângulo reto. Para que os centros dos dois círculos se toquem, basta que uma delas se mova 3 pontos para um lado e 2 pontos para cima ou para baixo (dependendo de qual seja a esfera que se move).

Calculando a distância euclidiana entre os dois pontos

Para calcular a distância propriamente dita, isto é, a distância euclidiana no plano bidimensional entre esses dois pontos, precisamos descobrir o valor da diagonal formada pelos lados que formam esse ângulo.

Colisão entre dois círculos

Se depois de ver a imagem, seu coração bateu mais forte e você quase pulou da cadeira gritando “PITÁGORAS!”, você acertou! A distância (d) entre o centro dos dois círculos corresponde à hipotenusa (h) do triângulo retângulo formado ligando os centros dos círculos ao seu “ponto de encontro”. As distâncias vertical e horizontal são então os catetos desse triângulo. E sabemos que h2=a2+b2(o quadrado da hipotenusa é igual à soma dos quadrados dos catetos). Então, para calcular a distância, d2 = dv2+dh2. Em nosso caso,

d2 = 22+32
= 4 + 9
= 13

Logo:

d = √13 ≈ 3,6.

Como as distâncias vertical e horizontal são elevadas ao quadrado, o sinal delas não importa, pois o resultado será sempre positivo.

Finalmente calculando a colisão entre dois círculos

Agora que temos a distância do centro de um círculo à outro, para sabermos se eles estão se tocando ou se sobrepondo, precisamos apenas somar o valor dos raios dos dois círculos. Se esse valor for maior que a distância entre os centros, então eles estão se sobrepondo, se os dois valores forem iguais, então os círculos estão apenas se tocando, e se o valor for menor, então eles não estão colidindo.

No nosso caso, como já imaginávamos, os dois círculos estão se sobrepondo, porque R1+R2 = 5 e d = 3,6.

Para finalizar, trago um exemplo em Python de como podemos implementar um algoritmo de detecção de colisão entre círculos. Supondo a existência de uma classe do tipo Circulo, com atributos x, y e rad (raio):

import math
def check_collision(circulo1, circulo2):
    dist_x = circulo1.x - circulo2.x
    dist_y = circulo1.y - circulo2.y
    distance = math.sqrt((dist_x * dist_x) + (dist_y * dist_y))
    if distance <= circulo.rad + circulo.rad: 
    #tem uma colisão!
        return True
    return False

Espero que tenha gostado do texto, até a próxima!

Related Posts

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *