This repository has been archived by the owner on Aug 28, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sketch.js
268 lines (235 loc) · 8.42 KB
/
sketch.js
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
let screen_dock;
let text_box;
if (screen.availWidth < 800 || screen.availHeight < 675) {
settings_dock = "bottom"; // Options: left, bottom
text_box = true;
} else {
settings_dock = "left";
text_box = false;
}
let friendly_boids = [];
let enemy_boids = []
let pointsOfInterest = [];
let texts = [];
let options = [];
let is_updating = true;
let canvas_position = 0;
let setting_displacement;
if (settings_dock == 'left') {
setting_displacement = 0;
canvas_position = 350;
} else if (settings_dock == 'bottom') {
setting_displacement = screen.availHeight;
canvas_position = 0;
}
// Boid variables
let friendly_boid_count = 200;
let enemy_boid_count = 3;
let enemy_boid_attack_constant = 0.5;
let enemy_avoidance_constant = 0.75;
let enemy_avoidance_range = 150;
let avoidance_constant = 0.15;
let alignment_constant = 0.3;
let cohesion_constant = 0.04;
let interest_constant = 0.1;
let poi_avoidance_constant = 0.5;
let turn_constant = 0.3;
let margin = 100;
let avoidance_range = 25;
let visible_range = 65;
let poi_attraction_range = 500;
let poi_protection_range = 50;
let max_speed = 5;
let min_speed = 3;
function setup() {
// Position the canvas to the right of the settings
let canvas = createCanvas(screen.availWidth - canvas_position, screen.availHeight);
canvas.position(canvas_position, 0);
for (let i = 0; i < friendly_boid_count; i++) {
// friendly_boids.push(new FriendlyBoid(random(width), random(height)));
friendly_boids.push(new FriendlyBoidOptimised(random(width), random(height)));
}
for (let i = 0; i < enemy_boid_count; i++) {
// enemy_boids.push(new EnemyBoid(random(width), random(height)));
enemy_boids.push(new EnemyBoidOptimised(random(width), random(height)));
}
title = createP("<h1>Boid settings</h1>");
title.position(10, -25 + setting_displacement);
texts.push(createP("Friendly boid count:"));
options.push(createSlider(0, 250, friendly_boid_count, 1));
texts.push(createP("Enemy boid count:"));
options.push(createSlider(0, 100, enemy_boid_count, 1));
texts.push(createP("Enemy boid attack:"));
options.push(createSlider(0, 5, enemy_boid_attack_constant, 0.25));
texts.push(createP("Enemy avoidance:"));
options.push(createSlider(0, 2, enemy_avoidance_constant, 0.1));
texts.push(createP("Enemy avoidance range:"));
options.push(createSlider(0, 200, enemy_avoidance_range, 10));
texts.push(createP("Friendly avoidance:"));
options.push(createSlider(0, 1, avoidance_constant, 0.01));
texts.push(createP("Friendly avoidance range:"));
options.push(createSlider(0, 100, avoidance_range, 5));
texts.push(createP("Show avoidance range:"));
options.push(createCheckbox('', false));
texts.push(createP("Alignment:"));
options.push(createSlider(0, 1, alignment_constant, 0.01));
texts.push(createP("Cohesion:"));
options.push(createSlider(0, 0.1, cohesion_constant, 0.001));
texts.push(createP("Visible range:"));
options.push(createSlider(0, 100, visible_range, 5));
texts.push(createP("Show visible range:"));
options.push(createCheckbox('', false));
texts.push(createP("Max speed:"));
options.push(createSlider(0, 25, max_speed, 1));
texts.push(createP("Min speed:"));
options.push(createSlider(0, 25, min_speed, 1));
texts.push(createP("Margin:"));
options.push(createSlider(0, 200, margin, 10));
texts.push(createP("Show margin:"));
options.push(createCheckbox('', false));
texts.push(createP("POI attraction range:"));
options.push(createSlider(0, 1000, poi_attraction_range, 5));
texts.push(createP("Show POI attraction range:"));
options.push(createCheckbox('', false));
texts.push(createP("POI protection range:"));
options.push(createSlider(0, 500, poi_protection_range, 5));
texts.push(createP("Show POI protection range:"));
options.push(createCheckbox('', false));
texts.push(createP("Show trail:"));
options.push(createCheckbox('', false));
texts.push(createP("Show velocity:"));
options.push(createCheckbox('', false));
texts.push(createP("Boid shape:"));
options.push(createSelect());
texts.push(createP("Use the <kbd>+</kbd> or <kbd>-</kbd> keys to add and remove POIs."));
x_pos = 10;
y_pos = 50 + setting_displacement;
for (let text of texts) {
text.position(x_pos, y_pos);
y_pos += 25;
}
createP("Made and hosted by <a href='https://sooraj.dev/'>Sooraj</a>.").position(x_pos, y_pos);
x_pos = 210;
y_pos = 62 + setting_displacement;
for (let option of options) {
option.position(x_pos, y_pos);
option.size();
y_pos += 25;
}
options[22].option("Triangle");
options[22].option("Circle");
frameRate(60);
}
function draw() {
friendly_boid_count = options[0].value();
enemy_boid_count = options[1].value();
enemy_boid_attack_constant = options[2].value();
enemy_avoidance_constant = options[3].value();
enemy_avoidance_range = options[4].value();
avoidance_constant = options[5].value();
avoidance_range = options[6].value();
alignment_constant = options[8].value();
cohesion_constant = options[9].value();
visible_range = options[10].value();
max_speed = options[12].value();
min_speed = options[13].value();
poi_attraction_range = options[16].value();
poi_protection_range = options[18].value();
if (friendly_boids.length < friendly_boid_count) {
// friendly_boids.push(new FriendlyBoid(random(width), random(height)));
friendly_boids.push(new FriendlyBoidOptimised(random(width), random(height)));
} else if (friendly_boids.length > friendly_boid_count) {
friendly_boids.pop();
}
if (enemy_boids.length < enemy_boid_count) {
// enemy_boids.push(new EnemyBoid(random(width), random(height)));
enemy_boids.push(new EnemyBoidOptimised(random(width), random(height)));
} else if (enemy_boids.length > enemy_boid_count) {
enemy_boids.pop();
}
// Update boids
for (let boid of friendly_boids) {
boid.update(trail = options[20].checked(), update = is_updating);
}
for (let boid of enemy_boids) {
boid.update(trail = options[20].checked(), update = is_updating);
}
background(0);
// Draw trails
if (options[20].checked()) {
for (let boid of friendly_boids) {
boid.drawTrail();
}
for (let boid of enemy_boids) {
boid.drawTrail();
}
}
// Draw the margins
if (options[15].checked()) {
drawMargins();
}
// Draw points of interest
for (let poi of pointsOfInterest) {
poi.draw(protect_range = options[19].checked(), attract_range = options[17].checked());
}
// Draw friendly boids
for (let boid of friendly_boids) {
boid.drawBoid(shape = options[22].value());
}
// Draw enemy boids
for (let boid of enemy_boids) {
boid.drawBoid(shape = options[22].value());
}
// Draw velocity vectors
if (options[21].checked()) {
for (let boid of friendly_boids) {
boid.drawVelocity();
}
for (let boid of enemy_boids) {
boid.drawVelocity();
}
}
// Draw avoidance ranges
if (options[7].checked()) {
for (let boid of friendly_boids) {
boid.drawAvoidanceRange();
}
for (let boid of enemy_boids) {
boid.drawAvoidanceRange();
}
}
// Draw visible ranges
if (options[11].checked()) {
for (let boid of friendly_boids) {
boid.drawVisibleRange();
}
for (let boid of enemy_boids) {
boid.drawVisibleRange();
}
}
}
function keyPressed() {
// Check if it was a right click
if (key == '=') {
pointsOfInterest.push(new PointOfInterest(mouseX, mouseY));
} else if (key == '-') {
for (let i = pointsOfInterest.length - 1; i >= 0; i--) {
if (dist(mouseX, mouseY, pointsOfInterest[i].position.x, pointsOfInterest[i].position.y) < 10) {
pointsOfInterest.splice(i, 1);
}
}
} else if (key == ' ') {
if (is_updating) {
is_updating = false;
} else {
is_updating = true;
}
}
}
function drawMargins() {
margin = options[14].value();
stroke(150, 0, 0, 200);
strokeWeight(2);
noFill();
rect(margin, margin, width - 2 * margin, height - 2 * margin);
}