Existe um algoritmo para um jogo de bilhar?

14

Eu estou procurando um algoritmo para calcular a direção e a velocidade das bolas em um jogo de bilhar. Estou certo de que deve haver algum tipo de código-fonte aberto para isso, pois os jogos de sinuca são alguns dos jogos de computador mais antigos que me lembro.

Quero dizer, quando uma bola bate na outra, preciso de um algoritmo para calcular a direção de ambas. Depende do ângulo exato de onde eles se batem e da velocidade.

Eu quero praticar a codificação Java, por isso estou procurando código java ou pacote que tenha esse tipo de código.

Vaillancourt
fonte
2
Se você quiser resolver sozinho, provavelmente precisará de algum conhecimento de vetores. Felizmente, alguém postou um grande passo a passo sobre matemática linear em outras partes deste site outro dia.
Doppelgreener
talvez este site pode ajudá-lo a archive.ncsa.illinois.edu/Classes/MATH198/townsend/...

Respostas:

8

Embora a detecção / resposta básica de colisão esfera-esfera seja bastante simples, fazê-lo com precisão suficiente para uma boa simulação de pool seria mais complicado, pois você teria que lidar com o spin.

Você está ciente da existência de mecanismos de física? Alguns exemplos populares são esses (e eles podem fazer muito mais do que apenas colisões com bolas de bilhar). Provavelmente uma boa escolha para fazer um jogo de bilhar, mas não tanto para aprender Java ...

Em 2D

Box2D: http://www.box2d.org

Esquilo: http://code.google.com/p/chipmunk-physics/

Em 3D

Bullet: http://bulletphysics.org/

ODE: http://www.ode.org

Se você estava criando um jogo comercial de grande orçamento:

Havok: http://www.havok.com

bluescrn
fonte
1
Quais destes são os mecanismos de física Java?
Ricket
Existem portas Java ou, pelo menos, ligações para Box2D, Chipmunk, Bullet e ODE
bluescrn
2

Para um jogo simples de sinuca onde o spin não é modelado, o algoritmo é bastante simples.

  1. Para verificar se uma colisão acontece, verifique se a distância entre as bolas é menor que a soma do raio.
  2. Calcular o normal do impacto
  3. Calcular a força de impacto com base na diferença de velocidade, normal, coeficiente de impacto e massas
  4. 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á.

msell
fonte
E se o ponto for menor que zero? Eu estive investigando esse pseudocódigo (e o que você vinculou também, mas o outro termina com a minha tentativa de tirar o quadrado de um número negativo - talvez seja esse o problema que você identificou com ele). Certamente você deseja produzir um resultado com cada conjunto de posições e velocidades de entrada?
@Poldie Se o ponto for negativo, as bolas já estão se afastando uma da outra. Não há necessidade de lidar com colisões nesse caso.
msell
Acabei de usar minha versão do seu código aqui: ideone.com/DhsAoW e estou recebendo -0,707 para posições de 110,90 e 100,100 e velocidades de 0,2 e 0, -3. Esta é uma colisão mais ou menos frontal. (Suponha que a verificação inicial da detecção de colisão com base no raio já tenha ocorrido).