visualizations

Programmatic visualizations
git clone git://git.laack.co/visualizations.git
Log | Files | Refs | README

boids.py (3598B)


      1 import pygame
      2 import random
      3 import time
      4 
      5 red = (255, 0, 0)
      6 white = (255,255,255)
      7 
      8 
      9 NUM_BOIDS = 300
     10 
     11 class Boid:
     12 
     13     pos_x = 0
     14     pos_y = 0
     15     vel_x = 100
     16     vel_y = 100
     17     delta_y = 0
     18     delta_x = 0
     19     max_velocity = 100
     20     ACC = 1
     21 
     22     NEARBY_DISTANCE = 40
     23     SEPERATION_DISTANCE = 10
     24 
     25     def __init__(self):
     26         self.pos_x = random.randint(0,500)
     27         self.pos_y = random.randint(0,500)
     28         self.last_time = time.time()
     29         self.vel_x = random.randint(-100,100)
     30         self.vel_y = random.randint(-100,100)
     31 
     32     def draw(self,display):
     33         pygame.draw.circle(display, white, (self.pos_x, self.pos_y), 2)
     34 
     35     def distance(self,otr):
     36         return ((self.pos_x - otr.pos_x) ** 2 + (self.pos_y - otr.pos_y) ** 2) ** .5
     37 
     38     def move(self):
     39         self.pos_x = self.pos_x + self.delta_x
     40         self.pos_y = self.pos_y + self.delta_y
     41 
     42     def compute_move(self, flock):
     43 
     44         if self.pos_x > 500 and self.vel_x > 0:
     45             self.vel_x *= -1
     46 
     47         if self.pos_x < 0 and self.vel_x < 0:
     48             self.vel_x *= -1
     49 
     50         if self.pos_y > 500 and self.vel_y > 0:
     51             self.vel_y *= -1
     52 
     53         if self.pos_y < 0 and self.vel_y < 0:
     54             self.vel_y *= -1
     55 
     56         nearby_headings = []
     57         nearby_positions = []
     58         too_close = []
     59 
     60         for i in range(0,len(flock)):
     61             if flock[i] == self:
     62                 continue
     63             dist = self.distance(flock[i])
     64 
     65             if dist < self.SEPERATION_DISTANCE:
     66                 too_close.append([flock[i].pos_x, flock[i].pos_y])
     67             if dist < self.NEARBY_DISTANCE:
     68                 nearby_headings.append([flock[i].vel_x, flock[i].vel_y])
     69                 nearby_positions.append([flock[i].pos_x, flock[i].pos_y])
     70 
     71         if nearby_positions:
     72             center_x = sum(p[0] for p in nearby_positions) / len(nearby_positions)
     73             center_y = sum(p[1] for p in nearby_positions) / len(nearby_positions)
     74             self.vel_x += (center_x - self.pos_x) * .08
     75             self.vel_y += (center_y - self.pos_y) * .08
     76 
     77         if nearby_headings:
     78             avg_x = sum(p[0] for p in nearby_headings) / len(nearby_headings)
     79             avg_y = sum(p[1] for p in nearby_headings) / len(nearby_headings)
     80             self.vel_x += (avg_x - self.vel_x) * .02
     81             self.vel_y += (avg_y - self.vel_y) * .02
     82 
     83         sep_x = 0
     84         sep_y = 0
     85 
     86         for pos in too_close:
     87             sep_x += self.pos_x - pos[0]
     88             sep_y += self.pos_y - pos[1]
     89 
     90         self.vel_x += sep_x * .04
     91         self.vel_y += sep_y * .04
     92 
     93         vel_current = ((self.vel_x ** 2) + (self.vel_y ** 2)) ** .5
     94 
     95         if vel_current > self.max_velocity:
     96             # make unit vector
     97             self.vel_x /= vel_current
     98             self.vel_y /= vel_current
     99 
    100             # make max speed
    101             self.vel_x *= self.max_velocity
    102             self.vel_y *= self.max_velocity
    103 
    104         current_time = time.time()
    105 
    106         self.vel_x += self.vel_x * (self.ACC * (current_time - self.last_time))
    107         self.vel_y += self.vel_y * (self.ACC * (current_time - self.last_time))
    108 
    109         self.delta_x = self.vel_x * (current_time - self.last_time)
    110         self.delta_y = self.vel_y * (current_time - self.last_time)
    111         self.last_time = current_time
    112 
    113 
    114 
    115 
    116 
    117 
    118 
    119 pygame.init()
    120 
    121 display = pygame.display.set_mode((500,500))
    122 
    123 flock = []
    124 
    125 for i in range(NUM_BOIDS):
    126     flock.append(Boid())
    127 
    128 while True:
    129     
    130     display.fill(red)
    131 
    132 
    133     for boid in flock:
    134         boid.compute_move(flock)
    135 
    136     for boid in flock:
    137         boid.move()
    138         boid.draw(display)
    139 
    140     pygame.display.update()