* Goals of this model * 1. Allow for the creation of bodies with the following properties * Position (X,Y) * Speed (X,Y) * Mass * 2. Add inertia * 3. Add gravitational force * 4. Place two bodies in some space and have one orbit the other DECLARE Sleep IN Win32API INTEGER nMilliseconds *LOCAL sun, earth *!* sun = CREATEOBJECT("body") *!* sun.mass = 1.98892 * 10^30 *!* sun.X = 200000000 *!* sun.Y = 200000000 *!* moon = CREATEOBJECT("body") *!* moon.mass = 5.9742 * 10^24 * .0123 apple = CREATEOBJECT("body") apple.mass = 1 *apple.X = 500 apple.X = 1200000 apple.Y = 5000000 apple.SpeedY = 5000 apple.SpeedX = 10000 apple.lSkipGravity = .T. apple2 = CREATEOBJECT("body") apple2.mass = 1 apple2.X = 3200000 apple2.Y = 0 apple2.SpeedX = 5000 apple2.lSkipGravity = .T. earth = CREATEOBJECT("body") earth.mass = 5.9742 * 10^24 *earth.X = 500 *earth.Y = 500 earth.X = 3200000 earth.Y = 3200000 earth.Speedx= 0 earth.Speedy= 0 *earth.lSkipGravity = .T. private aBodies[1], gui DIMENSION aBodies[3] aBodies[1] = apple && sun aBodies[2] = earth aBodies[3] = apple2 gui = CREATEOBJECT("modelview") earth.oObject = gui.AddBody() earth.oObject.BorderColor = RGB(0, 0, 255) earth.oObject.FillColor = RGB(0, 0, 255) apple.oObject = gui.AddBody() apple.oObject.BorderColor = RGB(255, 0, 0) apple.oObject.FillColor = RGB(255, 0, 0) apple2.oObject = gui.AddBody() apple2.oObject.BorderColor = RGB(0, 255, 0) apple2.oObject.FillColor = RGB(0, 255, 0) gui.Show() RefreshView() DO WHILE .T. GravitationalAcceleration() Inertia() RefreshView() =sleep(1) ENDDO * Gravitational Acceleration... the hard part FUNCTION GravitationalAcceleration * Adjust the acceleration of every object has on every other object LOCAL lo1, lo2, lng, ; lx, ly, ld, ; lxp, lyp FOR EACH lo1 IN aBodies IF lo1.lSkipGravity LOOP ENDIF FOR EACH lo2 IN aBodies IF lo1 = lo2 LOOP ENDIF * First, find out the acceleration due to gravitation * between these two objects lng = Newton(lo1, lo2) * Now apply the acceleration to the second body DO CASE * lo2 is below lo1 CASE lo1.X = lo2.X AND lo1.Y > lo2.Y lo2.SpeedY = lo2.SpeedY + lng * lo2 is above lo1 CASE lo1.X = lo2.X AND lo1.Y < lo2.Y lo2.SpeedY = lo2.SpeedY - lng * lo2 is left of lo1 CASE lo1.Y = lo2.Y AND lo1.X > lo2.X lo2.SpeedX = lo2.SpeedX + lng * lo2 is right of lo1 CASE lo1.Y = lo2.Y AND lo1.X < lo2.X lo2.SpeedX = lo2.SpeedX - lng *Otherwise, we're at an angle OTHERWISE * Step 1, find out the distance between o1 and o2 lx = lo1.X - lo2.X ly = lo1.Y - lo2.Y ld = SQRT(lx^2 + ly^2) * Step 2, find the legs of the new triangle lxp = lx * (lng / ld) lyp = ly * (lng / ld) lo2.SpeedX = lo2.SpeedX + lxp lo2.SpeedY = lo2.SpeedY + lyp ENDCASE ENDFOR ENDFOR RETURN FUNCTION Newton LPARAMETERS to1, to2 LOCAL lnResult * This should calculate the force of gravity based on G * (m1*m2)/r^2 * But for the apple/earth example we know the accelation is 4.9m/s/s lx = to1.X - to2.X ly = to1.Y - to2.Y ld = SQRT(lx^2 + ly^2) lnResult= 6.67300 * 10^-11 * ((to1.Mass * to2.Mass)/ld^2) *WAIT WINDOW TRANSFORM(lnResult) RETURN lnResult && 4.9 FUNCTION Inertia LOCAL loB FOR EACH loB IN aBodies IF loB.SpeedX = 0 AND loB.SpeedY = 0 loB.lChanged = .F. ELSE loB.X = loB.X + loB.SpeedX loB.Y = loB.Y + loB.SpeedY loB.lChanged = .T. ENDIF ENDFOR RETURN FUNCTION RefreshView LOCAL loB gui.LockScreen = .T. FOR EACH loB IN aBodies IF loB.lChanged loB.oObject.Left = loB.X / 10000 loB.oObject.Top = loB.Y / 10000 ENDIF ENDFOR gui.LockScreen = .F. * earth.oObject.Parent.LockScreen = .T. * earth.oObject.Left = earth.X * earth.oObject.Top = earth.Y * earth.oObject.Parent.LockScreen = .F. RETURN DEFINE CLASS body AS Custom Mass = 0 SpeedX = 0 SpeedY = 0 X = 0 Y = 0 lChanged = .T. lSkipGravity = .F. oObject = .NULL. FUNCTION Destroy this.oObject = .NULL. RETURN ENDDEFINE DEFINE CLASS modelview AS Form Desktop = .T. BackColor = 0 Width = 700 Height = 700 ShowWindow = 2 FUNCTION Init * this.WindowState = 2 RETURN FUNCTION AddBody LOCAL lcName, loO lcName = SYS(2015) this.AddObject(lcName, "BodyGui") loO = EVALUATE("this." + lcName) loO.Visible = .T. RETURN loO ENDDEFINE DEFINE CLASS bodygui as Shape fillstyle = 0 curvature = 99 width = 4 height = 4 ENDDEFINE