>>Is anyone familiar with the math associated with the rebound trajectory of >>two balls colliding on a two dimensional surface? >If you assume perfectly elastic collisions (no energy loss), and assume no >spin effects, then you can work out the final velocity vectors by appealing >to the laws of conservation of energy and conservation of momentum. FN BounceOnCollide below shows exactly how. The program is optimised for accuracy, not speed. It could be greatly improved by replacing the slow floating point arithmetic by fixed point. In many bouncing ball simulations you can get away with a quick and dirty bounce algorithm (just swap the velocity vectors), and this is also demonstrated. Robert COMPILE ,_dimmedvarsOnly DIM RECORD ballRec DIM xP!, yP!, xV!, yV! ' position and velocity DIM END RECORD .ballRec DIM gRect.8, gCollideDistSq! _bSize=170 END GLOBALS LOCAL FN BounceOnCollide(b1Ptr&, b2Ptr&) 'A bounce conserves x- and y-momentum, and also ' the energy (sum of the square of all velocity components) DIM sine!, cosine!, dV!, dVx!, dVy!, distSq!, dX!, dY!, hypotenuse! dX!=b1Ptr&.xP! - b2Ptr&.xP! dY!=b1Ptr&.yP! - b2Ptr&.yP! distSq!=dX!*dX!+dY!*dY! LONG IF distSq!<gCollideDistSq! ' collided LONG IF FN BUTTON hypotenuse!=SQR(dX!*dX! + dY!*dY!) ' calculate sin and cos of angle of the line between centres cosine!=dX!/hypotenuse! sine!=dY!/hypotenuse! dV!=(b1Ptr&.xV!-b2Ptr&.xV!)*cosine!+(b1Ptr&.yV!-b2Ptr&.yV!)*sine! dVx!=dV!*cosine! ' x velocity change dVy!=dV!*sine! ' y velocity change b1Ptr&.xV!=b1Ptr&.xV!-dVx! b2Ptr&.xV!=b2Ptr&.xV!+dVx! b1Ptr&.yV!=b1Ptr&.yV!-dVy! b2Ptr&.yV!=b2Ptr&.yV!+dVy! XELSE ' quick and dirty SWAP b1Ptr&.xV!,b2Ptr&.xV! SWAP b1Ptr&.yV!,b2Ptr&.yV! END IF DIM energy! energy!=b1Ptr&.xV!^2+b2Ptr&.xV!^2+b1Ptr&.yV!^2+b2Ptr&.yV!^2 CALL TEXTMODE(_srcCopy): COLOR=_zBlack: PRINT @(0,0) energy! END IF END FN LOCAL FN DrawBall(bPtr&,colour) DIM rect.8 CALL SETRECT(rect,bPtr&.xP!,bPtr&.yP!,bPtr&.xP!+_bSize,bPtr&.yP!+_bSize) COLOR=colour: CALL FRAMEOVAL(rect) END FN LOCAL FN MoveBall(bPtr&,colour,otherBPtr&) FN DrawBall(bPtr&,_zWhite) 'erase bPtr&.xP!=bPtr&.xP!+bPtr&.xV! ' new position bPtr&.yP!=bPtr&.yP!+bPtr&.yV! LONG IF bPtr&.xP!<gRect.left 'hit left wall bPtr&.xP!=gRect.left: bPtr&.xV!=-bPtr&.xV! END IF LONG IF bPtr&.xP!>gRect.right 'hit right bPtr&.xP!=gRect.right: bPtr&.xV!=-bPtr&.xV! END IF LONG IF bPtr&.yP!<gRect.top 'hit top bPtr&.yP!=gRect.top: bPtr&.yV!=-bPtr&.yV! END IF LONG IF bPtr&.yP!>gRect.bottom 'hit bottom bPtr&.yP!=gRect.bottom: bPtr&.yV!=-bPtr&.yV! END IF FN BounceOnCollide(bPtr&, otherBPtr&) FN DrawBall(bPtr&,colour) 'redraw END FN WINDOW 1,"Bouncers (Cmd-. to end)",(0,0)-(630,420),_docNoGrow DIM ball1.ballRec, ball2.ballRec, ticks& gCollideDistSq!=_bSize*_bSize CALL SETRECT(gRect,10,20,620,410) CALL FRAMERECT (gRect) PRINT@(20,0) "Press mouse button for best physics" CALL INSETRECT(gRect,_bSize/2+1,_bSize/2+1) CALL OFFSETRECT(gRect,-_bSize/2,-_bSize/2) ball1.xP!=40: ball1.yP!=50 ' initial positions ball2.xP!=40+_bSize: ball2.yP!=50+15*_bSize/16 ball1.xV!=0.7 : ball1.yV!=3.7 'initial velocities ball2.xV!=4.7: ball2.yV!=2.9 FN DrawBall(@ball1,_zRed) FN DrawBall(@ball2,_zBlue) DO CALL PENSIZE(4,4) ticks&=FN TICKCOUNT FN MoveBall(@ball1,_zRed,@ball2) FN MoveBall(@ball2,_zBlue,@ball1) HANDLEEVENTS DO UNTIL FN TICKCOUNT> ticks& UNTIL 0