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()