-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtraffic.js
105 lines (94 loc) · 2.81 KB
/
traffic.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
const NUMBER_OF_CARS = 30;
const NUMBER_OF_ROWS = 14;
const MAX_SPEED = 40;
const STARTING_DISTANCE = 200;
const MINIMUM_DISTANCE = 20;
const ACCELERATION = 1;
const INNER_RADIUS = 100;
const ROW_DISTANCE = 15;
const SLOWDOWN = 5000;
const container = document.body;
class Car {
constructor(t, row, color, opt_following) {
this.t = t;
this.row = row;
this.color = color;
this.following = opt_following;
this.speed = 0;
this.nextSpeed = 0;
this.element = document.createElement('div');
this.element.style.color = color;
this.element.classList.add('car');
container.appendChild(this.element);
}
updateSpeed() {
if (this.following &&
this.following.t < this.t + MINIMUM_DISTANCE * this.row) {
const reducedSpeed =
(this.following.t + this.following.speed - this.t) / MAX_SPEED;
this.nextSpeed =
reducedSpeed < this.nextSpeed ? reducedSpeed : this.nextSpeed;
} else if (!this.following ||
this.following.t > (this.t + STARTING_DISTANCE)) {
this.nextSpeed = this.nextSpeed + ACCELERATION;
}
this.nextSpeed = Math.min(this.nextSpeed, MAX_SPEED);
}
animate() {
this.updateSpeed();
this.element.style.color =
this.nextSpeed < this.speed ? '#8069ff' : this.color;
this.speed = this.nextSpeed;
this.t += this.speed;
this.element.style.left = Math.floor(
window.innerWidth / 2 +
((INNER_RADIUS + this.row * ROW_DISTANCE) *
Math.cos(this.t / SLOWDOWN))) + 'px';
this.element.style.top = Math.floor(
window.innerHeight / 2 +
((INNER_RADIUS + this.row * ROW_DISTANCE) *
Math.sin(this.t / SLOWDOWN))) + 'px';
}
}
class Leader extends Car {
constructor(t, row) {
super(t, row, '#000');
window.addEventListener('keydown', (e) => {
this.brake();
if (e.code == "Space" && !document.body.classList.contains('pauseTraffic')) {
e.preventDefault();
}
});
}
updateSpeed() {
super.updateSpeed();
if (Math.floor(this.t / MAX_SPEED) ==
Math.floor(SLOWDOWN * Math.PI / MAX_SPEED)) {
this.nextSpeed = 1;
}
}
brake() {
this.nextSpeed = Math.max(0, this.speed - 10);
}
}
const cars = [];
for (let row = 1; row < NUMBER_OF_ROWS + 1; row++) {
let leader = new Leader(NUMBER_OF_CARS, row);
cars.push(leader);
for (let c = 1; c < NUMBER_OF_CARS; c++) {
const value = Math.floor(c / NUMBER_OF_CARS * 100);
const color = `hsl(12, 83%, ${value}%)`;
let car = new Car((NUMBER_OF_CARS - c), row, color, leader);
leader = car;
cars.push(leader);
}
}
const animate = () => {
if (document.body.classList.contains('pauseTraffic')) {
window.setTimeout(animate, 100);
return;
}
cars.forEach(car => car.animate());
requestAnimationFrame(animate);
}
animate();