Copyright (c) 2008 Douglas Hammer # Vavaldi Decentralized Swarm Coordinates @include "Mathtools.tz" @include "Stationary.tz" @include "Control.tz" @include "Mobile.tz" @define SWARM_SIZE 80. Controller cCluster. Control : cCluster { + variables: birds,sublist (list). item (object). breveTexture, cloudTexture (object). selection (object). thetatwo (float). # the menu items corresponding to different flocking behaviors wackyMenu (object). obedientMenu (object). normalMenu (object). + to click on item (object): if selection: selection hide-neighbor-lines. if item: item show-neighbor-lines. selection = item. super click on item. + to init: floor (object). # Set up menus to modify the type of movement allowed. self add-menu named "Smoosh The Birdies" for-method "squish". self add-menu-separator. obedientMenu = (self add-menu named "Flock Obediently" for-method "flock-obediently"). normalMenu = (self add-menu named "Flock Normally" for-method "flock-normally"). wackyMenu = (self add-menu named "Flock Wackily" for-method "flock-wackily"). self enable-lighting. #self enable-smooth-drawing. self move-light to (0, 20, 20). breveTexture = (new Image load from "images/breve.png"). cloudTexture = (new Image load from "images/clouds.png"). # Add a huge floor. floor = new Floor. floor catch-shadows. birds = SWARM_SIZE new Birds. birds set-bitmap-image to breveTexture. # we'll call this method to set up the initial bird behavior. self flock-normally. self set-background-texture-image to cloudTexture. self offset-camera by (5, 1.5, 6). self enable-shadows. + to iterate: location (vector). topDiff (double). self update-neighbors. # get the average location, and point the camera at it. foreach item in birds: { item fly. location += (item get-location). } location /= | birds |. topDiff = 0.0. foreach item in birds: { if topDiff < |location - (item get-location) |: topDiff = | location - (item get-location) |. } # we'll try to keep the camera aimed at the center of the # flock, and zoom in and out depending on how spread out the # flock is. it's doesn't work very well :). self aim-camera at location. self zoom-camera to (.5 * topDiff) + 10. # call the superclass iterate method to step the simulation forward. super iterate. + to post-iterate: sum,mean(float). i,n,j,m (int). i=0. foreach item in birds: { sum+= (item get-phase). } mean=(1/SWARM_SIZE)*sum. n=|birds|. for i=0, i 10: worldCenterUrge = -(self get-location). # Add a random component to the accumulation. wanderUrge = random[(2, 2, 2)] - (1, 1, 1). # normalize all of the vectors to length 1. if |spacingUrge|: spacingUrge /= |spacingUrge|. if |worldCenterUrge|: worldCenterUrge /= |worldCenterUrge|. if |velocityUrge|: velocityUrge /= |velocityUrge|. if |centerUrge|: centerUrge /= |centerUrge|. if |wanderUrge|: wanderUrge /= |wanderUrge|. wanderUrge *= wanderConstant. worldCenterUrge *= worldCenterConstant. centerUrge *= centerConstant. velocityUrge *= velocityConstant. spacingUrge *= spacingConstant. acceleration = (worldCenterUrge + centerUrge + velocityUrge + spacingUrge + wanderUrge). if |acceleration| != 0: acceleration /= |acceleration|. self set-acceleration to maxAcceleration * acceleration. newVelocity = (self get-velocity). if |newVelocity| > maxVelocity: newVelocity = maxVelocity * newVelocity/|newVelocity|. self set-velocity to newVelocity. + to get-velocity-urge with flock (list): item (object). count (float). aveVelocity (vector). # get the average velocity of all the visible birds in the flock. if phase >= 3.141592635898: { foreach item in flock: { count += 1. aveVelocity += (item get-velocity). } } if count == 0: return (0, 0, 0). aveVelocity /= count. return aveVelocity - (self get-velocity). + to get-center-urge with flock (list): item (object). count (float). center (vector). # get the average location of all the visible birds in the flock. if phase >= 3.141592635898: { foreach item in flock: { count += 1. center += (item get-location). } } if count == 0: return (0, 0, 0). center /= count. return center - (self get-location). + to check-visibility of item (object): # An item is visible if it is within a certain angle (2.0 radians) # of the direction we're facing (assumed to be a vector in the # direction we're moving). if (item == self): return 0. if !(item is a "Bird"): return 0. if (item check-landed): return 0. if (self get-angle to item) > 2.0: return 0. return 1. + to get-angle to otherMobile (object): tempVector (vector). velocity (vector). velocity = ( self get-velocity ). if | velocity | == 0.0: return 0. tempVector = (otherMobile get-location) - (self get-location). return angle( velocity, tempVector). }