¿Hay algún algoritmo para un juego de billar?

14

Estoy buscando un algoritmo para calcular la dirección y la velocidad de las bolas en un juego de billar. Estoy seguro de que debe haber algún tipo de código fuente abierto para esto, ya que los juegos de billar son algunos de los juegos de computadora más antiguos que puedo recordar.

Quiero decir, cuando una pelota golpea a otra, necesito un algoritmo para calcular la dirección de ambas. Dependerá del ángulo exacto de dónde se golpean y de la velocidad.

Quiero practicar la codificación Java, por lo que estoy buscando un código o paquete Java que tenga este tipo de código.

Vaillancourt
fuente
2
Sin embargo, si desea resolverlo usted mismo, probablemente necesitará algunos conocimientos de vectores. Afortunadamente, alguien publicó un gran tutorial sobre matemáticas lineales en otro lugar de este sitio el otro día.
doppelgreener
tal vez este sitio pueda ayudarlo a archive.ncsa.illinois.edu/Classes/MATH198/townsend/…

Respuestas:

8

Si bien la detección / respuesta de colisión esfera-esfera básica es bastante simple, hacerlo con la precisión suficiente para una buena simulación de grupo sería más complicado, ya que tendrías que lidiar con el giro.

¿Eres consciente de la existencia de motores de física? Algunos ejemplos populares son estos (y pueden hacer mucho más que solo colisiones de bolas de billar). Probablemente sea una buena opción para hacer un juego de billar, pero no tanto para aprender Java ...

En 2D

Box2D: http://www.box2d.org

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

En 3D

Bullet: http://bulletphysics.org/

ODE: http://www.ode.org

Si estabas haciendo un juego comercial de gran presupuesto:

Havok: http://www.havok.com

bluescrn
fuente
1
¿Cuáles de estos son motores de física de Java?
Ricket
Hay puertos Java de, o al menos enlaces para Box2D, Chipmunk, Bullet y ODE
bluescrn
2

Para un juego de billar simple donde el giro no está modelado, el algoritmo es bastante simple.

  1. Para verificar si ocurre una colisión, verifique si la distancia entre las bolas es menor que la suma de su radio.
  2. Calcule la normalidad del impacto.
  3. Calcule la fuerza de impacto en función de la diferencia de velocidad, normal, coeficiente de impacto y masas
  4. Aplicar la fuerza de impacto a ambas bolas.

En pseudocódigo esto se convierte en:

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
    }
}

Puede omitir la masa del algoritmo si todas las bolas tienen la misma masa y también asumir un radio constante para todas las bolas para un juego de billar, pero el código será más útil para usted sin esas simplificaciones.

El código se basa en este tutorial , pero recuerdo que la multiplicación por impulso era incorrecta allí.

msell
fuente
¿Qué pasa si el punto es menor que cero? He estado investigando este pseudocódigo (y el que vinculaste también, pero el otro termina con mi intento de tomar el cuadrado de un número negativo, tal vez ese es el problema que identificaste con él). ¿Seguramente desea producir un resultado con cada conjunto de posiciones y velocidades de entrada?
@Poldie Si el punto es negativo, las bolas ya se están alejando entre sí. No es necesario manejar la colisión en ese caso.
msell
Acabo de activar mi versión de su código aquí: ideone.com/DhsAoW y obtengo -0.707 para una posición de 110,90 y 100,100, y velocidades de 0,2 y 0, -3. Esta es una colisión más o menos frontal. (Suponga que la verificación de detección de colisión basada en radio inicial ya ha ocurrido).