Balls colliding - vPython problems

2.2k Views Asked by At

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.

1

There are 1 best solutions below

1
RootTwo On

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