1

I'm basically totally knew to programming, been doing it for about 3 days and I became quite interested quite fast - as an exercise to help me learn, I've opted for trial by fire by just going straight in and using vPython to try to create a snooker simulation.

So far its going okay, I've got all the models for the table, cushions, pocket jaws etc, and I've managed to make the balls rebound off the cushions and jaws in a realistic fashion. I've also got the balls to slow down at a rate proportional to their speed - all quite simple stuff I know, but I'm new here so its all quite exciting really.

Anyway - the problem. I'm creating a function into which two balls are the input, and it firstly detects whether they are in contact then causes them to change direction (hitting each other). So far I have this:

def ballhit(ball1,ball2):

    v1 = ball1.velocity
    v2 = ball2.velocity
    btb = ball1.pos - ball2.pos # Ball To Ball
    nbtb = btb/abs(btb) # Normalised btb
    if abs(ball1.velocity) == 0:
        theta1 = 0
    else:
        theta1 = acos(abs(ball1.velocity.x)/abs(ball1.velocity))
    if abs(ball2.velocity) == 0:
        theta2 = 0
    else:
        theta2 = acos(abs(ball2.velocity.x)/abs(ball2.velocity))
    phi = acos(abs(vector(1,0,0))/abs(nbtb))

    ball1.velocity.x = ((2*bm*ball2.velocity*cos(theta2-phi)*cos(phi))/2*bm) + ball1.velocity*(sin(theta1-phi))*(cos(phi+(pi/2)))

    ball1.velocity.y = ((2*bm*ball2.velocity*cos(theta2-phi)*sin(phi))/2*bm) + ball1.velocity*(sin(theta1-phi))*(sin(phi+(pi/2)))

    ball2.velocity.x = ((2*bm*ball1.velocity*cos(theta1-phi)*cos(phi))/2*bm) + ball2.velocity*(sin(theta2-phi))*(cos(phi+(pi/2)))

    ball2.velocity.y = ((2*bm*ball1.velocity*cos(theta1-phi)*sin(phi))/2*bm) + ball2.velocity*(sin(theta2-phi))*(sin(phi+(pi/2)))

    return ball1.velocity
    return ball2.velocity

The two theta values are the angles the balls make with the x-axis, the phi value is the angle the normal (which is also normalized) at the point of contact makes with the x-axis, then my calculations for each of the components of each ball. As far as I can tell the calculations are correct, but the way I've written it must be absolutely dire (as I expect).

This is the error I get:

line 320, in <module>
ballhit(red1,blue)
line 302, in ballhit
ball1.velocity.x = ((2*bm*ball2.velocity*cos(theta2-phi)*cos(phi))/2*bm) +
ball1.velocity*(sin(theta1-phi))*(cos(phi+(pi/2))) ArgumentError:
Python argument types in
None.None(vector, vector) did not match C++ signature:
None(class cvisual::vector {lvalue}, double)

I have defined a velocity for both balls and there are no other unassigned variables from what I can see.

If anyone could just explain to me what the error actually means it'd be appreciated, and if someone could show me how its fixed that'd be double points.

Thanks :)

zondo
  • 19,901
  • 8
  • 44
  • 83
Cowmilker
  • 11
  • 3
  • As a quick edit - I have changed all the ball1.velocity and ball2.velocitys to v1s and v2s now as I originally intended them to be - sorry, I forgot about that assignment. Fool. – Cowmilker Mar 30 '16 at 23:51
  • Your velocity calculations look a bit strange to me: inside the formula you're multiplying velocity (a vector) by a bunch of scalars, so the result should be a vector. But then you're assigning it to `ball1.velocity.x`? Shouldn't you be using `ball#.velocity.x` (or `.y`) inside the formulas as appropriate, and not `ball#.velocity`? – rmunn Mar 31 '16 at 00:08
  • Aha, you're right I'm using vectors where I need scalars. Instead of changing them to x- and y- components though, I think I need to change them to moduli, as the direction is given by the trig functions used. New error is showing now, having changed the vectors in the calcs to moduli: line 302, in ballhit phi = acos(abs(vector(1,0,0))/abs(nbtb)) ValueError: math domain error – Cowmilker Mar 31 '16 at 00:19
  • I suggest asking a new question about this new error, since you can't put multiple lines of code in comments. But a "math domain error" usually indicates "you can't apply that mathematical function to that value"; most examples I found were about taking the `log` of a negative value, which is undefined. Here you're taking the arc cosine, which is defined from -1 to 1. Is it possible that `abs(vector(1,0,0))/abs(nbtb)` could ever, due to rounding error, end up less than -1 or greater than 1? If so, that could be causing it. – rmunn Mar 31 '16 at 01:02
  • 1
    I'll note that floating-point operations in programming are more complicated than you'd think. For example, load an interactive Python session and type `0.1 + 0.2 == 0.3`. The result will be `False`! See http://stackoverflow.com/q/588004/2314532 for why this happens -- and ask a new question about your math domain error, so that more people can see it and comment. – rmunn Mar 31 '16 at 01:06
  • Thanks for your help pal, much appreciated! – Cowmilker Mar 31 '16 at 12:20

0 Answers0