I'm still around :-) Here, as promised, are some space physics examples. Some are rather old, but I'll just post them as they are, warts and all.
First, a vector library and a ball shaped space ship, asteroids in orbit around a central planet, also featuring collision with friction.
You control the yellow ball with the arrow keys. Up = thrust, left/right = rotate, down = stop rotating.
Vec2.bi
Code: Select all
''*******************************************************************************
''
'' FreeBASIC 2D Floating Point Vector Library
'' Written in FreeBASIC 1.05
'' Version 1.3.0, November 2016, Michael "h4tt3n" Nissen
''
'' Function syntax:
''
'' (Return Type) (Name) (Argument Type (, ...)) (Description)
''
'' Vector Absolute ( Vector ) Absolute value
'' Vector AngleToUnit ( Scalar ) unit vector from angle scalar
'' Vector Component ( Vector, Vector ) Vector Component
'' Scalar Dot ( Vector, Vector ) Dot product
'' Vector Dot ( Vector, Scalar ) Dot product
'' Vector Dot ( Scalar, Vector ) Dot product
'' Vector PerpCW ( Vector ) Right hand perpendicular
'' Vector PerpCCW ( Vector ) Left hand perpendicular
'' Vector Unit ( Vector ) Unit Vector
'' Scalar Length ( Vector ) Length
'' Scalar LengthSquared ( Vector ) Length squared
'' Scalar PerpDot ( Vector, Vector ) Perp dot product (2d cross)
'' Vector PerpDot ( Vector, Scalar ) Perp dot product (2d cross)
'' Vector PerpDot ( Scalar, Vector ) Perp dot product (2d cross)
'' Vector Project ( Vector, Vector ) Vector Projection
'' Vector RandomizeSquare ( Scalar ) Randomize in range +/- value
'' Vector RandomizeCircle ( Scalar ) Randomize in range +/- value
'' Vector Rotate ( Vector ) Rotate
'' Scalar UnitToAngle ( Vector ) angle scalar from unit vector
''
'' Library supports both member and non-member function useage:
''
'' A.function(B) <-> function(A, B)
''
''*******************************************************************************
''
#Ifndef __VEC2_BI__
#Define __VEC2_BI__
'' Vec2 Vector class
Type Vec2
Public:
'' Vec2 constructor declarations
Declare Constructor ()
Declare Constructor ( ByRef v As Const Vec2 )
Declare Constructor ( ByVal x As Const Single, ByVal y As Const Single )
'' Vec2 destructor
Declare Destructor()
'' Vec2 assignment operator (=)
Declare Operator Let ( ByRef B As Const Vec2 )
'' Vec2 compound arithmetic member operator declarations
Declare Operator += ( ByRef B As Const Vec2 )
Declare Operator -= ( ByRef B As Const Vec2 )
Declare Operator *= ( ByRef B As Const Vec2 )
Declare Operator *= ( ByVal B As Const Single )
Declare Operator /= ( ByVal B As Const Single )
'' Vec2 member function declarations
Declare Const Function Absolute_ () As Vec2
Declare Const Function PerpCW () As Vec2
Declare Const Function PerpCCW () As Vec2
Declare Const Function Unit () As Vec2
Declare Const Function Length () As Single
Declare Const Function LengthSquared () As Single
Declare Const Function Dot ( ByRef B As Const Vec2 ) As Single
Declare Const Function Dot ( ByVal B As Const Single ) As Vec2
Declare Const Function PerpDot ( ByRef B As Const Vec2 ) As Single
Declare Const Function PerpDot ( ByVal B As Const Single ) As Vec2
Declare Const Function Project ( ByRef B As Const Vec2 ) As Vec2
Declare Const Function Component ( ByRef B As Const Vec2 ) As Vec2
Declare Const Function RandomizeCircle ( ByVal B As Const Single ) As Vec2
Declare Const Function RandomizeSquare ( ByVal B As Const Single ) As Vec2
Declare Const Function RotateCW ( ByRef B As Const Vec2 ) As Vec2
Declare Const Function RotateCCW ( ByRef B As Const Vec2 ) As Vec2
Declare Const Function RotateCW ( ByRef B As Const Single ) As Vec2
Declare Const Function RotateCCW ( ByRef B As Const Single ) As Vec2
'' Vec2 variables
As Single x, y
End Type
'' Vec2 unary arithmetic non-member operator declarations
Declare Operator - ( ByRef B As Const Vec2 ) As Vec2
'' Vec2 binary arithmetic non-member operator declarations
Declare Operator + ( ByRef A As Const Vec2 , ByRef B As Const Vec2 ) As Vec2
Declare Operator - ( ByRef A As Const Vec2 , ByRef B As Const Vec2 ) As Vec2
Declare Operator * ( ByVal A As Const Single, ByRef B As Const Vec2 ) As Vec2
Declare Operator * ( ByRef A As Const Vec2 , ByVal B As Const Single ) As Vec2
Declare Operator * ( ByRef A As Const Vec2 , ByRef B As Const Vec2 ) As Vec2
Declare Operator / ( ByRef A As Const Vec2 , ByVal B As Const Single ) As Vec2
'' Vec2 binary relational non-member operator declarations
Declare Operator = ( ByRef A As Const Vec2, ByVal B As Const Vec2 ) As Integer
Declare Operator <> ( ByRef A As Const Vec2, ByVal B As Const Vec2 ) As Integer
Declare Operator < ( ByRef A As Const Vec2, ByVal B As Const Vec2 ) As Integer
Declare Operator > ( ByRef A As Const Vec2, ByVal B As Const Vec2 ) As Integer
'' Vec2 non-member function declarations
Declare Function Absolute_ OverLoad ( ByRef A As Const Vec2 ) As Vec2
Declare Function Unit ( ByRef A As Const Vec2 ) As Vec2
Declare Function Length ( ByRef A As Const Vec2 ) As Single
Declare Function LengthSquared ( ByRef A As Const Vec2 ) As Single
Declare Function Dot Overload ( ByRef A As Const Vec2 , ByRef B As Const Vec2 ) As Single
Declare Function Dot ( ByRef A As Const Vec2 , ByVal B As Const Single ) As Vec2
Declare Function Dot ( ByVal A As Const Single, ByRef B As Const Vec2 ) As Vec2
Declare Function PerpDot OverLoad ( ByRef A As Const Vec2 , ByRef B As Const Vec2 ) As Single
Declare Function PerpDot ( ByRef A As Const Vec2 , ByVal B As Const Single ) As Vec2
Declare Function PerpDot ( ByVal A As Const Single, ByRef B As Const Vec2 ) As Vec2
Declare Function Project ( ByRef A As Const Vec2 , ByRef B As Const Vec2 ) As Vec2
Declare Function Component ( ByRef A As Const Vec2 , ByRef B As Const Vec2 ) As Vec2
Declare Function RandomizeCircle ( ByRef A As Const Vec2 , ByVal B As Const Single ) As Vec2
Declare Function RandomizeSquare ( ByRef A As Const Vec2 , ByVal B As Const Single ) As Vec2
Declare Function RotateCW OverLoad ( ByRef A As Const Vec2, ByVal B As Const Single ) As Vec2
Declare Function RotateCCW OverLoad ( ByRef A As Const Vec2, ByVal B As Const Single ) As Vec2
Declare Function AngleToUnit ( ByVal A As Const Single ) As Vec2
Declare Function UnitToAngle ( ByRef A As Const Vec2 ) As Single
'' Vec2 constructors
Constructor Vec2()
This.x = 0.0 : This.y = 0.0
End Constructor
Constructor Vec2( ByRef v As Const Vec2 )
This = v
End Constructor
Constructor Vec2( ByVal x As Const Single, ByVal y As Const Single )
This.x = x : This.y = y
End Constructor
'' Destructor
Destructor Vec2()
End Destructor
''
Operator Vec2.Let ( ByRef B As Const Vec2 )
If ( Not @This = @B ) Then
This.x = B.x : This.y = B.y
EndIf
End Operator
'' Vec2 compound arithmetic member operators
Operator Vec2.+= ( ByRef B As Const Vec2 )
This.x += B.x : This.y += B.y
End Operator
Operator Vec2.-= ( ByRef B As Const Vec2 )
This.x -= B.x : This.y -= B.y
End Operator
Operator Vec2.*= ( ByRef B As Const Vec2 )
This.x *= B.x : This.y *= B.y
End Operator
Operator Vec2.*= ( ByVal B As Const Single )
This.x *= B : This.y *= B
End Operator
Operator Vec2./= ( ByVal B As Const Single )
This.x /= B : This.y /= B
End Operator
'' Vec2 member functions
Function Vec2.Absolute_() As Vec2
Return Vec2( Abs( This.x ), Abs( This.y ) )
End Function
Function Vec2.PerpCW() As Vec2
Return Vec2( This.y, -This.x )
End Function
Function Vec2.PerpCCW() As Vec2
Return Vec2( -This.y, This.x )
End Function
Function Vec2.Unit() As Vec2
Return IIf( This <> Vec2( 0.0, 0.0 ) , Vec2( This / This.Length() ) , Vec2( 0.0, 0.0 ) )
End Function
Function Vec2.Length() As Single
'Dim As Single length_squared = This.LengthSquared()
'Return Sqr( length_squared )
Return Sqr( This.LengthSquared() )
End Function
Function Vec2.LengthSquared() As Single
'Return This.Dot( This )
Return ( This.x * This.x + This.y * This.y )
End Function
Function Vec2.Dot( ByVal B As Const Single ) As Vec2
Return Vec2( This.x * B, This.y * B )
End Function
Function Vec2.Dot( ByRef B As Const Vec2 ) As Single
Return ( This.x * B.x + This.y * B.y )
End Function
Function Vec2.PerpDot( ByVal B As Const Single ) As Vec2
Return Vec2( -This.y * B, This.x * B )
End Function
Function Vec2.PerpDot( ByRef B As Const Vec2 ) As Single
Return ( -This.y * B.x + This.x * B.y )
'Return ( This.x * B.y - This.y * B.x )
'Return ( This.Dot( B.Perp() ) )
End Function
Function Vec2.Project( ByRef B As Const Vec2 ) As Vec2
Return ( B.Dot( This ) / This.Dot( This ) ) * This
End Function
Function Vec2.Component( ByRef B As Const Vec2 ) As Vec2
Return ( This.Dot( B ) / B.Dot( B ) ) * B
End Function
Function Vec2.RandomizeCircle( ByVal B As Const Single ) As Vec2
Dim As Single a = Rnd() * 8.0 * Atn( 1.0 )
Dim As Single r = Sqr( Rnd() * B * B )
Return Vec2( Cos( a ), Sin( a ) ) * r
End Function
Function Vec2.RandomizeSquare( ByVal B As Const Single ) As Vec2
Return Vec2( ( Rnd() - Rnd() ) * B, ( Rnd() - Rnd() ) * B )
End Function
Function Vec2.RotateCW( ByRef B As Const Vec2 ) As Vec2
Return Vec2( B.Dot( This ), B.PerpDot( This ) )
End Function
Function Vec2.RotateCCW( ByRef B As Const Vec2 ) As Vec2
'Dim As vec2 v = Vec2( B.x, -B.y )
'Return Vec2( v.Dot( This ), v.PerpDot( This ) )
Return Vec2( B.x * This.x - B.y * This.y , B.y * This.x + B.x * This.y )
''perpccw = -y, x
End Function
Function Vec2.RotateCW( ByRef B As Const Single ) As Vec2
Dim As Vec2 v = Vec2( Cos( B ), Sin( B ) )
Return This.RotateCW( v )
End Function
Function Vec2.RotateCCW( ByRef B As Const Single ) As Vec2
Dim As Vec2 v = Vec2( Cos( B ), Sin( B ) )
Return This.RotateCCW( v )
End Function
'' Vec2 unary arithmetic non-member operators
Operator - ( ByRef B As Const Vec2 ) As Vec2
Return Vec2( -B.x, -B.y )
End Operator
'' Vec2 binary arithmetic non-member operators
Operator + ( ByRef A As Const Vec2, ByRef B As Const Vec2 ) As Vec2
Return Vec2( A.x + B.x, A.y + B.y )
End Operator
Operator - ( ByRef A As Const Vec2, ByRef B As Const Vec2 ) As Vec2
Return Vec2( A.x - B.x, A.y - B.y )
End Operator
Operator * ( ByVal A As Const Single, ByRef B As Const Vec2 ) As Vec2
Return Vec2( A * B.x, A * B.y)
End Operator
Operator * ( ByRef A As Const Vec2, ByVal B As Const Single ) As Vec2
Return Vec2( A.x * B, A.y * B)
End Operator
Operator * ( ByRef A As Const Vec2, ByRef B As Const Vec2 ) As Vec2
Return Vec2( A.x * B.x, A.y * B.y )
End Operator
Operator / ( ByRef A As Const Vec2, ByVal B As Const Single ) As Vec2
Return Vec2( A.x / B, A.y / B )
End Operator
'' Vec2 binary relational non-member operators
Operator = ( ByRef A As Const Vec2, ByVal B As Const Vec2 ) As Integer
Return ( A.x = B.x ) And ( A.y = B.y )
End Operator
Operator <> ( ByRef A As Const Vec2, ByVal B As Const Vec2 ) As Integer
Return ( A.x <> B.x ) Or ( A.y <> B.y )
End Operator
Operator < ( ByRef A As Const Vec2, ByVal B As Const Vec2 ) As Integer
Return ( A.x < B.x ) And ( A.y < B.y )
End Operator
Operator > ( ByRef A As Const Vec2, ByVal B As Const Vec2 ) As Integer
Return ( A.x > B.x ) And ( A.y > B.y )
End Operator
'' Vec2 non-member functions
Function Absolute_( ByRef A As Const Vec2 ) As Vec2
Return A.Absolute_()
End Function
Function Unit( ByRef A As Const Vec2 ) As Vec2
Return A.Unit()
End Function
Function Length( ByRef A As Const Vec2 ) As Single
Return A.Length()
End Function
Function LengthSquared( ByRef A As Const Vec2 ) As Single
Return A.LengthSquared()
End Function
Function Dot( ByRef A As Const Vec2, ByRef B As Const Vec2 ) As Single
Return A.Dot( B )
End Function
Function Dot( ByRef A As Const Vec2, ByVal B As Const Single ) As Vec2
Return A.Dot( B )
End Function
Function Dot( ByVal A As Const Single, ByRef B As Const Vec2 ) As Vec2
Return B.Dot( -A )
End Function
Function PerpDot( ByRef A As Const Vec2, ByRef B As Const Vec2 ) As Single
Return A.PerpDot( B )
End Function
Function PerpDot( ByRef A As Const Vec2, ByVal B As Const Single ) As Vec2
Return A.PerpDot( B )
End Function
Function PerpDot( ByVal A As Const Single, ByRef B As Const Vec2 ) As Vec2
Return B.PerpDot( -A )
End Function
Function Project( ByRef A As Const Vec2, ByRef B As Const Vec2 ) As Vec2
Return A.Project( B )
End Function
Function Component( ByRef A As Const Vec2, ByRef B As Const Vec2 ) As Vec2
Return A.Component( B )
End Function
Function RandomizeCircle( ByRef A As Const Vec2, ByVal B As Const Single ) As Vec2
Return A.RandomizeCircle( B )
End Function
Function RandomizeSquare( ByRef A As Const Vec2, ByVal B As Const Single ) As Vec2
Return A.RandomizeSquare( B )
End Function
Function RotateCW( ByRef A As Const Vec2, ByVal B As Const Single ) As Vec2
Return A.RotateCW( B )
End Function
Function RotateCCW( ByRef A As Const Vec2, ByVal B As Const Single ) As Vec2
Return A.RotateCCW( B )
End Function
Function AngleToUnit( ByVal A As Const Single ) As Vec2
Return Vec2( Cos( A ), Sin( A ) )
End Function
Function UnitToAngle( ByRef A As Const Vec2 ) As Single
Return ATan2( A.y, A.x )
End Function
#EndIf __VEC2_BI__
And here the physics doodle:
Code: Select all
'' Ball - Ball collision detection and response with friction.
'' Written by Michael "h4tt3n" Schmidt Nissen
''
''
#include "fbgfx.bi"
#include "Vec2.bi"
''
Const pi = 4*atn(1)
Const G = 4
const num_balls = 32
const rest_fps = 60 '' ideal framerate
'const inv_rest_fps = 1.0 / (rest_fps+2) '' inverse ideal framerate
Const inv_rest_fps = 1.0 / rest_fps '' inverse ideal framerate
Const dt = inv_rest_fps '' timestep, delta time
Const inv_dt = 1.0 / dt '' timestep, delta time
Const StaticFrictionVelocity = 1.0
randomize timer
''
type ball_type
As UInteger col
as Vec2 Impulse
as Vec2 Velocity
as Vec2 Position
as Vec2 AngleVector
as Single angular_impulse, ang_Velocity, sin_ang, cos_ang, ang_Position, mass, InverseMass, dens, radius, _
RadiusSquared, I, InverseI, CollisionStiffness, COllisionDamping, dynamicfriction, staticfriction
end type
dim shared as Vec2 dst, separation_vector, closest_point
dim shared as ball_type ptr ball
dim shared as Single dst_sqd, radius, RadiusSquared, distance
dim shared as integer a, b, scrn_wid, scrn_hgt
dim shared as integer FPS, FPS_Counter
dim shared as Single FPS_Timer, t0
declare sub InitBall(byref a as ball_type)
declare sub BallBallCollisionDetection()
Declare Sub Controls()
Declare Sub Gravity()
declare sub Integrate()
declare sub DrawSceneToScreen()
declare sub brake()
scrn_wid = 1000: scrn_hgt = 800
ScreenRes scrn_wid, scrn_hgt, 32
WindowTitle "force based 2d ball-ball collision with friction"
Color RGB(0, 0, 0), RGB(192, 192, 244)
'color 0, rgb(255, 255, 255)
ball = New Ball_Type[Num_Balls]
with ball[0]
Dim As UByte Clr = ((Num_Balls-a)/num_Balls)*255
.col = rgb(Clr, 255, clr)
.mass = 800000
.InverseMass = 1/.mass
.dens = 0.2
.radius = ((.mass/.dens)/((4/3)*pi))^(1/3)
.RadiusSquared = .radius*.radius
.I = 0.5*.mass*.RadiusSquared '' flat disc
'.I = (2*.mass*.RadiusSquared)/5 '' solid sphere
.InverseI = 1/.I
.Position.x = scrn_wid\2
.Position.y = scrn_hgt\2
.ang_Velocity = 0.0
.ang_Position = rnd*2*pi
.cos_ang = cos(.ang_Position)
.sin_ang = sin(.ang_Position)
.CollisionStiffness = 0.5
.COllisionDamping = 0.1
.dynamicfriction = 0.5
.staticfriction = 1.0
end with
'' set startup condition
for a = 1 to num_balls-1
Dim As Single angle = 2*pi*Rnd
Dim As Single radius = ball[0].radius + 128 + Rnd*256
with ball[a]
'' brightest first, darkest last
Dim As UByte Clr = ((Num_Balls-a)/num_Balls)*255
.col = rgb(Clr, 255, clr)
.mass = 10+(rnd*80^(1/2))^2
.InverseMass = 1/.mass
.dens = 0.01
.radius = ((.mass/.dens)/((4/3)*pi))^(1/3)
.RadiusSquared = .radius*.radius
'.I = 0.5*.mass*.RadiusSquared '' flat disc
.I = (2*.mass*.RadiusSquared)/5 '' solid sphere
.InverseI = 1/.I
.Position.x = ball[0].Position.x + Cos(angle)*Radius
.Position.y = ball[0].Position.y + Sin(angle)*Radius
.Velocity.X = Sqr((G*ball[0].mass)/radius)*Sin(-Angle)
.Velocity.Y = Sqr((G*ball[0].mass)/radius)*Cos(Angle)
ball[0].Velocity -= .Velocity*(.mass/ball[0].mass)
.ang_Position = rnd*2*pi
.cos_ang = cos(.ang_Position)
.sin_ang = sin(.ang_Position)
.ang_Velocity = 0.0'(Rnd-Rnd) * 0.2
.CollisionStiffness = 0.5
.COllisionDamping = 0.1
.dynamicfriction = 0.5
.staticfriction = 1.0
end with
Next
With ball[1]
.col = RGB(255, 255, 64)
.mass = 20
.InverseMass = 1/.mass
.dens = 0.001
.radius = ((.mass/.dens)/((4/3)*pi))^(1/3)
.RadiusSquared = .radius*.radius
.I = 0.5*.mass*.radius*.radius
.InverseI = 1/.I
End With
''----------------------------------------------------------------------------''
Do
BallBallCollisionDetection()
Integrate()
DrawSceneToScreen()
brake()
loop until multikey(1)
Delete[] Ball
end
''----------------------------------------------------------------------------''
sub BallBallCollisionDetection()
For a As Integer = 0 to num_balls-2
For b As Integer = a+1 to num_balls-1
Dim As Vec2 DistanceVector = ball[a].Position-ball[b].Position
Dim As Single DistanceSquared = LengthSquared(DistanceVector)
Dim As Single rest_distance = ball[a].radius + ball[b].radius
If DistanceSquared > ( rest_distance * rest_distance ) Then Continue For
Dim As Single Distance = sqr(DistanceSquared)
Dim as Vec2 NormalVector = IIf( Not Distance = 0.0 , DistanceVector/Distance , Vec2( 0.0, 0.0 ) )
Dim as Vec2 TangentVector = NormalVector.PerpCW()
Dim as Single distance_error = distance - rest_distance
Dim As Vec2 contact_a = ball[a].Position-ball[a].radius*NormalVector
Dim As Vec2 contact_b = ball[b].Position+ball[b].radius*NormalVector
Dim as Vec2 contact_velocity_a = ball[a].Velocity+ball[a].ang_Velocity*(ball[a].Position-contact_a).PerpCW()
Dim as Vec2 contact_velocity_b = ball[b].Velocity+ball[b].ang_Velocity*(ball[b].Position-contact_b).PerpCW()
Dim as Vec2 contact_velocity = contact_velocity_a - contact_velocity_b
Dim as Single contact_velocityNormal = Dot(contact_velocity, normalVector)
If contact_velocityNormal > 0.0 Then Continue For
Dim As Single K = ( ball[a].CollisionStiffness + ball[b].CollisionStiffness ) * 0.5
Dim As Single D = ( ball[a].CollisionDamping + ball[b].CollisionDamping ) * 0.5
'dim as Single impulseNormal = -(1+Restitution)*contact_velocityNormal/(ball[a].InverseMass+ball[b].InverseMass)
Dim as Single impulseNormal = -(distance_error*inv_dt*k + contact_velocityNormal*D ) * ( 1.0 / (ball[a].InverseMass+ball[b].InverseMass) )
Dim As Single contact_velocityTangent = Dot(contact_velocity, tangentvector)
Dim As Single FrictionCoefficient = IIf( Abs(contact_velocityTangent) < StaticFrictionVelocity, _
( Ball[a].StaticFriction + Ball[b].StaticFriction ) * 0.5, _
( Ball[a].DynamicFriction + Ball[b].DynamicFriction ) * 0.5 )
Dim as Single MaxImpulseTangent = -contact_velocityTangent * ( 1.0 / (Ball[a].InverseMass+Ball[b].InverseMass+_
Ball[a].RadiusSquared*Ball[a].InverseI+Ball[b].RadiusSquared*Ball[b].InverseI) )
Dim As Single ImpulseTangent = IIf( Abs( MaxImpulseTangent ) < ( FrictionCoefficient * ImpulseNormal ), _
MaxImpulseTangent, _
Sgn( MaxImpulseTangent ) * ( FrictionCoefficient * ImpulseNormal ) )
'Dim As Single ImpulseTangent = MaxImpulseTangent
Dim As Vec2 Impulse = ImpulseNormal * NormalVector + ImpulseTangent * TangentVector
ball[a].Impulse += Impulse*ball[a].InverseMass
ball[a].angular_impulse += PerpDot(Impulse, ball[a].Position-contact_a)*ball[a].InverseI
ball[b].Impulse -= Impulse*ball[b].InverseMass
ball[b].angular_impulse -= Perpdot(Impulse, ball[b].Position-contact_b)*ball[b].InverseI
Next
Next
End Sub
Sub Controls()
With Ball[1]
If MultiKey(&h48) Then
.Impulse.X += Cos(.Ang_Position)*100*.InverseMass
.Impulse.Y += Sin(.Ang_Position)*100*.InverseMass
EndIf
'If MultiKey(&h4b) Then .Ang_Position -= 0.05
'If MultiKey(&h4d) Then .Ang_Position += 0.05
If MultiKey(&h4b) Then .ang_Velocity -= 0.1
If MultiKey(&h4d) Then .ang_Velocity += 0.1
If MultiKey(&h50) Then .ang_Velocity = 0
'.ang_Velocity = 0
.cos_ang = cos(.ang_Position)
.sin_ang = sin(.ang_Position)
End With
End Sub
Sub Gravity()
For a As Integer = 0 to num_balls-2
For b As Integer = a+1 to num_balls-1
Dim As Vec2 DistanceVector = ball[a].Position-ball[b].Position
Dim As Single DistanceSquared = LengthSquared(DistanceVector)
Dim As Single DistanceCubed = DistanceSquared*Sqr(DistanceSquared)
Ball[a].Impulse -= Ball[b].mass * G * DT * DistanceVector / DistanceCubed
Ball[b].Impulse += Ball[a].mass * G * DT * DistanceVector / DistanceCubed
Next
Next
End Sub
Sub Integrate()
Controls()
Gravity()
For a As Integer = 0 to num_balls-1
With Ball[a]
.Velocity += .Impulse
.Position += .Velocity * dt
.Impulse = Vec2( 0.0, 0.0 )
.ang_Velocity += .angular_impulse
.ang_Position += .ang_Velocity * dt
.angular_impulse = 0.0
.cos_ang = cos(.ang_Position)
.sin_ang = sin(.ang_Position)
end With
Next
End Sub
sub DrawSceneToScreen()
ScreenLock()
Cls
locate 2, (scrn_wid\8)-3: print using "###"; fps
for a As Integer = 0 to num_balls-1
with ball[a]
circle (.Position.x, .Position.y), .radius, 0,,,1, f
circle (.Position.x, .Position.y), .radius-2, .col,,,1, f
Line(.Position.x, .Position.y)-(.Position.x+.cos_ang*.radius, .Position.y+.sin_ang*.radius), 0
end With
Next
ScreenUnLock()
end sub
sub brake()
if timer < fps_timer then
fps_counter += 1
Else
fps_timer = timer+1
fps = fps_counter
fps_counter = 0
end if
Do while ( Timer - t0 ) < ( inv_rest_fps )
Sleep 1, 1
Loop
t0 = timer
end Sub