[futurebasic] Re: [FB] Rebound trajectories

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : March 1999 : Group Archive : Group : All Groups

From: Robert Purves <robert.purves@...>
Date: Mon, 15 Mar 1999 10:35:40 +1300
>>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