Skip to content

Instantly share code, notes, and snippets.

@kjsman
Created March 5, 2021 18:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kjsman/80e09b038cff9fbe2b16691f5de15768 to your computer and use it in GitHub Desktop.
Save kjsman/80e09b038cff9fbe2b16691f5de15768 to your computer and use it in GitHub Desktop.
새떼 시뮬레이션 by Boids algorithm
# 2021, By Jinseo Kim
# CC BY 4.0으로 배포됩니다.
import random
import math
import time
import os
# Screen size
X = 200
Y = 80
# Parameters
FIELD = 10
CLOSE = 4
SEPERATION = 0.2
ALIGNMENT = 0.15
COHENSION = 0.1
def normalize(x, y):
l = math.sqrt(x ** 2 + y ** 2)
return x / l, y / l
class Bird:
def __init__(self):
self.x = random.random() * X
self.y = random.random() * Y
angle = random.random() * 2 * math.pi
self.vx = math.cos(angle)
self.vy = math.sin(angle)
def is_near(a, b, l):
dx = abs(a.x - b.x)
dy = abs(a.y - b.y)
dx = min(dx, X - dx)
dy = min(dy, Y - dy)
return dx ** 2 + dy ** 2 <= l ** 2
def apply(self, birds):
near_birds = []
for bird in birds:
if bird is not self and self.is_near(bird, FIELD):
near_birds.append(bird)
if not near_birds: # No-op
self.x += self.vx
self.y += self.vy
if self.x < 0: self.x += X
if self.y < 0: self.y += Y
if self.x >= X: self.x -= X
if self.y >= Y: self.y -= Y
return
xs = [bird.x for bird in near_birds]
ys = [bird.y for bird in near_birds]
vxs = [bird.vx for bird in near_birds]
vys = [bird.vy for bird in near_birds]
xavg = sum(xs) / len(xs)
yavg = sum(ys) / len(ys)
vxavg = sum(vxs) / len(vxs)
vyavg = sum(vys) / len(vys)
dvx = (vxavg - self.vx) * ALIGNMENT
dvy = (vyavg - self.vy) * ALIGNMENT
xcoh, ycoh = normalize(xavg - self.x, yavg - self.y)
dvx += xcoh * COHENSION
dvy += ycoh * COHENSION
close_birds = []
for bird in near_birds:
if self.is_near(bird, CLOSE):
xsep, ysep = normalize(bird.x - self.x, bird.y - self.y)
dvx -= xsep * SEPERATION
dvy -= ysep * SEPERATION
self.vx += dvx
self.vy += dvy
self.vx, self.vy = normalize(self.vx, self.vy)
self.x += self.vx
self.y += self.vy
if self.x < 0: self.x += X
if self.y < 0: self.y += Y
if self.x >= X: self.x -= X
if self.y >= Y: self.y -= Y
return
birds = [Bird() for _ in range(100)]
while True:
start = time.time()
show = ['.'] * (Y * X // 2)
for bird in birds:
bird.apply(birds)
try:
show[math.floor(bird.y / 2) * X + math.floor(bird.x)] = '#'
except:
print(bird.x, bird.y, math.floor(bird.y / 2) * X + math.floor(bird.x))
raise
print('\n'.join([''.join(show[i:i+X]) for i in range(0, len(show), X)]))
print(time.time() - start, end="\n" * 5)
time.sleep(0.05)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment