Para um jogo simples de sinuca onde o spin não é modelado, o algoritmo é bastante simples.
- Para verificar se uma colisão acontece, verifique se a distância entre as bolas é menor que a soma do raio.
- Calcular o normal do impacto
- Calcular a força de impacto com base na diferença de velocidade, normal, coeficiente de impacto e massas
- Aplique a força de impacto nas duas esferas
No pseudo-código, isso se torna:
vector difference = ball2.position - ball1.position
float distance = sqrt(difference)
if (distance < ball1.radius + ball2.radius) {
vector normal = difference / distance
//vector velocityDelta = ball2.velocity - ball1.velocity
vector velocityDelta = ball1.velocity - ball2.velocity
float dot = dotProduct(velocityDelta, normal)
if (dot > 0) {
float coefficient = 0.5
float impulseStrength = (1 + coefficient) * dot * (1 / ball1.mass + 1 / ball2.mass)
vector impulse = impulseStrength * normal
ball1.velocity -= impulse / ball1.mass
ball2.velocity += impulse / ball2.mass
}
}
Você pode omitir a massa do algoritmo se todas as bolas tiverem a mesma massa e também assumir raio constante para todas as bolas em um jogo de bilhar, mas o código será mais útil para você sem essas simplificações.
O código é baseado neste tutorial , mas lembro que a multiplicação de impulsos estava incorreta lá.