;******************************************************************************** ; ; Reynold's Boids Demonstration: ; Completed by Lindsay Grace: 10/06 ; ; ; The following code isa demonstration of boids using BlitzBasic ; It was completed for CS527 at the University of Illinois, Chicago ; ; ; ;******************************************************************************** SetGFx Global use_fog=True Dim strArray$(30) ;Constants Def - behavior Const FPS=30 Const Boid_Type_Prey = 0; Const Boid_Type_Predator = 1; ;Define Types Type Vector Field x#,y#,z# End Type Type Boid Field x#,y#,z#,Xvelocity#,Yvelocity#,Zvelocity#,perching,perch_timer Field entity,entity_chasing, number,boid_type,scale#,canPerch Field goalX#,goalY#,goalZ# Field shadow,shadow_on,speed# Field red#,green#,blue# End Type Type BoidSetup Field BoidsCount#,BoidsSeperation#,BoidsCohesion#,BoidsAlignment#,BoidsBounds#,BoidsMoveToward# Field BoidsSeperationMultiplier#,BoidsCohesionMultiplier#,BoidsAlignmentMultiplier#,BoidsBoundsMultiplier# Field BoidsMoveAwayMultiplier#,BoidsMoveTowardMultiplier# Field BoundsXMax#,BoundsYMax#,BoundsZMax#,BoundsXMin#,BoundsYMin#,BoundsZMin# Field multicolor$,prey_ratio# Field delayLowerBound#,delayUpperBound#,delayLowerBoundPrey#,delayUpperBoundPrey# Field initiativeMin#,initiativeMax# End Type Dim BoidArray(10) Dim ModelArray$(5) ;Define Globals Global BoidSettings.BoidSetup = New BoidSetup Global FrameCounter = 0 ;Global cube = CreateCube() ;Global cube2 = CreateSphere() Global bDisplayStats = False Global pivot=CreatePivot() Global pivot2=CreatePivot() Global Boing=Load3DSound("sounds/swoosh.wav") Global camera=CreateCamera() ;TurnEntity camera,0,90,0 cam_xr#=70:cam_yr#=180: cam_zr#=0: ;initial camera location: cam_x#=-7: cam_y#=10: cam_z#=-6: Global wand=LoadImage("models/metal.jpg") ;EntityOrder wand,-2 Global vGoal.Vector = New Vector Global vAvoid1.Vector = New Vector Global vAvoidBoid.Vector = New Vector Global intBoidCount = 1 Global intCountMovingPrey = 0 ;start at one to start hunting "state" Global bForceGoal = False Global IndicatorY = CreateCone(20) Global IndicatorX = CreateCone(20) Global IndicatorZ=CreateCone(20) light=CreateLight(3,cam) LightRange (light,50) PositionEntity light,0,100,0 TurnEntity light,90,90,90 Global roomLight = CreateLight(2) LightRange roomLight,80 LightConeAngles roomLight,30,30 RotateEntity roomlight,0,0,90 PositionEntity (roomLight, 0,150,-100 ) mysphere = CreateSphere() ScaleEntity mysphere,5,5,5 PositionEntity mysphere ,0,150,-100 Global gLightRange# = 80 ;BadCube = CreateCube() ;ScaleEntity (BadCube,5,5,5) ;PositionEntity BadCube,15,-9,20 ;vAvoid1\x = 15 ;vAvoid1\y = -9 ;vAvoid1\z = 10 Global leftPlane = CreatePlane() RotateEntity leftPlane,90,90,0 TranslateEntity leftPlane,60,0,0 EntityColor leftPlane,0,0,255 EntityAlpha leftPlane,0 SeedRnd (MilliSecs()) Global rightPlane= CreatePlane() RotateEntity rightPlane,90,90,0 TranslateEntity rightPlane,-60,0,0 EntityColor rightPlane,255,0,0 EntityAlpha rightPlane,0 ;FlipMesh rightPlane SeedRnd (MilliSecs()) segs=16 rebuild=True LoadSettings ;Global BoidYell=Load3DSound("yell.wav") PopulateModelArray() init_positions listen=CreateListener(camera,10) Global Multiplyer1#=BoidSettings\BoidsSeperationMultiplier Global Multiplyer2#=BoidSettings\BoidsCohesionMultiplier Global Multiplyer3#=BoidSettings\BoidsAlignmentMultiplier Global Multiplyer4#=BoidSettings\BoidsBoundsMultiplier Global Multiplyer5#=BoidSettings\BoidsMoveTowardMultiplier Function SetGfx() Print info1$:Print info2$:Print info3$:Print info4$:Print If Windowed3D() yn$=Input$( "Use windowed mode?" ) If Left$( Lower$( yn$ ),1 )="y" HidePointer Graphics3D 800,600,0,2 SetBuffer BackBuffer() Return EndIf EndIf Print "" Print "Display drivers:" Print "----------------" For k=1 To CountGfxDrivers() Print k+":"+GfxDriverName$(k) Next Print If CountGfxDrivers()>1 Repeat driver=Input$( "Display driver (1-"+CountGfxDrivers()+"):" ) Until driver>=1 And driver<=CountGfxDrivers() SetGfxDriver driver EndIf cnt=CountGfxModes3D() If cnt=0 Print "No 3D Graphics modes detected.":WaitKey:End Print "" Print "Display modes:" Print "--------------" For k=1 To CountGfxModes3D() ;Print k+":"+GfxModeWidth(k)+","+GfxModeHeight(k)+","+GfxModeDepth(k) Print k+":"+GfxModeWidth(k)+","+GfxModeHeight(k)+","+GfxModeDepth(k) If k Mod 10 = 1 Then ;if there are too many graphics modes, you wont see them all WaitKey End If Next Repeat mode=Input$( "Display Mode (1-"+cnt+"):" ) Until mode>=1 And mode<=cnt width=GfxModeWidth(mode) height=GfxModeHeight(mode) ;It's too slow with too much color depth - so let blitz pick the highest ;Graphics3D GfxModeWidth(mode),GfxModeHeight(mode),GfxModeDepth(mode),1 Graphics3D GfxModeWidth(mode),GfxModeHeight(mode),0,1 SetBuffer BackBuffer() End Function While Not KeyHit(1) If KeyHit(17) wire=Not wire WireFrame wire EndIf If KeyDown(203) cam_yr=cam_yr+2 Else If KeyDown(205) cam_yr=cam_yr-2 EndIf If KeyDown(200) cam_xr=cam_xr+2 If cam_xr>90 cam_xr=90 Else If KeyDown(208) cam_xr=cam_xr-2 ;If cam_xr<0 cam_xr=0 EndIf If KeyDown(26) cam_zr=cam_zr+2 Else If KeyDown(27) cam_zr=cam_zr-2 EndIf If KeyDown(30) cam_z=cam_z+1: Else If KeyDown(44) cam_z=cam_z-1: EndIf If KeyHit(12) Or KeyHit (74)Then ;12 = - decrease multipliers Multiplyer1# = Multiplyer1#*.9 Multiplyer2# = Multiplyer2#*.9 Multiplyer3# = Multiplyer3#*.9 Multiplyer4# = Multiplyer4#*.9 Multiplyer5# = Multiplyer5#*.9 End If If KeyHit(78) Or KeyHit (13) Then ;78 = + increase multipliers Multiplyer1# = Multiplyer1#*1.1 Multiplyer2# = Multiplyer2#*1.1 Multiplyer3# = Multiplyer3#*1.1 Multiplyer4# = Multiplyer4#*1.1 Multiplyer5# = Multiplyer5#*1.1 End If If KeyHit(32) Then ;32 = d - display stats If bDisplayStats = False Then bDisplayStats=True Else bDisplayStats=False End If End If If KeyHit (45) Then ;45 = x=dim light gLightRange = gLightRange - 5 LightRange roomLight,gLightRange End If If KeyHit(31) Then ;31 = s - add light gLightRange = gLightRange + 5 LightRange roomLight,gLightRange End If ;PositionEntity camera,0,30,-6 PositionEntity camera,0,0,0 RotateEntity camera,cam_xr,cam_yr,cam_zr MoveEntity camera,cam_x,cam_y,cam_z If MouseHit(1)>0 picked=CameraPick(camera,MouseX,MouseY) vGoal\x = MouseX() vGoal\y = EntityZ(camera) ;vAvoid1\z = EntityZ (camera) DrawImage wand,MouseX(),MouseY() End If DrawImage wand,MouseX(),MouseY () ;MoveEntity cube,vGoal\x,vGoal\y,vGoal\z If MouseHit(2) Then init_positions(); End If UpdateWorld RenderWorld FrameCounter = FrameCounter + 1; ;Turn on for less computation ;If FrameCounter Mod 2 = 1 Move_Boids(); ;CheckFlockingNeed() ;End If If FrameCounter > 30000 Then FrameCounter = 0 End If If bDisplayStats = True Then Text 0,0,"Cam-X:" + EntityX (camera) + " Cam-Y:" + EntityY (camera) + " Cam-Z:" + EntityZ (camera) Text 0,25,"cam rot X:" + cam_xr + " cam rot y:" + cam_ry + "cam rot z:" + cam_zr Text 0,50, "Goal Picked:" + vGoal\x + " " + vGoal\y + " " + vGoal\z Text 0,GraphicsHeight()-20,"Goal Forced Chosen?:" + bForceGoal Text 0,70, "Mouse-X:" + MouseX() + "Mouse-Y(camera):" + EntityZ(camera) Text 0,90, "Multipliers: 1:" + Multiplyer1# + " 2:" + Multiplyer2# + " 3:" +Multiplyer3# + " 4:" + Multiplyer4# + " 5:" + Multiplyer5# EntityAlpha IndicatorX,.8 EntityAlpha IndicatorY,.8 EntityAlpha IndicatorZ,.8 EntityColor IndicatorX , 255,0,0 PositionEntity IndicatorX,10,10,10 RotateEntity IndicatorX,0,0,270 ScaleEntity IndicatorX, 4,2,2 EntityColor IndicatorY, 0,255,0 PositionEntity IndicatorY,0,10,10 RotateEntity IndicatorY,0,-90,0 ScaleEntity IndicatorY, 2,4,2 EntityColor IndicatorZ, 0,0,255 PositionEntity IndicatorZ,0,10,0 RotateEntity IndicatorZ,90,0,180 ScaleEntity IndicatorZ, 2,2,4 Else EntityAlpha IndicatorX,0 EntityAlpha IndicatorY,0 EntityAlpha IndicatorZ,0 End If Flip Wend End ;###################################################################################### ; ; Init Positions: ; Setup initial environment ; ;###################################################################################### Function init_positions() For i = 1 To BoidSettings\BoidsCount-1 ;CreateBoid() ;B.Boid = CreateBoid(Boid_Type_Predator) If i Mod BoidSettings\prey_ratio=1 Then B.Boid = CreateBoid(Boid_Type_Prey) Else B.Boid = CreateBoid(Boid_Type_Predator) End If Next ;Place music sheet plane = LoadMesh ("models/sheet.3ds") PositionEntity plane,0,-10,-15 RotateEntity plane,90,0,0 ScaleEntity plane, 1,1.5,1.5 tex=LoadTexture( "models/sheet_music2.jpg" ) RotateTexture tex,180 ; ScaleTexture tex,500,500 EntityTexture plane,tex ;Place Floor ;ShiningFloor = CreatePlane() ;PositionEntity ShiningFloor,0,0,298 ;tex=LoadTexture( "models/wood.jpg" ) ;ScaleTexture tex, 10,10 ;RotateEntity ShiningFloor,0,90,90 ;EntityTexture ShiningFloor,tex ;EntityAlpha ShiningFloor,.5 ;Place Floor reflection ;mirror=CreateMirror() ;PositionEntity mirror,-400,0,0 ;RotateEntity mirror,0,180,90 room = CreateCube() ScaleEntity room,400,300,300 tex=LoadTexture( "models/bgtest.jpg" ) EntityTexture room,tex FlipMesh room RotateEntity room,20,0,0 TranslateEntity room,0,-25,0 ;PositionEntity cube,30,30,100 ; ScaleEntity cube,10,10,10 ; EntityRadius camera,10 ; EntityRadius plane,10 ; EntityType plane,10 ; EntityType camera,20 ; RotateEntity cube,0,30,0 ;tex =LoadTexture( "models/gClef.jpg" ) ;ScaleTexture tex,10,10 ; Tex = CreateTexture ( "models/gClef.bmp",2 ) ;EntityTexture cube,tex ; EntityTexture cube,tex,0,0 platform= LoadMesh("models/musicstand.3ds") RotateEntity platform,90,0,0 ScaleEntity platform,4,4,4 ;TurnEntity platform,2,0,0 PositionEntity platform,-2,-10,-65 FreeTexture tex End Function ;###################################################################################### ; ; Init Basic boids (notes) ; Neat ideas: ; I give each boid a goal, but for predators I set it as the starting ; position of the last created prey. In the move function I then ; restablish the goal ; ;###################################################################################### Function CreateBoid.Boid(BoidType) If BoidType = Boid_Type_Predator b.Boid=New Boid intRand = Rand(1,4) models$= ModelArray$(intRand); b\entity = LoadMesh ("models/" +models + ".3ds"); If intRand = 1 Then b\speed = 1 ElseIf intRand = 2 b\speed = 1.02 ElseIf intRand = 3 b\speed = 1.04 ElseIf intRand = 4 b\speed = 1 Else b\speed = 1 End If b\speed = 1 ;b\scale# = .2 ScaleEntity b\entity, .01,.01,.01 RotateEntity b\entity,90,90,90 If intRand = 1 Then b\red# = 255 b\green# = 255 b\blue# = 255 ElseIf intRand = 2 b\red# = 255 b\green# = 0 b\blue# = 0 ElseIf intRand = 3 b\red# = 0 b\green# = 255 b\blue# = 0 ElseIf intRand = 4 b\red# = 0 b\green# = 0 b\blue# = 255 Else b\red# = 0 b\green# = 0 b\blue# = 0 End If If BoidSettings\multicolor= "True" Then EntityColor b\entity,b\red,b\blue,b\green Else EntityColor b\entity,0,0,0 End If b\x = Rnd(-40,40) ;b\y = Rnd(-50,50) b\z = Rnd(-30,30) b\number = intBoidCount b\perching = True b\perch_timer = Rnd (BoidSettings\delayLowerBound,BoidSettings\delayUpperBound) b\canPerch = True b\shadow_on = False PositionEntity b\entity ,b\x,-9,b\z ;Stop() intBoidCount = intBoidCount + 1 b\boid_type = Boid_Type_Predator b\goalX = vGoal\x ;b\goalY = Rnd ( -40,40) b\goalZ = vGoal\z shadow=LoadMesh ("models/" +models + ".3ds"); ;ScaleEntity shadow, b\scale ,b\scale ,b\scale EntityFX shadow,1 EntityColor shadow,10,10,10 ScaleEntity shadow,.1,0.0005,.1 MoveEntity shadow,1,1,0 EntityAlpha shadow,0 b\shadow = shadow Else b.Boid=New Boid intRand = Rand(1,4) If intRand = 1 Then b\speed = .65 ElseIf intRand = 2 b\speed = .75 ElseIf intRand = 3 b\speed = .85 ElseIf intRand = 4 b\speed = 1 Else b\speed = 1 End If b\speed = 1.1 b\entity = LoadMesh ("models/bass_clef.3ds") RotateEntity b\entity,90,90,90 ScaleEntity b\entity,.1,.1,.1 b\boid_type = Boid_Type_Prey EntityColor b\entity,0,0,0 b\x = 30 b\y = -9 b\z = Rnd(-30,30) b\number = intBoidCount b\goalX = Rnd(10,-10) b\goalY = Rnd(10,-10) b\goalZ = Rnd(10,-10) b\perching = True b\perch_timer = Rnd (BoidSettings\delayLowerBoundPrey,BoidSettings\delayUpperBoundPrey) b\canPerch = True b\shadow_on = False PositionEntity b\entity ,b\x,-9,b\z ;Stop() intBoidCount = intBoidCount + 1 b\scale = .02 shadow=LoadMesh ("models/bass_clef.3ds"); ScaleEntity shadow, .2,.2,.2 EntityFX shadow,1 EntityColor shadow,10,10,10 ScaleEntity shadow,1,0.001,1 ;MoveEntity shadow,0,0.11,0 MoveEntity shadow,1,1,0 EntityAlpha shadow,0 b\shadow = shadow ;Set a few predators after this one, vGoal\x = b\x vGoal\y = b\y vGoal\z = b\z End If Return b End Function Function PopulateModelArray() ;********************************************************************* ; Populate the array of models ; ;********************************************************************* ; tired of trying to figure out what the syntax for ; directly populating the array is ModelArray$(1) = "qnote" ModelArray$(2) = "8note" ModelArray$(3) = "16note" ModelArray$(4) = "32note" End Function Function Move_Boids() ;********************************************************************* ; Function for moving all prey and predators ; This should clearly be chopped up - but not enought time ;********************************************************************* V1.Vector = New Vector V2.Vector = New Vector V3.Vector = New Vector V4.Vector = New Vector V5.Vector = New Vector V6.Vector = New Vector totalChange=0 pivot3 = CreatePivot() For b.Boid = Each Boid If b\perching = False Then If bDisplayStats Then EntityColor b\entity,b\red,b\blue,b\green Else EntityColor b\entity,0,0,0 End If b\shadow_on = True V1 = Cohesion(b) V2 = Seperation(b) V3 = Alignment(b) V4 = Bound(b) If b\boid_type = Boid_Type_Predator temp.Vector = New Vector temp = PickGoal(b) If temp\x <> 0 And temp\y <> 0 And temp\z Then temp\x = b\goalX temp\y = b\goaly temp\z = b\goalz End If V5 = MoveTowardObject(b,vGoal) V1\x = V1\x * Multiplyer1; V1\y = V1\y * Multiplyer1; V1\z = V1\z * Multiplyer1; V2\x = V2\x * Multiplyer2; V2\y = V2\y * Multiplyer2; V2\z = V2\z * Multiplyer2; V3\x = V3\x * Multiplyer3; V3\y = V3\y * Multiplyer3; V3\z = V3\z * Multiplyer3; V4\x = V4\x * Multiplyer4; V4\y = V4\y * Multiplyer4; V4\z = V4\z * Multiplyer4; V5\x = V5\x * Multiplyer5; V5\y = V5\y * Multiplyer5; V5\z = V5\z * Multiplyer5; V6\x = V5\x * Multiplyer5; V6\y = V5\y * Multiplyer5; V6\z = V5\z * Multiplyer5; V6 = MoveTowardObject(b,vAvoid1) ;Aha, this is the secret, give 'em two goals dynamiccaly Else temp.Vector = New Vector temp\x = b\goalX temp\y = b\goaly temp\z = b\goalz V5 = MoveTowardObject(b,temp) V1\x = V1\x * Multiplyer1; V1\y = V1\y * Multiplyer1; V1\z = V1\z * Multiplyer1; V2\x = V2\x * Multiplyer2 * 1.2; V2\y = V2\y * Multiplyer2 * 1.2; V2\z = V2\z * Multiplyer2 * 1.2; ;Also trick here - remvoe a factor so that they act "on their own" ;V3\x = V3\x * Multiplyer3 * 1.2; ;V3\y = V3\y * Multiplyer3* 1.2; ;V3\z = V3\z * Multiplyer3* 1.2; V4\x = V4\x * Multiplyer4; V4\y = V4\y * Multiplyer4; V4\z = V4\z * Multiplyer4; If (b\Xvelocity + b\Yvelocity + b\Zvelocity) < 20 Then b\goalX = Rnd(50,-20) b\goalY = 0 b\goalZ = Rnd(50,-20) b\Xvelocity =b\Xvelocity * 1.02 b\Yvelocity =b\Yvelocity * 1.02 b\Zvelocity =b\Zvelocity * 1.02 ElseIf (b\Xvelocity + b\Yvelocity + b\Zvelocity) > 200 Then b\Xvelocity =b\Xvelocity * .98 b\Yvelocity =b\Yvelocity b\Zvelocity =b\Zvelocity * .98 End If ;Considering slowing them down, but not right now ;End If ;End If V5\x = V5\x * Multiplyer5 * 1.5; V5\y = V5\y * Multiplyer5 * 1.5; V5\z = V5\z * Multiplyer5 * 1.5; End If b\Xvelocity =b\Xvelocity+V1\x+V2\x+V3\x+V4\x+V5\x+V6\x b\Yvelocity =b\Yvelocity+V1\y+V2\y+V3\y+V4\y+V5\y+V6\y b\Zvelocity = b\Zvelocity+V1\z+V2\z+V3\z+V4\z+V5\z+V6\z PositionEntity b\entity,(b\x+b\Xvelocity/500),(b\y+b\Yvelocity/500),(b\z+b\Zvelocity/500) ;********************************************************************* ; My simple Shadow Code ;Position And manipulate the shadow For added light effect ;********************************************************************* If b\shadow_on = True If EntityX(b\shadow) < EntityX(leftPlane) And EntityX(b\shadow) > EntityX(RightPlane) Then ;EntityAlpha b\shadow,.4 If gLightRange > 1 Then alpha# = (gLightRange#/2)/100 EntityAlpha b\shadow, alpha Else EntityAlpha b\shadow,0 End If PositionEntity b\shadow,(b\x+b\Xvelocity/500),-9,(b\z+b\Zvelocity/500) RotateEntity b\shadow,90,90,90 ;RotateEntity b\shadow,90,180,180 ;revers light ;ScaleEntity b\shadow,((EntityX(b\entity)-9)/500),((EntityY(b\entity)-9)/200)+.11,(EntityZ(b\entity)-9)/500 ;RotateEntity b\shadow,90,0,90 ;ScaleEntity b\shadow,((EntityX(b\entity)-9)/2500),((EntityY(b\entity)-9)/2000)+.11,(EntityZ(b\entity)-9)/2500 ScaleEntity b\shadow,((EntityX(b\entity)-9)/4500),((EntityY(b\entity)-9)/4500)+.04,(EntityZ(b\entity)-9)/4500 Else b\shadow_on = False EntityAlpha b\shadow,0 End If ;If EntityDistance (b\shadow,b\entity) < 2 Then ;End If Else EntityAlpha b\shadow,0 End If ;********************************************************************* ; Increase sense of motion by "twirling" the objects by degree ;********************************************************************* ;Now turn them like leaves If ( b\Xvelocity > 100) Then TurnEntity b\entity,1,0,0 TurnEntity b\shadow,1,0,0 End If If ( b\Yvelocity > 100) Then TurnEntity b\entity,0,1,0 TurnEntity b\shadow,1,0,0 End If If ( b\Zvelocity > 100) Then TurnEntity b\entity,0,0,1 TurnEntity b\shadow,1,0,0 End If ;********************************************************************* ; Add 3D sound - ideally I wanted to add note sounds, but it ; becomes a complete cacuaphony ;********************************************************************* ;If EntityDistance (camera,b\entity) < 10 Then If ( b\Xvelocity > 10) And ( b\Yvelocity > 10) And ( b\Zvelocity > 10) ;If FrameCounter = 20 Then ;Let there be sound in 3D! SoundPitch Boing, Rand(1,44000) EmitSound (Boing,b\entity) ;End If End If Else If b\canPerch = True ;********************************************************************* ; Perching state code ; ;********************************************************************* b\shadow_on = False If b\perch_timer > 0 Then b\perch_timer = b\perch_timer - 1 RotateEntity b\entity,90,90,90 ;b\perching = False ;Decrease the velcoity as it sits, this way it seems to have momentum b\Xvelocity = b\Xvelocity * .1 b\Yvelocity = b\Yvelocity * .1 b\Zvelocity = b\Zvelocity * .1 b\shadow_on = False b\canPerch = True b\perching = True Else ;RotateEntity b\entity, 90,90,90 b\perch_timer= Rnd(BoidSettings\initiativeMin,BoidSettings\initiativeMax) ;Stop b\perching = False b\shadow_on = True b\canPerch = True End If End If ;********************************************************************* ; More perching state code ;********************************************************************* If EntityZ(b\entity) > 12 Then If EntityZ(b\entity) < 50 Then ;protect them from perchign off the platform ;b\scale = b\scale * 1.10 b\canPerch = False ;b\perch_timer= 0 ;ScaleEntity (b\entity,b\scale,b\scale,b\scale) Else b\canPerch = True End If Else b\canPerch = True End If b\x = EntityX(b\entity) b\y = EntityY(b\entity) b\z = EntityZ(b\entity) If b\y <= -9.1 Then ;LAst minute hack RotateEntity b\entity,90,90,90 RotateEntity b\shadow,90,90,90 ;b\shadow_on=False ;b\perching = True End If If b\boid_Type = Boid_Type_Prey Then vGoal\x = b\x vGoal\y = b\y vGoal\z = b\z End If Next End Function Function Cohesion.Vector(bj.Boid) ;********************************************************************* ; Function for encouraging similar movement ; Rule1: Flow towards the center of mass ; Cohesion factor - how closely each follows the other ;********************************************************************* intCohesionFactor = BoidSettings\BoidsCohesion pcJ.Vector = New Vector N = BoidSettings\BoidsCount ;number of boids For b.Boid = Each Boid If b\entity <> bJ\entity Then If b\entity <> bJ\entity Then ;pcJ = pcJ + b.position pcj\x = pcj\x+ b\x pcj\y = pcj\y+ b\y pcj\z = pcj\z+ b\z End If End If Next pcJ\x = pcJ\x / N-1 pcJ\y = pcJ\y / N-1 pcJ\z = pcJ\z / N-1 pcJ\x = (pcJ\x - bj\x) / intCohesionFactor pcJ\y = (pcJ\y - bj\y) / intCohesionFactor pcJ\z = (pcJ\z - bj\z) / intCohesionFactor Return pcJ End Function Function Seperation.Vector(bJ.Boid) ;********************************************************************* ; Function for discouraging the exact same movement ;Rule2: Keep distance from other boids ;********************************************************************* c.Vector = New Vector distance_factor = BoidSettings\BoidsSeperation c\x= 2;displacement c\y= 2 c\z= 2 For b.Boid = Each Boid If b\entity <> bJ\entity And b\boid_type = 0 Then ;If EntityDistance (b\entity,bJ\entity) < distance_factor Then If Abs(bJ\x- b\x) < distance_factor Then If Abs(bJ\y- b\y) < distance_factor Then If Abs(bJ\z- b\z) < distance_factor Then c\x = c\x - (bJ\x- b\x) c\y = c\y - (bJ\y- b\y) c\z = c\z - (bJ\z- b\z) End If End If End If End If Next If Abs(c\x) > 10 And Abs(c\y) > 10 And Abs(c\z) > 10 Then ;Limit vector c\x = 0 c\y = 0 c\z = 0 End If Return c End Function Function Alignment.Vector(bj.Boid) ;********************************************************************* ; Function for ecnouragin like-minded behavior ;Rule 3: Try to Match other boids Velocity ; pvJ = percieved velocity ;********************************************************************* intAntiSocialFactor = BoidSettings\BoidsAlignment pvJ.Vector = New Vector N = BoidSettings\BoidsCount;number of boids For b.Boid = Each Boid If b\entity <> bJ\entity Then ;Use these to icnrease velcoty - and make them go frantic ;pvJ\x = pvJ\x + b\Xvelocity ;pvJ\y = pvJ\y + b\Yvelocity ;pvJ\z = pvJ\z + b\Zvelocity pvJ\x = pvJ\x + b\x pvJ\y = pvJ\y + b\y pvJ\z = pvJ\z + b\z End If Next pvJ\x = pvJ\x / N-1 pvJ\y = pvJ\y / N-1 pvJ\z = pvJ\z / N-1 pvJ\x = (pvJ\x - bj\Xvelocity ) / intAntiSocialFactor pvJ\y = (pvJ\y - bj\Yvelocity ) / intAntiSocialFactor pvJ\z = (pvJ\z - bj\Zvelocity ) / intAntiSocialFactor If Abs(pvJ\x) > 20 And Abs(pvJ\y) > 20 And Abs(pvJ\z) > 20 Then ;Limit vector pvJ\x = 0 pvJ\y = 0 pvJ\z = 0 End If Return pvJ End Function Function Bound.Vector(bJ.Boid) ;********************************************************************* ; Function for enforcing bounds ; ;********************************************************************* ;Bounds of movement v.Vector = New Vector bounds_enforcement_factor = BoidSettings\BoidsBounds xMin=-15 xMax=15 yMin=-9 yMax=10 zMin=-15 zMax=15 If bJ\x < xMin Then v\x = bounds_enforcement_factor ; Else If bJ\x > xMax Then v\x = -bounds_enforcement_factor ; ;Stop End If If bJ\y < yMin Then v\y = bounds_enforcement_factor ; Else If bJ\y > yMax Then v\y = -bounds_enforcement_factor ; End If If bJ\z < zMin Then v\z = bounds_enforcement_factor ; Else If bJ\z > zMax Then v\z = -bounds_enforcement_factor ; End If ;Next If bJ\y < yMin Then bJ\y = yMin bJ\perching = True ;RotateEntity bJ\entity, -90,-90,-90 If bJ\boid_type = Boid_Type_Prey Then intCountMovingPrey = intCountMovingPrey + 1 End If End If Return v End Function Function PickGoal.Vector(bJ.Boid) ;********************************************************************* ; Function for dynamically picking goals ; The bids will find the nearest prey and seek it ; ;********************************************************************* ;For use by predators only v.Vector = New Vector lastdistance# = 1 For b.Boid = Each Boid If b\entity <> bJ\entity Then If b\boid_Type = Boid_Type_Prey Then If EntityDistance (bJ\entity,b\entity) < lastdistance# Then lastdistance# = EntityDistance (bJ\entity,b\entity) v\x = EntityX(b\entity) v\y = EntityY(b\entity) v\z = EntityZ(b\entity) End If End If End If Next Return v End Function Function MoveTowardObject.Vector (b.Boid,goal.Vector) ;********************************************************************* ; Goal setting and goal avvoiding function ; ; ;********************************************************************* v.Vector = New Vector ;intelFactor = 20 ;Intellegence factor controls how easily they tend toward the object intelFactor = BoidSettings\BoidsMoveToward v\x = (goal\x - b\x)/intelFactor v\y = (goal\y - b\y)/intelFactor v\z = (goal\z - b\z)/intelFactor ;v\x = ( b\x-goal\x)/intelFactor ;v\y = (b\y-goal\y)/intelFactor ;v\z = (b\z-goal\z)/intelFactor If Abs(v\x) > 20 And Abs(v\y) > 20 And Abs(v\z) > 20 Then ;Limit vector v\x = 0 v\y = 0 v\z = 0 End If Return v End Function Function CheckFlockingNeed() ;********************************************************************* ; will drive boids down once there is nothing to attach ; ; ;********************************************************************* bSleepingCount = 0 For b.boid = Each boid If b\boid_type = Boid_Type_Prey And b\perching = True Then bSleepingCount = bSleepingCount + 1 End If Next If (bSleepingCount - BoidSettings\prey_ratio) < 1 Then For b.boid = Each boid b\perching = True vGoal\y = -9 Next End If End Function Function LoadSettings() ;********************************************************************* ; Loads files from boids.ini ; ; ;********************************************************************* file=ReadFile("boids.ini") ;For a=1 To BoidSettings\BoidsCount#=Left$(ReadLine(file),4) ;The main factors BoidSettings\BoidsSeperation=Left$(ReadLine(file),4) BoidSettings\BoidsCohesion=Left$(ReadLine(file),4) BoidSettings\BoidsAlignment=Left$(ReadLine(file),4) BoidSettings\BoidsBounds=Left$(ReadLine(file),4) BoidSettings\BoidsMoveToward=Left$(ReadLine(file),4) ;The multipliers for main factors BoidSettings\BoidsSeperationMultiplier=Left$(ReadLine(file),4) BoidSettings\BoidsCohesionMultiplier=Left$(ReadLine(file),4) BoidSettings\BoidsAlignmentMultiplier=Left$(ReadLine(file),4) BoidSettings\BoidsBoundsMultiplier=Left$(ReadLine(file),4) BoidSettings\BoidsMoveTowardMultiplier=Left$(ReadLine(file),4) BoidSettings\BoidsMoveAwayMultiplier=Left$(ReadLine(file),4) BoidSettings\BoundsXMin#=Left$(ReadLine(file),4) BoidSettings\BoundsXMax#=Left$(ReadLine(file),4) BoidSettings\BoundsYMin#=Left$(ReadLine(file),4) BoidSettings\BoundsYMax#=Left$(ReadLine(file),4) BoidSettings\BoundsYMin#=Left$(ReadLine(file),4) BoidSettings\BoundsZMax#=Left$(ReadLine(file),4) BoidSettings\multicolor=Left$(ReadLine(file),4) BoidSettings\prey_ratio#=Left$(ReadLine(file),4) BoidSettings\delayLowerBound=Left$(ReadLine(file),4) BoidSettings\delayUpperBound=Left$(ReadLine(file),4) BoidSettings\delayLowerBoundPrey=Left$(ReadLine(file),4) BoidSettings\delayUpperBoundPrey=Left$(ReadLine(file),4) BoidSettings\initiativeMin=Left$(ReadLine(file),4) BoidSettings\initiativeMax=Left$(ReadLine(file),4) ;Next CloseFile (file) End Function