Hi,

I am trying to work out how to calculate the physics of two balls colliding. I was wondering if anybody here can help? 2D collisions only.

I know how to know if they are hitting (I'll write in PHP as that's common to us all)

OK, i have a ball class with the following properties (they are fairly self explanatory);

x
y
xspeed
yspeed
radius

I know how to detect they are touching;

// Avoid negative variables and calculate the distance apart along 
// the x and y axis

$x = (($ball1->x - $ball2->x) > 0) ? ($ball1->x - $ball2->x) : -($ball1->x - $ball2->x);
$y = (($ball1->y - $ball2->y) > 0) ? ($ball1->y - $ball2->y) : -($ball1->y - $ball2->y);

// Get the square of the distance between the balls
$h = ($x * $x) + ($y * $y);

// Calculate distance between balls, get square root of 
$d = sqrt($h);;

if($d < ($ball1->radius + $ball2->radius)){

// balls are touching

} else {

// balls are not touching

}

How do I calculate;
The new direction?
The new speed?

I'm only planning on implementing a fully elastic collision, IE. no loss of 'energy'

The mass would be calculated by the radius side, assuming the same 'material' is used, so a radius of 50 is half the 'mass' of a ball with the radius of 100.

I've tried googling a few things, but I've only really found rather complicated math formulas that I've not been able to follow... so any tips would be appreciated.

    This may be completely wrong but....

    Would you be happy with "Angle of Incidence = Angle of Reaction"? I mean, just figure the "slope" of the line, then invert it, then move it vertically so that the lower number is the current point of the ball.....

    \
     \   <-- Angle after
      \
       \
        o
       /
      /
     /    <-- Angle previous
    /

    That's kinda what I would do.... so just plot the first point, save it in a public variable in the class. When they touch, update the variable, calculate the slope (m = x/y), then invert it (m*-1) then move it to the current Y value (m + y), then start moving away at the new angle. So in essence you have a few steps:

    1.) Record starting position of ball
    2.) Record "impact" position of ball
    3.) Calculate slope
    4.) Inverse slope
    5.) Calculate next coordinate(s)
    6.) Update "starting position" to be current position
    7.) Move ball

    Not sure if that's what you want, but that's the most basic thing I can think of.

    If there's no loss of energy, then speed is constant.

      You example works well in the case of a ball hitting a wall. In fact, its exactly what i used to stop the balls escaping.

      However, if you consider a ball hitting another ball, it doesn't work the same way.

      for example, think about playing pool or something... say a ball just hits the side of the other ball it effects it completely differently than if they hit right in the middle.

      or if one ball is travelling at 5 units its speed and the other is not moving then you get a transfer of momentum.

      and so on...

      I started implementing this in JavaScript, if i remember I'll upload what i have tomorrow and let you see.

      It's surprisingly fun working with little things bouncing around! hehe.

        dougal85 wrote:

        Hi,
        The mass would be calculated by the radius side, assuming the same 'material' is used, so a radius of 50 is half the 'mass' of a ball with the radius of 100.

        As the mass of a ball is the result of the volume of that sphere, and we know that a sphere has a volume of 4/3 PI radius3. Therefore the mass does not double with a doubling of r, but increments with a factor 23 = 8.

        For your collision probem, have a look here: http://xna101.spaces.live.com/blog/cns!77EE4BD533D8ECAE!238.entry where they deal with this.

          Thanks leatherback, I don't really kno what i'm talking about 🙂 i'm just guessing my way there.

          I'll check out the link, thanks again.

            leatherback wrote:

            As the mass of a ball is the result of the volume of that sphere,

            Well, it depends on the density too - I figure it would be easier to regard them as independent properties. But here are some notes I knocked together.

            Two balls; I'll call them A and B. (I have a very good imagination.)

            Ball A has a mass "ma", a radius "ra", a position "pa" represented in Cartesian coordinates as "pxa" and "pya", and finally a velocity "va" which is also represented by its Cartesian components.

            Ball B has similar labels.

            First thing to do is decide whether or not the two balls are in collision. If they're not colliding there's nothing to do. This will happen if the distance between the centres of the two balls is not more than the sum of their radii. (Ideally, if the collisions are purely elastic, you never want it to be less, but roundoff and model resolution errors may cause the balls to overlap slightly.)

            For performance's sake, calculate the square of the two distances involved: if s and t are nonnegative (as distances are wont to be), then if s<t then sqrt(s)<sqrt(t). Only take the square root (you'll only need one of them) when you've decided you need it.

            I'm going to call the distance sqrt((pxa-pxb)2+(pya-pyb)2) between the two balls' centres "d". If they're not colliding, d>ra+rb; if just touching, then d=ra+rb. If they're overlapping, d<ra+rb and we need to model the collision we just missed and tweak them apart. It's not physically kosher, but it wasn't physically kosher to allow them to overlap in the first place. We'll just move them away from each other by half the amount of overlap each. With luck the visible magnitude of the fraud will be less than a pixel. I guess it's not strictly necessary to do this bit, but we'll be using dpx and dpy quite a bit later, so seeing as we need them anyway:

            $overlap = $ra + $rb - $d;
            $dpx = ($pxb - $pxa)/$d;
            $dpy = ($pyb - $pya)/$d;
            $pxa -= $dpx*$overlap/2;
            $pya -= $dpy*$overlap/2;
            $pxb += $dpx*$overlap/2;
            $pyb += $dpy*$overlap/2;
            

            Now for the juicy stuff. dpx and dpy represent a change of position - a direction. To be precise, it's the direction to move in to get from the centre of A to the centre of B. This is call the "axis of collision" and all the action will be happening there; the axis of collision passes through the point where the balls touch and this of course is where all the exchange of momentum happens. At right angles to the axis at this point you can imagine a second line that represents the "wall" the two balls are bouncing off of. The wall may only consist of one point on the surface of the other ball, but one point of contact is all we have with the wall anyway.

            Ultimately it boils down to the conservation of two quantities: momentum and kinetic energy. The momentum of the system beforehand is mava+mbvb before the collision and ma'va'+mb'vb' afterward. Since the masses don't change ma=ma' and mb=mb'. The kinetic energy of the system before the collision is (ma*va2)/2+(mb+vb2)/2, and that equals the kinetic energy afterwards - by the definition of "elastic collision".
            Let's say for the moment that B is stationary and that A is doing all the moving before the collision.

            mava = mava' + mbvb' (conservation of momentum)
            and
            (ma
            va2)/2 = (mava' + mbvb2)/2 (conservation of kinetic energy)

            Which can each be rearranged as

            ma(va - va') = mbvb'
            and
            ma(va - va')(va + va') = mb
            vb'

            respectively.
            Dividing one by the other and a bit of tidying up we have

            va' = va(ma - mb)/(ma + mb)
            vb' = va
            (ma + ma)/(ma + mb)

            The new velocities of A and B.

            That was if B started out at rest, though. What if it had been moving? Well, the momentum and energy transfers will be the same as if B were not moving and A's initial velocity had been its own less B's. In effect we shift to a new coordinate system that's tracking B's motion; afterwards we shift back again by adding B's initial velocity back in to both final velocities.

            All that was working with the velocity vectors va and vb directly, though, rather than their x and y components (vxa, vya, vxb and vyb). Fortunately, that principle that the angle of incidence equals the angle of reflection applies: it means that all the action happens along that axis. Any movement that is perpendicular to the axis is unchanged.

            $vca = $vxa*$dpx + $vya*$dpy;
            $vcb = $vxb*$dpx + $vyb*$dpy;
            

            Now everything is happening along the axis of collision; the two dimensional problem has been reduced to a one-dimensional one, and those velocity vectors we were working with a moment ago are now just ordinary numbers. Noting the shifting of coordinate systems above, and (because we'll actually want the change in velocity) subtracting the initial velocities:

            $dva = ($vca*($ma - $mb) + 2*$vcb*$mb)/($ma + $mb) - $vca;
            $dvb = ($vcb*($mb - $ma) + 2*$vca*$ma)/($ma + $mb) - $vcb;
            

            And finally rotate back into the original X-Y system:

            $vxa += $dva*$dpx;
            $vya += $dva*$dpy;
            $vxb += $dvb*$dpx;
            $vyb += $dvb*$dpy;
            

            If you have N balls numbered [0..N-1], you'd loop A from [0..n-2] and inside that loop B from [A+1..n-1]. That way you'll compare each distinct pair of balls precisely once. Possibly you might want to store each ball's changes in velocity (there shouldn't be that many unless things are really crowded) in a separate array and then add them all to the initial velocities after they've all been calculated.

              I'm convinced weedpacket is the son of Albert Einstein.... that can't be straight from your head.... you had to look some of it up...... either way, I learned quite a bit today.... and I havent' even gone to class today 🙁

                ive picked up more in this forum than i did @ 5 years of college

                  scrupul0us wrote:

                  I've picked up more in this forum than i did @ 5 years of college

                  lol, yeah its a funny thing about studying at college or university I don't feel i learn much there but it leaves me time to learn things elsewhere.

                  I think we should start asking weedpacket hardcore questions just to test him :rolleyes:

                  Back to subject, i'm starting to try and implement this into my script and see how its gets on.

                  I did get one kinda of working, but i had a problem with the balls slightly overlapping and getting stuck together.

                    Well, I've learnt all this stuff in college, not in a programming language, but in algebraic form.

                    Applying it to a specific purpose is merely a task of thinking of what equations you're going to use, and how you're going to use them :p

                    Talking of which, I have an exam with this sort of stuff coming up very soon...

                      Weedpacket wrote:

                      Well, it depends on the density too - I figure it would be easier to regard them as independent properties.

                      well.. he did say they were made of the same material. And since they are going to collide, I presumed they are in the same space, and would have the same temperature..

                      But besides that.. Nice post. You dove deeper than I wanted to risk ;-)

                        leatherback wrote:

                        well.. he did say they were made of the same material. And since they are going to collide, I presumed they are in the same space, and would have the same temperature..

                        Eh... good point. Thing was though I was thinking of them really as being two-dimensional - their mass therefore proportional to their area. If they really were three dimensional then either we're talking about having them moving about in three dimensions or they're rolling about on a surface (more exactly, sliding about on a frictionless one - I don't want to get onto spinning balls). More like pucks than balls (at least that's what one girlfriend told me). If they're spheres sliding about on a surface you've got extra problems: a small ball hitting a larger one will - because its centre is closer to the surface - give the larger ball a nudge upwards, starting it rolling so you're back to dealing with spinning balls again (and also requiring gravity to bring it back down)...

                        bpat1434 wrote:

                        that can't be straight from your head...

                        Sprung. Some of it was from my ever-reliable Halliday&Resnick (viz. the conservation of kinetic energy and its formulation).

                          bradgrafelman wrote:

                          Elizabeth?

                          runs

                          While a "pucks versus balls" comment definitely has my signature written all over it, unfortunately I can't claim this one. 🙂

                            I can't claim this one. 🙂

                            And rather than impugn the Queen's honor further, we should add that there are multiple and provable reasons for that. 😃

                              All of this reminds me way too much of the physics class I had last semester. (shudder) But I must say that I'm proud that I understood Weedpacket's post entirely. Just to clarify, Weedpacket was talking about putting the velocity of A in B's frame of reference. (You know, in case you ever learned about frames of reference...):queasy:

                                Write a Reply...