set display mode 1024,768,32 sync on sync rate 60 autocam off position camera 0,300,-500 point camera 0,0,0 numberoffish=60 numberofleaders=4 type fishtype x as float y as float z as float vx as float vy as float vz as float newvx as float newvy as float newvz as float intent as string speed as float endtype dim fishproperty(numberoffish) as fishtype tankx=500 tanky=200 tankz=200 tank=free_object() make object box tank,tankx,tanky,tankz color object tank,rgb(0,0,255) ghost object on tank pebbles=free_object() make object box pebbles,tankx,tanky/10,tankz color object pebbles,rgb(255,200,0) position object pebbles,0,-tanky/2-object size y(pebbles)/2,0 glass=free_object() make object box glass,tankx,tanky/5,tankz ghost object on glass,2 fade object glass,50 position object glass,0,tanky/2+object size y(glass)/2,0 fishseed=free_object() fish=fishseed make object sphere 1000,10 scale object 1000,30,80,140 make object cone 1001,12 scale object 1001,30,80,120 xrotate object 1001,90 position object 1001,0,0,-25 make mesh from object 1,1001 delete object 1001 add limb 1000,1,1 delete mesh 1 make mesh from object 1,1000 delete object 1000 make object fish,1,0 delete mesh 1 color object fish,rgb(255,128,0) fishproperty(n).x=rnd(tankx)-tankx/2 fishproperty(n).y=rnd(tanky)-tanky/2 fishproperty(n).z=rnd(tankz)-tankz/2 fishproperty(n).intent="lead" for n=1 to numberoffish-1 fish=fishseed+n clone object fish,fishseed fishproperty(n).x=rnd(tankx)-tankx/2 fishproperty(n).y=rnd(tanky)-tanky/2 fishproperty(n).z=rnd(tankz)-tankz/2 if n<numberofleaders fishproperty(n).intent="lead" else fishproperty(n).intent="follow" endif color object fish,rgb(rnd(100)+55,rnd(200),rnd(100)) next n do for n=0 to numberoffish-1 fish=fishseed+n if fishproperty(n).intent="lead" if rnd(60)=0 `set new random direction/velocity fishproperty(n).newvx=rnd(40)/10.0-2 fishproperty(n).newvy=rnd(40)/10.0-2 fishproperty(n).newvz=rnd(40)/10.0-2 endif fishproperty(n).vx=curvevalue(fishproperty(n).newvx,fishproperty(n).vx,10) fishproperty(n).vy=curvevalue(fishproperty(n).newvy,fishproperty(n).vy,10) fishproperty(n).vz=curvevalue(fishproperty(n).newvz,fishproperty(n).vz,10) fishproperty(n).speed=sqrt(fishproperty(n).vx^2+fishproperty(n).vy^2+fishproperty(n).vz^2) angxy=atanfull(fishproperty(n).vx,fishproperty(n).vy) angxz=atanfull(fishproperty(n).vx,fishproperty(n).vz) angyz=atanfull(fishproperty(n).vy,fishproperty(n).vz) oldangx#=object angle x(fish) oldangy#=object angle y(fish) oldangz#=object angle z(fish) point object fish,object position x(fish)+fishproperty(n).vx,object position y(fish)+fishproperty(n).vy,object position z(fish)+fishproperty(n).vz newangx#=object angle x(fish) newangy#=object angle y(fish) newangz#=object angle z(fish) rotate object fish,oldangx#,oldangy#,oldangz# rotate object fish,curveangle(newangx#,oldangx#,5),curveangle(newangy#,oldangy#,5),curveangle(newangz#,oldangz#,5) endif if fishproperty(n).intent="follow" closest#=1000 for check=0 to numberoffish-1 targetfish=fishseed+check if n<>check x#=fishproperty(check).x-fishproperty(n).x y#=fishproperty(check).y-fishproperty(n).y z#=fishproperty(check).z-fishproperty(n).z dist#=sqrt(x#^2+y#^2+z#^2) if dist#<10.0 then fishproperty(n).intent="disperse":exit if dist#<closest# and fishproperty(check).intent="lead" closest#=dist# leader=check endif endif next check oldangx#=object angle x(fish) oldangy#=object angle y(fish) oldangz#=object angle z(fish) point object fish,fishproperty(leader).x,fishproperty(leader).y,fishproperty(leader).z newangx#=object angle x(fish) newangy#=object angle y(fish) newangz#=object angle z(fish) rotate object fish,oldangx#,oldangy#,oldangz# rotate object fish,curveangle(newangx#,oldangx#,25),curveangle(newangy#,oldangy#,5),curveangle(newangz#,oldangz#,5) oldx#=object position x(fish) oldy#=object position y(fish) oldz#=object position z(fish) move object fish,fishproperty(leader).speed*0.75 fishproperty(n).vx=object position x(fish)-oldx# fishproperty(n).vy=object position y(fish)-oldy# fishproperty(n).vz=object position z(fish)-oldz# fishproperty(n).speed=sqrt(fishproperty(n).vx^2+fishproperty(n).vy^2+fishproperty(n).vz^2) position object fish,oldx#,oldy#,oldz# angxy=atanfull(fishproperty(n).vx,fishproperty(n).vy) angxz=atanfull(fishproperty(n).vx,fishproperty(n).vz) angyz=atanfull(fishproperty(n).vy,fishproperty(n).vz) endif if fishproperty(n).intent="disperse" if fish<>fishseed closest#=1000 for check=0 to numberoffish-1 targetfish=fishseed+check if fish<>targetfish x#=object position x(targetfish)-object position x(fish) y#=object position y(targetfish)-object position y(fish) z#=object position z(targetfish)-object position z(fish) dist#=sqrt(x#^2+y#^2+z#^2) if dist#<closest# and fishproperty(check).speed>0.1 closest#=dist# leader=check endif endif next check if closest#>20.0 then fishproperty(n).intent="follow" oldangx#=object angle x(fish) oldangy#=object angle y(fish) oldangz#=object angle z(fish) point object fish,fishproperty(leader).x,fishproperty(leader).y,fishproperty(leader).z if rnd(1)=0 then turn object right fish,180 else pitch object down fish,180 newangx#=object angle x(fish) newangy#=object angle y(fish) newangz#=object angle z(fish) rotate object fish,oldangx#,oldangy#,oldangz# rotate object fish,curveangle(newangx#,oldangx#,25),curveangle(newangy#,oldangy#,5),curveangle(newangz#,oldangz#,5) oldx#=object position x(fish) oldy#=object position y(fish) oldz#=object position z(fish) move object fish,fishproperty(leader).speed fishproperty(n).vx=object position x(fish)-oldx# fishproperty(n).vy=object position y(fish)-oldy# fishproperty(n).vz=object position z(fish)-oldz# fishproperty(n).speed=sqrt(fishproperty(n).vx^2+fishproperty(n).vy^2+fishproperty(n).vz^2) position object fish,oldx#,oldy#,oldz# angxy=atanfull(fishproperty(n).vx,fishproperty(n).vy) angxz=atanfull(fishproperty(n).vx,fishproperty(n).vz) angyz=atanfull(fishproperty(n).vy,fishproperty(n).vz) endif endif inc fishproperty(n).x,fishproperty(n).vx inc fishproperty(n).y,fishproperty(n).vy inc fishproperty(n).z,fishproperty(n).vz limit=0 if fishproperty(n).x<-tankx/2 then fishproperty(n).x=-tankx/2:limit=1 if fishproperty(n).x>tankx/2 then fishproperty(n).x=tankx/2:limit=1 if fishproperty(n).y<-tanky/2 then fishproperty(n).y=-tanky/2:limit=1 if fishproperty(n).y>tanky/2 then fishproperty(n).y=tanky/2:limit=1 if fishproperty(n).z<-tankz/2 then fishproperty(n).z=-tankz/2:limit=1 if fishproperty(n).z>tankz/2 then fishproperty(n).z=tankz/2:limit=1 if limit=1 and fishproperty(n).intent="disperse" then fishproperty(n).intent="follow" position object fish,fishproperty(n).x,fishproperty(n).y,fishproperty(n).z next n following=0 leading=0 dispersing=0 for n=0 to numberoffish-1 if fishproperty(n).intent="lead" then inc leading if fishproperty(n).intent="follow" then inc following if fishproperty(n).intent="disperse" then inc dispersing next n `text 0,0,str$(screen fps()) `text 0,20,"Leading: "+str$(leading) `text 0,40,"Following: "+str$(following) `text 0,60,"Dispersing: "+str$(dispersing) sync loop function free_object() repeat inc n until object exist(n)=0 endfunction n