Example #1
0
 def constrain(self):
     
     """ Cages the flock inside the x, y, w, h area.
     
     The actual cage is a bit larger,
     so boids don't seem to bounce of invisible walls
     (they are rather "encouraged" to stay in the area).
     
     If a boid touches the ground level,
     it may decide to perch there for a while.
     
     """
     
     dx = self.w * 0.1
     dy = self.h * 0.1 
     
     for b in self:
         
         if b.x < self.x-dx: b.vx += random(dx)
         if b.y < self.y-dy: b.vy += random(dy)
         if b.x > self.x+self.w+dx: b.vx -= random(dx)
         if b.y > self.y+self.h+dy: b.vy -= random(dy)
         if b.z < 0: b.vz += 10
         if b.z > 100: b.vz -= 10
         
         if b.y > self._perch_y and random() < self._perch:
             b.y = self._perch_y
             b.vy = -abs(b.vy) * 0.2
             b.is_perching = True
             try:
                 b._perch_t = self._perch_t()
             except:
                 b._perch_t = self._perch_t
Example #2
0
    def wander(self, d=0.3):
        """
        Wander around randomly.
        
        Ants wander around randomly until they find food.
        The d parameter controls the chaos with which the ant moves:
        a higher d means a more erratic ant,
        but too high is inefficient as the ant becomes indecisive.
        
        Eventually, ants that have been doing nothing to long,
        return to the colony.
        
        """
        
        self.vx += random(-d, d)
        self.vy += random(-d, d)
        

        self.wandering += 1

        if self.wandering > self.colony.r: 
            self.goal(self.colony)

        if self.near(self.colony): 
            self.wandering = 0
Example #3
0
 def __init__(self, n, x, y, w, h):
     
     for i in range(n):
         dx = random(w)
         dy = random(h)
         z = random(200)
         b = Boid(self, x+dx, y+dy, z)
         self.append(b)
         
     self.x = x
     self.y = y
     self.w = w
     self.h = h
     
     self.scattered = False
     self._scatter = 0.005
     self._scatter_t = 50
     self._scatter_i = 0
     
     self._perch = 1.0 # Lower this number to simulate diving.
     self._perch_y = HEIGHT
     self._perch_t = lambda:25+random(50)
 
     self.has_goal = False
     self.flee = False
     self._gx = 0
     self._gy = 0
     self._gz = 0
Example #4
0
def demo_setup():
    ## Starts a colony with 30 ants in it.
    global colony
    colony = colony(30, WIDTH/2, HEIGHT/2, 100)
    
    ## Add some food in the vicinity of the colony.
    for i in range(8):
        x = 50 + random(WIDTH-100)
        y = 50 + random(HEIGHT-100)
        s = random(20, 40)
        
        colony.foodsources.append(food(x, y, s))
Example #5
0
 def perch(self, ground=None, chance=1.0, frames=lambda:25+random(50)):
     
     if ground == None:
         ground = _ctx.HEIGHT
         
     self._perch = chance
     self._perch_y = ground
     self._perch_t = frames
Example #6
0
def root(x, y, angle=0, depth=5, alpha=1.0, decay=0.005):
    """ Recursive root branches to smaller roots.
    """
    w = depth * 6
    for i in range(depth * random(10, 20)):
        v = float(depth)/5
        alpha -= i * decay
        alpha = max(0, alpha)
        
        if alpha > 0:
            # Next direction to grow in.,
            # e.g. between -60 and 60 degrees of current heading.
            angle += random(-60, 60)
            dx = x + cos(radians(angle)) * w
            dy = y + sin(radians(angle)) * w
            
            # Oval dropshadow.
            #ctx.nostroke()
            ctx.fill(0, 0, 0, alpha*0.25)
            ctx.oval(x-w/6+depth, y-w/6+depth, w/3, w/3)
 
            # Line segment to next position.
            ctx.nofill()
            ctx.stroke(0.8-v*0.25, 0.8, 0.8-v, alpha)
            ctx.strokewidth((depth + 1)*0.5)

            ctx.line(x, y, dx, dy)

            
            # Colored oval.
            ctx.strokewidth((depth+1)*0.25)
            ctx.fill(0.8-v*0.25, 0.8, 0.8-v, alpha*0.5)
            ctx.oval(x-w/6, y-w/6, w/3, w/3)
            
            # Create a branching root.
            if random() > 0.8 and depth > 0:
                root(x, y, angle, depth-1, alpha)
            
            x = dx
            y = dy
    
    # Continue growing at less alpha and depth.
    if depth > 0:
        root(x, y, angle, depth-1, alpha)
