-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathboid.js
More file actions
163 lines (135 loc) · 3.95 KB
/
boid.js
File metadata and controls
163 lines (135 loc) · 3.95 KB
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
154
155
156
157
158
159
160
161
162
163
class Boid {
constructor(x, y) {
this.position = createVector(x, y);
this.velocity = p5.Vector.random2D();
this.velocity.setMag(random(2, 4));
this.acceleration = createVector();
this.r = 10;
this.maxspeed = 3; // Maximum speed
this.maxforce = 0.15; // Maximum steering force
}
// We accumulate a new acceleration each time based on three rules
flock(neighbors, obstacles) {
// let neighbors = this.getNeighbors(otherBoids);
// console.log(neighbors);
let sep = this.separate(neighbors); // Separation
let ali = this.align(neighbors); // Alignment
let coh = this.cohesion(neighbors); // Cohesion
let obs = this.obstacle(obstacles); // Obstacle Avoidance
// Arbitrarily weight these forces
sep.mult(separationSlider.value());
ali.mult(alignSlider.value());
coh.mult(cohesionSlider.value());
sep.mult(1.4);
ali.mult(1.0);
coh.mult(1.1);
obs.mult(1.0);
// Add the force vectors to acceleration
this.acceleration.add(sep);
this.acceleration.add(ali);
this.acceleration.add(coh);
this.acceleration.add(obs);
}
getNeighbors(boids) {
const neighbors = [];
for (let i = 0; i < boids.length; i++) {
let d = p5.Vector.dist(this.position, boids[i].position);
if (d > 0 && d < 50) {
neighbors.push(boids[i]);
}
}
return neighbors;
}
// Method to update location
update() {
this.updateLocation();
this.borders();
this.render();
}
updateLocation() {
this.velocity.add(this.acceleration);
this.velocity.limit(this.maxspeed);
this.position.add(this.velocity);
this.acceleration.mult(0);
}
render() {
// Draw a triangle rotated in the direction of velocity
if (debugMode) {
stroke("black");
strokeWeight(4);
point(this.position.x, this.position.y);
strokeWeight(1);
} else {
let theta = this.velocity.heading() + radians(90);
this.rotateAndDrawImage(this.position.x, this.position.y, theta);
}
}
rotateAndDrawImage(x, y, imgAngle) {
translate(x, y);
rotate(imgAngle);
image(img, 0, 0, 20, 20);
rotate(-imgAngle);
translate(-x, -y);
}
// Wraparound
borders() {
this.position.x = (this.position.x + width) % width;
this.position.y = (this.position.y + height) % height;
}
// Separation
separate(neighbors) {
let n = neighbors.length;
let steering = createVector(0, 0);
for (let i = 0; i < n; i++) {
let d = p5.Vector.dist(this.position, neighbors[i].position);
let diff = p5.Vector.sub(this.position, neighbors[i].position);
if (d != 0) diff.div(d * d);
steering.add(diff);
}
// Average -- divide by how many
if (n > 0) {
steering.div(n);
steering.setMag(this.maxspeed);
steering.sub(this.velocity);
steering.limit(this.maxforce);
}
return steering;
}
// Alignment
// For every nearby boid in the system, calculate the average velocity
align(neighbors) {
let n = neighbors.length;
let steering = createVector();
for (let i = 0; i < n; i++) {
steering.add(neighbors[i].velocity);
}
if (n > 0) {
steering.div(n);
steering.setMag(this.maxspeed);
steering.sub(this.velocity);
steering.limit(this.maxforce);
}
return steering;
}
// Cohesion
// For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location
cohesion(neighbors) {
let n = neighbors.length;
let steering = createVector(); // Start with empty vector to accumulate all locations
for (let i = 0; i < n; i++) {
steering.add(neighbors[i].position); // Add location
}
if (n > 0) {
steering.div(n);
steering.sub(this.position);
steering.setMag(this.maxspeed);
steering.sub(this.velocity);
steering.limit(this.maxforce);
}
return steering;
}
obstacle(obstacles) {
let steering = createVector();
return steering;
}
}