Advertisement

air hockey table simulator physics

Started by May 20, 2001 02:41 PM
4 comments, last by faz1 23 years, 8 months ago
Hey People, I am writing an Air Hockey Table simulator. So far so good, I have got the table friction working with the puck, the bat moving about ok. I am struggling on the collision handling between the bat and the puck, I am using the technique of measuring the distance between the two objects and checking if it is less than the sum of the bat''s radius and puck''s radius. This works fine, problem is when a collision is found between the bat and the puck, they are usually overlapped. I am trying to find the actual point of time when the collision occurs. Has anyone got any source code or links, I read a few articles @ gdmag about a pool simulator which helped alot, but I can''t quite get my head around some of the code in the examples.
Strangely enough I just did this a couple of days ago, for pool balls, but the principle is the same. How I did it was to define a function of t (time), f(t), equal to the distance between the centres of the two spheres (pucks in this case). It''s actually quite easy. Then you set f(t) = R1 + R2 and solve it for t. It''s a quadratic (which is obvious when you think about it) and it will tell you at what time the objects collided, and you can use their current velocities to work out where they were at that time.

Now I''m just working on the collision, which is harder than I anticipated. The articeles here at gamedev are pretty useful though.

I am prototyping it in VB, so this code may be a bit alien to you if you don''t know VB but then BASIC isn''t exactly hard to red

  Public Function CheckBall2BallCollision(Ball1 As tBall, Ball2 As tBall) As BooleanDim DistanceSquared As DoubleDim RadiiAdded As DoubleDim vPosDiff As tVector2DDim vVelDiff As tVector2DvPosDiff = Vector2DMath(VEC_OP_SUB, Ball1.vPos, Ball2.vPos)DistanceSquared = (vPosDiff.x * vPosDiff.x) + (vPosDiff.y * vPosDiff.y)RadiiAdded = Ball1.dRadius + Ball2.dRadiusDim vMomentum As tVector2DDim dEnergy As DoubleDim vPrevPos As tVector2DDim t As Double, t1 As Double, t2 As DoubleDim QuadA As Double, Quad2A As DoubleDim QuadB As DoubleDim QuadC As DoubleDim dDeterminant As DoubleDim dDetSquared As DoubleDim vNewPos1 As tVector2DDim vNewPos2 As tVector2DIf (vPosDiff.x < vVelDiff.x + RadiiAdded) And (vPosDiff.y < vVelDiff.y + RadiiAdded) Then ''possible collision (bounding rect)    vMomentum.x = (Ball1.vVel.x * Ball1.dMass) + (Ball2.vVel.x * Ball2.dMass)    vMomentum.y = (Ball1.vVel.y * Ball1.dMass) + (Ball2.vVel.y * Ball2.dMass)    dEnergy = (Ball1.dMass * (Ball1.vVel.x * Ball1.vVel.x + Ball1.vVel.y * Ball1.vVel.y) + _               Ball2.dMass * (Ball2.vVel.x * Ball2.vVel.x + Ball2.vVel.y * Ball2.vVel.y)) / 2    vVelDiff = Vector2DMath(VEC_OP_SUB, Ball1.vVel, Ball2.vVel)        QuadA = vVelDiff.x * vVelDiff.x + vVelDiff.y * vVelDiff.y    Quad2A = QuadA * 2    QuadB = (vVelDiff.x + vVelDiff.y) * 2    QuadC = vPosDiff.x * vPosDiff.x + vPosDiff.y * vPosDiff.y - RadiiAdded * RadiiAdded    dDetSquared = QuadB * QuadB - 4 * QuadA * QuadC    If dDetSquared < 0 Then Exit Function    dDeterminant = Sqr(dDetSquared)        If Quad2A = 0 Then Exit Function    t1 = ((-QuadB + dDeterminant) / Quad2A)    t2 = ((-QuadB - dDeterminant) / Quad2A)    If (t1 < 0 Or t1 > 1) And (t2 < 0 Or t2 > 1) Then Exit Function    If t1 >= 0 And t1 < t2 Then        t = t1    ElseIf t2 >= 0 Then        t = t2    End If        If t < 0 Or t > 1 Then Exit Function    vNewPos1 = Vector2DMath(VEC_OP_ADD, Ball1.vPos, Vector2DMath(VEC_OP_MUL, Ball1.vVel, NullVector2D, t))    vNewPos2 = Vector2DMath(VEC_OP_ADD, Ball2.vPos, Vector2DMath(VEC_OP_MUL, Ball2.vVel, NullVector2D, t))        ''stop when collision is detected    Do        DoEvents    Loop    End IfEnd Function  


Harry.
Harry.
Advertisement
Thanks for the reply HarryW. Could you elaborate a little more on what you mean by function of time f(t). I understand delta time and all that and integrating, but could you explain the maths a bit more clearly (I am bit rusty!)
Well f(t) = the distance between the centre points of the two spheres/discs at time t, where t should be a number between 0 and 1 and represents one tick in game time. You know the velocities of the objects, and you know their positions, so you know where they were 1 tick ago (currentpos - currentvel).

You can basically use this to figure out what the distance between the centre points is at any time t. At the time of the collision, f(t) = R1 + R2, where R1 and R2 are the radii of your discs. You can use a bit of pythagoras to find the distance from the differences in the X and Y coords.

if you define these variables...
deltaX = the difference in X coordinates
deltaY = the difference in Y coordinates
t = time
deltaVx = the difference in X velocities
deltaVy = the difference in Y velocities

then you can formulate this function:

f(t) = sqr((deltaX + t*deltaVx)² + (deltaY + t*deltaVy)²)
f(t)² = (deltaX + t*deltaVx)² + (deltaY + t*deltaVy)²

Now let f(t) = R1 + R2 (the moment of impact)

f(t)² = (R1 + R2)²

Thus

(R1 + R2)² = (deltaX + t*deltaVx)² + (deltaY + t*deltaVy)²

You can rearrange this and solve it for t, I'm not gonna retype it all. You end up with a quadratic equation like this:

(deltaVx² + deltaVy²)t² + 2(deltaVx + deltaVy)t + (deltaX² + deltaY²) - (R1 + R2)² = 0

Now you can solve this using the quadratic equation. The coeffictients A, B and C in Ax² + Bx + C are represented in the VB code by QuadA, QuadB and QuadC. I'm pretty sure you know how to solve a quatratic using the quadratic equation

That's how I've done it so far anyway. If you can think of a better way to do it, or any improvements on this way, then I'd definitely be interested in hearing it

(Edit - oops, messed up one of those eqns)

Edited by - HarryW on May 21, 2001 7:07:49 PM
Harry.
Oh yes, and a note on the actual detection of a collision:

If the objects are moving fast, you may miss a collision by just testing to see if they overlap. What I do (as you may notice from the code) is check whether the current velocities and positions mean that the objects could have crossed paths in the previous tick. If they could have been in close proximity over the course of the last tick, then calculate the collision point (if there is one). If one of the solutions of t comes out between 0 and 1 there was a collision in the last tick, otherwise... well there wasn''t

Harry.
Harry.
Hey HarryW, Cheers for the help on the maths, its making sense now, just typing the code in now, but I think problem is sorted.

This topic is closed to new replies.

Advertisement