extra-game-loop 0.3.6 → 0.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,9 +15,8 @@ class GameLoopLite {
15
15
  constructor(options) {
16
16
  this.fsm = new extra_fsm_1.FiniteStateMachine(schema, State.Stopped);
17
17
  this.lastDeltaTime = 0;
18
- this.loop = () => {
19
- const timestamp = performance.now();
20
- const deltaTime = timestamp - this.lastTimestamp;
18
+ this.loop = (timestamp) => {
19
+ const deltaTime = Math.max(timestamp - this.lastTimestamp, 0);
21
20
  this.lastDeltaTime = deltaTime;
22
21
  this.lastTimestamp = timestamp;
23
22
  this.nextFrame(deltaTime);
@@ -28,14 +27,15 @@ class GameLoopLite {
28
27
  }
29
28
  start() {
30
29
  this.fsm.send('start');
31
- this.lastTimestamp = performance.now();
32
- this.loop();
30
+ const timestamp = performance.now();
31
+ this.lastTimestamp = timestamp;
32
+ this.loop(timestamp);
33
33
  }
34
34
  stop() {
35
35
  this.fsm.send('stop');
36
36
  cancelAnimationFrame(this.requstId);
37
- delete this.requstId;
38
- delete this.lastTimestamp;
37
+ this.requstId = undefined;
38
+ this.lastTimestamp = undefined;
39
39
  this.lastDeltaTime = 0;
40
40
  }
41
41
  getFramesOfSecond() {
@@ -1 +1 @@
1
- {"version":3,"file":"game-loop-lite.js","sourceRoot":"","sources":["../src/game-loop-lite.ts"],"names":[],"mappings":";;;AAAA,yCAAyE;AAczE,IAAK,KAGJ;AAHD,WAAK,KAAK;IACR,4BAAmB,CAAA;IACnB,4BAAmB,CAAA;AACrB,CAAC,EAHI,KAAK,KAAL,KAAK,QAGT;AAMD,MAAM,MAAM,GAA4C;IACtD,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE;IACzC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE;CACzC,CAAA;AAED,MAAa,YAAY;IAQvB,YAAY,OAA6B;QAPxB,QAAG,GAAG,IAAI,8BAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;QAK5D,kBAAa,GAAG,CAAC,CAAA;QAkCjB,SAAI,GAAG,GAAS,EAAE;YAIxB,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;YACnC,MAAM,SAAS,GAAG,SAAS,GAAG,IAAI,CAAC,aAAc,CAAA;YACjD,IAAI,CAAC,aAAa,GAAG,SAAS,CAAA;YAC9B,IAAI,CAAC,aAAa,GAAG,SAAS,CAAA;YAE9B,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;YAEzB,IAAI,CAAC,QAAQ,GAAG,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAClD,CAAC,CAAA;QA3CC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;QAC5B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;IAC9B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAEtB,IAAI,CAAC,aAAa,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;QACtC,IAAI,CAAC,IAAI,EAAE,CAAA;IACb,CAAC;IAED,IAAI;QACF,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAErB,oBAAoB,CAAC,IAAI,CAAC,QAAS,CAAC,CAAA;QAEpC,OAAO,IAAI,CAAC,QAAQ,CAAA;QACpB,OAAO,IAAI,CAAC,aAAa,CAAA;QACzB,IAAI,CAAC,aAAa,GAAG,CAAC,CAAA;IACxB,CAAC;IAED,iBAAiB;QACf,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;YACnC,OAAO,IAAI,CAAC,aAAa,KAAK,CAAC;gBAC1B,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,aAAa;gBAC3B,CAAC,CAAC,CAAC,CAAA;SACT;aAAM;YACL,OAAO,CAAC,CAAA;SACT;IACH,CAAC;IAgBD,SAAS,CAAC,SAAiB;;QACzB,MAAA,IAAI,CAAC,MAAM,qDAAG,SAAS,CAAC,CAAA;QAExB,MAAA,IAAI,CAAC,MAAM,oDAAI,CAAA;IACjB,CAAC;CACF;AA3DD,oCA2DC"}
1
+ {"version":3,"file":"game-loop-lite.js","sourceRoot":"","sources":["../src/game-loop-lite.ts"],"names":[],"mappings":";;;AAAA,yCAAyE;AAczE,IAAK,KAGJ;AAHD,WAAK,KAAK;IACR,4BAAmB,CAAA;IACnB,4BAAmB,CAAA;AACrB,CAAC,EAHI,KAAK,KAAL,KAAK,QAGT;AAMD,MAAM,MAAM,GAA4C;IACtD,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE;IACzC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE;CACzC,CAAA;AAED,MAAa,YAAY;IAQvB,YAAY,OAA6B;QAPxB,QAAG,GAAG,IAAI,8BAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;QAK5D,kBAAa,GAAG,CAAC,CAAA;QAmCjB,SAAI,GAAG,CAAC,SAAiB,EAAQ,EAAE;YAGzC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,aAAc,EAAE,CAAC,CAAC,CAAA;YAE9D,IAAI,CAAC,aAAa,GAAG,SAAS,CAAA;YAC9B,IAAI,CAAC,aAAa,GAAG,SAAS,CAAA;YAE9B,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;YAEzB,IAAI,CAAC,QAAQ,GAAG,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAClD,CAAC,CAAA;QA3CC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;QAC5B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;IAC9B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAEtB,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;QACnC,IAAI,CAAC,aAAa,GAAG,SAAS,CAAA;QAC9B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACtB,CAAC;IAED,IAAI;QACF,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAErB,oBAAoB,CAAC,IAAI,CAAC,QAAS,CAAC,CAAA;QAEpC,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAA;QACzB,IAAI,CAAC,aAAa,GAAG,SAAS,CAAA;QAC9B,IAAI,CAAC,aAAa,GAAG,CAAC,CAAA;IACxB,CAAC;IAED,iBAAiB;QACf,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;YACnC,OAAO,IAAI,CAAC,aAAa,KAAK,CAAC;gBAC1B,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,aAAa;gBAC3B,CAAC,CAAC,CAAC,CAAA;SACT;aAAM;YACL,OAAO,CAAC,CAAA;SACT;IACH,CAAC;IAeD,SAAS,CAAC,SAAiB;;QACzB,MAAA,IAAI,CAAC,MAAM,qDAAG,SAAS,CAAC,CAAA;QAExB,MAAA,IAAI,CAAC,MAAM,oDAAI,CAAA;IACjB,CAAC;CACF;AA3DD,oCA2DC"}
package/lib/game-loop.js CHANGED
@@ -17,9 +17,8 @@ class GameLoop {
17
17
  this.fsm = new extra_fsm_1.FiniteStateMachine(schema, State.Stopped);
18
18
  this.deltaTimeAccumulator = 0;
19
19
  this.lastDeltaTime = 0;
20
- this.loop = () => {
21
- const timestamp = performance.now();
22
- const deltaTime = timestamp - this.lastTimestamp;
20
+ this.loop = (timestamp) => {
21
+ const deltaTime = Math.max(timestamp - this.lastTimestamp, 0);
23
22
  this.lastDeltaTime = deltaTime;
24
23
  this.lastTimestamp = timestamp;
25
24
  this.nextFrame(deltaTime);
@@ -35,14 +34,15 @@ class GameLoop {
35
34
  }
36
35
  start() {
37
36
  this.fsm.send('start');
38
- this.lastTimestamp = performance.now();
39
- this.loop();
37
+ const timestamp = performance.now();
38
+ this.lastTimestamp = timestamp;
39
+ this.loop(timestamp);
40
40
  }
41
41
  stop() {
42
42
  this.fsm.send('stop');
43
43
  cancelAnimationFrame(this.requstId);
44
- delete this.requstId;
45
- delete this.lastTimestamp;
44
+ this.requstId = undefined;
45
+ this.lastTimestamp = undefined;
46
46
  this.lastDeltaTime = 0;
47
47
  }
48
48
  getFramesOfSecond() {
@@ -1 +1 @@
1
- {"version":3,"file":"game-loop.js","sourceRoot":"","sources":["../src/game-loop.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"game-loop.js","sourceRoot":"","sources":["../src/game-loop.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "extra-game-loop",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "files": [
@@ -42,8 +42,9 @@ export class GameLoopLite {
42
42
  start(): void {
43
43
  this.fsm.send('start')
44
44
 
45
- this.lastTimestamp = performance.now()
46
- this.loop()
45
+ const timestamp = performance.now()
46
+ this.lastTimestamp = timestamp
47
+ this.loop(timestamp)
47
48
  }
48
49
 
49
50
  stop(): void {
@@ -51,8 +52,8 @@ export class GameLoopLite {
51
52
 
52
53
  cancelAnimationFrame(this.requstId!)
53
54
 
54
- delete this.requstId
55
- delete this.lastTimestamp
55
+ this.requstId = undefined
56
+ this.lastTimestamp = undefined
56
57
  this.lastDeltaTime = 0
57
58
  }
58
59
 
@@ -66,12 +67,11 @@ export class GameLoopLite {
66
67
  }
67
68
  }
68
69
 
69
- private loop = (): void => {
70
- // requestAnimationFrame的实现存在陷阱, 它提供的timestamp参数有时会比`performance.now()`早.
71
- // 因此主动调用`performance.now()`来获取时间戳.
72
- // https://stackoverflow.com/questions/50895206/exact-time-of-display-requestanimationframe-usage-and-timeline
73
- const timestamp = performance.now()
74
- const deltaTime = timestamp - this.lastTimestamp!
70
+ private loop = (timestamp: number): void => {
71
+ // 如果传入的timestamp可能来自`performance.now()`, 则有可能出现deltaTime小于0的情况.
72
+ // 因为rAF的时间戳来自V-Sync, 出于动画帧同步方面的原因, 它的值可能会小于`performance.now()`.
73
+ const deltaTime = Math.max(timestamp - this.lastTimestamp!, 0)
74
+
75
75
  this.lastDeltaTime = deltaTime
76
76
  this.lastTimestamp = timestamp
77
77
 
package/src/game-loop.ts CHANGED
@@ -83,8 +83,9 @@ export class GameLoop<FixedDeltaTime extends number> {
83
83
  start(): void {
84
84
  this.fsm.send('start')
85
85
 
86
- this.lastTimestamp = performance.now()
87
- this.loop()
86
+ const timestamp = performance.now()
87
+ this.lastTimestamp = timestamp
88
+ this.loop(timestamp)
88
89
  }
89
90
 
90
91
  stop(): void {
@@ -92,8 +93,8 @@ export class GameLoop<FixedDeltaTime extends number> {
92
93
 
93
94
  cancelAnimationFrame(this.requstId!)
94
95
 
95
- delete this.requstId
96
- delete this.lastTimestamp
96
+ this.requstId = undefined
97
+ this.lastTimestamp = undefined
97
98
  this.lastDeltaTime = 0
98
99
  }
99
100
 
@@ -107,12 +108,11 @@ export class GameLoop<FixedDeltaTime extends number> {
107
108
  }
108
109
  }
109
110
 
110
- private loop = (): void => {
111
- // requestAnimationFrame的实现存在陷阱, 它提供的timestamp参数有时会比`performance.now()`早.
112
- // 因此主动调用`performance.now()`来获取时间戳.
113
- // https://stackoverflow.com/questions/50895206/exact-time-of-display-requestanimationframe-usage-and-timeline
114
- const timestamp = performance.now()
115
- const deltaTime = timestamp - this.lastTimestamp!
111
+ private loop = (timestamp: number): void => {
112
+ // 如果传入的timestamp可能来自`performance.now()`, 则有可能出现deltaTime小于0的情况.
113
+ // 因为rAF的时间戳来自V-Sync, 出于动画帧同步方面的原因, 它的值可能会小于`performance.now()`.
114
+ const deltaTime = Math.max(timestamp - this.lastTimestamp!, 0)
115
+
116
116
  this.lastDeltaTime = deltaTime
117
117
  this.lastTimestamp = timestamp
118
118