'******************************************************************************' ' ' Michael "h4tt3n" Nissen's FreeBasic mass-spring-damper tutorial, feb 2008 ' ' Example # 2.1 ' ' Simple two dimensional spring simulation. This program simulates an elastic ' rope made of serially connected springs and masses. (Press esc to quit) ' '******************************************************************************' '' set constants. experiment with these and see how the simulation reacts Const Pi = 4*Atn(1) '' pi (better not change ^^) Const Timestep = 0.01 '' timestep Const Num_Masses = 5 -1 '' number of masses in rope Const Point_Mass = 10 '' mass of each point mass Const Point_Density = 0.01 '' density of each point mass Const Rope_Length = 350 '' rope length Const Spring_Stiffnes = 6000 '' spring stiffnes Const Grav_Acc = 800 '' gravitational acceleration Const Rest_Length = Rope_Length/Num_Masses '' rest length of each spring '' define types '' two dimensional vector type Type Vector_Type As Single X, Y End Type '' mass type including force-, acceleration-, velocity-, and position vectors Type Mass_Type As Single Mass, Density, Radius As Vector_Type Frc, Acc, Vel, Pos End Type '' dimension variables Dim As Vector_Type Length, Normalised_Length, Vel Dim As Mass_Type Mass(Num_Masses) Dim As Single Force, Spring_Length Dim As Integer i, i2, Scrn_Wid, Scrn_Hgt '' set screen width, height, and bit depth Scrn_Wid = 800 Scrn_Hgt = 600 ScreenRes Scrn_Wid, Scrn_hgt, 16 '' set startup conditions of masses For i = 0 To Num_Masses With Mass(i) .Mass = Point_Mass .Density = Point_Density .Radius = ((.Mass/.Density)/((4/3)*pi))^(1/3) .Pos.x = (Scrn_Wid\2)+(i*Rest_Length) .pos.y = 100 End With Next '' main program loop Do '' calculate the spring forces acting upon each point mass in the rope For i = 0 To Num_Masses-1 i2 = i+1 '' spring length (Pythagoras' theorem) '' (we need this to find the magnitude of the spring force) Length.X = Mass(i2).Pos.X-Mass(i).Pos.X Length.Y = Mass(i2).Pos.Y-Mass(i).Pos.Y Spring_Length = Sqr(Length.X*Length.X+Length.Y*Length.Y) '' normalise the spring length vector '' (same as finding sine and cosine to the angle between masses) '' (we need this to find the direction of the spring force) Normalised_Length.X = Length.X/Spring_Length Normalised_Length.Y = Length.Y/Spring_Length '' spring force (Hooke's law of elasticity) Force = -Spring_Stiffnes*(Spring_Length-Rest_Length) '' split spring force into horizontal and vertical vector component '' (each action has an equal opposite reaction, hence the - and + sign) Mass(i).Frc.X -= Force*Normalised_Length.X Mass(i).Frc.Y -= Force*Normalised_Length.Y Mass(i2).Frc.X += Force*Normalised_Length.X Mass(i2).Frc.Y += Force*Normalised_Length.Y Next '' update acceleration, velocity, and position of point masses '' (except for mass 0, which we'd like to keep fixed) For i = 1 To Num_Masses With Mass(i) '' accelerate masses: '' acceleration = force / mass .Acc.X = .Frc.X/.mass .Acc.Y = .Frc.Y/.mass '' add gravity (downwards acceleration) .Acc.Y += Grav_Acc '' update velocity: '' delta velocity = acceleration * delta time '' new velocity = old velocity + delta velocity .Vel.X += .Acc.X*Timestep .Vel.Y += .Acc.Y*Timestep '' update position: '' delta position = velocity * delta time '' new position = old position + delta position .Pos.X += .Vel.X*Timestep .Pos.Y += .Vel.Y*Timestep '' reset force vector .frc.x = 0 .frc.y = 0 End With Next '' display the rope in graphics ScreenLock '' clear screen Cls '' draw springs For i = 0 To Num_Masses-1 i2 = i+1 Line (Mass(i).Pos.X, Mass(i).Pos.Y)-(Mass(i2).Pos.X, Mass(i2).Pos.Y), Rgb(64, 255, 64) Next i '' draw masses For i = 0 To Num_Masses With Mass(i) Circle(.Pos.X, .Pos.Y), .Radius, Rgb(255, 64, 64),,, 1, f End With Next i ScreenUnlock Sleep 1, 1 Loop Until Multikey(1) End