@vpmedia/phaser 1.123.0 → 1.125.0

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.
Files changed (221) hide show
  1. package/dist/index.js +635 -623
  2. package/dist/index.js.map +1 -1
  3. package/dist/phaser/core/animation.d.ts +3 -3
  4. package/dist/phaser/core/animation.d.ts.map +1 -1
  5. package/dist/phaser/core/animation_manager.d.ts.map +1 -1
  6. package/dist/phaser/core/animation_parser.d.ts +27 -2
  7. package/dist/phaser/core/animation_parser.d.ts.map +1 -1
  8. package/dist/phaser/core/array_set.d.ts +11 -11
  9. package/dist/phaser/core/array_set.d.ts.map +1 -1
  10. package/dist/phaser/core/cache.d.ts.map +1 -1
  11. package/dist/phaser/core/callback.d.ts.map +1 -1
  12. package/dist/phaser/core/dom.d.ts +125 -19
  13. package/dist/phaser/core/dom.d.ts.map +1 -1
  14. package/dist/phaser/core/factory.d.ts +3 -2
  15. package/dist/phaser/core/factory.d.ts.map +1 -1
  16. package/dist/phaser/core/frame_data.d.ts.map +1 -1
  17. package/dist/phaser/core/input.d.ts +3 -2
  18. package/dist/phaser/core/input.d.ts.map +1 -1
  19. package/dist/phaser/core/input_handler.d.ts.map +1 -1
  20. package/dist/phaser/core/input_mouse.d.ts +5 -1
  21. package/dist/phaser/core/input_mouse.d.ts.map +1 -1
  22. package/dist/phaser/core/input_pointer.d.ts +3 -3
  23. package/dist/phaser/core/input_pointer.d.ts.map +1 -1
  24. package/dist/phaser/core/input_touch.d.ts +8 -8
  25. package/dist/phaser/core/input_touch.d.ts.map +1 -1
  26. package/dist/phaser/core/loader.d.ts +11 -2
  27. package/dist/phaser/core/loader.d.ts.map +1 -1
  28. package/dist/phaser/core/loader_parser.d.ts +14 -1
  29. package/dist/phaser/core/loader_parser.d.ts.map +1 -1
  30. package/dist/phaser/core/raf.d.ts +1 -1
  31. package/dist/phaser/core/raf.d.ts.map +1 -1
  32. package/dist/phaser/core/scale_manager.d.ts.map +1 -1
  33. package/dist/phaser/core/scene_manager.d.ts.map +1 -1
  34. package/dist/phaser/core/signal.d.ts.map +1 -1
  35. package/dist/phaser/core/sound.d.ts.map +1 -1
  36. package/dist/phaser/core/sound_manager.d.ts +1 -1
  37. package/dist/phaser/core/sound_manager.d.ts.map +1 -1
  38. package/dist/phaser/core/stage.d.ts +16 -6
  39. package/dist/phaser/core/stage.d.ts.map +1 -1
  40. package/dist/phaser/core/time.d.ts.map +1 -1
  41. package/dist/phaser/core/timer.d.ts +1 -1
  42. package/dist/phaser/core/timer.d.ts.map +1 -1
  43. package/dist/phaser/core/tween.d.ts +13 -5
  44. package/dist/phaser/core/tween.d.ts.map +1 -1
  45. package/dist/phaser/core/tween_data.d.ts +9 -7
  46. package/dist/phaser/core/tween_data.d.ts.map +1 -1
  47. package/dist/phaser/core/tween_manager.d.ts.map +1 -1
  48. package/dist/phaser/display/button.d.ts +6 -5
  49. package/dist/phaser/display/button.d.ts.map +1 -1
  50. package/dist/phaser/display/canvas/buffer.d.ts +1 -1
  51. package/dist/phaser/display/canvas/buffer.d.ts.map +1 -1
  52. package/dist/phaser/display/canvas/masker.d.ts +1 -1
  53. package/dist/phaser/display/canvas/masker.d.ts.map +1 -1
  54. package/dist/phaser/display/canvas/pool.d.ts +2 -2
  55. package/dist/phaser/display/canvas/pool.d.ts.map +1 -1
  56. package/dist/phaser/display/canvas/renderer.d.ts +9 -8
  57. package/dist/phaser/display/canvas/renderer.d.ts.map +1 -1
  58. package/dist/phaser/display/display_object.d.ts +5 -3
  59. package/dist/phaser/display/display_object.d.ts.map +1 -1
  60. package/dist/phaser/display/graphics.d.ts +1 -1
  61. package/dist/phaser/display/graphics.d.ts.map +1 -1
  62. package/dist/phaser/display/group.d.ts +1 -1
  63. package/dist/phaser/display/group.d.ts.map +1 -1
  64. package/dist/phaser/display/image.d.ts +6 -5
  65. package/dist/phaser/display/image.d.ts.map +1 -1
  66. package/dist/phaser/display/sprite_util.d.ts +3 -2
  67. package/dist/phaser/display/sprite_util.d.ts.map +1 -1
  68. package/dist/phaser/display/text.d.ts +2 -16
  69. package/dist/phaser/display/text.d.ts.map +1 -1
  70. package/dist/phaser/display/webgl/abstract_filter.d.ts +14 -8
  71. package/dist/phaser/display/webgl/abstract_filter.d.ts.map +1 -1
  72. package/dist/phaser/display/webgl/blend_manager.d.ts +2 -3
  73. package/dist/phaser/display/webgl/blend_manager.d.ts.map +1 -1
  74. package/dist/phaser/display/webgl/earcut.d.ts.map +1 -1
  75. package/dist/phaser/display/webgl/fast_sprite_batch.d.ts +11 -5
  76. package/dist/phaser/display/webgl/fast_sprite_batch.d.ts.map +1 -1
  77. package/dist/phaser/display/webgl/filter_manager.d.ts +6 -4
  78. package/dist/phaser/display/webgl/filter_manager.d.ts.map +1 -1
  79. package/dist/phaser/display/webgl/filter_texture.d.ts +4 -4
  80. package/dist/phaser/display/webgl/filter_texture.d.ts.map +1 -1
  81. package/dist/phaser/display/webgl/graphics.d.ts +2 -2
  82. package/dist/phaser/display/webgl/graphics.d.ts.map +1 -1
  83. package/dist/phaser/display/webgl/mask_manager.d.ts +3 -2
  84. package/dist/phaser/display/webgl/mask_manager.d.ts.map +1 -1
  85. package/dist/phaser/display/webgl/render_texture.d.ts +11 -8
  86. package/dist/phaser/display/webgl/render_texture.d.ts.map +1 -1
  87. package/dist/phaser/display/webgl/renderer.d.ts +8 -4
  88. package/dist/phaser/display/webgl/renderer.d.ts.map +1 -1
  89. package/dist/phaser/display/webgl/shader/normal.d.ts +28 -3
  90. package/dist/phaser/display/webgl/shader/normal.d.ts.map +1 -1
  91. package/dist/phaser/display/webgl/sprite_batch.d.ts +6 -5
  92. package/dist/phaser/display/webgl/sprite_batch.d.ts.map +1 -1
  93. package/dist/phaser/display/webgl/stencil_manager.d.ts +3 -3
  94. package/dist/phaser/display/webgl/stencil_manager.d.ts.map +1 -1
  95. package/dist/phaser/display/webgl/texture.d.ts.map +1 -1
  96. package/dist/phaser/display/webgl/texture_util.d.ts +2 -2
  97. package/dist/phaser/display/webgl/texture_util.d.ts.map +1 -1
  98. package/dist/phaser/display/webgl/util.d.ts +1 -1
  99. package/dist/phaser/display/webgl/util.d.ts.map +1 -1
  100. package/dist/phaser/geom/circle.d.ts.map +1 -1
  101. package/dist/phaser/geom/line.d.ts +10 -1
  102. package/dist/phaser/geom/line.d.ts.map +1 -1
  103. package/dist/phaser/geom/rectangle.d.ts.map +1 -1
  104. package/dist/phaser/geom/util/circle.d.ts +2 -1
  105. package/dist/phaser/geom/util/circle.d.ts.map +1 -1
  106. package/dist/phaser/geom/util/point.d.ts +1 -1
  107. package/dist/phaser/geom/util/point.d.ts.map +1 -1
  108. package/dist/phaser/geom/util/rectangle.d.ts +1 -1
  109. package/dist/phaser/geom/util/rectangle.d.ts.map +1 -1
  110. package/dist/phaser/util/math.d.ts.map +1 -1
  111. package/package.json +1 -1
  112. package/src/phaser/core/animation.ts +11 -11
  113. package/src/phaser/core/animation_manager.ts +12 -12
  114. package/src/phaser/core/animation_parser.ts +39 -37
  115. package/src/phaser/core/array_set.ts +28 -28
  116. package/src/phaser/core/cache.test.ts +33 -33
  117. package/src/phaser/core/cache.ts +7 -7
  118. package/src/phaser/core/callback.ts +1 -0
  119. package/src/phaser/core/callback_context.test.ts +8 -8
  120. package/src/phaser/core/device_util.ts +4 -4
  121. package/src/phaser/core/dom.ts +38 -24
  122. package/src/phaser/core/factory.ts +9 -2
  123. package/src/phaser/core/frame_data.test.ts +23 -23
  124. package/src/phaser/core/frame_data.ts +2 -5
  125. package/src/phaser/core/game.ts +12 -12
  126. package/src/phaser/core/input.ts +11 -10
  127. package/src/phaser/core/input_handler.test.ts +18 -18
  128. package/src/phaser/core/input_handler.ts +14 -14
  129. package/src/phaser/core/input_mouse.ts +13 -12
  130. package/src/phaser/core/input_pointer.test.ts +26 -26
  131. package/src/phaser/core/input_pointer.ts +4 -4
  132. package/src/phaser/core/input_touch.ts +8 -8
  133. package/src/phaser/core/loader.test.ts +26 -26
  134. package/src/phaser/core/loader.ts +63 -75
  135. package/src/phaser/core/loader_parser.test.ts +16 -16
  136. package/src/phaser/core/loader_parser.ts +16 -6
  137. package/src/phaser/core/raf.ts +1 -1
  138. package/src/phaser/core/registry.test.ts +6 -6
  139. package/src/phaser/core/scale_manager.ts +12 -11
  140. package/src/phaser/core/scene_manager.test.ts +30 -30
  141. package/src/phaser/core/scene_manager.ts +3 -3
  142. package/src/phaser/core/signal.test.ts +8 -8
  143. package/src/phaser/core/signal.ts +3 -3
  144. package/src/phaser/core/signal_dispatch.test.ts +30 -30
  145. package/src/phaser/core/sound.ts +45 -40
  146. package/src/phaser/core/sound_manager.ts +18 -22
  147. package/src/phaser/core/sound_sprite.ts +1 -1
  148. package/src/phaser/core/stage.ts +22 -12
  149. package/src/phaser/core/time.ts +1 -1
  150. package/src/phaser/core/timer.test.ts +47 -47
  151. package/src/phaser/core/timer.ts +2 -2
  152. package/src/phaser/core/tween.ts +34 -36
  153. package/src/phaser/core/tween_data.test.ts +119 -0
  154. package/src/phaser/core/tween_data.ts +54 -39
  155. package/src/phaser/core/tween_easing.test.ts +5 -5
  156. package/src/phaser/core/tween_manager.ts +2 -2
  157. package/src/phaser/display/bitmap_text.test.ts +30 -30
  158. package/src/phaser/display/bitmap_text.ts +3 -3
  159. package/src/phaser/display/button.ts +20 -18
  160. package/src/phaser/display/canvas/buffer.ts +2 -2
  161. package/src/phaser/display/canvas/graphics.ts +2 -2
  162. package/src/phaser/display/canvas/masker.ts +1 -1
  163. package/src/phaser/display/canvas/pool.test.ts +20 -20
  164. package/src/phaser/display/canvas/pool.ts +6 -6
  165. package/src/phaser/display/canvas/renderer.ts +18 -16
  166. package/src/phaser/display/canvas/tinter.ts +1 -1
  167. package/src/phaser/display/canvas/util.test.ts +25 -25
  168. package/src/phaser/display/canvas/util.ts +2 -2
  169. package/src/phaser/display/display_object.ts +16 -15
  170. package/src/phaser/display/graphics.test.ts +70 -20
  171. package/src/phaser/display/graphics.ts +46 -42
  172. package/src/phaser/display/group.ts +13 -12
  173. package/src/phaser/display/image.ts +35 -31
  174. package/src/phaser/display/sprite_util.ts +4 -3
  175. package/src/phaser/display/text.test.ts +28 -25
  176. package/src/phaser/display/text.ts +56 -62
  177. package/src/phaser/display/webgl/abstract_filter.ts +21 -11
  178. package/src/phaser/display/webgl/blend_manager.ts +4 -5
  179. package/src/phaser/display/webgl/earcut.test.ts +20 -20
  180. package/src/phaser/display/webgl/earcut.ts +46 -42
  181. package/src/phaser/display/webgl/fast_sprite_batch.ts +21 -16
  182. package/src/phaser/display/webgl/filter_manager.ts +7 -4
  183. package/src/phaser/display/webgl/filter_texture.ts +5 -5
  184. package/src/phaser/display/webgl/graphics.ts +3 -3
  185. package/src/phaser/display/webgl/mask_manager.ts +9 -14
  186. package/src/phaser/display/webgl/render_texture.ts +15 -14
  187. package/src/phaser/display/webgl/renderer.ts +10 -9
  188. package/src/phaser/display/webgl/shader/normal.ts +45 -35
  189. package/src/phaser/display/webgl/shader/shader.test.ts +24 -24
  190. package/src/phaser/display/webgl/shader_manager.test.ts +18 -18
  191. package/src/phaser/display/webgl/shader_manager.ts +1 -1
  192. package/src/phaser/display/webgl/sprite_batch.ts +10 -10
  193. package/src/phaser/display/webgl/stencil_manager.ts +4 -4
  194. package/src/phaser/display/webgl/texture.ts +2 -1
  195. package/src/phaser/display/webgl/texture_util.ts +2 -2
  196. package/src/phaser/display/webgl/util.ts +4 -4
  197. package/src/phaser/geom/circle.test.ts +38 -38
  198. package/src/phaser/geom/circle.ts +7 -7
  199. package/src/phaser/geom/ellipse.test.ts +12 -12
  200. package/src/phaser/geom/line.test.ts +15 -15
  201. package/src/phaser/geom/line.ts +5 -2
  202. package/src/phaser/geom/matrix.test.ts +31 -31
  203. package/src/phaser/geom/point.test.ts +31 -31
  204. package/src/phaser/geom/polygon.test.ts +27 -27
  205. package/src/phaser/geom/polygon.ts +2 -2
  206. package/src/phaser/geom/rectangle.test.ts +87 -87
  207. package/src/phaser/geom/rectangle.ts +12 -13
  208. package/src/phaser/geom/rounded_rectangle.test.ts +9 -9
  209. package/src/phaser/geom/util/circle.test.ts +5 -5
  210. package/src/phaser/geom/util/circle.ts +8 -11
  211. package/src/phaser/geom/util/ellipse.test.ts +2 -2
  212. package/src/phaser/geom/util/line.test.ts +2 -2
  213. package/src/phaser/geom/util/matrix.test.ts +4 -4
  214. package/src/phaser/geom/util/point.test.ts +2 -2
  215. package/src/phaser/geom/util/point.ts +6 -8
  216. package/src/phaser/geom/util/polygon.test.ts +2 -2
  217. package/src/phaser/geom/util/rectangle.test.ts +2 -2
  218. package/src/phaser/geom/util/rectangle.ts +1 -1
  219. package/src/phaser/geom/util/rounded_rectangle.test.ts +2 -2
  220. package/src/phaser/util/math.test.ts +41 -41
  221. package/src/phaser/util/math.ts +7 -5
