0

So I'm coding a snooker game, and I decided the best way to figure out how to make the balls collide with one another was to do so in a separate program then copy it in. I'm a pretty competent mathematician, so I've sat down, drawn the event and gone through the maths of what's actually happening.

My approach is to break each balls' initial velocity into xr- and yr-components, in a frame of reference in which the xr-component is in line with the vector through the center of each ball, and the yr-component is perpendicular to this. I then do a simple switch of the xr components of the balls and leave the yr components as they are, then calculate what the x- and y- components of the velocity are back in the standard reference frame.

For some reason, whether it be through mathematical or programming error, I can't seem to get it to work. The following is what I have so far and I have looked over virtually every related page on the internet I could find and all the similar-ish questions asked on this site. I'm not exactly a well versed programmer either.

from visual import *

dt = 0.01
r = 5

red = sphere(pos=(-25,25,0),radius = r,color=color.red)
green = sphere(pos=(25,-25,0),radius = r,color=color.green)


red.velocity = vector(10,-10,0)
green.velocity = vector(-10,10,0)


def posupdate(ball):

        ball.pos = ball.pos + ball.velocity*dt


def ballhit(ball1,ball2):

        v1 = ball1.velocity
        v1x = ball1.velocity.x
        v1y = ball1.velocity.y
        v2 = ball2.velocity
        v2x = ball2.velocity.x
        v2y = ball2.velocity.y
        xaxis = vector(1,0,0)

        btb = ball2.pos - ball1.pos
        nbtb = btb/abs(btb)

        if abs(btb) < 2*r:
                phi = acos(dot(nbtb,xaxis)/abs(nbtb)*abs(xaxis))
                ang1 = acos(dot(v1,xaxis)/abs(v1)*abs(xaxis))
                ang2 = acos(dot(v2,xaxis)/abs(v2)*abs(xaxis))

                v1xr = abs(v1)*cos((ang1-phi))
                v1yr = abs(v1)*sin((ang1-phi))
                v2xr = abs(v2)*cos((ang2-phi))
                v2yr = abs(v2)*sin((ang2-phi))

                v1fxr = v2xr
                v2fxr = v1xr
                v1fyr = v1yr
                v2fyr = v2yr

                v1fx = cos(phi)*v1fxr+cos(phi+pi/2)*v1fyr
                v1fy = sin(phi)*v1fxr+sin(phi+pi/2)*v1fyr
                v2fx = cos(phi)*v2fxr+cos(phi+pi/2)*v2fyr
                v2fy = sin(phi)*v2fxr+sin(phi+pi/2)*v2fyr

                ball1.velocity.x = v1fx
                ball1.velocity.y = v1fy
                ball2.velocity.x = v2fx
                ball2.velocity.y = v2fy

        return ball1.velocity, ball2.velocity


while 1==1:

        rate(100)

        posupdate(red)
        posupdate(green)
        ballhit(red,green)

Thanks in advance for any help you can give.

Edit: The collision detection is no issue, just the calculation of the velocity vectors of the balls after the collision. Apologies, I should have made that clearer.

Cowmilker
  • 11
  • 3
  • The direction the balls take is just wrong for most cases. There's a small few, eg motion only along the X axis which work properly, but in general the direction of repulsion is just wrong. – Cowmilker Apr 08 '16 at 00:53

1 Answers1

0

Check out Physics of Billiards:

Conservation of momentum applies and, assuming inelastic collisions, kinetic energy is conserved. So you get the following vector equations (subscripts _0 and _1 indicate before and after collision):

m1*v1_0 + m2*v2_0 = M1*v1_1 + m2*v2_1

0.5*m1*v1_0**2 + 0.5*m2*v2_0**2 = 0.5*m1*v1_1**2 + 0.5*m2*v2_1**2

Usually m1 == m2, so these simplify to:

v1_0 + v2_0 = v1_1 + v2_1

v1_0**2 + v2_0**2 = v1_1**2 + v2_1**2
RootTwo
  • 4,288
  • 1
  • 11
  • 15
  • The problem is more to do with the angles, but thanks anyway. I have checked out that article before, and it is quite handy when it comes to gaining an understanding of what's going on in the collision. My main problem is putting into code form. – Cowmilker Apr 09 '16 at 16:31