Example #7
0
 def __init__(self, colony, x, y):
     self.colony = colony
 
     self.x = x
     self.y = y
     self.vx = 0
     self.vy = 0
     
     self.has_food = False
     self.trail = []
     self.wandering = random(10)
Example #8
0
    def __init__(self, x, y, width=15):
        """ 
        A new sinewy tendril at location x and y.
        Its segment width will gradually become smaller as it grows.
        """

        self.x = x
        self.y = y
        self.width = width
        self.angle = random(2*pi) - pi ## random angle in radians.
        self.segments = []
        self.v = 0
Example #9
0
 def grow(self, distance=3.0, curl=1.0, step=0.02):
     """ Tendril segment growth using fluid, spiral sine functions,
     taken from the ART+COM Tendrils class for Processing.
     """
     ## Think of a tendril having a steering compass.
     ## For each new segment, the compass shifts a bit left or right.
     self.x += cos(self.angle) * distance
     self.y += sin(self.angle) * distance
     self.v += random(-step, step)
     self.v *= 0.9 + curl*0.1
     self.angle += self.v
     self.segments.append(
         (self.x, self.y, self.angle)
     )
Example #10
0
 def follow(self):
     
     """Follow a nearby pheromone trail.
     
     If the ant is not carrying food to the colony,
     follow any nearby trail.
     If the pheromone has evaporated to much,
     the ant might lose interest in the trail,
     this ensures it doesn't get "stuck" on a useless trail.
     
     """
     
     for ant in self.colony:
         if ant != self or self.has_food == False:
             for pheromone in ant.trail:
                 if self.near(pheromone):
                     if random() > pheromone.strength: return
                     self.goal(pheromone)
                     if pheromone.strength > 0.5: return
                     else: break
Example #11
0
 def hoard(self, trail=0.5):
     
     """Return straight home with food.
     
     Leave a trail of pheromone markers,
     which the other ants smell and follow to the food.
     
     """
     
     if self.has_food:
         self.goal(self.colony)
         if random() < trail:
             self.trail.append(Pheromone(self.x, self.y))
     
     #Drop food and start wandering again
     if self.near(self.colony) and self.has_food:
         self.trail.append(Pheromone(self.colony.x, self.colony.y))
         self.vx = 0
         self.vy = 0
         self.has_food = False
         self.colony.food += 1
Example #12
0
    def update(self, 
               shuffled=True, 
               cohesion=100, 
               separation=10, 
               alignment=5, 
               goal=20,
               limit=30):
        
        """ Calculates the next motion frame for the flock.
        """
        
        # Shuffling the list of boids ensures fluid movement.
        # If you need the boids to retain their position in the list
        # each update, set the shuffled parameter to False.
        from random import shuffle
        if shuffled: shuffle(self)
        
        m1 = 1.0 # cohesion
        m2 = 1.0 # separation
        m3 = 1.0 # alignment
        m4 = 1.0 # goal
        
        # The flock scatters randomly with a Boids.scatter chance.
        # This means their cohesion (m1) is reversed,
        # and their joint alignment (m3) is dimished,
        # causing boids to oscillate in confusion.
        # Setting Boids.scatter(chance=0) ensures they never scatter.
        if not self.scattered and random() < self._scatter:
            self.scattered = True
        if self.scattered:
            m1 = -m1
            m3 *= 0.25
            self._scatter_i += 1
        if self._scatter_i >= self._scatter_t:
            self.scattered = False
            self._scatter_i = 0

        # A flock can have a goal defined with Boids.goal(x,y,z),
        # a place of interest to flock around.
        if not self.has_goal:
            m4 = 0
        if self.flee:
            m4 = -m4
        
        for b in self:
            
            # A boid that is perching will continue to do so
            # until Boid._perch_t reaches zero.
            if b.is_perching:
                if b._perch_t > 0:
                    b._perch_t -= 1
                    continue
                else:
                    b.is_perching = False
            
            vx1, vy1, vz1 = b.cohesion(cohesion)
            vx2, vy2, vz2 = b.separation(separation)
            vx3, vy3, vz3 = b.alignment(alignment)
            vx4, vy4, vz4 = b.goal(self._gx, self._gy, self._gz, goal)
            
            b.vx += m1*vx1 + m2*vx2 + m3*vx3 + m4*vx4
            b.vy += m1*vy1 + m2*vy2 + m3*vy3 + m4*vy4
            b.vz += m1*vz1 + m2*vz2 + m3*vz3 + m4*vz4
            
            b.limit(limit)
        
            b.x += b.vx
            b.y += b.vy
            b.z += b.vz
        
        self.constrain()