Skip to content

Commit b5d4633

Browse files
committed
Compiled results
1 parent 6e89340 commit b5d4633

File tree

10 files changed

+1040
-0
lines changed

10 files changed

+1040
-0
lines changed

couzin_model/Boid.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
class Boid {
2+
constructor(position, velocity) {
3+
this.position = position;
4+
this.velocity = velocity;
5+
this.req_velocity = velocity;
6+
}
7+
8+
setVelocity(velocity) {
9+
this.req_velocity = velocity;
10+
}
11+
12+
updateVelocity() {
13+
let angle = Math.atan2(this.req_velocity.y, this.req_velocity.x) - Math.atan2(this.velocity.y, this.velocity.x);
14+
while (angle > Math.PI) {
15+
angle -= 2 * Math.PI;
16+
}
17+
while (angle < -Math.PI) {
18+
angle += 2 * Math.PI;
19+
}
20+
21+
if (angle > turning_speed) {
22+
angle = turning_speed;
23+
}
24+
else if (angle < -turning_speed) {
25+
angle = -turning_speed;
26+
}
27+
28+
let rotation_matrix = [
29+
[Math.cos(angle), -Math.sin(angle)],
30+
[Math.sin(angle), Math.cos(angle)]
31+
];
32+
this.velocity.x = rotation_matrix[0][0] * this.velocity.x + rotation_matrix[0][1] * this.velocity.y;
33+
this.velocity.y = rotation_matrix[1][0] * this.velocity.x + rotation_matrix[1][1] * this.velocity.y;
34+
this.velocity.normalize();
35+
}
36+
37+
update() {
38+
// update position
39+
this.position.x += moving_speed * this.velocity.x
40+
this.position.y += moving_speed * this.velocity.y;
41+
42+
if (this.position.x < 0) {
43+
this.position.x = 0;
44+
this.velocity.x *= -1;
45+
}
46+
else if (this.position.x > canvas_width) {
47+
this.position.x = canvas_width;
48+
this.velocity.x *= -1;
49+
}
50+
if (this.position.y < 0) {
51+
this.position.y = 0;
52+
this.velocity.y *= -1;
53+
}
54+
else if (this.position.y > canvas_height) {
55+
this.position.y = canvas_height;
56+
this.velocity.y *= -1;
57+
}
58+
59+
this.direction = this.velocity.getHeading();
60+
}
61+
62+
render() {
63+
context.fillStyle = "#ffffff";
64+
context.beginPath();
65+
context.moveTo(this.position.x + spoke_length * Math.cos(this.direction), this.position.y + spoke_length * Math.sin(this.direction));
66+
context.lineTo(this.position.x + spoke_length * Math.cos(this.direction + spoke_angle), this.position.y + spoke_length * Math.sin(this.direction + spoke_angle));
67+
context.lineTo(this.position.x + spoke_length * Math.cos(this.direction - spoke_angle), this.position.y + spoke_length * Math.sin(this.direction - spoke_angle));
68+
context.lineTo(this.position.x + spoke_length * Math.cos(this.direction), this.position.y + spoke_length * Math.sin(this.direction));
69+
context.fill();
70+
}
71+
}

