@vpmedia/phaser 1.124.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 (76) hide show
  1. package/dist/index.js +305 -309
  2. package/dist/index.js.map +1 -1
  3. package/dist/phaser/core/animation_parser.d.ts.map +1 -1
  4. package/dist/phaser/core/dom.d.ts.map +1 -1
  5. package/dist/phaser/core/frame_data.d.ts.map +1 -1
  6. package/dist/phaser/core/loader.d.ts.map +1 -1
  7. package/dist/phaser/core/scale_manager.d.ts.map +1 -1
  8. package/dist/phaser/core/sound.d.ts.map +1 -1
  9. package/dist/phaser/core/sound_manager.d.ts.map +1 -1
  10. package/dist/phaser/core/tween.d.ts.map +1 -1
  11. package/dist/phaser/display/canvas/renderer.d.ts.map +1 -1
  12. package/dist/phaser/display/display_object.d.ts +2 -2
  13. package/dist/phaser/display/display_object.d.ts.map +1 -1
  14. package/dist/phaser/display/graphics.d.ts +1 -1
  15. package/dist/phaser/display/graphics.d.ts.map +1 -1
  16. package/dist/phaser/display/group.d.ts.map +1 -1
  17. package/dist/phaser/display/image.d.ts.map +1 -1
  18. package/dist/phaser/display/text.d.ts.map +1 -1
  19. package/dist/phaser/display/webgl/earcut.d.ts.map +1 -1
  20. package/dist/phaser/display/webgl/texture.d.ts.map +1 -1
  21. package/dist/phaser/geom/rectangle.d.ts.map +1 -1
  22. package/dist/phaser/geom/util/circle.d.ts.map +1 -1
  23. package/dist/phaser/geom/util/point.d.ts.map +1 -1
  24. package/dist/phaser/util/math.d.ts.map +1 -1
  25. package/package.json +1 -1
  26. package/src/phaser/core/animation.ts +7 -7
  27. package/src/phaser/core/animation_manager.ts +2 -2
  28. package/src/phaser/core/animation_parser.ts +11 -15
  29. package/src/phaser/core/array_set.ts +2 -2
  30. package/src/phaser/core/cache.ts +4 -4
  31. package/src/phaser/core/device_util.ts +4 -4
  32. package/src/phaser/core/dom.ts +23 -19
  33. package/src/phaser/core/frame_data.ts +2 -5
  34. package/src/phaser/core/game.ts +12 -12
  35. package/src/phaser/core/input.ts +2 -2
  36. package/src/phaser/core/input_handler.ts +13 -13
  37. package/src/phaser/core/input_mouse.ts +4 -4
  38. package/src/phaser/core/input_pointer.ts +1 -1
  39. package/src/phaser/core/loader.ts +38 -50
  40. package/src/phaser/core/scale_manager.ts +10 -9
  41. package/src/phaser/core/scene_manager.ts +2 -2
  42. package/src/phaser/core/signal.ts +2 -2
  43. package/src/phaser/core/sound.ts +25 -32
  44. package/src/phaser/core/sound_manager.ts +12 -16
  45. package/src/phaser/core/sound_sprite.ts +1 -1
  46. package/src/phaser/core/stage.ts +3 -3
  47. package/src/phaser/core/timer.ts +1 -1
  48. package/src/phaser/core/tween.ts +6 -11
  49. package/src/phaser/display/bitmap_text.ts +3 -3
  50. package/src/phaser/display/button.ts +12 -12
  51. package/src/phaser/display/canvas/graphics.ts +2 -2
  52. package/src/phaser/display/canvas/pool.ts +3 -3
  53. package/src/phaser/display/canvas/renderer.ts +6 -5
  54. package/src/phaser/display/canvas/tinter.ts +1 -1
  55. package/src/phaser/display/canvas/util.ts +2 -2
  56. package/src/phaser/display/display_object.ts +13 -14
  57. package/src/phaser/display/graphics.test.ts +2 -2
  58. package/src/phaser/display/graphics.ts +9 -11
  59. package/src/phaser/display/group.ts +10 -9
  60. package/src/phaser/display/image.ts +7 -6
  61. package/src/phaser/display/sprite_util.ts +1 -1
  62. package/src/phaser/display/text.ts +35 -44
  63. package/src/phaser/display/webgl/abstract_filter.ts +1 -1
  64. package/src/phaser/display/webgl/earcut.ts +46 -42
  65. package/src/phaser/display/webgl/graphics.ts +1 -1
  66. package/src/phaser/display/webgl/renderer.ts +3 -3
  67. package/src/phaser/display/webgl/shader/normal.ts +6 -6
  68. package/src/phaser/display/webgl/shader_manager.ts +1 -1
  69. package/src/phaser/display/webgl/sprite_batch.ts +2 -2
  70. package/src/phaser/display/webgl/texture.ts +2 -1
  71. package/src/phaser/display/webgl/util.ts +3 -3
  72. package/src/phaser/geom/polygon.ts +2 -2
  73. package/src/phaser/geom/rectangle.ts +1 -2
  74. package/src/phaser/geom/util/circle.ts +6 -10
  75. package/src/phaser/geom/util/point.ts +5 -7
  76. package/src/phaser/util/math.ts +2 -3
