Alright, the deadline draws near.
Here's my final entry:
`================================================
` Boids Simulation
` Written by Kira Vakaan
`================================================
`Setup Environment
set display mode 1024,768,32,1
sync on
autocam off
hide mouse
`In a fit of rage at DBPro's vector and matrix command set, I wrote many of my own some time back.
`I've included only the one's I need for this project.
type Vector
x as float
y as float
z as float
w as float
endtype
`Global vector used for returning
global v as Vector
#constant FieldRadius 200
#constant SqrFieldRadius 40000
`Constants for Boid behavior (all squared to avoid using sgrt())
#constant CohesionDistance 900 `Head towards Boids up to 30 units away
#constant AlignmentDistance 225 `Align with Boids up to 15 units away
#constant BoidCrowdingDistance 169 `Stay away from Boids up to 13 units away
#constant EnemyDistance 400 `Avoid enemies up to 20 units away
`#constant ObstacleDistance 400
`Constant for Enemy behavior
#constant EnemyCrowdingDistance 256 `Stay away from Enemies up to 16 units away
type Boid
Object as integer
Position as Vector
Look as Vector
Speed# as float
endtype
type Enemy
Object as integer
Position as Vector
Look as Vector
Speed# as float
Radius# as float
endtype
type Obstacle
Object as integer
Position as Vector
Radius# as float
endtype
`Dynamic Arrays
global BoidCount=150
dim Boids(0) as Boid : empty array Boids(0)
global EnemyCount=10
dim Enemies(0) as Enemy : empty array Enemies(0)
global ObstacleCount=10
dim Obstacles(0) as Obstacle : empty array Obstacles(0)
`Setup Field Sphere
make object sphere 1000,-2*FieldRadius
set object wireframe 1000,1
fog on
fog distance 400
fog color 0xFFBBBBBB
color backdrop 0xFFBBBBBB
`Setup Objects
SetupBoids()
SetupEnemies()
SetupObstacles()
`SetVec(0,0,0,1)
`Obstacles(0).Position=v
`position object Obstacles(0).Object,v.x,v.y,v.z
gosub SetupCamera
`Temporary variables used mainly to avoid excessive array access
TempB as Boid
TempE as Enemy
TempO as Obstacle
Temp as Vector
Paused=1
do
`Print everything
set cursor 0,0
print "FPS: ";screen fps()
print "Boids: ";BoidCount
print "Enemies: ";EnemyCount
print "Obstacles: ";ObstacleCount
print
select Paused
case 0 : print "Simulation Running" : endcase
case 1 : print "Simulation Paused" : endcase
endselect
print
print "Target Group: ";
select TargetGroup
case 0: print "None" : endcase
case 1: print "Boids" : print "Target: ";CameraTarget+1 : endcase
case 2: print "Enemies" : print "Target: ";CameraTarget+1 : endcase
endselect
print "Follow Distance: ";TargetFollowDist#
print
if TargetGroup>0
print "Control Type: ";
select ControlType
case 0: print "Automatic" : endcase
case 1: print "Manual" : endcase
endselect
if TargetGroup=1
TempB=Boids(CameraTarget)
print "Position: ( ";TempB.Position.x;" , ";TempB.Position.y;" , ";TempB.Position.z;" )"
print "Look Vector: ( ";TempB.Look.x;" , ";TempB.Look.y;" , ";TempB.Look.z;" )"
print "Speed: ";TempB.Speed#
endif
if TargetGroup=2
TempE=Enemies(CameraTarget)
print "Position: ( ";TempE.Position.x;" , ";TempE.Position.y;" , ";TempE.Position.z;" )"
print "Look Vector: ( ";TempE.Look.x;" , ";TempE.Look.y;" , ";TempE.Look.z;" )"
print "Speed: ";TempE.Speed#
endif
print
endif
if keystate(35)=0
print "Hold 'H' to display control help"
else
print "Spacebar - Pause/Unpause Simulation"
print "Mouse Movement - Move camera around target."
print "Mouse Scroll Wheel - Change Follow Distance to Target"
print "Up, Down - Cycle through Target Groups: None, Boids, Enemies"
print "Right, Left - Cycle through members of current Target Group"
print "Tab - Toggle between Automatic and Manual control of current Target"
print "Manual Controls:"
print " W, S - Pitch Target"
print " A, D - Rotate Target"
print " Left Mouse Button - Increase Target speed"
print " Right Mouse Button - Decrease Target speed"
endif
`Toggle pause
if spacekey()=1 and SpaceHold=0 then SpaceHold=1 : Paused=(Paused+1)%%2
if spacekey()=0 and SpaceHold=1 then SpaceHold=0
if not Paused
gosub ControlBoids
gosub ControlEnemies
endif
gosub ControlCamera
sync
loop
end
SetupCamera:
set camera range 0.01,1000
global TargetGroup=0
global CameraTarget=0
global ControlType=0
TargetFollowDist#=200 : FollowDist#=200
TargetXAng#=0 : TargetYAng#=0
XAng#=0 : YAng#=0
return
ControlBoids:
for a=0 to BoidCount-1
if TargetGroup=1 and CameraTarget=a and ControlType=1 `Manual control of the current Boid
TempB=Boids(a)
`Turn Boid
if keystate(17) then pitch object down TempB.Object,2
if keystate(31) then pitch object up TempB.Object,2
if keystate(30) then turn object left TempB.Object,2
if keystate(32) then turn object right TempB.Object,2
`Get new look vector
position object TempB.Object,0,0,0
move object TempB.Object,1
SetVec(object position x(TempB.Object),object position y(TempB.Object),object position z(TempB.Object),1)
TempB.Look=v
`Change speed
if mouseclick()=1 then inc TempB.Speed#,0.01 : if TempB.Speed#>1.5 then TempB.Speed#=1.5
if mouseclick()=2 then dec TempB.Speed#,0.01 : if TempB.Speed#<0.0 then TempB.Speed#=0.0
else `Automatic control
`Apply Rules
CohereToFlock(a)
AlignWithFlock(a)
BoidAvoidCrowding(a)
MoveTowardsCenter(a)
AvoidEnemies(a)
BoidAvoidObstacles(a)
TempB=Boids(a)
endif
OrientBoid(TempB)
move object TempB.Object,TempB.Speed#
`Store new position
BoidWrapField(TempB)
TempB.Position.x=object position x(TempB.Object)
TempB.Position.y=object position y(TempB.Object)
TempB.Position.z=object position z(TempB.Object)
Boids(a)=TempB
next a
return
ControlEnemies:
for a=0 to EnemyCount-1
if TargetGroup=2 and CameraTarget=a and ControlType=1 `Manual
TempE=Enemies(a)
if keystate(17) then pitch object down TempE.Object,2
if keystate(31) then pitch object up TempE.Object,2
if keystate(30) then turn object left TempE.Object,2
if keystate(32) then turn object right TempE.Object,2
position object TempE.Object,0,0,0
move object TempE.Object,1
SetVec(object position x(TempE.Object),object position y(TempE.Object),object position z(TempE.Object),1)
TempE.Look=v
if mouseclick()=1 then inc TempE.Speed#,0.01 : if TempE.Speed#>1.5 then TempE.Speed#=1.5
if mouseclick()=2 then dec TempE.Speed#,0.01 : if TempE.Speed#<0.0 then TempE.Speed#=0.0
else `Automatic
`Apply Rules
PickTarget(a)
EnemyAvoidCrowding(a)
EnemyAvoidObstacles(a)
TempE=Enemies(a)
endif
OrientEnemy(TempE)
move object TempE.Object,TempE.Speed#
EnemyWrapField(TempE)
TempE.Position.x=object position x(TempE.Object)
TempE.Position.y=object position y(TempE.Object)
TempE.Position.z=object position z(TempE.Object)
Enemies(a)=TempE
next a
return
ControlCamera:
select TargetGroup
`None
case 0: SetVec(0,0,0,1) : Temp=v : endcase `Focus around the world's center
`Boids
case 1
if BoidCount>0
`if Camera's target no longer exists, take the last available
if CameraTarget>BoidCount-1 then CameraTarget=BoidCount-1 : ControlType=0
Temp=Boids(CameraTarget).Position
else
`No more Boids
TargetGroup=0 : gosub ChangeTargetGroup
endif
endcase
`Enemies
case 2: Temp=Enemies(CameraTarget).Position : endcase
endselect
FollowDist#=curvevalue(TargetFollowDist#,FollowDist#,10)
XAng#=curveangle(TargetXAng#,XAng#,10)
YAng#=curveangle(TargetYAng#,YAng#,10)
position camera 0,Temp.x,Temp.y,Temp.z
rotate camera 0,XAng#,YAng#,0
move camera 0,-FollowDist#
inc TargetXAng#,mousemovey() `Rotate camera around
inc TargetYAng#,mousemovex() `-
dec TargetFollowDist#,mousemovez()/20.0 `Scroll wheel zooms
if upkey()=1 and UpHold=0
UpHold=1
TargetGroup=(TargetGroup+1)%%3
if TargetGroup=1 and BoidCount=0 then TargetGroup=2 `If there aren't any Boids, change group to Enemies
if TargetGroup=2 and EnemyCount=0 then TargetGroup=0 `If there aren't any Enemies, change group to None
gosub ChangeTargetGroup
endif
if upkey()=0 and UpHold=1 then UpHold=0
if downkey()=1 and DownHold=0
DownHold=1
dec TargetGroup
if TargetGroup<0 then TargetGroup=2
if TargetGroup=1 and BoidCount=0 then TargetGroup=2
if TargetGroup=2 and EnemyCount=0 then TargetGroup=0
gosub ChangeTargetGroup
endif
if downkey()=0 and DownHold=1 then DownHold=0
`Cycle through members of current group
if rightkey()=1 and RightHold=0 then RightHold=1 : gosub ChangeTarget
if rightkey()=0 and RightHold=1 then RightHold=0
if leftkey()=1 and LeftHold=0 then LeftHold=1 : gosub ChangeTarget
if leftkey()=0 and LeftHold=1 then LeftHold=0
if TargetGroup>0 `If group is not None,
if keystate(15)=1 and TabHold=0 then TabHold=1 : ControlType=(ControlType+1)%%2 `Toggle ControlType
if keystate(15)=0 and TabHold=1 then TabHold=0
endif
return
ChangeTargetGroup: `Set default following distances and fog distances
CameraTarget=0 : ControlType=0
select TargetGroup
case 0: TargetFollowDist#=200 : fog distance 400 : endcase
case 1: TargetFollowDist#=30 : fog distance 300 : endcase
case 2: TargetFollowDist#=50 : fog distance 320 : endcase
endselect
return
ChangeTarget:
if RightHold
select TargetGroup
case 1: if BoidCount>0 : ControlType=0 : CameraTarget=(CameraTarget+1)%%BoidCount : endif : endcase
case 2: if EnemyCount>0 : ControlType=0 : CameraTarget=(CameraTarget+1)%%EnemyCount : endif : endcase
endselect
endif
if LeftHold
select TargetGroup
case 1: if BoidCount>0 : ControlType=0 : dec CameraTarget : if CameraTarget<0 : CameraTarget=BoidCount-1 : endif : endif : endcase
case 2: if EnemyCount>0 : ControlType=0 : dec CameraTarget : if CameraTarget<0 : CameraTarget=EnemyCount-1 : endif : endif : endcase
endselect
endif
return
function CohereToFlock(obj)
Look as Vector
Current as Boid
Current=Boids(obj)
Count=0
for a=0 to BoidCount-1
if a<>obj `Skip current Boid
v=Boids(a).Position
SubtractVec(v,Current.Position) `Get difference in position
Distance#=SqrLengthVec(v) `Get distance^2
if Distance#<CohesionDistance `If within the range, add it to the new Look vector
AddVec(v,Look) : Look=v
inc Count
endif
endif
next a
if Count `If there were any Boids in range,
NormalizeVec(Look)
CurveVec(v,Current.Look,40) : NormalizeVec(v) `Blend current Look vector with the new one
Boids(obj).Look=v
endif
endfunction
function AlignWithFlock(obj) `Average Look vectors and speeds of near-by Boids
Look as Vector
Speed# as float
Current as Boid
Current=Boids(obj)
Count=0
for a=0 to BoidCount-1
if a<>obj
v=Boids(a).Position
SubtractVec(v,Current.Position)
Distance#=SqrLengthVec(v)
if Distance#<AlignmentDistance
v=Boids(a).Look
AddVec(v,Look) : Look=v
inc Speed#,Boids(a).Speed#
inc Count
endif
endif
next a
if Count
NormalizeVec(Look)
Speed#=Speed#/Count
CurveVec(v,Current.Look,30) : NormalizeVec(v) : Current.Look=v
Current.Speed#=curvevalue(Speed#,Current.Speed#,30)
Boids(obj)=Current
endif
endfunction
function BoidAvoidCrowding(obj) `Point current Boid away from close crowds of Boids, taking into account distance to neighbors
Look as Vector
Current as Boid
Current=Boids(obj)
Count=0
for a=0 to BoidCount-1
if a<>obj
v=Boids(a).Position
SubtractVec(Current.Position,v)
Distance#=SqrLengthVec(v)
if Distance#<BoidCrowdingDistance
ScaleVec(v,(BoidCrowdingDistance-Distance#)/BoidCrowdingDistance)
AddVec(v,Look) : Look=v
inc Count
endif
endif
next a
if Count
NormalizeVec(Look)
CurveVec(v,Current.Look,20) : NormalizeVec(v)
Boids(obj).Look=v
endif
endfunction
function MoveTowardsCenter(obj) `Lightly encourage Boid to stay somewhere around the field
Current as Boid
Current=Boids(obj)
Distance#=SqrLengthVec(Current.Position)
ScaleVec(Current.Position,-1.0)
NormalizeVec(v)
CurveVec(v,Current.Look,80) : NormalizeVec(v)
Boids(obj).Look=v
endfunction
function AvoidEnemies(obj) `Average escape vectors from close-by enemies
Look as Vector
Current as Boid
Current=Boids(obj)
Count=0
for a=0 to EnemyCount-1
v=Enemies(a).Position
SubtractVec(v,Current.Position) `Get difference in position between Boid and Enemy
Distance#=SqrLengthVec(v) `Get distance^2
if Distance#<EnemyDistance `Enemy's in range
CrossVec(Current.Look,v) `Cross multiply Boid's Look vector with the vector containing the difference in positions to get the Right vector
CrossVec(Current.Look,v) `Cross mulitply Boid's Look vector with the the Right vector to get it's Up Vector, a good escape route.
NormalizeVec(v) `Normalize the new escape vector
ScaleVec(v,(EnemyDistance-Distance#)/EnemyDistance) `Factor in the "urgency" due to the proximity of the enemy
AddVec(v,Look) : Look=v `Add it to the new Look vector
inc Count
endif
next a
if Count `If any enemies were in range,
NormalizeVec(Look)
CurveVec(v,Current.Look,15) : NormalizeVec(v)
Boids(obj).Look=v
endif
endfunction
function BoidAvoidObstacles(obj) `Works like pretty much like AvoidEnemies()
Look as Vector
Current as Boid
Current=Boids(obj)
Count=0
for a=0 to ObstacleCount-1
v=Obstacles(a).Position
SubtractVec(v,Current.Position) : v.y=0
Distance#=SqrLengthVec(v)
Radius#=Obstacles(a).Radius#+20
Radius#=Radius#*Radius#
if Distance#<Radius#
Look=Current.Look : Look.y=0
CrossVec(Look,v)
CrossVec(Look,v)
NormalizeVec(v)
ScaleVec(v,(Radius#-Distance#)/Radius#)
AddVec(v,Look) : Look=v
inc Count
endif
next a
if Count
NormalizeVec(Look)
CurveVec(v,Current.Look,10) : NormalizeVec(v)
Boids(obj).Look=v
endif
endfunction
function BoidWrapField(Current as Boid)
Distance#=SqrLengthVec(Current.Position)
if Distance#>SqrFieldRadius
NormalizeVec(Current.Position)
ScaleVec(v,-(FieldRadius-1))
Current.Position=v
OrientBoid(Current)
endif
endfunction
function PickTarget(obj) `Go after the closest Boid
Look as Vector
Current as Enemy
Current=Enemies(obj)
ShortestDistance#=1000000
for a=0 to BoidCount-1
v=Boids(a).Position
SubtractVec(v,Current.Position)
Distance#=SqrLengthVec(v)
if Distance#<ShortestDistance#
if Distance#<(Current.Radius#*Current.Radius#) `The enemy has hit a Boid. Destroy the Boid.
delete object Boids(a).Object
array delete element Boids(0),a
if TargetGroup=1 and CameraTarget=a then ControlType=0 `If the dead Boid was being controlled by the user, set control to automatic for the next
dec BoidCount
dec a
else
ShortestDistance#=Distance#
Look=v
endif
endif
next a
if BoidCount>0
NormalizeVec(Look)
CurveVec(v,Current.Look,10) : NormalizeVec(v)
Enemies(obj).Look=v
endif
endfunction
function EnemyAvoidCrowding(obj) `Works just like the Boid version of this function
Look as Vector
Current as Enemy
Current=Enemies(obj)
Count=0
for a=0 to EnemyCount-1
if a<>obj
v=Enemies(a).Position
SubtractVec(Current.Position,v)
Distance#=SqrLengthVec(v)
if Distance#<EnemyCrowdingDistance
ScaleVec(v,(EnemyCrowdingDistance-Distance#)/EnemyCrowdingDistance)
AddVec(v,Look) : Look=v
inc Count
endif
endif
next a
if Count
NormalizeVec(Look)
CurveVec(v,Current.Look,20) : NormalizeVec(v)
Enemies(obj).Look=v
endif
endfunction
function EnemyAvoidObstacles(obj)
Look as Vector
Current as Enemy
Current=Enemies(obj)
Count=0
for a=0 to ObstacleCount-1
v=Obstacles(a).Position
SubtractVec(v,Current.Position) : v.y=0
Distance#=SqrLengthVec(v)
Radius#=Obstacles(a).Radius#+20
Radius#=Radius#*Radius#
if Distance#<Radius#
Look=Current.Look : Look.y=0
CrossVec(Look,v)
CrossVec(Look,v)
NormalizeVec(v)
ScaleVec(v,(Radius#-Distance#)/Radius#)
AddVec(v,Look) : Look=v
inc Count
endif
next a
if Count
NormalizeVec(Look)
CurveVec(v,Current.Look,10) : NormalizeVec(v)
Enemies(obj).Look=v
endif
endfunction
function EnemyWrapField(Current as Enemy)
Distance#=SqrLengthVec(Current.Position)
if Distance#>SqrFieldRadius
NormalizeVec(Current.Position)
ScaleVec(v,-(FieldRadius-1))
Current.Position=v
OrientEnemy(Current)
endif
endfunction
function SetupBoids() `Initialize Boids
`randomize 0
Temp as Boid
CreateBoidObject() `Manually create object 1, containing the Boid mesh
for a=0 to BoidCount-1
array insert at bottom Boids(0)
instance object a+2,1 `Copy the Boid mesh
Temp.Object=a+2
v.x=rnd(200)-100
v.y=rnd(200)-100
v.z=rnd(200)-100
Temp.Position=v `Randomize position
v.x=rnd(1000)-500
v.y=rnd(1000)-500
v.z=rnd(1000)-500
NormalizeVec(v) : Temp.Look=v `Randomize the Look vector
Temp.Speed#=0.5+rnd(5)/10.0
OrientBoid(Temp) `Place Boid in its initial position
Boids(a)=Temp
next a
endfunction
function SetupEnemies() `Essentially do everything the Boid version does, but sets up a Radius# for collision detection
Temp as Enemy
for a=0 to EnemyCount-1
array insert at bottom Enemies(0)
Temp.Object=BoidCount+2+a
Temp.Radius#=8.0
make object sphere Temp.Object,2*Temp.Radius#,6,6
`color object Temp.Object,0xFFFF0000
v.x=rnd(200)-100
v.y=rnd(200)-100
v.z=rnd(200)-100
Temp.Position=v
v.x=rnd(1000)-500
v.y=rnd(1000)-500
v.z=rnd(1000)-500
NormalizeVec(v) : Temp.Look=v
Temp.Speed#=0.3+rnd(3)/10.0
OrientEnemy(Temp)
Enemies(a)=Temp
next a
endfunction
function SetupObstacles()
Temp as Obstacle
for a=0 to ObstacleCount-1
array insert at bottom Obstacles(0)
Temp.Object=BoidCount+EnemyCount+2+a
Temp.Radius#=5+rnd(5)
make object cylinder Temp.Object,1
scale object Temp.Object,2*Temp.Radius#*100,2*FieldRadius*100,2*Temp.Radius#*100
v.x=rnd(300)-150
v.y=0
v.z=rnd(300)-150
Temp.Position=v
position object Temp.Object,v.x,v.y,v.z
Obstacles(a)=Temp
next a
endfunction
`The next two functions place an object in space and orient it according to its Look vector
function OrientBoid(obj as Boid)
position object obj.Object,obj.Position.x,obj.Position.y,obj.Position.z
point object obj.Object,obj.Position.x+obj.Look.x,obj.Position.y+obj.Look.y,obj.Position.z+obj.Look.z
endfunction
function OrientEnemy(obj as Enemy)
position object obj.Object,obj.Position.x,obj.Position.y,obj.Position.z
point object obj.Object,obj.Position.x+obj.Look.x,obj.Position.y+obj.Look.y,obj.Position.z+obj.Look.z
endfunction
function AddVertex(Memblock,Vertex,x as float,y as float,z as float) `Adds a vertex to a memblock mesh
Position=12+Vertex*32
`Position
write memblock float Memblock,Position+4*0,x
write memblock float Memblock,Position+4*1,y
write memblock float Memblock,Position+4*2,z
`Normal (We'll calculate all of these later)
write memblock float Memblock,Position+4*3,0.0
write memblock float Memblock,Position+4*4,0.0
write memblock float Memblock,Position+4*5,0.0
`UV (Unnecessary, so just set to 0.0)
write memblock float Memblock,Position+4*6,0.0
write memblock float Memblock,Position+4*7,0.0
endfunction
function CalculateNormals(Memblock) `Go through an entire memblock mesh, adding in the normals
VertexCount=memblock dword(Memblock,8)
FaceCount=VertexCount/3
Edge1 as Vector
Edge2 as Vector
for Face=0 to FaceCount-1
FaceStart=12+32*(3*Face)
`Basically, for each set of three vertices, cross multiply the edges together to get the normal
SetVec(memblock float(Memblock,FaceStart+0*32+0),memblock float(Memblock,FaceStart+0*32+4),memblock float(Memblock,FaceStart+0*32+8),1) : Edge1=v
SetVec(memblock float(Memblock,FaceStart+1*32+0),memblock float(Memblock,FaceStart+1*32+4),memblock float(Memblock,FaceStart+1*32+8),1) : Edge2=v
SubtractVec(Edge2,Edge1) : Edge1=v
SetVec(memblock float(Memblock,FaceStart+2*32+0),memblock float(Memblock,FaceStart+2*32+4),memblock float(Memblock,FaceStart+2*32+8),1)
SubtractVec(v,Edge2) : Edge2=v
NormalizeVec(Edge1) : Edge1=v
NormalizeVec(Edge2) : Edge2=v
CrossVec(Edge1,Edge2)
for Vertex=0 to 2
write memblock float Memblock,FaceStart+Vertex*32+12,v.x
write memblock float Memblock,FaceStart+Vertex*32+16,v.y
write memblock float Memblock,FaceStart+Vertex*32+20,v.z
next Vertex
next Face
endfunction
function CreateBoidObject() `Setup the Boid mesh to be used by the Boid objects
if memblock exist(1) then delete memblock 1
if mesh exist(1) then delete mesh 1
if object exist(1) then delete object 1
make memblock 1,12+32*24
write memblock dword 1,0,274
write memblock dword 1,4,32
write memblock dword 1,8,24
AddVertex(1,0,0,0,3) : AddVertex(1,1,2,0,0) : AddVertex(1,2,0,1,0)
AddVertex(1,3,0,0,3) : AddVertex(1,4,0,1,0) : AddVertex(1,5,-2,0,0)
AddVertex(1,6,0,0,3) : AddVertex(1,7,0,-1,0) : AddVertex(1,8,2,0,0)
AddVertex(1,9,0,0,3) : AddVertex(1,10,-2,0,0) : AddVertex(1,11,0,-1,0)
AddVertex(1,12,0,1,0) : AddVertex(1,13,2,0,0) : AddVertex(1,14,0,0,-0.5)
AddVertex(1,15,0,1,0) : AddVertex(1,16,0,0,-0.5) : AddVertex(1,17,-2,0,0)
AddVertex(1,18,0,0,-0.5) : AddVertex(1,19,2,0,0) : AddVertex(1,20,0,-1,0)
AddVertex(1,21,0,0,-0.5) : AddVertex(1,22,0,-1,0) :AddVertex(1,23,-2,0,0)
CalculateNormals(1)
make mesh from memblock 1,1
make object 1,1,0
`color object 1,0xFF008080
hide object 1
endfunction
`A few necessary commands to use my system of vectors
`v is a global return vector because DBPro can't return UDTs from functions
function SetVec(x as float,y as float,z as float,w as float)
v.x=x : v.y=y : v.z=z : v.w=w
endfunction
function AddVec(vec1 as Vector,vec2 as Vector)
v.x=vec1.x+vec2.x
v.y=vec1.y+vec2.y
v.z=vec1.z+vec2.z
v.w=1.0
endfunction
function SubtractVec(vec1 as Vector,vec2 as Vector)
v.x=vec1.x-vec2.x
v.y=vec1.y-vec2.y
v.z=vec1.z-vec2.z
v.w=1.0
endfunction
function ScaleVec(vec as Vector,scale as float)
v.x=vec.x*scale
v.y=vec.y*scale
v.z=vec.z*scale
v.w=1.0
endfunction
function CrossVec(vec1 as Vector,vec2 as Vector)
v.x=vec1.y*vec2.z-vec1.z*vec2.y
v.y=vec1.z*vec2.x-vec1.x*vec2.z
v.z=vec1.x*vec2.y-vec1.y*vec2.x
v.w=1.0
endfunction
function NormalizeVec(vec as Vector)
Length#=sqrt(vec.x*vec.x+vec.y*vec.y+vec.z*vec.z)
v.x=vec.x/Length#
v.y=vec.y/Length#
v.z=vec.z/Length#
v.w=1.0
endfunction
function SqrLengthVec(vec as Vector)
Length#=vec.x*vec.x+vec.y*vec.y+vec.z*vec.z
endfunction Length#
function CurveVec(dest as Vector,cur as Vector,speed as float)
v.x=curvevalue(dest.x,cur.x,speed)
v.y=curvevalue(dest.y,cur.y,speed)
v.z=curvevalue(dest.z,cur.z,speed)
v.w=1.0
endfunction
Hold H to display control help, and mess around with the Count variables like BoidCount, EnemyCount, and ObstacleCount, especially if your computer starts to complain with the current settings.