-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathboid.py
153 lines (126 loc) · 4.06 KB
/
boid.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import pygame
from tools import *
from random import uniform
import colorsys
from matrix import *
from math import pi,sin,cos
# def hsvToRGB(h, s, v):
# return tuple(round(i * 255) for i in colorsys.hsv_to_rgb(h,s,v))
class Boid:
def __init__(self, x, y):
self.position = Vector(x, y)
vec_x = uniform(-1, 1)
vec_y = uniform(-1, 1)
self.velocity = Vector(vec_x, vec_y)
self.velocity.normalize()
#set a random magnitude
self.velocity = self.velocity * uniform(1.5, 4)
self.acceleration = Vector()
self.color = (255, 255,255)
self.temp = self.color
self.secondaryColor = (70, 70, 70)
self.max_speed = 5
self.max_length = 1
self.size = 2
self.stroke = 5
self.angle = 0
self.hue = 0
self.toggles = {"separation":True, "alignment":True, "cohesion":True}
self.values = {"separation":0.1, "alignment":0.1, "cohesion":0.1}
self.radius = 40
def limits(self, width , height):
if self.position.x > width:
self.position.x = 0
elif self.position.x < 0:
self.position.x = width
if self.position.y > height:
self.position.y = 0
elif self.position.y < 0:
self.position.y = height
def behaviour(self, flock):
self.acceleration.reset()
if self.toggles["separation"] == True:
avoid = self.separation(flock)
avoid = avoid * self.values["separation"]
self.acceleration.add(avoid)
if self.toggles["cohesion"]== True:
coh = self.cohesion(flock)
coh = coh * self.values["cohesion"]
self.acceleration.add(coh)
if self.toggles["alignment"] == True:
align = self.alignment(flock)
align = align * self.values["alignment"]
self.acceleration.add(align)
def separation(self, flockMates):
total = 0
steering = Vector()
for mate in flockMates:
dist = getDistance(self.position, mate.position)
if mate is not self and dist < self.radius:
temp = SubVectors(self.position,mate.position)
temp = temp/(dist ** 2)
steering.add(temp)
total += 1
if total > 0:
steering = steering / total
# steering = steering - self.position
steering.normalize()
steering = steering * self.max_speed
steering = steering - self.velocity
steering.limit(self.max_length)
return steering
def alignment(self, flockMates):
total = 0
steering = Vector()
# hue = uniform(0, 0.5)
for mate in flockMates:
dist = getDistance(self.position, mate.position)
if mate is not self and dist < self.radius:
vel = mate.velocity.Normalize()
steering.add(vel)
mate.color = hsv_to_rgb( self.hue ,1, 1)
total += 1
if total > 0:
steering = steering / total
steering.normalize()
steering = steering * self.max_speed
steering = steering - self.velocity.Normalize()
steering.limit(self.max_length)
return steering
def cohesion(self, flockMates):
total = 0
steering = Vector()
for mate in flockMates:
dist = getDistance(self.position, mate.position)
if mate is not self and dist < self.radius:
steering.add(mate.position)
total += 1
if total > 0:
steering = steering / total
steering = steering - self.position
steering.normalize()
steering = steering * self.max_speed
steering = steering - self.velocity
steering.limit(self.max_length)
return steering
def update(self):
self.position = self.position + self.velocity
self.velocity = self.velocity + self.acceleration
self.velocity.limit(self.max_speed)
self.angle = self.velocity.heading() + pi/2
def Draw(self, screen, distance, scale):
ps = []
points = [None for _ in range(3)]
points[0] = [[0],[-self.size],[0]]
points[1] = [[self.size//2],[self.size//2],[0]]
points[2] = [[-self.size//2],[self.size//2],[0]]
for point in points:
rotated = matrix_multiplication(rotationZ(self.angle) , point)
z = 1/(distance - rotated[2][0])
projection_matrix = [[z, 0, 0], [0, z, 0]]
projected_2d = matrix_multiplication(projection_matrix, rotated)
x = int(projected_2d[0][0] * scale) + self.position.x
y = int(projected_2d[1][0] * scale) + self.position.y
ps.append((x, y))
pygame.draw.polygon(screen, self.secondaryColor, ps)
pygame.draw.polygon(screen, self.color, ps, self.stroke)