REM 'Double Pendulum' simulation using Verlet integration REM Note: energy 'leaks' from the system quite rapidly REM Based on the "Verlet Integration Tutorial" by Coding Math: REM http://www.youtube.com/watch?v=3HjO_RGIjCU REM Change to *FLOAT 64 if not using BB4W v6 *FLOAT 80 MODE 8 : OFF ON ERROR OSCLI "REFRESH ON" : CLS : REPORT : PRINT ERL : END WinW% = @vdu%!208 WinH% = @vdu%!212 nPts% = 3 nSticks% = 2 DIM points{(nPts%-1) pinned%, x#, y#, oldx#, oldy#, mass# } DIM sticks{(nSticks%-1) p0%, p1%, hidden%, length# } gravity# = -0.5 REM fixed pivot point points{(0)}.x# = 320 points{(0)}.y# = 500 points{(0)}.oldx# = points{(0)}.x# points{(0)}.oldy# = points{(0)}.y# points{(0)}.mass# = 1.0 points{(0)}.pinned% = TRUE REM pendulum bob 1 points{(1)}.x# = 320 points{(1)}.y# = 230 points{(1)}.oldx# = points{(1)}.x# points{(1)}.oldy# = points{(1)}.y# points{(1)}.mass# = 1.0 points{(1)}.pinned% = FALSE REM pendulum bob 2 points{(2)}.x# = 200 points{(2)}.y# = 420 points{(2)}.oldx# = points{(2)}.x# points{(2)}.oldy# = points{(2)}.y# points{(2)}.mass# = 1.0 points{(2)}.pinned% = FALSE sticks{(0)}.p0% = 0 sticks{(0)}.p1% = 1 sticks{(0)}.length# = FNstickLength#( 0 ) sticks{(0)}.hidden% = FALSE sticks{(1)}.p0% = 1 sticks{(1)}.p1% = 2 sticks{(1)}.length# = FNstickLength#( 1 ) sticks{(1)}.hidden% = FALSE *REFRESH OFF REPEAT CLS PROCupdate *REFRESH WAIT 1 UNTIL FALSE END DEF PROCupdate PROCupdatePoints FOR I% = 1 TO 5 PROCupdateSticks NEXT I% PROCrenderPoints PROCrenderSticks ENDPROC DEF PROCupdatePoints LOCAL I%, vx#, vy# FOR I% = 0 TO nPts%-1 IF NOT points{(I%)}.pinned% THEN vx# = points{(I%)}.x# - points{(I%)}.oldx# vy# = points{(I%)}.y# - points{(I%)}.oldy# points{(I%)}.oldx# = points{(I%)}.x# points{(I%)}.oldy# = points{(I%)}.y# points{(I%)}.x# += vx# points{(I%)}.y# += vy# points{(I%)}.y# += gravity# * points{(I%)}.mass# ENDIF NEXT I% ENDPROC DEF PROCupdateSticks LOCAL I%, dx#, dy#, distance#, difference#, percent#, offsetX#, offsetY# FOR I% = 0 TO nSticks%-1 dx# = 1.0 * (points{(sticks{(I%)}.p1%)}.x# - points{(sticks{(I%)}.p0%)}.x#) dy# = 1.0 * (points{(sticks{(I%)}.p1%)}.y# - points{(sticks{(I%)}.p0%)}.y#) distance# = 1.0 * SQR(dx#^2 + dy#^2) difference# = sticks{(I%)}.length# - distance# percent# = difference# / distance# / 2.0 offsetX# = dx# * percent# offsetY# = dy# * percent# IF NOT points{( sticks{(I%)}.p0% )}.pinned% THEN points{( sticks{(I%)}.p0% )}.x# -= offsetX# points{( sticks{(I%)}.p0% )}.y# -= offsetY# ENDIF IF NOT points{( sticks{(I%)}.p1% )}.pinned% THEN points{( sticks{(I%)}.p1% )}.x# += offsetX# points{( sticks{(I%)}.p1% )}.y# += offsetY# ENDIF NEXT I% ENDPROC DEF PROCrenderPoints LOCAL I% FOR I% = 0 TO nPts%-1 CIRCLE 2*points{(I%)}.x#, 2*points{(I%)}.y#, 2*4 NEXT I% ENDPROC DEF PROCrenderSticks LOCAL I%, x0%, y0%, x1%, y1% FOR I% = 0 TO nSticks%-1 IF NOT sticks{(I%)}.hidden% THEN x0% = points{( sticks{(I%)}.p0% )}.x# y0% = points{( sticks{(I%)}.p0% )}.y# x1% = points{( sticks{(I%)}.p1% )}.x# y1% = points{( sticks{(I%)}.p1% )}.y# LINE 2*x0%, 2*y0%, 2*x1%, 2*y1% ENDIF NEXT I% ENDPROC DEF FNstickLength#( S% ) = 1.0 * SQR( (points{( sticks{(S%)}.p0% )}.x# - points{( sticks{(S%)}.p1% )}.x#)^2 + \ \ (points{( sticks{(S%)}.p0% )}.y# - points{( sticks{(S%)}.p1% )}.y#)^2 )