[futurebasic] Re: Spoim (boids)

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : November 2001 : Group Archive : Group : All Groups

From: Robert Covington <artlythere@...>
Date: Sat, 17 Nov 2001 11:56:41 -0500
This is a lame attempt at the Boids thing...sort of works, until they fly
offscreen into a lake of DDT.

There is a logical flaw somewhere... maybe more clear thinkers can divine
the problem given this starting approach/planform though.

Robert

/*

Re:
>' "Spoim", an FB^3 program for Standard Runtime.

rc:

Have you read "Artificial Minds" by Stan Franklin?  It's a
fascinating AI book. In the book, there is a program called "boids"
-- no code, just a description. The program goes like this:
'~'8

Place a bunch of points (each point a boid) within the limits of a screen.
'~'8

Have each boid then scan the surrounding area looking for other boids.
'~'8

Then have each boid determine the center of the entire mass of boids.
'~'8

Then have each boid move toward the center, but keeping a specific
distance from other boids.
'~'8

The book describes the resultant act of the program to be that of
birds flying around.
'~'8

*/

' "Boids", FB^3 program for Standard Runtime.
'  Robert Covington
' Logical Flaw somewhere....
' (Hide Control Strip if animation is jerky)

_MaxBoids = 40

Begin Record BoidRec
DIM x as double
DIM y as double
End Record

DIM boid(_MaxBoids) as BoidRec

DIM gMassX as double
DIM gMassY as Double

_BoidSpace = 9

DIM gBoidWorld as Long
DIM gScreenGW as Long
DIM gScreenDV as Long
DIM lastTicks as long
DIm gRect as Rect

End Globals
'~'1
'~'1
LOCAL FN MakeLockedGWorld(theRect as Ptr To rect, depth)
dim qdErr
DIM @ myGWorld as long
qdErr = FN NEWGWORLD(myGWorld, depth, #theRect, 0,0,0)
LONG IF (qdErr != _noErr)
if myGWorld then Call DisposeGWorld(myGWorld)
myGWorld = 0
Xelse
long if FN LOCKPIXELS(FN GETGWORLDPIXMAP(myGWorld)) = _false
if myGWorld then Call DisposeGWorld(myGWorld)
myGWorld = 0
end if
End if
END FN = myGWorld

LOCAL FN CopyBlitz(sPort&,dPort&,sRect as ptr,dRect as ptr)
Call ForeColor(_BlackColor)
Call BackColor(_whiteColor)
CALL COPYBITS(#sPort&+2,#dPort&+2,#sRect,#dRect,_srcCopy,0)
END FN

'~'1
'~'1

CLEAR LOCAL
' Wu Pixel approach.
' Brightness of the 4 pixels covered by boid particle
' (top left, top right, bottom left, bottom right)
DIM as Double btl, btr, bbl, bbr
' The fraction part of the coordinates
DIM as Double fx, fy
LOCAL FN DrawBoid(wx as double,wy as double)
' Integer coordinates of Wupixel
DIM x, y

' Calculate the coordinates of the top left pixel
x = FIx(wx)  // INT inverts
y = FIX(wy)                          '

' Calculate the <displacement> from exact integer
fx = wx - x
fy = wy - y

' Calculate the brightness of each of the 4 pixels
' and multiply by the brightness parameter
btl = (1-fx) * (1-fy)
btr =  (fx)  * (1-fy)
bbl = (1-fx) *  (fy)
bbr =  (fx)  *  (fy)

// Dark on Light
btl = 65535-(btl*65535)
btr = 65535-(btr*65535)
bbl = 65535-(bbl*65535)
bbr = 65535-(bbr*65535)
'~'8

'Plot the pixels
'Totality of all 4 = brightness of 1 standard pixel
'~'8

LONG COLOR btl,btl,btl
PLOT x,y
LONG COLOR btr,btr,btr
PLOT x+1,y
LONG COLOR bbl,bbl,bbl
PLOT x,y+1
LONG COLOR bbr,bbr,bbr
PLOT x+1,y+1

END FN

Local
DIM as Double mass
Local FN MassLogic
DIM as long totalX,totalY
DIM j'blue

// Should this be per boid?

gMassX = 0 : gMassY = 0

for j = 0 to _MaxBoids

gMassX = gMassX + boid.x(j)
gMassY = gMassY + boid.y(j)

next j

gMassX = gMassX/_MaxBoids
gMassY = gMassY/_MaxBoids

ENd FN
'~'8

Local
DIM dist as Double
Local FN AvoidDaBoid(thisBoid)
DIM j'blue

// Move toward Center

If boid.x(thisBoid) <= gMassX then boid.x(thisBoid)++ Else boid.x(thisBoid)--
If boid.y(thisBoid) <= gMassY then boid.y(thisBoid)++ Else boid.y(thisBoid)--

FOr j = 0 to _MaxBoids

dist = SQR((boid.x(j)-boid.x(thisBoid))^2 + (boid.y(j)-boid.y(thisBoid))^2)

long if dist < _BoidSpace // Move it away

Long if boid.x(j) - boid.x(thisBoid) <= 0
boid.x(thisBoid) = boid.x(thisBoid) + 1.1
XElse
boid.x(thisBoid) = boid.x(thisBoid) - 1.1
End If
Long if boid.y(j) - boid.y(thisBoid) <= 0
boid.y(thisBoid) = boid.y(thisBoid) + 1.1
XElse
boid.y(thisBoid) = boid.y(thisBoid) - 1.1
End If
End If

next j

End FN
'~'8

Local FN BoidThink(thisBoid)
FN MassLogic
FN AvoidDaBoid(thisBoid)
FN DrawBoid(boid.x(thisBoid) , boid.y(thisBoid) )               'Draw New Boid
End FN

'~'1

CLEAR LOCAL
DIM adp as double
DIM as Double x,y
LOCAL FN AnimateBoids(theTicks as long)
DIM @tmpWorld as long
DIM @tmpDevice as long
DIM direction
DIM as long j

Long if theTicks-lastTicks > 2
Call getGWorld(tmpWorld,tmpDevice)
Call SetGWorld(gBoidWorld,0)
Call BackColor(_WhiteColor)
cls ' Erase Old

FOR j=0 TO _MaxBoids
FN BoidThink(j)
NEXT j

Call SetGWorld(tmpWorld,tmpDevice)
FN CopyBlitz(gBoidWorld,gScreenGW,gRect,gRect)
lastTicks = theTicks // global lastTicks
End If

END FN

'~'1

CLEAR LOCAL
LOCAL FN loadArray
DIM j
FOR j=0 TO _MaxBoids            ' Fill Points array
Boid.x(j) = RND(320)+RND(10)*.1 //Starting X
Boid.y(j) = RND(320)+RND(10)*.1 //Starting Y
FN DrawBoid(Boid.x(j) , Boid.y(j) )
NEXT j
END FN

'~'1
"Main"

DIm Invert,i // Flag

DIM system(400*400*4) // 640 K for GWorld

Call SetRect(gRect,0,0,320,320)
WINDOW 1, "Spoim",@gRect,_docNoGrow
Call GetGworld(gScreenGW,gScreenDV)

gBoidWorld = FN MakeLockedGWorld(gRect,32)

Long if gBoidWorld

FN loadArray

lastTicks = FN TickCount

DO
FN AnimateBoids(FN TickCount)
HandleEvents
UNTIL FN BUTTON OR LEN(INKEY$)// Mouse or Key press

END
Xelse
Stop "Increase Dim System Total"
End If