@@ -13,6 +13,16 @@ export type SoundMarker = {
13
13
  loop: boolean;
14
14
  };
15
15
 
16
+ /** The pre-standard Web Audio names, still the only ones some older engines expose. */
17
+ type LegacyAudioContext = { createGainNode: () => GainNode };
18
+
19
+ /** The pre-standard source-node names, alongside the playback position those engines reported. */
20
+ type LegacyBufferSource = {
21
+ noteOff: (when: number) => void;
22
+ noteGrainOn: (when: number, offset: number, duration: number) => void;
23
+ currentTime: number;
24
+ };
25
+
16
26
  export class Sound {
17
27
  public _paused!: boolean;
18
28
  public game!: Game;
@@ -71,7 +81,7 @@ export class Sound {
71
81
  */
72
82
  public constructor(game: Game, key: string, volume = 1, loop = false, connect: boolean | null = null) {
73
83
  // https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Migrating_from_webkitAudioContext
74
- connect ??= game.sound.connectToMaster;
84
+ const connectToMaster = connect ?? game.sound.connectToMaster;
75
85
  this.game = game;
76
86
  this.name = key;
77
87
  this.key = key;
@@ -101,10 +111,12 @@ export class Sound {
101
111
  this.context = this.game.sound.context;
102
112
  this.masterGainNode = this.game.sound.masterGain;
103
113
  const gainNode: GainNode =
104
- this.context!.createGain === undefined ? (this.context as any).createGainNode() : this.context!.createGain();
114
+ this.context!.createGain === undefined
115
+ ? (this.context as unknown as LegacyAudioContext).createGainNode()
116
+ : this.context!.createGain();
105
117
  this.gainNode = gainNode;
106
118
  gainNode.gain.value = volume * this.game.sound.volume;
107
- if (connect && this.masterGainNode) {
119
+ if (connectToMaster && this.masterGainNode !== null) {
108
120
  gainNode.connect(this.masterGainNode);
109
121
  }
110
122
  this.onPlay = new Signal();
@@ -181,7 +193,7 @@ export class Sound {
181
193
  }
182
194
  if (this.externalNode) {
183
195
  this._sound.disconnect(this.externalNode);
184
- } else if (this.gainNode) {
196
+ } else if (this.gainNode as GainNode | undefined) {
185
197
  this._sound.disconnect(this.gainNode);
186
198
  }
187
199
  if (this._removeFromSoundManager) {
@@ -258,37 +270,35 @@ export class Sound {
258
270
  * @returns {Sound} This Sound instance for chaining.
259
271
  */
260
272
  public play(marker: string | false | null = '', position = 0, volume = 1, loop = false, forceRestart = true): this {
261
- if (marker === undefined || marker === false || marker === null) {
262
- marker = '';
263
- }
264
- forceRestart ??= true;
273
+ const markerName = marker === undefined || marker === false || marker === null ? '' : marker;
265
274
 
266
275
  if (this.isPlaying && !this.allowMultiple && !forceRestart && !this.override) {
267
276
  // Use Restart instead
268
277
  return this;
269
278
  }
270
- if (this._sound && this.isPlaying && !this.allowMultiple && (this.override || forceRestart)) {
279
+ const source = this._sound as AudioBufferSourceNode | undefined;
280
+ if (source && this.isPlaying && !this.allowMultiple && (this.override || forceRestart)) {
271
281
  if (this._sound.stop === undefined) {
272
- (this._sound as any).noteOff(0);
282
+ (this._sound as unknown as LegacyBufferSource).noteOff(0);
273
283
  } else {
274
284
  this._sound.stop(0);
275
285
  }
276
286
  if (this.externalNode) {
277
287
  this._sound.disconnect(this.externalNode);
278
- } else if (this.gainNode) {
288
+ } else if (this.gainNode as GainNode | undefined) {
279
289
  this._sound.disconnect(this.gainNode);
280
290
  }
281
291
  this.isPlaying = false;
282
292
  }
283
- if (marker === '' && Object.keys(this.markers).length > 0) {
293
+ if (markerName === '' && Object.keys(this.markers).length > 0) {
284
294
  // If they didn't specify a marker but this is an audio sprite,
285
295
  // We should never play the entire thing
286
296
  return this;
287
297
  }
288
- const markerData = marker === '' ? undefined : this.markers[marker];
289
- if (marker !== '') {
298
+ const markerData = markerName === '' ? undefined : this.markers[markerName];
299
+ if (markerName !== '') {
290
300
  if (markerData) {
291
- this.currentMarker = marker;
301
+ this.currentMarker = markerName;
292
302
  // Playing a marker? Then we default to the marker values
293
303
  this.position = markerData.start;
294
304
  this.volume = markerData.volume;
@@ -301,32 +311,27 @@ export class Sound {
301
311
  if (loop !== undefined) {
302
312
  this.loop = loop;
303
313
  }
304
- this._tempMarker = marker;
314
+ this._tempMarker = markerName;
305
315
  this._tempPosition = this.position;
306
316
  this._tempVolume = this.volume;
307
317
  this._tempLoop = this.loop;
308
318
  } else {
309
- this.game.logger.warn(`Sound.play: audio marker ${marker} does not exist`);
319
+ this.game.logger.warn(`Sound.play: audio marker ${markerName} does not exist`);
310
320
  return this;
311
321
  }
312
322
  } else {
313
- position ??= 0;
314
- volume ??= this._volume;
315
- if (loop === undefined) {
316
- ({ loop } = this);
317
- }
318
- this.position = Math.max(0, position);
319
- this.volume = volume;
320
- this.loop = loop;
323
+ this.position = Math.max(0, position ?? 0);
324
+ this.volume = volume ?? this._volume;
325
+ this.loop = loop ?? this.loop;
321
326
  this.duration = 0;
322
327
  this.durationMS = 0;
323
- this._tempMarker = marker;
328
+ this._tempMarker = markerName;
324
329
  this._tempPosition = position;
325
330
  this._tempVolume = volume;
326
331
  this._tempLoop = loop;
327
332
  }
328
333
  // Does the sound need decoding?
329
- if (this.game.cache.isSoundDecoded(this.key)) {
334
+ if (this.game.cache.isSoundDecoded(this.key) === true) {
330
335
  this._sound = this.context!.createBufferSource();
331
336
  if (this.externalNode) {
332
337
  this._sound.connect(this.externalNode);
@@ -335,10 +340,10 @@ export class Sound {
335
340
  }
336
341
  this._buffer = this.game.cache.getSoundData(this.key) as AudioBuffer | null;
337
342
  this._sound.buffer = this._buffer;
338
- if (this.loop && marker === '') {
343
+ if (this.loop && markerName === '') {
339
344
  this._sound.loop = true;
340
345
  }
341
- if (!this.loop && marker === '') {
346
+ if (!this.loop && markerName === '') {
342
347
  this._sound.addEventListener('ended', this.onEndedHandler, { once: true });
343
348
  }
344
349
  this.totalDuration = this._sound.buffer?.duration ?? 0;
@@ -348,8 +353,8 @@ export class Sound {
348
353
  }
349
354
  // Useful to cache this somewhere perhaps?
350
355
  if (this._sound.start === undefined) {
351
- (this._sound as any).noteGrainOn(0, this.position, this.duration);
352
- } else if (this.loop && marker === '') {
356
+ (this._sound as unknown as LegacyBufferSource).noteGrainOn(0, this.position, this.duration);
357
+ } else if (this.loop && markerName === '') {
353
358
  this._sound.start(0, 0);
354
359
  } else {
355
360
  this._sound.start(0, this.position, this.duration);
@@ -383,11 +388,11 @@ export class Sound {
383
388
  * Pauses the sound.
384
389
  */
385
390
  public pause(): void {
386
- if (this.isPlaying && this._sound) {
391
+ if (this.isPlaying && (this._sound as AudioBufferSourceNode | undefined)) {
387
392
  this.paused = true;
388
393
  this.pausedPosition = this.currentTime;
389
394
  this.pausedTime = this.game.time.time;
390
- this._tempPause = (this._sound as any).currentTime;
395
+ this._tempPause = (this._sound as unknown as LegacyBufferSource).currentTime;
391
396
  this.onPause.dispatch(this);
392
397
  this.stop();
393
398
  }
@@ -397,7 +402,7 @@ export class Sound {
397
402
  * Resumes the sound.
398
403
  */
399
404
  public resume(): void {
400
- if (this.paused && this._sound) {
405
+ if (this.paused && (this._sound as AudioBufferSourceNode | undefined)) {
401
406
  const p = Math.max(0, this.position + this.pausedPosition / 1000);
402
407
  this._sound = this.context!.createBufferSource();
403
408
  this._sound.buffer = this._buffer;
@@ -414,7 +419,7 @@ export class Sound {
414
419
  }
415
420
  const duration = this.duration - this.pausedPosition / 1000;
416
421
  if (this._sound.start === undefined) {
417
- (this._sound as any).noteGrainOn(0, p, duration);
422
+ (this._sound as unknown as LegacyBufferSource).noteGrainOn(0, p, duration);
418
423
  } else {
419
424
  this._sound.start(0, p, duration);
420
425
  }
@@ -429,15 +434,15 @@ export class Sound {
429
434
  * Stops the sound.
430
435
  */
431
436
  public stop(): void {
432
- if (this.isPlaying && this._sound) {
437
+ if (this.isPlaying && (this._sound as AudioBufferSourceNode | undefined)) {
433
438
  if (this._sound.stop === undefined) {
434
- (this._sound as any).noteOff(0);
439
+ (this._sound as unknown as LegacyBufferSource).noteOff(0);
435
440
  } else {
436
441
  this._sound.stop(0);
437
442
  }
438
443
  if (this.externalNode) {
439
444
  this._sound.disconnect(this.externalNode);
440
- } else if (this.gainNode) {
445
+ } else if (this.gainNode as GainNode | undefined) {
441
446
  this._sound.disconnect(this.gainNode);
442
447
  }
443
448
  }
@@ -531,7 +536,7 @@ export class Sound {
531
536
  * Gets the muted state of the sound.
532
537
  * @returns {boolean} True if the sound is muted, false otherwise.
533
538
  */
534
- public get mute() {
539
+ public get mute(): boolean | null {
535
540
  return this._muted || this.game.sound.mute;
536
541
  }
537
542
 
@@ -565,7 +570,7 @@ export class Sound {
565
570
  /**
566
571
  * Sets the volume of the sound.
567
572
  */
568
- public set volume(value) {
573
+ public set volume(value: number) {
569
574
  if (this._muted) {
570
575
  this._muteVolume = value;
571
576
  return;
@@ -27,7 +27,7 @@ export class SoundManager {
27
27
  public _unlockSource!: AudioBufferSourceNode | null;
28
28
  public _volume!: number;
29
29
  public _sounds!: Sound[];
30
- public _watchList!: ArraySet;
30
+ public _watchList!: ArraySet<string>;
31
31
  public _watching!: boolean;
32
32
  public _watchCallback!: Callback | null;
33
33
  public _watchContext!: unknown;
@@ -54,7 +54,7 @@ export class SoundManager {
54
54
  this._volume = 1;
55
55
  /** @type {Sound[]} */
56
56
  this._sounds = [];
57
- this._watchList = new ArraySet();
57
+ this._watchList = new ArraySet<string>();
58
58
  this._watching = false;
59
59
  this._watchCallback = null;
60
60
  this._watchContext = null;
@@ -73,7 +73,7 @@ export class SoundManager {
73
73
  setAudioDisabledState();
74
74
  return;
75
75
  }
76
- if (globalThis.AudioContext) {
76
+ if (globalThis.AudioContext as typeof AudioContext | undefined) {
77
77
  try {
78
78
  this.game.logger.info('initAudioContext');
79
79
  this.context = new globalThis.AudioContext();
@@ -240,7 +240,7 @@ export class SoundManager {
240
240
  return;
241
241
  }
242
242
  for (const sound of this._sounds) {
243
- if (sound) {
243
+ if (sound !== null) {
244
244
  sound.stop();
245
245
  }
246
246
  }
@@ -254,7 +254,7 @@ export class SoundManager {
254
254
  return;
255
255
  }
256
256
  for (const sound of this._sounds) {
257
- if (sound) {
257
+ if (sound !== null) {
258
258
  sound.pause();
259
259
  }
260
260
  }
@@ -268,7 +268,7 @@ export class SoundManager {
268
268
  return;
269
269
  }
270
270
  for (const sound of this._sounds) {
271
- if (sound) {
271
+ if (sound !== null) {
272
272
  sound.resume();
273
273
  }
274
274
  }
@@ -317,7 +317,7 @@ export class SoundManager {
317
317
  this._watchList.reset();
318
318
  for (const file of candidates) {
319
319
  const key = file instanceof Sound ? file.key : file;
320
- if (!this.game.cache.isSoundDecoded(key)) {
320
+ if (this.game.cache.isSoundDecoded(key) !== true) {
321
321
  this._watchList.add(key);
322
322
  }
323
323
  }
@@ -344,8 +344,8 @@ export class SoundManager {
344
344
  }
345
345
  if (this._watching) {
346
346
  let key = this._watchList.first;
347
- while (key) {
348
- if (this.game.cache.isSoundDecoded(key)) {
347
+ while (key !== null) {
348
+ if (this.game.cache.isSoundDecoded(key) === true) {
349
349
  this._watchList.remove(key);
350
350
  }
351
351
  key = this._watchList.next;
@@ -469,7 +469,7 @@ export class SoundManager {
469
469
  public destroy(): void {
470
470
  this.stopAll();
471
471
  for (const sound of this._sounds) {
472
- if (sound) {
472
+ if (sound !== null) {
473
473
  sound.destroy();
474
474
  }
475
475
  }
@@ -484,14 +484,14 @@ export class SoundManager {
484
484
  * Gets the muted state of the sound manager.
485
485
  * @returns {boolean} True if the manager is muted, false otherwise.
486
486
  */
487
- public get mute() {
487
+ public get mute(): boolean {
488
488
  return this._muted;
489
489
  }
490
490
 
491
491
  /**
492
492
  * Sets the muted state of the sound manager.
493
493
  */
494
- public set mute(value) {
494
+ public set mute(value: boolean) {
495
495
  if (value || false) {
496
496
  if (this._muted) {
497
497
  return;
@@ -511,23 +511,19 @@ export class SoundManager {
511
511
  * Gets the volume level of the sound manager.
512
512
  * @returns {number} The volume level (0.0 to 1.0).
513
513
  */
514
- public get volume() {
514
+ public get volume(): number {
515
515
  return this._volume;
516
516
  }
517
517
 
518
518
  /**
519
519
  * Sets the volume level of the sound manager.
520
520
  */
521
- public set volume(value) {
522
- if (value < 0) {
523
- value = 0;
524
- } else if (value > 1) {
525
- value = 1;
526
- }
527
- if (this._volume !== value) {
528
- this._volume = value;
521
+ public set volume(value: number) {
522
+ const level = Math.min(1, Math.max(0, value));
523
+ if (this._volume !== level) {
524
+ this._volume = level;
529
525
  if (!this.noAudio) {
530
- this.masterGain.gain.value = value;
526
+ this.masterGain.gain.value = level;
531
527
  }
532
528
  }
533
529
  }
@@ -38,7 +38,7 @@ export class SoundSprite {
38
38
  sound.addMarker(markerKey, marker.start, marker.end - marker.start, undefined, marker.loop);
39
39
  this.sounds[markerKey] = sound;
40
40
  }
41
- if (this.config.autoplay) {
41
+ if (this.config.autoplay !== undefined) {
42
42
  this.autoplayKey = this.config.autoplay;
43
43
  this.play(this.autoplayKey);
44
44
  this.autoplay = this.sounds[this.autoplayKey]!;
@@ -5,11 +5,21 @@ import { valueToColor } from '../util/math.js';
5
5
  import { SCALE_LINEAR, SCALE_NEAREST } from './const.js';
6
6
  import type { Game } from './game.js';
7
7
 
8
+ /** The stage clear colour, kept in every form the two renderers need. */
9
+ export type StageBackgroundColor = {
10
+ r: number;
11
+ g: number;
12
+ b: number;
13
+ a: number;
14
+ color: number;
15
+ rgba: string;
16
+ };
17
+
8
18
  export class Stage extends DisplayObject {
9
- declare public name: any;
10
- declare public worldTransform: any;
11
- public currentRenderOrderID!: any;
12
- public _bgColor!: any;
19
+ declare public name: string;
20
+ declare public worldTransform: Matrix;
21
+ public currentRenderOrderID!: number;
22
+ public _bgColor!: StageBackgroundColor;
13
23
  /**
14
24
  * Creates a new Stage instance.
15
25
  * @param {Game} game - The game instance.
@@ -27,11 +37,11 @@ export class Stage extends DisplayObject {
27
37
  color: 0,
28
38
  rgba: '#000000',
29
39
  };
30
- if (!game.config.transparent) {
40
+ if (game.config.transparent === false) {
31
41
  // transparent = 0,0,0,0 - otherwise r,g,b,1
32
42
  this._bgColor.a = 1;
33
43
  }
34
- if (game.config.backgroundColor && !this.game.config.transparent) {
44
+ if (game.config.backgroundColor !== 0 && this.game.config.transparent === false) {
35
45
  this.setBackgroundColor(game.config.backgroundColor);
36
46
  }
37
47
  }
@@ -41,7 +51,7 @@ export class Stage extends DisplayObject {
41
51
  * @param {number} color - The color to set as the background.
42
52
  */
43
53
  public setBackgroundColor(color: number): void {
44
- if (this.game.config.transparent) {
54
+ if (this.game.config.transparent !== false) {
45
55
  return;
46
56
  }
47
57
  valueToColor(color, this._bgColor);
@@ -109,22 +119,22 @@ export class Stage extends DisplayObject {
109
119
  public override destroy(): void {
110
120
  this.exists = false;
111
121
  this.game = null!;
112
- this.worldTransform = null;
113
- this._bgColor = null;
122
+ this.worldTransform = null!;
123
+ this._bgColor = null!;
114
124
  }
115
125
 
116
126
  /**
117
127
  * Gets the background color of the stage.
118
128
  * @returns {number} The background color.
119
129
  */
120
- public get backgroundColor() {
130
+ public get backgroundColor(): number {
121
131
  return this._bgColor.color;
122
132
  }
123
133
 
124
134
  /**
125
135
  * Sets the background color of the stage.
126
136
  */
127
- public set backgroundColor(value) {
137
+ public set backgroundColor(value: number) {
128
138
  this.setBackgroundColor(value);
129
139
  }
130
140
 
@@ -139,7 +149,7 @@ export class Stage extends DisplayObject {
139
149
  /**
140
150
  * Sets whether texture smoothing is enabled.
141
151
  */
142
- public set smoothed(value) {
152
+ public set smoothed(value: boolean) {
143
153
  globalThis.PhaserRegistry.TEXTURE_SCALE_MODE = value ? SCALE_LINEAR : SCALE_NEAREST;
144
154
  }
145
155
  }
@@ -268,7 +268,7 @@ export class Time {
268
268
  /**
269
269
  * Sets the desired frames per second.
270
270
  */
271
- public set desiredFps(value) {
271
+ public set desiredFps(value: number) {
272
272
  this._desiredFps = value;
273
273
  this.desiredFpsMult = 1 / value;
274
274
  }
@@ -10,37 +10,37 @@ const createTimer = (startTime = 0): Timer => {
10
10
  return timer;
11
11
  };
12
12
 
13
- describe('Timer', () => {
14
- describe('start', () => {
15
- it('rebases every queued event onto the start time', () => {
13
+ describe('Timer', (): void => {
14
+ describe('start', (): void => {
15
+ it('rebases every queued event onto the start time', (): void => {
16
16
  const timer = createTimer(1000);
17
- timer.add(100, () => undefined);
18
- timer.add(300, () => undefined);
17
+ timer.add(100, (): undefined => undefined);
18
+ timer.add(300, (): undefined => undefined);
19
19
  timer.start();
20
- expect(timer.events.map((event) => event.tick)).toStrictEqual([1100, 1300]);
20
+ expect(timer.events.map((event): number => event.tick)).toStrictEqual([1100, 1300]);
21
21
  });
22
22
 
23
- it('is a no-op once already running', () => {
23
+ it('is a no-op once already running', (): void => {
24
24
  const timer = createTimer(1000);
25
- timer.add(100, () => undefined);
25
+ timer.add(100, (): undefined => undefined);
26
26
  timer.start();
27
- const ticks = timer.events.map((event) => event.tick);
27
+ const ticks = timer.events.map((event): number => event.tick);
28
28
  timer.start(500);
29
- expect(timer.events.map((event) => event.tick)).toStrictEqual(ticks);
29
+ expect(timer.events.map((event): number => event.tick)).toStrictEqual(ticks);
30
30
  });
31
31
  });
32
32
 
33
- describe('order', () => {
34
- it('sorts events by tick and exposes the earliest as nextTick', () => {
33
+ describe('order', (): void => {
34
+ it('sorts events by tick and exposes the earliest as nextTick', (): void => {
35
35
  const timer = createTimer(0);
36
- timer.add(500, () => undefined);
37
- timer.add(100, () => undefined);
38
- timer.add(300, () => undefined);
39
- expect(timer.events.map((event) => event.delay)).toStrictEqual([100, 300, 500]);
36
+ timer.add(500, (): undefined => undefined);
37
+ timer.add(100, (): undefined => undefined);
38
+ timer.add(300, (): undefined => undefined);
39
+ expect(timer.events.map((event): number => event.delay)).toStrictEqual([100, 300, 500]);
40
40
  expect(timer.nextTick).toBe(100);
41
41
  });
42
42
 
43
- it('leaves nextTick untouched when there are no events', () => {
43
+ it('leaves nextTick untouched when there are no events', (): void => {
44
44
  const timer = createTimer(0);
45
45
  timer.nextTick = 42;
46
46
  timer.order();
@@ -48,33 +48,33 @@ describe('Timer', () => {
48
48
  });
49
49
  });
50
50
 
51
- describe('remove', () => {
52
- it('marks a matching event for deletion and reports success', () => {
51
+ describe('remove', (): void => {
52
+ it('marks a matching event for deletion and reports success', (): void => {
53
53
  const timer = createTimer(0);
54
- const event = timer.add(100, () => undefined);
54
+ const event = timer.add(100, (): undefined => undefined);
55
55
  expect(timer.remove(event)).toBe(true);
56
56
  expect(event.pendingDelete).toBe(true);
57
57
  });
58
58
 
59
- it('reports failure for an event it does not hold', () => {
59
+ it('reports failure for an event it does not hold', (): void => {
60
60
  const timer = createTimer(0);
61
- timer.add(100, () => undefined);
62
- const other = createTimer(0).add(100, () => undefined);
61
+ timer.add(100, (): undefined => undefined);
62
+ const other = createTimer(0).add(100, (): undefined => undefined);
63
63
  expect(timer.remove(other)).toBe(false);
64
64
  });
65
65
 
66
- it('reports failure for null without throwing', () => {
66
+ it('reports failure for null without throwing', (): void => {
67
67
  const timer = createTimer(0);
68
- timer.add(100, () => undefined);
68
+ timer.add(100, (): undefined => undefined);
69
69
  expect(timer.remove(null)).toBe(false);
70
70
  });
71
71
  });
72
72
 
73
- describe('clearPendingEvents', () => {
74
- it('drops only the events marked for deletion', () => {
73
+ describe('clearPendingEvents', (): void => {
74
+ it('drops only the events marked for deletion', (): void => {
75
75
  const timer = createTimer(0);
76
- const first = timer.add(100, () => undefined);
77
- const second = timer.add(200, () => undefined);
76
+ const first = timer.add(100, (): undefined => undefined);
77
+ const second = timer.add(200, (): undefined => undefined);
78
78
  timer.remove(first);
79
79
  timer.clearPendingEvents();
80
80
  expect(timer.events).toStrictEqual([second]);
@@ -82,8 +82,8 @@ describe('Timer', () => {
82
82
  });
83
83
  });
84
84
 
85
- describe('update', () => {
86
- it('fires a one-shot event once its tick is reached and marks it spent', () => {
85
+ describe('update', (): void => {
86
+ it('fires a one-shot event once its tick is reached and marks it spent', (): void => {
87
87
  const timer = createTimer(0);
88
88
  const callback = vi.fn();
89
89
  timer.add(100, callback);
@@ -95,7 +95,7 @@ describe('Timer', () => {
95
95
  expect(timer.events[0]?.pendingDelete).toBe(true);
96
96
  });
97
97
 
98
- it('keeps firing a looping event and reschedules its tick', () => {
98
+ it('keeps firing a looping event and reschedules its tick', (): void => {
99
99
  const timer = createTimer(0);
100
100
  const callback = vi.fn();
101
101
  timer.loop(100, callback);
@@ -107,7 +107,7 @@ describe('Timer', () => {
107
107
  expect(timer.events[0]?.pendingDelete).toBe(false);
108
108
  });
109
109
 
110
- it('fires a repeating event exactly repeatCount times', () => {
110
+ it('fires a repeating event exactly repeatCount times', (): void => {
111
111
  const timer = createTimer(0);
112
112
  const callback = vi.fn();
113
113
  timer.repeat(100, 2, callback);
@@ -120,10 +120,10 @@ describe('Timer', () => {
120
120
  expect(timer.expired).toBe(true);
121
121
  });
122
122
 
123
- it('passes the configured context and arguments to the callback', () => {
123
+ it('passes the configured context and arguments to the callback', (): void => {
124
124
  const timer = createTimer(0);
125
125
  const context = { seen: null as unknown };
126
- const callback = vi.fn(function callbackImpl(this: typeof context, value: string) {
126
+ const callback = vi.fn(function callbackImpl(this: typeof context, value: string): void {
127
127
  this.seen = value;
128
128
  });
129
129
  timer.add(100, callback, context, 'payload');
@@ -133,49 +133,49 @@ describe('Timer', () => {
133
133
  expect(context.seen).toBe('payload');
134
134
  });
135
135
 
136
- it('completes and dispatches onComplete once every event is spent', () => {
136
+ it('completes and dispatches onComplete once every event is spent', (): void => {
137
137
  const timer = createTimer(0);
138
138
  const onComplete = vi.fn();
139
139
  timer.onComplete.add(onComplete);
140
- timer.add(100, () => undefined);
140
+ timer.add(100, (): undefined => undefined);
141
141
  timer.start();
142
142
  timer.update(100);
143
143
  expect(timer.expired).toBe(true);
144
144
  expect(onComplete).toHaveBeenCalledTimes(1);
145
145
  });
146
146
 
147
- it('survives a callback that removes every event mid-tick', () => {
147
+ it('survives a callback that removes every event mid-tick', (): void => {
148
148
  const timer = createTimer(0);
149
- timer.add(100, () => {
149
+ timer.add(100, (): void => {
150
150
  timer.events.length = 0;
151
151
  });
152
152
  timer.start();
153
- expect(() => timer.update(100)).not.toThrow();
153
+ expect((): boolean => timer.update(100)).not.toThrow();
154
154
  });
155
155
  });
156
156
 
157
- describe('adjustEvents', () => {
158
- it('shifts pending events forward by the time they missed', () => {
157
+ describe('adjustEvents', (): void => {
158
+ it('shifts pending events forward by the time they missed', (): void => {
159
159
  const timer = createTimer(0);
160
- const event = timer.add(100, () => undefined);
160
+ const event = timer.add(100, (): undefined => undefined);
161
161
  timer.start();
162
162
  timer._now = 5000;
163
163
  timer.adjustEvents(0);
164
164
  expect(event.tick).toBe(5100);
165
165
  });
166
166
 
167
- it('clamps events whose tick already passed to the current time', () => {
167
+ it('clamps events whose tick already passed to the current time', (): void => {
168
168
  const timer = createTimer(0);
169
- const event = timer.add(100, () => undefined);
169
+ const event = timer.add(100, (): undefined => undefined);
170
170
  timer.start();
171
171
  timer._now = 5000;
172
172
  timer.adjustEvents(500);
173
173
  expect(event.tick).toBe(5000);
174
174
  });
175
175
 
176
- it('leaves events marked for deletion alone', () => {
176
+ it('leaves events marked for deletion alone', (): void => {
177
177
  const timer = createTimer(0);
178
- const event = timer.add(100, () => undefined);
178
+ const event = timer.add(100, (): undefined => undefined);
179
179
  timer.start();
180
180
  timer.remove(event);
181
181
  const { tick } = event;
@@ -68,7 +68,7 @@ export class Timer {
68
68
  repeatCount: number,
69
69
  callback: Callback,
70
70
  callbackContext: unknown = null,
71
- args: any = []
71
+ args: unknown[] = []
72
72
  ): TimerEvent {
73
73
  const roundedDelay = Math.round(delay);
74
74
  let tick = roundedDelay;
@@ -215,7 +215,7 @@ export class Timer {
215
215
  this._i = this.events.length;
216
216
  while (this._i) {
217
217
  this._i -= 1;
218
- if (this.events[this._i]?.pendingDelete) {
218
+ if (this.events[this._i]?.pendingDelete === true) {
219
219
  this.events.splice(this._i, 1);
220
220
  }
221
221
  }