Fall2006.SampleProgram History

Hide minor edits - Show changes to output

Added lines 1-143:
(:source lang=Python tabwidth=3 -trim :)

# flock1.py Version 1.0 9-oct-06 (bzm)
#
# Simulates 3D boid behavior in VPython.
#
# The following general algorithm is followed:
# (see http://www.visualbots.com/flock_project.htm)
#
#For each Time Step Do the Following....
# For Each Bot In Bots ("sensing" loop)
# Calculate steering behaviors
# Calculate composite behavior
# Store composite behavior into Bot memory
# For Each Bot In Bots ("action" loop)
# Turn according to the stored composite behavior
# Move to next position
#
# For steering behavior possibilities see:
# http://www.vergenet.net/~conrad/boids/pseudocode.html
#

"Simulates 3D flocking behavior of boids in VPython."

from math import *
from boid import *

dt = 1.0 # time interval between animation frames

# boid constants
boidColor = color.blue # color of boids
boidRadius = 0.2 # radius of boids
boidDiameter = boidRadius*2

# boid behavior constants
minSeparation = boidDiameter # closest allowable distance between boids
flockThershold = boidDiameter * 500 # boids closer than this are in a local flock
cohesionFactor = 1.0/200 # larger for quicker cohesion
alignmentFactor = 1.0/2 # larger for quicker alignment

def main():
"Performs boid simulation."

boids = [] # list of boids
numBoids = input("Enter number of boids: ")

#boids = randomBoids(boids, numBoids, boidRadius, boidColor)
boids = placeBoidsViaMouse(boids, numBoids, boidRadius, boidColor)

# if you want obstacles, append them to boids
# (but you have to treat them differently when rules are considered)

# convert to array for faster indexing access
boids = array(boids)

# animate boids (press 'Escape' to end)
while (True):

# sensing and action loop
for boid in boids:

# calculate steering behaviors

# Rule 1 - Cohesion: Boids try to fly towards the centre of mass of neighbouring boids
v1 = boidCohesion(boid, boids)

# Rule 2 - Separation: Boids try to keep a small distance away from other objects (including other boids)
v2 = boidSeparation(boid, boids)

# Rule 3 - Alignment: Boids try to match velocity with near boids
v3 = boidAlignment(boid, boids)

# create composite behavior
boid.setVelocity(boid.getVelocity() + v1 + v2 + v3)

# action loop
for boid in boids:
boid.move(dt) # adjust boid position

# check mouse events and update boids as specified
moveBoidViaMouse(boids)


def boidCohesion(boid, boids):
"Return new velocity aiming towards center of flock."

flockCenter = vector(0,0,0) # initialize

# calculate cumulative position of flock mates
for flockmate in boids:
if flockmate != boid:
flockCenter = flockCenter + flockmate.getPos()

# get center of mass of all other boids
flockCenter = flockCenter / (len(boids)-1)
velocity = (flockCenter - boid.getPos()) * cohesionFactor

return velocity


def boidSeparation(boid, boids):
"Return new velocity vector to best avoid crowding flockmates."

velocity = vector(0,0,0)
# calculate velocity vector to best avoid crowding flockmates
for flockmate in boids:
separation = boid.distance(flockmate)
# are we too close for comfort?
if flockmate != boid and separation < minSeparation:
velocity = velocity - (flockmate.getPos() - boid.getPos())

return velocity


def boidAlignment(boid, boids):
"Return new velocity to match boid's velocity with local flockmates."

flockVelocity = vector(0,0,0) # initialize
flockMateCount = 0 # number of local flock mates
# calculate cumulative velocity of local flock mates
for flockmate in boids:
separation = boid.distance(flockmate)
# select only local flockmates
if flockmate != boid and separation < flockThershold:
flockMateCount += 1 # found one more flock mate
flockVelocity = flockVelocity + flockmate.getVelocity()

# calculate velocity aiming towards average position of flockmates (if any)
if flockMateCount > 0:
flockVelocity = flockVelocity / flockMateCount
velocity = (flockVelocity - boid.getVelocity()) * alignmentFactor
else:
velocity = vector(0,0,0) # no local flock mates to aim towards

return velocity

#-----

if __name__ == '__main__':
main()


(:sourcend:)