colisão círculo-círculo

Eu vou desenvolver um jogo de bola 2-d onde duas bolas (círculos) colidem. Agora eu tenho o problema de determinar o ponto de colisão (na verdade, determinar se eles estão colidindo no eixo x / eixo-y). Eu tenho uma idéia de que quando a diferença entre a coordenada y de 2 bolas é maior que a diferença de coordenadas x, elas colidem em seu eixo y, caso contrário, elas colidem em seu eixo x. Minha ideia é correta? Eu implementei essa coisa nos meus jogos. Normalmente funciona bem, mas às vezes falha. Alguém pode me dizer se a minha ideia está certa? Se não, então por que, e é de alguma maneira melhor?

Por colisão no eixo x, quero dizer o 1º, 4º, 5º ou 8º octante do círculo, o eixo y significa o 2º, 3º, 6º ou 7º octante do círculo.

Desde já, obrigado!

    Colisão entre círculos é fácil. Imagine que há dois círculos:

    • C1 com centro (x1, y1) e raio r1;
    • C2 com centro (x2, y2) e raio r2.

    Imagine que haja uma linha entre esses dois pontos centrais. A distância dos pontos centrais até a borda de cada círculo é, por definição, igual aos seus respectivos raios. Assim:

    • se as bordas dos círculos se tocam, a distância entre os centros é r1 + r2;
    • qualquer distância maior e os círculos não tocam ou colidem; e
    • menos e depois colidir.

    Então você pode detectar colisão se:

    (x2-x1)^2 + (y1-y2)^2 < = (r1+r2)^2 

    ou seja, a distância entre os pontos centrais é menor que a sum dos raios.

    O mesmo princípio pode ser aplicado para detectar colisões entre esferas em três dimensões.

    Edit: se você quiser calcular o ponto de colisão, alguma trigonometria básica pode fazer isso. Você tem um triângulo:

      (x1,y1) |\ | \ | \ sqrt((x2-x1)^2 + (y2-y1)^2) = r1+r2 |y2-y1| | \ | \ | X \ (x1,y2) +------+ (x2,y2) |x2-x1| 

    As expressões |x2-x1| e |y2-y1| são valores absolutos. Então, para o ângulo X:

      |y2 - y1| sin X = ------- r1 + r2 |x2 - x1| cos X = ------- r1 + r2 |y2 - y1| tan X = ------- |x2 - x1| 

    Depois de ter o ângulo, você pode calcular o ponto de intersecção, aplicando-os a um novo triângulo:

      + |\ | \ b | \ r2 | \ | X \ +-----+ a 

    Onde:

      a cos X = -- r2 

    assim

     a = r2 cos X 

    Das fórmulas anteriores:

      |x2 - x1| a = r2 ------- r1 + r2 

    Depois de ter aeb você pode calcular o ponto de colisão em termos de (x2, y2) compensado por (a, b) conforme apropriado. Você não precisa nem calcular senos, cossenos ou senos inversos ou cossenos para isso. Ou qualquer raiz quadrada para esse assunto. Então é rápido

    Mas se você não precisa de um ângulo exato ou ponto de colisão e apenas quer o oitante, você pode otimizar ainda mais, entendendo algo sobre tangentes, que é:

    • 0 < = tan X <= 1 para 0 <= X <= 45 graus;
    • tan X> = 1 para 45 < = X <= 90
    • 0> = tan X> = -1 para 0> = X => -45;
    • tan X < = -1 para -45> = X => -90; e
    • tan X = tan (X + 180) = tan (X-180).

    Essas faixas de quatro graus correspondem a quatro octants do cirlce. Os outros quatro são compensados ​​por 180 graus. Como demonstrado acima, a tangente pode ser calculada simplesmente como:

      |y2 - y1| tan X = ------- |x2 - x1| 

    Perca os valores absolutos e esta relação lhe dirá em qual dos quatro octantes a colisão se encontra (pelas faixas tangentes acima). Para calcular o octant exato apenas compare x1 e x2 para determinar qual é o mais à esquerda.

    O octant da colisão no outro single é compensado (o octant 1 em C1 significa o octant 5 em C2, 2 e 6, 3 e 7, 4 e 8, etc.).

    Como diz Cletus, você quer usar a sum dos raios das duas bolas. Você quer calcular a distância total entre os centros das bolas, como segue:

     Ball 1: center: p1=(x1,y1) radius: r1 Ball 2: center: p2=(x2,y2) radius: r2 collision distance: R= r1 + r2 actual distance: r12= sqrt( (x2-x1)^2 + (y2-y2)^2 ) 

    Uma colisão acontecerá sempre que (r12

     collision vector: d12= (x2-x1,y2-y1) = (dx,dy) actual distance: r12= sqrt( dx*dx + dy*dy ) 

    Note que você já calculou dx e dy acima quando calculou a distância real, então você pode também rastreá-los para propósitos como este. Você pode usar este vetor de colisão para determinar a nova velocidade das bolas – você vai acabar escalando o vetor de colisão por alguns fatores, e adicionando isso às velocidades antigas … mas, para voltar à colisão real ponto:

     collision point: pcollision= ( (x1*r2+x2*r1)/(r1+r2), (y1*r2+y2*r1)/(r1+r2) ) 

    Para descobrir como encontrar a nova velocidade das bolas (e, em geral, fazer mais sentido para toda a situação), você provavelmente deve encontrar um livro de física do ensino médio, ou o equivalente. Infelizmente, eu não sei de um bom tutorial na web – sugestões, alguém?

    Ah, e se ainda quiser continuar com o eixo x / y, acho que você acertou em:

     if( abs(dx) > abs(dy) ) then { x-axis } else { y-axis } 

    Quanto ao motivo pelo qual ele pode falhar, é difícil dizer sem mais informações, mas você pode ter um problema em suas bolas se moverem muito rápido e passarem uma para a outra em um único intervalo de tempo. Existem maneiras de corrigir esse problema, mas a maneira mais simples é garantir que elas não se movam muito rápido …

    Este site explica a física , deriva o algoritmo e fornece código para colisões de bolas 2D.

    Calcular o oitante após esta function calcula o seguinte: posição do ponto de colisão em relação ao centro de massa do corpo a; posição do ponto de colisão em relação ao centro de massa do corpo a

     /** This function calulates the velocities after a 2D collision vaf, vbf, waf and wbf from information about the colliding bodies @param double e coefficient of restitution which depends on the nature of the two colliding materials @param double ma total mass of body a @param double mb total mass of body b @param double Ia inertia for body a. @param double Ib inertia for body b. @param vector ra position of collision point relative to centre of mass of body a in absolute coordinates (if this is known in local body coordinates it must be converted before this is called). @param vector rb position of collision point relative to centre of mass of body b in absolute coordinates (if this is known in local body coordinates it must be converted before this is called). @param vector n normal to collision point, the line along which the impulse acts. @param vector vai initial velocity of centre of mass on object a @param vector vbi initial velocity of centre of mass on object b @param vector wai initial angular velocity of object a @param vector wbi initial angular velocity of object b @param vector vaf final velocity of centre of mass on object a @param vector vbf final velocity of centre of mass on object a @param vector waf final angular velocity of object a @param vector wbf final angular velocity of object b */ CollisionResponce(double e,double ma,double mb,matrix Ia,matrix Ib,vector ra,vector rb,vector n, vector vai, vector vbi, vector wai, vector wbi, vector vaf, vector vbf, vector waf, vector wbf) { double k=1/(ma*ma)+ 2/(ma*mb) +1/(mb*mb) - ra.x*ra.x/(ma*Ia) - rb.x*rb.x/(ma*Ib) - ra.y*ra.y/(ma*Ia) - ra.y*ra.y/(mb*Ia) - ra.x*ra.x/(mb*Ia) - rb.x*rb.x/(mb*Ib) - rb.y*rb.y/(ma*Ib) - rb.y*rb.y/(mb*Ib) + ra.y*ra.y*rb.x*rb.x/(Ia*Ib) + ra.x*ra.x*rb.y*rb.y/(Ia*Ib) - 2*ra.x*ra.y*rb.x*rb.y/(Ia*Ib); double Jx = (e+1)/k * (Vai.x - Vbi.x)( 1/ma - ra.x*ra.x/Ia + 1/mb - rb.x*rb.x/Ib) - (e+1)/k * (Vai.y - Vbi.y) (ra.x*ra.y / Ia + rb.x*rb.y / Ib); double Jy = - (e+1)/k * (Vai.x - Vbi.x) (ra.x*ra.y / Ia + rb.x*rb.y / Ib) + (e+1)/k * (Vai.y - Vbi.y) ( 1/ma - ra.y*ra.y/Ia + 1/mb - rb.y*rb.y/Ib); Vaf.x = Vai.x - Jx/Ma; Vaf.y = Vai.y - Jy/Ma; Vbf.x = Vbi.x - Jx/Mb; Vbf.y = Vbi.y - Jy/Mb; waf.x = wai.x - (Jx*ra.y - Jy*ra.x) /Ia; waf.y = wai.y - (Jx*ra.y - Jy*ra.x) /Ia; wbf.x = wbi.x - (Jx*rb.y - Jy*rb.x) /Ib; wbf.y = wbi.y - (Jx*rb.y - Jy*rb.x) /Ib; } 

    O ponto em que eles colidem está na linha entre os pontos médios dos dois círculos, e sua distância a partir de qualquer ponto médio é o raio daquele círculo respectivo.

    Eu concordo com as respostas fornecidas, elas são muito boas.
    Eu só quero apontar uma pequena armadilha: se a velocidade das bolas for alta, você pode perder a colisão, porque os círculos nunca se cruzam em determinadas etapas.
    A solução é resolver a equação do movimento e encontrar o momento correto da colisão.

    De qualquer forma, se você implementasse sua solução (comparações nos eixos X e Y), você obteria o bom e velho ping pong! http://en.wikipedia.org/wiki/Pong
    🙂

    Para responder mais diretamente à sua pergunta: Sim, de acordo com as regras e requisitos expostos, essas bolas colidem no eixo Y se a diferença em Y for maior que a diferença em X quando as bolas se tocam.

    Se isso é o que você está implementando, então você está recebendo uma resposta correta para a pergunta “colisão do eixo X ou Y?”. Mas eu acho que a razão pela qual você está recebendo tantas respostas aqui que você não consegue usar é que

    • você está fazendo a pergunta errada (não aqui – no seu programa); ou

    • você não está usando a resposta corretamente.

    Tenho certeza que muitos de nós programaram programas de bolas saltitantes, e eu suspeito que nenhum de nós tentou modelar colisões baseadas em octants e axes. Então eu suspeito que ou você tem uma nova abordagem muito original ou simplesmente está fazendo errado. Por isso, recomendo voltar e verificar o seu método e suposições.