-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathInterval.js
More file actions
80 lines (66 loc) · 2.23 KB
/
Interval.js
File metadata and controls
80 lines (66 loc) · 2.23 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
/*
Executes synchronous functions at a recurring frequency. The first
or "base" loop determines the shared alpha value for all sibling functions.
Tip: Add your physics loop first (ex: 1000ms / 30fps = ~33ms), then add the
rendering loop without any delay. Use the alpha value to interpolate
rendered objects during your physics engine delay.
*/
class Interval {
constructor() {
this.loops = [];
this.speed = 1;
this.thread = timestamp => this.update(timestamp);
this.threadTimestamp = 0;
this.threadFrame = 0;
this.paused = true;
}
add(callback, delay = -1) {
// Create a loop with a callback and delay (milliseconds)
return this.loops.push({ callback, delay, delta: 0, alpha: 0, frame: 0, sum: 0, timestamp: 0 });
}
get(i) {
return this.loops[i];
}
remove(i) {
return this.loops.splice(i, 1);
}
start() {
// Only start if thread is paused
if (this.paused === true) {
this.paused = false;
// Set initial timestamps before starting thread
this.threadFrame = requestAnimationFrame(timestamp => {
this.threadTimestamp = timestamp;
this.loops.forEach(loop => loop.timestamp = timestamp);
this.thread(timestamp);
});
}
}
stop() {
this.paused = true;
}
update(timestamp) {
// Cancel the interval thread
if (this.paused === true) return;
// Rerun thread on next repaint
this.threadFrame = requestAnimationFrame(this.thread);
// Set thread delta from thread timestamp
const threadDelta = timestamp - this.threadTimestamp;
this.threadTimestamp = timestamp;
// Loop through array of loops (descending order)
for (let i = this.loops.length - 1; i >= 0; i--) {
// Add thread delta to loop sum
this.loops[i].sum += threadDelta * this.speed;
// Trigger loop callback
if (this.loops[i].sum >= this.loops[i].delay) {
this.loops[i].sum %= this.loops[i].delay;
this.loops[i].delta = (timestamp - this.loops[i].timestamp) * this.speed;
this.loops[i].alpha = this.loops[0].sum / this.loops[0].delay;
this.loops[i].frame++;
this.loops[i].timestamp = timestamp;
this.loops[i].callback(this.loops[i]);
}
}
}
}
export { Interval };