>This modified code should solve the problem, it checks to see that a ball >hits the right ball and also to see if it hits a ball before a wall >or one wall before the other wall. >Michael Kluskens Good code, Michael! In fact, too good. If my original was 50% acceptable, your additions bring us up to 95%. With a few tiny fixes, your code works fine in FBII as well as FB^3 (things like putting on a few missing ! suffices in FN Backoff!). Why too good? Well, your code, unlike my original, is "self-repairing" in the sense that if two balls should ever overlap, they don't get stuck. That's good, but it disguises a remaining defect: balls _can_ get overlapped after a collision. That's not good physics. In fact if you make the following settings in Michael's program _bSize = 20 _nBalls = 90 _initSpeed = 40 and stop animation every second or two by holding down the mouse in the menu bar, you'll quite often see overlapping balls. The reason is that no test is made for collisions along a moving ball's path, only at the end of its step. My fix for that is a replacement for Michael's FN TestCollides, the rest of the program being unchanged. For reasons unclear, this code does not work properly in FBII (it runs, but you still get overlaps), so I can by no means claim 100% solution at this point, even if the algorithm is actually correct. Robert P. ' -- replacement for FN TestCollides in M.S.K.'s 2nd program--- LOCAL FN TestCollides(ballone) DIM ball1&,ball2&, k, ballOneX!, ballOneY!, dX!, dY! DIM fraction!' collision's fractional distance from original position DIM closestCollision!' closest distance to collision with any ball DIM hitWhat' the ball that this ball actually hit DIM dangerDistD!' for extended test along route of ball1 (new, by Robert P.) ball1& = @gBall(ballone) dangerDistD! = SQR(ball1&.xVF!*ball1&.xVF! + ball1&.yVF!*ball1&.yVF!) +gCollideDist! ballOneX! = ball1&.xF! ballOneY! = ball1&.yF! hitWhat = 0' initialize targeting variables closestCollision! = 1e9 ' check walls first but do not decide yet LONG IF (ball1&.yVF! <> 0.0) LONG IF (ball1&.yF! < 0.0)'top bounce closestCollision! = 1.0 - ball1&.yF! / ball1&.yVF! hitWhat = -1 XELSE LONG IF (ball1&.yF! >= gBoundsRect.yBottomp!)'bottom bounce closestCollision! = 1.0 - (ball1&.yF! - gBoundsRect.yBottomp!) / ball1&.yVF! hitWhat = -2 END IF END IF END IF LONG IF ball1&.xVF! <> 0.0 LONG IF (ball1&.xF! < 0.0)'left bounce fraction! = 1.0 - ball1&.xF! / ball1&.xVF! LONG IF (fraction! < closestCollision!) closestCollision! = fraction! hitWhat = -3 END IF XELSE LONG IF (ball1&.xF! >= gBoundsRect.xRightp!)'right bounce fraction! = 1.0 - (ball1&.xF! - gBoundsRect.xRightp!) / ball1&.xVF! LONG IF (fraction! < closestCollision!) closestCollision! = fraction! hitWhat = -4 END IF END IF END IF END IF ' next check all the balls but do not decide yet FOR k = 1 TO _nBalls ball2& = @gBall(k) LONG IF (ABS(ballOneX! - ball2&.xF!) < dangerDistD!)'quickly exclude LONG IF (ABS(ballOneY! - ball2&.yF!) < dangerDistD!)'quickly exclude LONG IF (ball1& <> ball2&)' don't compare with self dX! = ballOneX! - ball2&.xF! dY! = ballOneY! - ball2&.yF! LONG IF ((dX!*dX! + dY!*dY!) < gCollideDistSq!)' accurate test at endpoint fraction! = FN BackOff!(ball1&, ball2&)' fractional distance to contact LONG IF (fraction! < closestCollision!) closestCollision! = fraction! hitWhat = k END IF XELSE' new stuff by Robert P. 'look along track for collisions en route to endpoint DIM ballOneOrigX!, ballOneOrigY! ,ballTwoX!, ballTwoY!, u!, x!, y! 'the track is (ballOneOrigX!,ballOneOrigY!) to (ballOneX!,ballOneY!) ballOneOrigX! = ballOneX! - ball1&.xVF! ballOneOrigY! = ballOneY! - ball1&.yVF! ' the point ballTwoX! = ball2&.xF! ballTwoY! = ball2&.yF! dX! = ballOneX! - ballOneOrigX! dY! = ballOneY! - ballOneOrigY! u! =((ballTwoX!-ballOneOrigX!)*dX!+(ballTwoY!-ballOneOrigY!)*dY!)/(dX!*dX! + dY!*dY!) ' the meeting point is in the track segment if 0 < u < 1 LONG IF ((u! > 0.0) AND (u! < 1.0)) ' shortest line from ball2 to track meets it at(x!,y!) x! = ballOneOrigX! + u!*(ballOneX! - ballOneOrigX!) LONG IF (x! >= 0.0) AND (x! < gBoundsRect.xRightp!)' reject out of bounds y! = ballOneOrigY! + u!*(ballOneY! - ballOneOrigY!) LONG IF (y! >= 0.0) AND (y! < gBoundsRect.yBottomp!)' reject out of bounds dX! = x! - ballTwoX!: dY! = y! - ballTwoY!' offsets from track to ball2 ' accurate test for contact en route LONG IF ((dX!*dX! + dY!*dY!) <= gCollideDistSq!) dX! = ball1&.xVF!: dY! = ball1&.yVF!' save for restore ' adjust velocity ball1&.xVF! = ball1&.xVF! * u!: ball1&.yVF! = ball1&.yVF! * u! 'advance temporarily to maximum-overlap place ball1&.xF! = x!: ball1&.yF! = y! ' adjusted fractional distance to contact fraction! = FN BackOff!(ball1&, ball2&)*u! LONG IF (fraction! < closestCollision!) closestCollision! = fraction! hitWhat = k END IF ball1&.xF! = ballOneX! : ball1&.yF! = ballOneY!' restore after temp advance ball1&.xVF! = dX!: ball1&.yVF! = dY!' restore END IF END IF END IF END IF ' end of new stuff END IF END IF END IF END IF NEXT ' now we decide what we hit LONG IF hitWhat ' step back to original position and move forward fractional distance tocollision POINT ball1&.xF! = ball1&.xF! + (closestCollision! - 1.0) * ball1&.xVF! ball1&.yF! = ball1&.yF! + (closestCollision! - 1.0) * ball1&.yVF! LONG IF (hitWhat > 0) ball2& = @gBall(hitWhat) FN Bounce (ball1&, ball2&)' now handle the right collision XELSE LONG IF (hitWhat > -3) ball1&.yVF! = -ball1&.yVF! XELSE ball1&.xVF! = -ball1&.xVF! END IF END IF END IF END FN '-----------------------------