@@ -96,7 +96,7 @@ export const checkFullScreenSupport = (device: Device): void => {
96
96
  const element = document.createElement('div');
97
97
  const elementApi = element as unknown as Record<string, unknown>;
98
98
  for (const name of fs) {
99
- if (elementApi[name]) {
99
+ if (elementApi[name] !== undefined) {
100
100
  device.fullscreen = true;
101
101
  device.requestFullscreen = name;
102
102
  break;
@@ -105,13 +105,13 @@ export const checkFullScreenSupport = (device: Device): void => {
105
105
  if (device.fullscreen) {
106
106
  const documentApi = document as unknown as Record<string, unknown>;
107
107
  for (const name of cfs) {
108
- if (documentApi[name]) {
108
+ if (documentApi[name] !== undefined) {
109
109
  device.cancelFullscreen = name;
110
110
  break;
111
111
  }
112
112
  }
113
113
  // ALLOW_KEYBOARD_INPUT is a legacy webkit fullscreen flag, absent from lib.dom
114
- if (globalThis.Element && (Element as unknown as { ALLOW_KEYBOARD_INPUT?: number }).ALLOW_KEYBOARD_INPUT) {
114
+ if ((Element as unknown as { ALLOW_KEYBOARD_INPUT?: number }).ALLOW_KEYBOARD_INPUT !== undefined) {
115
115
  device.fullscreenKeyboard = true;
116
116
  }
117
117
  }
@@ -190,7 +190,7 @@ export const checkAudio = (device: Device): void => {
190
190
  for (const format of formats) {
191
191
  const { type, codecs } = format;
192
192
  for (const codec of codecs) {
193
- if (!device.supportedAudioFormats[type]) {
193
+ if (device.supportedAudioFormats[type] !== true) {
194
194
  const isSupported = isMediaSourceTypeSupported(codec) || canPlayType(audioElement, codec);
195
195
  if (isSupported) {
196
196
  device.supportedAudioFormats[type] = isSupported;
@@ -17,7 +17,7 @@ class VisualBoundsDesktopRectangle {
17
17
  * @returns {number} The horizontal scroll position in pixels.
18
18
  */
19
19
  public get x(): number {
20
- return globalThis && 'pageXOffset' in globalThis ? window.pageXOffset : document.documentElement.scrollLeft;
20
+ return 'pageXOffset' in globalThis ? window.pageXOffset : document.documentElement.scrollLeft;
21
21
  }
22
22
 
23
23
  /**
@@ -25,7 +25,7 @@ class VisualBoundsDesktopRectangle {
25
25
  * @returns {number} The vertical scroll position in pixels.
26
26
  */
27
27
  public get y(): number {
28
- return globalThis && 'pageYOffset' in globalThis ? window.pageYOffset : document.documentElement.scrollTop;
28
+ return 'pageYOffset' in globalThis ? window.pageYOffset : document.documentElement.scrollTop;
29
29
  }
30
30
 
31
31
  /**
@@ -81,7 +81,7 @@ class VisualBoundsRectangle {
81
81
  * @returns {number} The horizontal scroll position in pixels.
82
82
  */
83
83
  public get x(): number {
84
- return globalThis && 'pageXOffset' in globalThis ? window.pageXOffset : document.documentElement.scrollLeft;
84
+ return 'pageXOffset' in globalThis ? window.pageXOffset : document.documentElement.scrollLeft;
85
85
  }
86
86
 
87
87
  /**
@@ -89,7 +89,7 @@ class VisualBoundsRectangle {
89
89
  * @returns {number} The vertical scroll position in pixels.
90
90
  */
91
91
  public get y(): number {
92
- return globalThis && 'pageYOffset' in globalThis ? window.pageYOffset : document.documentElement.scrollTop;
92
+ return 'pageYOffset' in globalThis ? window.pageYOffset : document.documentElement.scrollTop;
93
93
  }
94
94
 
95
95
  /**
@@ -199,13 +199,11 @@ export class DOM {
199
199
  this.layoutBounds = this.treatAsDesktop ? new LayoutBoundsDesktopRectangle() : new LayoutBoundsRectangle();
200
200
  this.documentBounds = new DocumentBoundsRectangle();
201
201
  this.scrollXProvider =
202
- globalThis && 'pageXOffset' in globalThis
202
+ 'pageXOffset' in globalThis
203
203
  ? (): number => window.pageXOffset
204
204
  : (): number => document.documentElement.scrollLeft;
205
205
  this.scrollYProvider =
206
- globalThis && 'pageYOffset' in globalThis
207
- ? (): number => window.pageYOffset
208
- : (): number => document.documentElement.scrollTop;
206
+ 'pageYOffset' in globalThis ? (): number => window.pageYOffset : (): number => document.documentElement.scrollTop;
209
207
  }
210
208
 
211
209
  /**
@@ -233,11 +231,12 @@ export class DOM {
233
231
  * @returns {boolean} True if bounds were successfully retrieved, false otherwise.
234
232
  */
235
233
  public getBounds(element: HTMLCanvasElement, cushion = 0): CalibratedBounds | false {
236
- element = element && !element.nodeType ? (element as unknown as HTMLCanvasElement[])[0]! : element;
237
- if (!element || element.nodeType !== 1) {
234
+ // a jQuery-style wrapper was accepted here historically, so unwrap the first entry of one
235
+ const target = element.nodeType === undefined ? (element as unknown as HTMLCanvasElement[])[0] : element;
236
+ if (target?.nodeType !== 1) {
238
237
  return false;
239
238
  }
240
- return this.calibrate(element.getBoundingClientRect(), cushion);
239
+ return this.calibrate(target.getBoundingClientRect(), cushion);
241
240
  }
242
241
 
243
242
  /**
@@ -266,16 +265,21 @@ export class DOM {
266
265
  * @returns {string} The screen orientation ('portrait-primary', 'landscape-primary', etc.).
267
266
  */
268
267
  public getScreenOrientation(primaryFallback: string | null = null): OrientationType {
269
- const { screen } = globalThis;
270
- // @ts-expect-error the prefixed orientation properties predate the standard one and are absent from lib.dom
271
- const orientation = screen.orientation || screen.mozOrientation || screen.msOrientation;
272
- if (orientation && typeof orientation.type === 'string') {
273
- // Screen Orientation API specification
274
- return orientation.type;
275
- } else if (typeof orientation === 'string') {
268
+ // the prefixed orientation properties predate the standard one and are absent from lib.dom
269
+ const screen = globalThis.screen as Screen & {
270
+ mozOrientation?: string;
271
+ msOrientation?: string;
272
+ };
273
+ const orientation: ScreenOrientation | string | undefined =
274
+ screen.orientation ?? screen.mozOrientation ?? screen.msOrientation;
275
+ if (typeof orientation === 'string') {
276
276
  // moz/ms-orientation are strings
277
277
  return orientation;
278
278
  }
279
+ if (typeof orientation?.type === 'string') {
280
+ // Screen Orientation API specification
281
+ return orientation.type;
282
+ }
279
283
  const PORTRAIT = 'portrait-primary';
280
284
  const LANDSCAPE = 'landscape-primary';
281
285
  if (primaryFallback === 'screen') {
@@ -288,7 +292,7 @@ export class DOM {
288
292
  if (primaryFallback === 'window.orientation' && typeof legacyOrientation === 'number') {
289
293
  // This may change by device based on "natural" orientation.
290
294
  return legacyOrientation === 0 || legacyOrientation === 180 ? PORTRAIT : LANDSCAPE;
291
- } else if (globalThis.matchMedia) {
295
+ } else if (typeof globalThis.matchMedia === 'function') {
292
296
  if (globalThis.matchMedia('(orientation: portrait)').matches) {
293
297
  return PORTRAIT;
294
298
  } else if (globalThis.matchMedia('(orientation: landscape)').matches) {
@@ -20,10 +20,7 @@ export class FrameData {
20
20
  }
21
21
 
22
22
  public getFrame(index = 0): Frame {
23
- if (index >= this._frames.length) {
24
- index = 0;
25
- }
26
- return this._frames[index]!;
23
+ return this._frames[index >= this._frames.length ? 0 : index]!;
27
24
  }
28
25
 
29
26
  public getFrameByName(name: string): Frame | null {
@@ -59,7 +56,7 @@ export class FrameData {
59
56
  output: number[] | null = null
60
57
  ): number[] {
61
58
  const result = output ?? [];
62
- if (frames && frames.length > 0) {
59
+ if (frames.length > 0) {
63
60
  for (const f of frames) {
64
61
  if (useNumericIndex && this._frames[f as number]) {
65
62
  result.push(this._frames[f as number]!.index);
@@ -165,10 +165,10 @@ export class Game {
165
165
  this.input.boot();
166
166
  this.sound.boot();
167
167
  this.state.boot();
168
- if (window.focus) {
168
+ if (typeof window.focus === 'function') {
169
169
  window.focus();
170
170
  }
171
- if (!this.config.isSkipTicker) {
171
+ if (this.config.isSkipTicker !== true) {
172
172
  this.raf = new RequestAnimationFrame(this);
173
173
  this.raf.start();
174
174
  }
@@ -180,7 +180,7 @@ export class Game {
180
180
  */
181
181
  public createRendererCanvas(): void {
182
182
  this.logger.info('createRendererCanvas');
183
- if (this.canvas) {
183
+ if (this.canvas as HTMLCanvasElement | undefined) {
184
184
  removeFromDOM(this.canvas);
185
185
  }
186
186
  this.canvas = this.config.canvas ?? create(this, this.width, this.height, this.config.canvasID, true);
@@ -212,10 +212,10 @@ export class Game {
212
212
  isWebGlReady = true;
213
213
  } catch (error) {
214
214
  isWebGlReady = false;
215
- if (globalThis.PhaserRegistry?.GL_PROGRAM_INFO_LOG) {
215
+ if (globalThis.PhaserRegistry?.GL_PROGRAM_INFO_LOG != null) {
216
216
  this.logger.warn('WebGL program info', { log: globalThis.PhaserRegistry.GL_PROGRAM_INFO_LOG });
217
217
  }
218
- if (globalThis.PhaserRegistry?.GL_SHADER_INFO_LOG) {
218
+ if (globalThis.PhaserRegistry?.GL_SHADER_INFO_LOG != null) {
219
219
  this.logger.warn('WebGL shader info', { log: globalThis.PhaserRegistry.GL_SHADER_INFO_LOG });
220
220
  }
221
221
  const typedError = error instanceof Error ? error : new Error(String(error));
@@ -229,7 +229,7 @@ export class Game {
229
229
  if (this.contextRestoredBinded) {
230
230
  this.canvas.removeEventListener('webglcontextlost', this.contextRestoredBinded, false);
231
231
  }
232
- if (this.renderer) {
232
+ if (this.renderer as CanvasRenderer | WebGLRenderer | undefined) {
233
233
  this.renderer.destroy();
234
234
  }
235
235
  this.createRendererCanvas();
@@ -278,7 +278,7 @@ export class Game {
278
278
  this.parseConfigElement(config, 'renderType', RENDER_AUTO);
279
279
  this.parseConfigElement(config, 'isForceDisabledAudio', false);
280
280
  this.parseConfigElement(config, 'maxParallelDownloads', 16);
281
- if (config.parent) {
281
+ if (config.parent !== undefined) {
282
282
  this.parent = config.parent;
283
283
  }
284
284
  this.state = new SceneManager(this, config.state ?? null);
@@ -291,7 +291,7 @@ export class Game {
291
291
  public contextLost(event: Event): void {
292
292
  this.logger.info('contextLost', { type: event.type });
293
293
  event.preventDefault();
294
- if (this.renderer) {
294
+ if (this.renderer as CanvasRenderer | WebGLRenderer | undefined) {
295
295
  this.renderer.contextLost = true;
296
296
  }
297
297
  }
@@ -302,7 +302,7 @@ export class Game {
302
302
  */
303
303
  public contextRestored(event: Event): void {
304
304
  this.logger.info('contextRestored', { type: event.type });
305
- if (this.renderer) {
305
+ if (this.renderer as CanvasRenderer | WebGLRenderer | undefined) {
306
306
  this.renderer.initContext(this);
307
307
  // This.cache.clearGLTextures();
308
308
  this.renderer.contextLost = false;
@@ -340,10 +340,10 @@ export class Game {
340
340
  this.logger.info('destroy');
341
341
  this.isPaused = true;
342
342
 
343
- if (!this.cache) {
343
+ if (!(this.cache as Cache | undefined)) {
344
344
  return;
345
345
  }
346
- if (this.raf) {
346
+ if (this.raf as RequestAnimationFrame | undefined) {
347
347
  this.raf.stop();
348
348
  }
349
349
 
@@ -354,7 +354,7 @@ export class Game {
354
354
  this.stage.destroy();
355
355
  this.input.destroy();
356
356
 
357
- if (this.canvas) {
357
+ if (this.canvas as HTMLCanvasElement | undefined) {
358
358
  if (this.contextLostBinded) {
359
359
  this.canvas.removeEventListener('webglcontextlost', this.contextLostBinded, false);
360
360
  }
@@ -443,7 +443,7 @@ export class Input {
443
443
  }
444
444
  this.getLocalPosition(displayObject, pointer, this._localPoint);
445
445
  localPoint.copyFrom(this._localPoint);
446
- if (displayObject.hitArea && displayObject.hitArea.contains) {
446
+ if (displayObject.hitArea !== null) {
447
447
  return displayObject.hitArea.contains(this._localPoint.x, this._localPoint.y);
448
448
  } else if (displayObject instanceof Image) {
449
449
  const { width } = displayObject.texture.frame;
@@ -457,7 +457,7 @@ export class Input {
457
457
  }
458
458
  } else if (displayObject instanceof Graphics) {
459
459
  for (const data of displayObject.graphicsData) {
460
- if (data.fill && data.shape && data.shape.contains(this._localPoint.x, this._localPoint.y)) {
460
+ if (data.fill && (data.shape?.contains(this._localPoint.x, this._localPoint.y) ?? false)) {
461
461
  // Only deal with fills..
462
462
  return true;
463
463
  }
@@ -223,7 +223,7 @@ export class InputHandler {
223
223
  * TBD.
224
224
  */
225
225
  public destroy(): void {
226
- if (this.sprite) {
226
+ if (this.sprite !== null) {
227
227
  if (this._setHandCursor) {
228
228
  this.game.canvas.style.cursor = 'default';
229
229
  this._setHandCursor = false;
@@ -402,7 +402,7 @@ export class InputHandler {
402
402
  if (
403
403
  !pointer.isDown ||
404
404
  !this.enabled ||
405
- !this.sprite ||
405
+ this.sprite === null ||
406
406
  !this.sprite.parent ||
407
407
  !this.sprite.visible ||
408
408
  !this.sprite.parent.visible ||
@@ -430,7 +430,7 @@ export class InputHandler {
430
430
  public checkPointerOver(pointer: Pointer, fastTest = false): boolean {
431
431
  if (
432
432
  !this.enabled ||
433
- !this.sprite ||
433
+ this.sprite === null ||
434
434
  !this.sprite.parent ||
435
435
  !this.sprite.visible ||
436
436
  !this.sprite.parent.visible ||
@@ -511,7 +511,7 @@ export class InputHandler {
511
511
  // Abort. We've been destroyed.
512
512
  return false;
513
513
  }
514
- if (!this.enabled || !this.sprite.visible || !this.sprite.parent?.visible) {
514
+ if (!this.enabled || !this.sprite.visible || this.sprite.parent?.visible !== true) {
515
515
  this._pointerOutHandler(pointer);
516
516
  return false;
517
517
  }
@@ -560,7 +560,7 @@ export class InputHandler {
560
560
  this.game.canvas.style.cursor = 'pointer';
561
561
  this._setHandCursor = true;
562
562
  }
563
- if (!silent && sendEvent && this.sprite && this.sprite.events) {
563
+ if (!silent && sendEvent && this.sprite !== null) {
564
564
  this.sprite.events.onInputOver$dispatch(this.sprite, pointer);
565
565
  }
566
566
  if (this.sprite.parent && this.sprite.parent.type === GROUP) {
@@ -587,9 +587,9 @@ export class InputHandler {
587
587
  this.game.canvas.style.cursor = 'default';
588
588
  this._setHandCursor = false;
589
589
  }
590
- if (!silent && this.sprite && this.sprite.events) {
590
+ if (!silent && this.sprite !== null) {
591
591
  this.sprite.events.onInputOut$dispatch(this.sprite, pointer);
592
- if (this.sprite && this.sprite.parent && this.sprite.parent.type === GROUP) {
592
+ if (this.sprite?.parent?.type === GROUP) {
593
593
  (this.sprite.parent as Group).onChildInputOut.dispatch(this.sprite, pointer);
594
594
  }
595
595
  }
@@ -615,10 +615,10 @@ export class InputHandler {
615
615
  this.downPoint.setTo(pointer.x, pointer.y);
616
616
  // It's possible the onInputDown event creates a new Sprite that is on-top of this one, so we ought to force a Pointer update
617
617
  pointer.dirty = true;
618
- if (this.sprite && this.sprite.events) {
618
+ if (this.sprite !== null) {
619
619
  this.sprite.events.onInputDown$dispatch(this.sprite, pointer);
620
620
  // The event above might have destroyed this sprite.
621
- if (this.sprite && this.sprite.parent && this.sprite.parent.type === GROUP) {
621
+ if (this.sprite?.parent?.type === GROUP) {
622
622
  (this.sprite.parent as Group).onChildInputDown.dispatch(this.sprite, pointer);
623
623
  }
624
624
  // The events might have destroyed this sprite.
@@ -650,7 +650,7 @@ export class InputHandler {
650
650
  */
651
651
  public dragTimeElapsed(pointer: Pointer): void {
652
652
  this._dragTimePass = true;
653
- if (this._pendingDrag && this.sprite && this._dragDistancePass) {
653
+ if (this._pendingDrag && this.sprite !== null && this._dragDistancePass) {
654
654
  this.startDrag(pointer);
655
655
  }
656
656
  }
@@ -673,14 +673,14 @@ export class InputHandler {
673
673
  data.downDuration = data.timeUp - data.timeDown;
674
674
  // Only release the InputUp signal if the pointer is still over this sprite
675
675
  let isOver = this.checkPointerOver(pointer);
676
- if (this.sprite && this.sprite.events) {
676
+ if (this.sprite !== null) {
677
677
  if (
678
678
  !this.dragStopBlocksInputUp ||
679
679
  (this.dragStopBlocksInputUp && !(this.draggable && this.isDragged && this._draggedPointerID === pointer.id))
680
680
  ) {
681
681
  this.sprite.events.onInputUp$dispatch(this.sprite, pointer, isOver);
682
682
  }
683
- if (this.sprite && this.sprite.parent && this.sprite.parent.type === GROUP) {
683
+ if (this.sprite?.parent?.type === GROUP) {
684
684
  (this.sprite.parent as Group).onChildInputUp.dispatch(this.sprite, pointer, isOver);
685
685
  }
686
686
  // The onInputUp event may have changed the sprite so that checkPointerOver is no longer true, so update it.
@@ -843,7 +843,7 @@ export class InputHandler {
843
843
  * TBD.
844
844
  */
845
845
  public disableDrag(): void {
846
- if (this._pointerData) {
846
+ if (this._pointerData.length > 0) {
847
847
  for (let i = 0; i < 10; i += 1) {
848
848
  this.pointerData(i).isDragged = false;
849
849
  }
@@ -106,7 +106,7 @@ export class Mouse {
106
106
  canvas.addEventListener('mouseover', this._onMouseOver, true);
107
107
  canvas.addEventListener('mouseout', this._onMouseOut, true);
108
108
  const { wheelEvent } = this.game.device;
109
- if (wheelEvent) {
109
+ if (wheelEvent !== null) {
110
110
  canvas.addEventListener(wheelEvent, this._onMouseWheel, true);
111
111
  }
112
112
  }
@@ -132,13 +132,13 @@ export class Mouse {
132
132
  canvas.removeEventListener('mouseout', this._onMouseOut, true);
133
133
  }
134
134
  const { wheelEvent } = this.game.device;
135
- if (wheelEvent && this._onMouseWheel) {
135
+ if (wheelEvent !== null && this._onMouseWheel) {
136
136
  canvas.removeEventListener(wheelEvent, this._onMouseWheel, true);
137
137
  }
138
- if (this._onMouseUpGlobal) {
138
+ if (this._onMouseUpGlobal !== null) {
139
139
  globalThis.removeEventListener('mouseup', this._onMouseUpGlobal, true);
140
140
  }
141
- if (this._onMouseOutGlobal) {
141
+ if (this._onMouseOutGlobal !== null) {
142
142
  globalThis.removeEventListener('mouseout', this._onMouseOutGlobal, true);
143
143
  }
144
144
  }
@@ -149,7 +149,7 @@ export class Pointer {
149
149
  */
150
150
  public start(event: InputEvent): this {
151
151
  const { input } = this.game;
152
- if (event.pointerId) {
152
+ if (event.pointerId !== undefined) {
153
153
  this.pointerId = event.pointerId;
154
154
  }
155
155
  this.identifier = event.identifier ?? null;
@@ -282,19 +282,19 @@ export class Loader {
282
282
  this.game.logger.warn(`Loader: Invalid or no key given of type ${type}`);
283
283
  return this;
284
284
  }
285
- if (url === undefined || url === null) {
286
- if (extension) {
287
- url = key + extension;
288
- } else {
285
+ let resolvedUrl = url;
286
+ if (resolvedUrl === undefined || resolvedUrl === null) {
287
+ if (extension === null) {
289
288
  this.game.logger.warn(`Loader: No URL given for file type: ${type} key: ${key}`);
290
289
  return this;
291
290
  }
291
+ resolvedUrl = key + extension;
292
292
  }
293
293
  const file: LoaderFile = {
294
294
  type,
295
295
  key,
296
296
  path: this.path,
297
- url,
297
+ url: resolvedUrl,
298
298
  syncPoint: this._withSyncPointDepth > 0,
299
299
  data: null,
300
300
  loading: false,
@@ -351,11 +351,9 @@ export class Loader {
351
351
  error: false,
352
352
  callbackContext,
353
353
  };
354
- if (data) {
355
- if (typeof data === 'string') {
356
- data = JSON.parse(data);
357
- }
358
- pack.data = (data ?? {}) as LoaderFileData;
354
+ if (data !== null) {
355
+ const parsed: unknown = typeof data === 'string' ? JSON.parse(data) : data;
356
+ pack.data = (parsed ?? {}) as LoaderFileData;
359
357
  pack.loaded = true;
360
358
  }
361
359
  for (let i = 0; i < this._fileList.length + 1; i += 1) {
@@ -473,10 +471,8 @@ export class Loader {
473
471
  if (this.game.sound.noAudio || this.game.device.noAudioFormat) {
474
472
  return this;
475
473
  }
476
- if (typeof urls === 'string') {
477
- urls = [urls];
478
- }
479
- return this.addToFileList('audio', key, urls, { buffer: null, autoDecode });
474
+ const sources = typeof urls === 'string' ? [urls] : urls;
475
+ return this.addToFileList('audio', key, sources, { buffer: null, autoDecode });
480
476
  }
481
477
 
482
478
  /**
@@ -495,11 +491,9 @@ export class Loader {
495
491
  this.audio(key, urls, autoDecode);
496
492
  if (jsonURL) {
497
493
  this.json(`${key}-audioatlas`, jsonURL);
498
- } else if (jsonData) {
499
- if (typeof jsonData === 'string') {
500
- jsonData = JSON.parse(jsonData);
501
- }
502
- this.cache.addJSON(`${key}-audioatlas`, '', jsonData);
494
+ } else if (jsonData !== null) {
495
+ const parsed: unknown = typeof jsonData === 'string' ? JSON.parse(jsonData) : jsonData;
496
+ this.cache.addJSON(`${key}-audioatlas`, '', parsed);
503
497
  }
504
498
  return this;
505
499
  }
@@ -523,13 +517,11 @@ export class Loader {
523
517
  xSpacing = 0,
524
518
  ySpacing = 0
525
519
  ): this {
526
- textureURL ??= `${key}.png`;
527
- if (atlasURL === null && atlasData === null) {
528
- atlasURL = `${key}.xml`;
529
- }
520
+ const texture = textureURL ?? `${key}.png`;
521
+ const atlas = atlasURL === null && atlasData === null ? `${key}.xml` : atlasURL;
530
522
  // A URL to a json/xml atlas has been given
531
- if (atlasURL) {
532
- this.addToFileList('bitmapfont', key, textureURL, { atlasURL, xSpacing, ySpacing });
523
+ if (atlas !== null) {
524
+ this.addToFileList('bitmapfont', key, texture, { atlasURL: atlas, xSpacing, ySpacing });
533
525
  } else if (typeof atlasData === 'string') {
534
526
  // A stringified xml/json atlas has been given
535
527
  let json: unknown = null;
@@ -539,13 +531,13 @@ export class Loader {
539
531
  } catch {
540
532
  xml = this.parseXml(atlasData);
541
533
  }
542
- if (!xml && !json) {
534
+ if (xml === null && json === null) {
543
535
  throw new Error(ENGINE_ERROR_INVALID_BITMAP_FONT_ATLAS);
544
536
  }
545
- this.addToFileList('bitmapfont', key, textureURL, {
537
+ this.addToFileList('bitmapfont', key, texture, {
546
538
  atlasURL: null,
547
539
  atlasData: json ?? xml,
548
- atlasType: json ? 'json' : 'xml',
540
+ atlasType: json === null ? 'xml' : 'json',
549
541
  xSpacing,
550
542
  ySpacing,
551
543
  });
@@ -569,15 +561,13 @@ export class Loader {
569
561
  atlasData: unknown = null,
570
562
  format: number = TEXTURE_ATLAS_JSON_HASH
571
563
  ): this {
572
- textureURL ??= `${key}.png`;
573
- if (!atlasURL && !atlasData) {
574
- atlasURL = `${key}.json`;
575
- }
564
+ const texture = textureURL ?? `${key}.png`;
565
+ const atlas = atlasURL === null && atlasData === null ? `${key}.json` : atlasURL;
576
566
  // A URL to a json/xml file has been given
577
- if (atlasURL) {
578
- this.addToFileList('textureatlas', key, textureURL, { atlasURL, format });
567
+ if (atlas !== null) {
568
+ this.addToFileList('textureatlas', key, texture, { atlasURL: atlas, format });
579
569
  } else {
580
- this.addToFileList('textureatlas', key, textureURL, { atlasURL: null, atlasData, format });
570
+ this.addToFileList('textureatlas', key, texture, { atlasURL: null, atlasData, format });
581
571
  }
582
572
  return this;
583
573
  }
@@ -701,7 +691,7 @@ export class Loader {
701
691
  }
702
692
  } else if (!file.loading && this._flightQueue.length < inflightLimit) {
703
693
  // -> not loaded/failed, not loading
704
- if (file.type === 'packfile' && !file.data) {
694
+ if (file.type === 'packfile' && file.data === null) {
705
695
  // Fetches the pack data: the pack is processed above as it reaches queue-start.
706
696
  // (Packs do not trigger onLoadStart or onFileStart.)
707
697
  this._flightQueue.push(file);
@@ -892,7 +882,7 @@ export class Loader {
892
882
  }
893
883
  case 'audio': {
894
884
  const resolved = this.getAudioURL(file.url);
895
- if (resolved) {
885
+ if (resolved !== null) {
896
886
  file.url = resolved;
897
887
  this.xhrLoad(file, this.transformUrl(resolved, file), 'arraybuffer', this.fileComplete);
898
888
  } else if (this.game.sound.noAudio) {
@@ -947,9 +937,9 @@ export class Loader {
947
937
  { once: true }
948
938
  );
949
939
  image.addEventListener('error', (): void => {
950
- if (this.isUseRetry && (!file.numRetry || file.numRetry < this.maxRetry)) {
940
+ if (this.isUseRetry && (file.numRetry === undefined || file.numRetry < this.maxRetry)) {
951
941
  setTimeout((): void => {
952
- file.numRetry = file.numRetry ? file.numRetry + 1 : 1;
942
+ file.numRetry = file.numRetry === undefined ? 1 : file.numRetry + 1;
953
943
  this.loadImageTag(file);
954
944
  }, 1000);
955
945
  } else if (!settled) {
@@ -993,16 +983,16 @@ export class Loader {
993
983
  xhr.setRequestHeader('X-Requested-With', requestedWith);
994
984
  }
995
985
  const acceptHeader = this.headers[file.type];
996
- if (acceptHeader) {
986
+ if (acceptHeader !== undefined && acceptHeader !== false) {
997
987
  xhr.setRequestHeader('Accept', acceptHeader);
998
988
  }
999
989
  const handleError = onerror ?? this.fileError;
1000
990
  const retry = (): boolean => {
1001
- if (!this.isUseRetry || (file.numRetry && file.numRetry >= this.maxRetry)) {
991
+ if (!this.isUseRetry || (file.numRetry !== undefined && file.numRetry >= this.maxRetry)) {
1002
992
  return false;
1003
993
  }
1004
994
  setTimeout((): void => {
1005
- file.numRetry = file.numRetry ? file.numRetry + 1 : 1;
995
+ file.numRetry = file.numRetry === undefined ? 1 : file.numRetry + 1;
1006
996
  this.xhrLoad(file, url, type, onload, handleError);
1007
997
  }, 1000);
1008
998
  return true;
@@ -1101,10 +1091,8 @@ export class Loader {
1101
1091
  */
1102
1092
  public fileError(file: LoaderFile, xhr: XMLHttpRequest | null = null, reason: unknown = 0): void {
1103
1093
  // const url = file.requestUrl || this.transformUrl(file.url, file);
1104
- if (!reason && xhr) {
1105
- reason = xhr.status;
1106
- }
1107
- const message = `Error loading asset (${String(reason)})`;
1094
+ const cause = reason === 0 && xhr !== null ? xhr.status : reason;
1095
+ const message = `Error loading asset (${String(cause)})`;
1108
1096
  this.asyncComplete(file, message);
1109
1097
  }
1110
1098
 
@@ -1156,7 +1144,7 @@ export class Loader {
1156
1144
  break;
1157
1145
  }
1158
1146
  case 'bitmapfont': {
1159
- if (!file.atlasURL) {
1147
+ if (file.atlasURL === null || file.atlasURL === undefined) {
1160
1148
  this.cache.addBitmapFont(
1161
1149
  file.key,
1162
1150
  url,
@@ -1181,7 +1169,7 @@ export class Loader {
1181
1169
  } catch {
1182
1170
  // pass
1183
1171
  }
1184
- if (json) {
1172
+ if (json !== undefined) {
1185
1173
  bitmapFontFile.atlasType = 'json';
1186
1174
  this.jsonLoadComplete(bitmapFontFile, bitmapFontXhr);
1187
1175
  } else {
@@ -1197,7 +1185,7 @@ export class Loader {
1197
1185
  const audio = response.response as ArrayBuffer;
1198
1186
  file.data = audio;
1199
1187
  this.cache.addSound(file.key, url, audio);
1200
- if (file.autoDecode) {
1188
+ if (file.autoDecode === true) {
1201
1189
  void this.game.sound.decode(file.key);
1202
1190
  }
1203
1191
  break;
@@ -1314,7 +1302,7 @@ export class Loader {
1314
1302
  } else {
1315
1303
  this.preloadSprite.rect.height = Math.floor((this.preloadSprite.height / 100) * this.progress);
1316
1304
  }
1317
- if (this.preloadSprite.sprite) {
1305
+ if (this.preloadSprite.sprite !== null) {
1318
1306
  this.preloadSprite.sprite.updateCrop();
1319
1307
  } else {
1320
1308
  // We seem to have lost our sprite - maybe it was destroyed?