couzin_model/Vector.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
class Vector {
2+
constructor(x, y) {
3+
this.x = x;
4+
this.y = y;
5+
}
6+
7+
magnitude() {
8+
return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
9+
}
10+
11+
negate() {
12+
this.x *= -1;
13+
this.y *= -1;
14+
}
15+
16+
normalize() {
17+
let magnitude = this.magnitude();
18+
this.x /= magnitude;
19+
this.y /= magnitude;
20+
}
21+
22+
getHeading() {
23+
return Math.atan2(this.y, this.x);
24+
}
25+
26+
add(vector) {
27+
this.x += vector.x;
28+
this.y += vector.y;
29+
}
30+
31+
scale(scale) {
32+
this.x *= scale;
33+
this.y *= scale;
34+
}
35+
36+
static add(vector1, vector2) {
37+
return new Vector(vector1.x + vector2.x, vector1.y + vector2.y);
38+
}
39+
40+
static normalize(vector) {
41+
let magnitude = vector.magnitude();
42+
return new Vector(vector.x / magnitude, vector.y / magnitude);
43+
}
44+
45+
static dot(vector1, vector2) {
46+
return vector1.x * vector2.x + vector1.y * vector2.y;
47+
}
48+
49+
static cross(vector1, vector2) {
50+
return vector1.x * vector2.y - vector1.y * vector2.x;
51+
}
52+
53+
static angleBetween(vector1, vector2) {
54+
return Math.acos(Vector.dot(vector1, vector2) / (vector1.magnitude() * vector2.magnitude()));
55+
}
56+
57+
static fromHeading(heading) {
58+
return new Vector(Math.cos(heading), Math.sin(heading));
59+
}
60+
61+
static distanceBetween(vector1, vector2) {
62+
return Math.sqrt(Math.pow(vector1.x - vector2.x, 2) + Math.pow(vector1.y - vector2.y, 2));
63+
}
64+
65+
static subtract(vector1, vector2) {
66+
return new Vector(vector1.x - vector2.x, vector1.y - vector2.y);
67+
}
68+
}

couzin_model/basic.js

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
let screen_width = window.innerWidth, screen_height = window.innerHeight;
2+
let canvas_width, canvas_height;
3+
let fps = 24, paused = false;
4+
let mobile;
5+
6+
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
7+
mobile = true;
8+
} else {
9+
mobile = false;
10+
}
11+
12+
let canvas = document.getElementById("canvas");
13+
let context = canvas.getContext("2d");
14+
15+
let polar_display = document.getElementById("polar-display");
16+
let ang_display = document.getElementById("ang-display");
17+
18+
let num_display = document.getElementById("num-display")
19+
20+
let repulsion_display = document.getElementById("repulsion-display");
21+
let repulsion_input = document.getElementById("repulsion-input");
22+
23+
let orientation_display = document.getElementById("orientation-display");
24+
let orientation_input = document.getElementById("orientation-input");
25+
26+
let attraction_display = document.getElementById("attraction-display");
27+
let attraction_input = document.getElementById("attraction-input");
28+
29+
let moving_speed_display = document.getElementById("moving-speed-display");
30+
let moving_speed_input = document.getElementById("moving-speed-input");
31+
32+
let turning_speed_display = document.getElementById("turning-speed-display");
33+
let turning_speed_input = document.getElementById("turning-speed-input");
34+
35+
let noise_display = document.getElementById("noise-display");
36+
let noise_input = document.getElementById("noise-input");
37+
38+
let blind_display = document.getElementById("blind-display");
39+
let blind_input = document.getElementById("blind-input");
40+
41+
let reflect_button = document.getElementById("reflect-button");
42+
let pause_button = document.getElementById("pause-button");
43+
44+
if (mobile) {
45+
canvas_width = 0.9 * screen_width;
46+
}
47+
else {
48+
canvas_width = 0.45 * screen_width;
49+
}
50+
canvas_height = canvas_width;
51+
52+
canvas.width = canvas_width;
53+
canvas.height = canvas_height;
54+
55+
let animate = window.requestAnimationFrame
56+
|| window.webkitRequestAnimationFrame
57+
|| window.mozRequestAnimationFrame
58+
|| function (callback) {
59+
window.setTimeout(callback, 1000 / fps);
60+
};
61+
62+
function step() {
63+
if (!paused) {
64+
update();
65+
}
66+
render();
67+
animate(step);
68+
}
69+
70+
window.onload = function () {
71+
defaultParams();
72+
initParams();
73+
animate(step);
74+
}
75+
76+
function defaultParams() {
77+
if (mobile) {
78+
spoke_length = 5;
79+
characteristic_length = 8;
80+
}
81+
else {
82+
spoke_length = 8;
83+
characteristic_length = 12;
84+
}
85+
86+
repulsion_input.value = 1;
87+
orientation_input.value = 3;
88+
attraction_input.value = 15;
89+
90+
moving_speed_input.value = 7;
91+
turning_speed_input.value = 8;
92+
noise_input.value = 10;
93+
94+
blind_input.value = 90;
95+
reflect = false;
96+
97+
if (reflect == false) {
98+
reflect_button.innerHTML = "Reflect: Off";
99+
}
100+
else {
101+
reflect_button.innerHTML = "Reflect: On";
102+
}
103+
}
104+
105+
let click_x, click_y, pressed;
106+
107+
if(mobile) {
108+
canvas.addEventListener("touchstart", function (e) {
109+
getTouchPosition(canvas, e);
110+
let touch = e.touches[0];
111+
let mouseEvent = new MouseEvent("mousedown", {
112+
clientX: touch.clientX,
113+
clientY: touch.clientY
114+
});
115+
canvas.dispatchEvent(mouseEvent);
116+
pressed = true;
117+
clicked();
118+
}, false);
119+
120+
canvas.addEventListener("touchmove", function (e) {
121+
getTouchPosition(canvas, e);
122+
let touch = e.touches[0];
123+
let mouseEvent = new MouseEvent("mousemove", {
124+
clientX: touch.clientX,
125+
clientY: touch.clientY
126+
});
127+
canvas.dispatchEvent(mouseEvent);
128+
moved();
129+
}, false);
130+
131+
canvas.addEventListener("touchend", function (e) {
132+
getTouchPosition(canvas, e);
133+
let touch = e.touches[0];
134+
let mouseEvent = new MouseEvent("mouseup", {
135+
clientX: touch.clientX,
136+
clientY: touch.clientY
137+
});
138+
canvas.dispatchEvent(mouseEvent);
139+
pressed = false;
140+
released();
141+
}, false);
142+
}
143+
else {
144+
canvas.addEventListener("mousedown", function (e) {
145+
getMousePosition(canvas, e);
146+
pressed = true;
147+
clicked();
148+
});
149+
150+
canvas.addEventListener("mousemove", function (e) {
151+
getMousePosition(canvas, e);
152+
moved();
153+
});
154+
155+
canvas.addEventListener("mouseup", function (e) {
156+
getMousePosition(canvas, e);
157+
pressed = false;
158+
released();
159+
});
160+
161+
window.addEventListener("keydown", function(e) {
162+
keyPressed(e.keyCode);
163+
}, false);
164+
165+
window.addEventListener("keydown", function(e) {
166+
keyReleased(e.keyCode);
167+
}, false);
168+
}
169+
170+
function getMousePosition(canvas, event) {
171+
rect = canvas.getBoundingClientRect();
172+
click_x = event.clientX - rect.left;
173+
click_y = event.clientY - rect.top;
174+
}
175+
176+
function getTouchPosition(canvas, event) {
177+
var rect = canvas.getBoundingClientRect();
178+
click_x = event.touches[0].clientX - rect.left;
179+
click_y = event.touches[0].clientY - rect.top;
180+
}
181+
182+
function pauseToggle() {
183+
if (paused) {
184+
paused = false;
185+
pause_button.innerHTML = "Pause";
186+
}
187+
else {
188+
paused = true;
189+
pause_button.innerHTML = "Resume";
190+
}
191+
}
192+
193+
function toggleReflection() {
194+
if (reflect) {
195+
reflect = false;
196+
reflect_button.innerHTML = "Reflect: Off";
197+
}
198+
else {
199+
reflect = true;
200+
reflect_button.innerHTML = "Reflect: On";
201+
}
202+
}

couzin_model/couzin_model.pdf

363 KB
Binary file not shown.

0 commit comments

Comments
 (0)