excalibur 0.26.0-alpha.310 → 0.26.0-alpha.311

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 (96) hide show
  1. package/CHANGELOG.md +8 -2
  2. package/build/dist/Actor.js +3 -1
  3. package/build/dist/Actor.js.map +1 -1
  4. package/build/dist/Debug/Debug.d.ts +16 -0
  5. package/build/dist/Debug/Debug.js +35 -0
  6. package/build/dist/Debug/Debug.js.map +1 -1
  7. package/build/dist/Drawing/Animation.js +10 -1
  8. package/build/dist/Drawing/Animation.js.map +1 -1
  9. package/build/dist/Drawing/Polygon.js +11 -1
  10. package/build/dist/Drawing/Polygon.js.map +1 -1
  11. package/build/dist/Drawing/Sprite.js +24 -25
  12. package/build/dist/Drawing/Sprite.js.map +1 -1
  13. package/build/dist/Drawing/Texture.js +25 -36
  14. package/build/dist/Drawing/Texture.js.map +1 -1
  15. package/build/dist/Engine.d.ts +34 -1
  16. package/build/dist/Engine.js +114 -60
  17. package/build/dist/Engine.js.map +1 -1
  18. package/build/dist/EntityComponentSystem/SystemManager.d.ts +6 -0
  19. package/build/dist/EntityComponentSystem/SystemManager.js +12 -5
  20. package/build/dist/EntityComponentSystem/SystemManager.js.map +1 -1
  21. package/build/dist/Graphics/Animation.js +7 -1
  22. package/build/dist/Graphics/Animation.js.map +1 -1
  23. package/build/dist/Graphics/Canvas.js +5 -1
  24. package/build/dist/Graphics/Canvas.js.map +1 -1
  25. package/build/dist/Graphics/Circle.js +5 -1
  26. package/build/dist/Graphics/Circle.js.map +1 -1
  27. package/build/dist/Graphics/Context/ExcaliburGraphicsContextWebGL.js +4 -4
  28. package/build/dist/Graphics/Context/ExcaliburGraphicsContextWebGL.js.map +1 -1
  29. package/build/dist/Graphics/Font.js +14 -2
  30. package/build/dist/Graphics/Font.js.map +1 -1
  31. package/build/dist/Graphics/GraphicsComponent.js +6 -3
  32. package/build/dist/Graphics/GraphicsComponent.js.map +1 -1
  33. package/build/dist/Graphics/GraphicsGroup.js +4 -1
  34. package/build/dist/Graphics/GraphicsGroup.js.map +1 -1
  35. package/build/dist/Graphics/ImageSource.js +25 -36
  36. package/build/dist/Graphics/ImageSource.js.map +1 -1
  37. package/build/dist/Graphics/Polygon.js +5 -1
  38. package/build/dist/Graphics/Polygon.js.map +1 -1
  39. package/build/dist/Graphics/Rectangle.js +6 -1
  40. package/build/dist/Graphics/Rectangle.js.map +1 -1
  41. package/build/dist/Graphics/Sprite.js +6 -1
  42. package/build/dist/Graphics/Sprite.js.map +1 -1
  43. package/build/dist/Graphics/SpriteSheet.js +2 -2
  44. package/build/dist/Graphics/SpriteSheet.js.map +1 -1
  45. package/build/dist/Loader.d.ts +4 -1
  46. package/build/dist/Loader.js +31 -31
  47. package/build/dist/Loader.js.map +1 -1
  48. package/build/dist/Particles.js +1 -1
  49. package/build/dist/Particles.js.map +1 -1
  50. package/build/dist/Resources/Gif.js +8 -19
  51. package/build/dist/Resources/Gif.js.map +1 -1
  52. package/build/dist/Resources/Sound/Sound.js +42 -59
  53. package/build/dist/Resources/Sound/Sound.js.map +1 -1
  54. package/build/dist/Scene.js +1 -0
  55. package/build/dist/Scene.js.map +1 -1
  56. package/build/dist/Screen.js +3 -3
  57. package/build/dist/Screen.js.map +1 -1
  58. package/build/dist/ScreenElement.js +1 -1
  59. package/build/dist/ScreenElement.js.map +1 -1
  60. package/build/dist/Trigger.js +4 -1
  61. package/build/dist/Trigger.js.map +1 -1
  62. package/build/dist/Util/Clock.d.ts +117 -0
  63. package/build/dist/Util/Clock.js +209 -0
  64. package/build/dist/Util/Clock.js.map +1 -0
  65. package/build/dist/Util/Decorators.js +7 -2
  66. package/build/dist/Util/Decorators.js.map +1 -1
  67. package/build/dist/Util/Fps.d.ts +40 -0
  68. package/build/dist/Util/Fps.js +47 -0
  69. package/build/dist/Util/Fps.js.map +1 -0
  70. package/build/dist/Util/Util.d.ts +6 -1
  71. package/build/dist/Util/Util.js +9 -3
  72. package/build/dist/Util/Util.js.map +1 -1
  73. package/build/dist/Util/WebAudio.js.map +1 -1
  74. package/build/dist/excalibur.js +699 -306
  75. package/build/dist/excalibur.js.map +1 -1
  76. package/build/dist/excalibur.min.js +1 -1
  77. package/build/dist/excalibur.min.js.LICENSE.txt +1 -1
  78. package/build/dist/excalibur.min.js.map +1 -1
  79. package/build/dist/index.d.ts +3 -0
  80. package/build/dist/index.js +5 -2
  81. package/build/dist/index.js.map +1 -1
  82. package/build/esm/Debug/Debug.d.ts +16 -0
  83. package/build/esm/Engine.d.ts +34 -1
  84. package/build/esm/EntityComponentSystem/SystemManager.d.ts +6 -0
  85. package/build/esm/Loader.d.ts +4 -1
  86. package/build/esm/Util/Clock.d.ts +117 -0
  87. package/build/esm/Util/Fps.d.ts +40 -0
  88. package/build/esm/Util/Util.d.ts +6 -1
  89. package/build/esm/excalibur.js +705 -307
  90. package/build/esm/excalibur.js.map +1 -1
  91. package/build/esm/excalibur.min.js +1 -1
  92. package/build/esm/excalibur.min.js.LICENSE.txt +1 -1
  93. package/build/esm/excalibur.min.js.map +1 -1
  94. package/build/esm/index.d.ts +3 -0
  95. package/package.json +1 -1
  96. package/wallaby.js +1 -0
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * excalibur - 0.26.0-alpha.310+5f94c2f - 2021-11-27
2
+ * excalibur - 0.26.0-alpha.311+c19e8da - 2021-11-28
3
3
  * https://github.com/excaliburjs/Excalibur
4
4
  * Copyright (c) 2021 Excalibur.js <https://github.com/excaliburjs/Excalibur/graphs/contributors>
5
5
  * Licensed BSD-2-Clause
@@ -1918,6 +1918,7 @@ __webpack_require__.d(__webpack_exports__, {
1918
1918
  "Circle": () => (/* reexport */ Circle),
1919
1919
  "CircleCollider": () => (/* reexport */ CircleCollider),
1920
1920
  "Class": () => (/* reexport */ Class),
1921
+ "Clock": () => (/* reexport */ Clock),
1921
1922
  "ClosestLine": () => (/* reexport */ ClosestLine),
1922
1923
  "ClosestLineJumpTable": () => (/* reexport */ ClosestLineJumpTable),
1923
1924
  "Collider": () => (/* reexport */ Collider),
@@ -1984,6 +1985,7 @@ __webpack_require__.d(__webpack_exports__, {
1984
1985
  "Font": () => (/* reexport */ Font),
1985
1986
  "FontStyle": () => (/* reexport */ FontStyle),
1986
1987
  "FontUnit": () => (/* reexport */ FontUnit),
1988
+ "FpsSampler": () => (/* reexport */ FpsSampler),
1987
1989
  "FrameStats": () => (/* reexport */ FrameStats),
1988
1990
  "GameEvent": () => (/* reexport */ GameEvent),
1989
1991
  "GameStartEvent": () => (/* reexport */ GameStartEvent),
@@ -2084,6 +2086,7 @@ __webpack_require__.d(__webpack_exports__, {
2084
2086
  "Sprite": () => (/* reexport */ Sprite),
2085
2087
  "SpriteFont": () => (/* reexport */ SpriteFont_SpriteFont),
2086
2088
  "SpriteSheet": () => (/* reexport */ SpriteSheet),
2089
+ "StandardClock": () => (/* reexport */ StandardClock),
2087
2090
  "StrategyContainer": () => (/* reexport */ StrategyContainer),
2088
2091
  "Stream": () => (/* reexport */ Stream),
2089
2092
  "SubscribeEvent": () => (/* reexport */ SubscribeEvent),
@@ -2091,6 +2094,7 @@ __webpack_require__.d(__webpack_exports__, {
2091
2094
  "SystemManager": () => (/* reexport */ SystemManager),
2092
2095
  "SystemType": () => (/* reexport */ SystemType),
2093
2096
  "TagComponent": () => (/* reexport */ TagComponent),
2097
+ "TestClock": () => (/* reexport */ TestClock),
2094
2098
  "Text": () => (/* reexport */ Text),
2095
2099
  "TextAlign": () => (/* reexport */ TextAlign),
2096
2100
  "TileMap": () => (/* reexport */ TileMap),
@@ -2104,6 +2108,7 @@ __webpack_require__.d(__webpack_exports__, {
2104
2108
  "Vector": () => (/* reexport */ Vector),
2105
2109
  "VectorView": () => (/* reexport */ VectorView),
2106
2110
  "VisibleEvent": () => (/* reexport */ VisibleEvent),
2111
+ "WebAudio": () => (/* reexport */ WebAudio),
2107
2112
  "WebAudioInstance": () => (/* reexport */ WebAudioInstance),
2108
2113
  "World": () => (/* reexport */ World),
2109
2114
  "canonicalizeAngle": () => (/* reexport */ canonicalizeAngle),
@@ -2664,7 +2669,12 @@ const logMessage = (message, options) => {
2664
2669
  * method do the deprecated one. Inspired by https://github.com/jayphelps/core-decorators.js
2665
2670
  */
2666
2671
  function obsolete(options) {
2667
- options = Object.assign({ message: 'This feature will be removed in future versions of Excalibur.', alternateMethod: null, showStackTrace: false }, options);
2672
+ options = {
2673
+ message: 'This feature will be removed in future versions of Excalibur.',
2674
+ alternateMethod: null,
2675
+ showStackTrace: false,
2676
+ ...options
2677
+ };
2668
2678
  return function (target, property, descriptor) {
2669
2679
  if (descriptor &&
2670
2680
  !(typeof descriptor.value === 'function' || typeof descriptor.get === 'function' || typeof descriptor.set === 'function')) {
@@ -2677,7 +2687,7 @@ function obsolete(options) {
2677
2687
  obsoleteMessage[message] = 0;
2678
2688
  }
2679
2689
  // If descriptor is null it is a class
2680
- const method = descriptor ? Object.assign({}, descriptor) : target;
2690
+ const method = descriptor ? { ...descriptor } : target;
2681
2691
  if (!descriptor) {
2682
2692
  // with es2015 classes we need to change our decoration tactic
2683
2693
  class DecoratedClass extends method {
@@ -4491,11 +4501,17 @@ function fail(message) {
4491
4501
  const range = (from, to) => Array.from(new Array(to - from + 1), (_x, i) => i + from);
4492
4502
  /**
4493
4503
  * Create a promise that resolves after a certain number of milliseconds
4504
+ *
4505
+ * It is strongly recommended you pass the excalibur clock so delays are bound to the
4506
+ * excalibur clock which would be unaffected by stop/pause.
4494
4507
  * @param milliseconds
4508
+ * @param clock
4495
4509
  */
4496
- function delay(milliseconds) {
4497
- return new Promise((resolve) => {
4498
- setTimeout(() => {
4510
+ function delay(milliseconds, clock) {
4511
+ var _a;
4512
+ const schedule = (_a = clock === null || clock === void 0 ? void 0 : clock.schedule.bind(clock)) !== null && _a !== void 0 ? _a : setTimeout;
4513
+ return new Promise(resolve => {
4514
+ schedule(() => {
4499
4515
  resolve();
4500
4516
  }, milliseconds);
4501
4517
  });
@@ -6547,7 +6563,11 @@ class Canvas extends Raster {
6547
6563
  return this._ctx;
6548
6564
  }
6549
6565
  clone() {
6550
- return new Canvas(Object.assign(Object.assign(Object.assign({}, this._options), this.cloneGraphicOptions()), this.cloneRasterOptions()));
6566
+ return new Canvas({
6567
+ ...this._options,
6568
+ ...this.cloneGraphicOptions(),
6569
+ ...this.cloneRasterOptions()
6570
+ });
6551
6571
  }
6552
6572
  execute(ctx) {
6553
6573
  var _a, _b;
@@ -7496,15 +7516,6 @@ Fill = SpriteEffects_decorate([
7496
7516
 
7497
7517
 
7498
7518
  ;// CONCATENATED MODULE: ./Drawing/Texture.ts
7499
- var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
7500
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
7501
- return new (P || (P = Promise))(function (resolve, reject) {
7502
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
7503
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7504
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7505
- step((generator = generator.apply(thisArg, _arguments || [])).next());
7506
- });
7507
- };
7508
7519
 
7509
7520
 
7510
7521
  /**
@@ -7541,35 +7552,33 @@ class Texture {
7541
7552
  /**
7542
7553
  * Begins loading the texture and returns a promise to be resolved on completion
7543
7554
  */
7544
- load() {
7545
- return __awaiter(this, void 0, void 0, function* () {
7546
- try {
7547
- // Load base64 or blob if needed
7548
- let url;
7549
- if (!this.path.includes('data:image/')) {
7550
- const blob = yield this._resource.load();
7551
- url = URL.createObjectURL(blob);
7552
- }
7553
- else {
7554
- url = this.path;
7555
- }
7556
- // Decode the image
7557
- const image = new Image();
7558
- image.src = url;
7559
- yield image.decode();
7560
- // Set results
7561
- this.data = image;
7562
- this.width = this._sprite.width = image.naturalWidth;
7563
- this.height = this._sprite.height = image.naturalHeight;
7564
- this._sprite = new Sprite_Sprite(this, 0, 0, this.width, this.height);
7565
- }
7566
- catch (_a) {
7567
- yield Promise.reject('Error loading texture');
7555
+ async load() {
7556
+ try {
7557
+ // Load base64 or blob if needed
7558
+ let url;
7559
+ if (!this.path.includes('data:image/')) {
7560
+ const blob = await this._resource.load();
7561
+ url = URL.createObjectURL(blob);
7568
7562
  }
7569
- // todo emit complete
7570
- this._loadedResolve(this.data);
7571
- return this.data;
7572
- });
7563
+ else {
7564
+ url = this.path;
7565
+ }
7566
+ // Decode the image
7567
+ const image = new Image();
7568
+ image.src = url;
7569
+ await image.decode();
7570
+ // Set results
7571
+ this.data = image;
7572
+ this.width = this._sprite.width = image.naturalWidth;
7573
+ this.height = this._sprite.height = image.naturalHeight;
7574
+ this._sprite = new Sprite_Sprite(this, 0, 0, this.width, this.height);
7575
+ }
7576
+ catch (_a) {
7577
+ await Promise.reject('Error loading texture');
7578
+ }
7579
+ // todo emit complete
7580
+ this._loadedResolve(this.data);
7581
+ return this.data;
7573
7582
  }
7574
7583
  asSprite() {
7575
7584
  return this._sprite;
@@ -7616,15 +7625,6 @@ var Sprite_decorate = (undefined && undefined.__decorate) || function (decorator
7616
7625
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
7617
7626
  return c > 3 && r && Object.defineProperty(target, key, r), r;
7618
7627
  };
7619
- var Sprite_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
7620
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
7621
- return new (P || (P = Promise))(function (resolve, reject) {
7622
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
7623
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7624
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7625
- step((generator = generator.apply(thisArg, _arguments || [])).next());
7626
- });
7627
- };
7628
7628
 
7629
7629
 
7630
7630
 
@@ -7704,21 +7704,19 @@ class SpriteImpl {
7704
7704
  get drawHeight() {
7705
7705
  return Math.abs(this.height * this.scale.y);
7706
7706
  }
7707
- _initPixelsFromTexture() {
7708
- return Sprite_awaiter(this, void 0, void 0, function* () {
7709
- try {
7710
- const image = yield this.texture.loaded;
7711
- this.width = this.width || image.naturalWidth;
7712
- this.height = this.height || image.naturalHeight;
7713
- this._spriteCanvas.width = this._spriteCanvas.width || image.naturalWidth;
7714
- this._spriteCanvas.height = this._spriteCanvas.height || image.naturalHeight;
7715
- this._loadPixels();
7716
- this._dirtyEffect = true;
7717
- }
7718
- catch (e) {
7719
- this.logger.error('Error loading texture ', this.texture.path, e);
7720
- }
7721
- });
7707
+ async _initPixelsFromTexture() {
7708
+ try {
7709
+ const image = await this.texture.loaded;
7710
+ this.width = this.width || image.naturalWidth;
7711
+ this.height = this.height || image.naturalHeight;
7712
+ this._spriteCanvas.width = this._spriteCanvas.width || image.naturalWidth;
7713
+ this._spriteCanvas.height = this._spriteCanvas.height || image.naturalHeight;
7714
+ this._loadPixels();
7715
+ this._dirtyEffect = true;
7716
+ }
7717
+ catch (e) {
7718
+ this.logger.error('Error loading texture ', this.texture.path, e);
7719
+ }
7722
7720
  }
7723
7721
  _loadPixels() {
7724
7722
  if (this.texture.isLoaded() && !this._pixelsLoaded) {
@@ -7890,7 +7888,17 @@ class SpriteImpl {
7890
7888
  }
7891
7889
  _drawWithOptions(options) {
7892
7890
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
7893
- const { ctx, x, y, rotation, drawWidth, drawHeight, anchor, offset, opacity, flipHorizontal, flipVertical } = Object.assign(Object.assign({}, options), { rotation: (_a = options.rotation) !== null && _a !== void 0 ? _a : this.rotation, drawWidth: (_b = options.drawWidth) !== null && _b !== void 0 ? _b : this.width, drawHeight: (_c = options.drawHeight) !== null && _c !== void 0 ? _c : this.height, flipHorizontal: (_d = options.flipHorizontal) !== null && _d !== void 0 ? _d : this.flipHorizontal, flipVertical: (_e = options.flipVertical) !== null && _e !== void 0 ? _e : this.flipVertical, anchor: (_f = options.anchor) !== null && _f !== void 0 ? _f : this.anchor, offset: (_g = options.offset) !== null && _g !== void 0 ? _g : this.offset, opacity: ((_h = options.opacity) !== null && _h !== void 0 ? _h : 1) * ((_j = this._opacity) !== null && _j !== void 0 ? _j : 1) });
7891
+ const { ctx, x, y, rotation, drawWidth, drawHeight, anchor, offset, opacity, flipHorizontal, flipVertical } = {
7892
+ ...options,
7893
+ rotation: (_a = options.rotation) !== null && _a !== void 0 ? _a : this.rotation,
7894
+ drawWidth: (_b = options.drawWidth) !== null && _b !== void 0 ? _b : this.width,
7895
+ drawHeight: (_c = options.drawHeight) !== null && _c !== void 0 ? _c : this.height,
7896
+ flipHorizontal: (_d = options.flipHorizontal) !== null && _d !== void 0 ? _d : this.flipHorizontal,
7897
+ flipVertical: (_e = options.flipVertical) !== null && _e !== void 0 ? _e : this.flipVertical,
7898
+ anchor: (_f = options.anchor) !== null && _f !== void 0 ? _f : this.anchor,
7899
+ offset: (_g = options.offset) !== null && _g !== void 0 ? _g : this.offset,
7900
+ opacity: ((_h = options.opacity) !== null && _h !== void 0 ? _h : 1) * ((_j = this._opacity) !== null && _j !== void 0 ? _j : 1)
7901
+ };
7894
7902
  if (this._dirtyEffect) {
7895
7903
  this._applyEffects();
7896
7904
  }
@@ -8058,20 +8066,16 @@ class Sprite extends Graphic {
8058
8066
  return new Sprite_Sprite(tex, sprite.sourceView.x, sprite.sourceView.y, sprite.sourceView.width, sprite.sourceView.height);
8059
8067
  }
8060
8068
  clone() {
8061
- return new Sprite(Object.assign({ image: this.image, sourceView: Object.assign({}, this.sourceView), destSize: Object.assign({}, this.destSize) }, this.cloneGraphicOptions()));
8069
+ return new Sprite({
8070
+ image: this.image,
8071
+ sourceView: { ...this.sourceView },
8072
+ destSize: { ...this.destSize },
8073
+ ...this.cloneGraphicOptions()
8074
+ });
8062
8075
  }
8063
8076
  }
8064
8077
 
8065
8078
  ;// CONCATENATED MODULE: ./Graphics/ImageSource.ts
8066
- var ImageSource_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
8067
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
8068
- return new (P || (P = Promise))(function (resolve, reject) {
8069
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
8070
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
8071
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8072
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8073
- });
8074
- };
8075
8079
 
8076
8080
 
8077
8081
 
@@ -8120,35 +8124,33 @@ class ImageSource {
8120
8124
  /**
8121
8125
  * Begins loading the image and returns a promise that resolves when the image is loaded
8122
8126
  */
8123
- load() {
8124
- return ImageSource_awaiter(this, void 0, void 0, function* () {
8125
- if (this.isLoaded()) {
8126
- return this.data;
8127
- }
8128
- try {
8129
- // Load base64 or blob if needed
8130
- let url;
8131
- if (!this.path.includes('data:image/')) {
8132
- const blob = yield this._resource.load();
8133
- url = URL.createObjectURL(blob);
8134
- }
8135
- else {
8136
- url = this.path;
8137
- }
8138
- // Decode the image
8139
- const image = new Image();
8140
- image.src = url;
8141
- yield image.decode();
8142
- // Set results
8143
- this.data = image;
8144
- }
8145
- catch (error) {
8146
- throw `Error loading ImageSource from path '${this.path}' with error [${error.message}]`;
8147
- }
8148
- // todo emit complete
8149
- this._loadedResolve(this.data);
8127
+ async load() {
8128
+ if (this.isLoaded()) {
8150
8129
  return this.data;
8151
- });
8130
+ }
8131
+ try {
8132
+ // Load base64 or blob if needed
8133
+ let url;
8134
+ if (!this.path.includes('data:image/')) {
8135
+ const blob = await this._resource.load();
8136
+ url = URL.createObjectURL(blob);
8137
+ }
8138
+ else {
8139
+ url = this.path;
8140
+ }
8141
+ // Decode the image
8142
+ const image = new Image();
8143
+ image.src = url;
8144
+ await image.decode();
8145
+ // Set results
8146
+ this.data = image;
8147
+ }
8148
+ catch (error) {
8149
+ throw `Error loading ImageSource from path '${this.path}' with error [${error.message}]`;
8150
+ }
8151
+ // todo emit complete
8152
+ this._loadedResolve(this.data);
8153
+ return this.data;
8152
8154
  }
8153
8155
  /**
8154
8156
  * Build a sprite from this ImageSource
@@ -8421,7 +8423,16 @@ class AnimationImpl {
8421
8423
  }
8422
8424
  _drawWithOptions(options) {
8423
8425
  var _a, _b, _c, _d, _e, _f, _g, _h;
8424
- const animOptions = Object.assign(Object.assign({}, options), { rotation: (_a = options.rotation) !== null && _a !== void 0 ? _a : this.rotation, drawWidth: (_b = options.drawWidth) !== null && _b !== void 0 ? _b : this.drawWidth, drawHeight: (_c = options.drawHeight) !== null && _c !== void 0 ? _c : this.drawHeight, flipHorizontal: (_d = options.flipHorizontal) !== null && _d !== void 0 ? _d : this.flipHorizontal, flipVertical: (_e = options.flipVertical) !== null && _e !== void 0 ? _e : this.flipVertical, anchor: (_f = options.anchor) !== null && _f !== void 0 ? _f : this.anchor, opacity: ((_g = options.opacity) !== null && _g !== void 0 ? _g : 1) * ((_h = this._opacity) !== null && _h !== void 0 ? _h : 1) });
8426
+ const animOptions = {
8427
+ ...options,
8428
+ rotation: (_a = options.rotation) !== null && _a !== void 0 ? _a : this.rotation,
8429
+ drawWidth: (_b = options.drawWidth) !== null && _b !== void 0 ? _b : this.drawWidth,
8430
+ drawHeight: (_c = options.drawHeight) !== null && _c !== void 0 ? _c : this.drawHeight,
8431
+ flipHorizontal: (_d = options.flipHorizontal) !== null && _d !== void 0 ? _d : this.flipHorizontal,
8432
+ flipVertical: (_e = options.flipVertical) !== null && _e !== void 0 ? _e : this.flipVertical,
8433
+ anchor: (_f = options.anchor) !== null && _f !== void 0 ? _f : this.anchor,
8434
+ opacity: ((_g = options.opacity) !== null && _g !== void 0 ? _g : 1) * ((_h = this._opacity) !== null && _h !== void 0 ? _h : 1)
8435
+ };
8425
8436
  this._updateValues();
8426
8437
  let currSprite;
8427
8438
  if (this.currentFrame < this.sprites.length) {
@@ -9080,8 +9091,8 @@ class SpriteSheet {
9080
9091
  const sprites = [];
9081
9092
  options.spacing = (_a = options.spacing) !== null && _a !== void 0 ? _a : {};
9082
9093
  const { image, grid: { rows, columns: cols, spriteWidth, spriteHeight }, spacing: { originOffset, margin } } = options;
9083
- const offsetDefaults = Object.assign({ x: 0, y: 0 }, originOffset);
9084
- const marginDefaults = Object.assign({ x: 0, y: 0 }, margin);
9094
+ const offsetDefaults = { x: 0, y: 0, ...originOffset };
9095
+ const marginDefaults = { x: 0, y: 0, ...margin };
9085
9096
  for (let x = 0; x < cols; x++) {
9086
9097
  for (let y = 0; y < rows; y++) {
9087
9098
  sprites[x + y * cols] = new Sprite({
@@ -9297,10 +9308,10 @@ class ExcaliburGraphicsContextWebGLDebug {
9297
9308
  * @param height
9298
9309
  */
9299
9310
  drawRect(x, y, width, height, rectOptions = { color: Color.Black }) {
9300
- this.drawLine(vec(x, y), vec(x + width, y), Object.assign({}, rectOptions));
9301
- this.drawLine(vec(x + width, y), vec(x + width, y + height), Object.assign({}, rectOptions));
9302
- this.drawLine(vec(x + width, y + height), vec(x, y + height), Object.assign({}, rectOptions));
9303
- this.drawLine(vec(x, y + height), vec(x, y), Object.assign({}, rectOptions));
9311
+ this.drawLine(vec(x, y), vec(x + width, y), { ...rectOptions });
9312
+ this.drawLine(vec(x + width, y), vec(x + width, y + height), { ...rectOptions });
9313
+ this.drawLine(vec(x + width, y + height), vec(x, y + height), { ...rectOptions });
9314
+ this.drawLine(vec(x, y + height), vec(x, y), { ...rectOptions });
9304
9315
  }
9305
9316
  /**
9306
9317
  * Draw a debugging line to the context
@@ -9606,7 +9617,7 @@ class Screen {
9606
9617
  this._devicePixelRatio = this._calculateDevicePixelRatio();
9607
9618
  this._alreadyWarned = false;
9608
9619
  this.viewport = options.viewport;
9609
- this.resolution = (_a = options.resolution) !== null && _a !== void 0 ? _a : Object.assign({}, this.viewport);
9620
+ this.resolution = (_a = options.resolution) !== null && _a !== void 0 ? _a : { ...this.viewport };
9610
9621
  this._displayMode = (_b = options.displayMode) !== null && _b !== void 0 ? _b : DisplayMode.Fixed;
9611
9622
  this._canvas = options.canvas;
9612
9623
  this._ctx = options.context;
@@ -9702,8 +9713,8 @@ class Screen {
9702
9713
  pushResolutionAndViewport() {
9703
9714
  this._resolutionStack.push(this.resolution);
9704
9715
  this._viewportStack.push(this.viewport);
9705
- this.resolution = Object.assign({}, this.resolution);
9706
- this.viewport = Object.assign({}, this.viewport);
9716
+ this.resolution = { ...this.resolution };
9717
+ this.viewport = { ...this.viewport };
9707
9718
  }
9708
9719
  peekViewport() {
9709
9720
  return this._viewportStack[this._viewportStack.length - 1];
@@ -10371,15 +10382,6 @@ function circle(ctx, x, y, radius, stroke = Color.White, fill = null) {
10371
10382
  // EXTERNAL MODULE: ./Loader.css
10372
10383
  var Loader_0 = __webpack_require__(1388);
10373
10384
  ;// CONCATENATED MODULE: ./Loader.ts
10374
- var Loader_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
10375
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
10376
- return new (P || (P = Promise))(function (resolve, reject) {
10377
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
10378
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
10379
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
10380
- step((generator = generator.apply(thisArg, _arguments || [])).next());
10381
- });
10382
- };
10383
10385
 
10384
10386
 
10385
10387
 
@@ -10503,6 +10505,9 @@ class Loader extends Class {
10503
10505
  buttonElement.style.display = 'none';
10504
10506
  return buttonElement;
10505
10507
  };
10508
+ this._isLoadedPromise = new Promise(resolve => {
10509
+ this._isLoadedResolve = resolve;
10510
+ });
10506
10511
  if (loadables) {
10507
10512
  this.addResources(loadables);
10508
10513
  }
@@ -10578,17 +10583,18 @@ class Loader extends Class {
10578
10583
  /**
10579
10584
  * Shows the play button and returns a promise that resolves when clicked
10580
10585
  */
10581
- showPlayButton() {
10582
- var _a;
10586
+ async showPlayButton() {
10587
+ var _a, _b;
10583
10588
  if (this.suppressPlayButton) {
10584
10589
  this.hidePlayButton();
10585
- return Promise.resolve();
10590
+ // Delay is to give the logo a chance to show, otherwise don't delay
10591
+ await delay(500, (_a = this._engine) === null || _a === void 0 ? void 0 : _a.clock);
10586
10592
  }
10587
10593
  else {
10588
10594
  const resizeHandler = () => {
10589
10595
  this._positionPlayButton();
10590
10596
  };
10591
- if ((_a = this._engine) === null || _a === void 0 ? void 0 : _a.browser) {
10597
+ if ((_b = this._engine) === null || _b === void 0 ? void 0 : _b.browser) {
10592
10598
  this._engine.browser.window.on('resize', resizeHandler);
10593
10599
  }
10594
10600
  this._playButtonShown = true;
@@ -10598,7 +10604,8 @@ class Loader extends Class {
10598
10604
  this._playButton.click();
10599
10605
  }
10600
10606
  });
10601
- const promise = new Promise((resolve) => {
10607
+ this._positionPlayButton();
10608
+ const playButtonClicked = new Promise((resolve) => {
10602
10609
  const startButtonHandler = (e) => {
10603
10610
  var _a;
10604
10611
  // We want to stop propogation to keep bubbling to the engine pointer handlers
@@ -10614,7 +10621,7 @@ class Loader extends Class {
10614
10621
  this._playButton.addEventListener('touchend', startButtonHandler);
10615
10622
  this._playButton.addEventListener('pointerup', startButtonHandler);
10616
10623
  });
10617
- return promise;
10624
+ return await playButtonClicked;
10618
10625
  }
10619
10626
  }
10620
10627
  hidePlayButton() {
@@ -10637,25 +10644,29 @@ class Loader extends Class {
10637
10644
  update(_engine, _delta) {
10638
10645
  // override me
10639
10646
  }
10647
+ areResourcesLoaded() {
10648
+ return this._isLoadedPromise;
10649
+ }
10640
10650
  /**
10641
10651
  * Begin loading all of the supplied resources, returning a promise
10642
- * that resolves when loading of all is complete
10652
+ * that resolves when loading of all is complete AND the user has clicked the "Play button"
10643
10653
  */
10644
- load() {
10645
- return Loader_awaiter(this, void 0, void 0, function* () {
10646
- yield Promise.all(this._resourceList.map((r) => r.load().finally(() => {
10647
- // capture progress
10648
- this._numLoaded++;
10649
- })));
10650
- // short delay in showing the button for aesthetics
10651
- yield delay(200);
10652
- yield this.showPlayButton();
10653
- // Unlock browser AudioContext in after user gesture
10654
- // See: https://github.com/excaliburjs/Excalibur/issues/262
10655
- // See: https://github.com/excaliburjs/Excalibur/issues/1031
10656
- yield WebAudio.unlock();
10657
- return (this.data = this._resourceList);
10658
- });
10654
+ async load() {
10655
+ var _a, _b;
10656
+ await ((_a = this._image) === null || _a === void 0 ? void 0 : _a.decode()); // decode logo if it exists
10657
+ await Promise.all(this._resourceList.map((r) => r.load().finally(() => {
10658
+ // capture progress
10659
+ this._numLoaded++;
10660
+ })));
10661
+ this._isLoadedResolve();
10662
+ // short delay in showing the button for aesthetics
10663
+ await delay(200, (_b = this._engine) === null || _b === void 0 ? void 0 : _b.clock);
10664
+ await this.showPlayButton();
10665
+ // Unlock browser AudioContext in after user gesture
10666
+ // See: https://github.com/excaliburjs/Excalibur/issues/262
10667
+ // See: https://github.com/excaliburjs/Excalibur/issues/1031
10668
+ await WebAudio.unlock();
10669
+ return (this.data = this._resourceList);
10659
10670
  }
10660
10671
  markResourceComplete() {
10661
10672
  this._numLoaded++;
@@ -15730,7 +15741,7 @@ class GraphicsLayer {
15730
15741
  * @param options
15731
15742
  */
15732
15743
  show(nameOrGraphic, options) {
15733
- options = Object.assign({}, options);
15744
+ options = { ...options };
15734
15745
  let gfx;
15735
15746
  if (nameOrGraphic instanceof Graphic) {
15736
15747
  gfx = this._graphics.copyGraphics ? nameOrGraphic.clone() : nameOrGraphic;
@@ -15755,7 +15766,7 @@ class GraphicsLayer {
15755
15766
  * @param options
15756
15767
  */
15757
15768
  use(nameOrGraphic, options) {
15758
- options = Object.assign({}, options);
15769
+ options = { ...options };
15759
15770
  this.hide();
15760
15771
  return this.show(nameOrGraphic, options);
15761
15772
  }
@@ -15862,7 +15873,10 @@ class GraphicsComponent extends Component {
15862
15873
  this.copyGraphics = false;
15863
15874
  this._bounds = null;
15864
15875
  // Defaults
15865
- options = Object.assign({ visible: this.visible }, options);
15876
+ options = {
15877
+ visible: this.visible,
15878
+ ...options
15879
+ };
15866
15880
  const { current, anchor, opacity, visible, graphics, offset, copyGraphics, onPreDraw, onPostDraw } = options;
15867
15881
  this._graphics = graphics || {};
15868
15882
  this.offset = offset !== null && offset !== void 0 ? offset : this.offset;
@@ -15986,7 +16000,12 @@ class Rectangle extends Raster {
15986
16000
  this.rasterize();
15987
16001
  }
15988
16002
  clone() {
15989
- return new Rectangle(Object.assign(Object.assign({ width: this.width, height: this.height }, this.cloneGraphicOptions()), this.cloneRasterOptions()));
16003
+ return new Rectangle({
16004
+ width: this.width,
16005
+ height: this.height,
16006
+ ...this.cloneGraphicOptions(),
16007
+ ...this.cloneRasterOptions()
16008
+ });
15990
16009
  }
15991
16010
  execute(ctx) {
15992
16011
  if (this.color) {
@@ -16022,7 +16041,11 @@ class Circle extends Raster {
16022
16041
  this.flagDirty();
16023
16042
  }
16024
16043
  clone() {
16025
- return new Circle(Object.assign(Object.assign({ radius: this.radius }, this.cloneGraphicOptions()), this.cloneRasterOptions()));
16044
+ return new Circle({
16045
+ radius: this.radius,
16046
+ ...this.cloneGraphicOptions(),
16047
+ ...this.cloneRasterOptions()
16048
+ });
16026
16049
  }
16027
16050
  execute(ctx) {
16028
16051
  if (this.radius > 0) {
@@ -17706,7 +17729,9 @@ class Actor extends Entity {
17706
17729
  * @deprecated will be removed in v0.26.0
17707
17730
  */
17708
17731
  this.traits = [];
17709
- const { name, x, y, pos, scale, width, height, radius, collider, vel, acc, rotation, angularVelocity, z, color, visible, anchor, collisionType, collisionGroup } = Object.assign({}, config);
17732
+ const { name, x, y, pos, scale, width, height, radius, collider, vel, acc, rotation, angularVelocity, z, color, visible, anchor, collisionType, collisionGroup } = {
17733
+ ...config
17734
+ };
17710
17735
  this._setName(name);
17711
17736
  this.anchor = anchor !== null && anchor !== void 0 ? anchor : Actor.defaults.anchor.clone();
17712
17737
  this.addComponent(new TransformComponent());
@@ -18425,7 +18450,7 @@ Actor_decorate([
18425
18450
  */
18426
18451
  class ScreenElement_ScreenElement extends Actor {
18427
18452
  constructor(config) {
18428
- super(Object.assign({}, config));
18453
+ super({ ...config });
18429
18454
  this.get(TransformComponent).coordPlane = CoordPlane.Screen;
18430
18455
  this.anchor = vec(0, 0);
18431
18456
  this.body.collisionType = CollisionType.PreventCollision;
@@ -19809,7 +19834,10 @@ class Trigger_Trigger extends Actor {
19809
19834
  * Number of times to repeat before killing the trigger,
19810
19835
  */
19811
19836
  this.repeat = -1;
19812
- opts = Object.assign(Object.assign({}, triggerDefaults), opts);
19837
+ opts = {
19838
+ ...triggerDefaults,
19839
+ ...opts
19840
+ };
19813
19841
  this.filter = opts.filter || this.filter;
19814
19842
  this.repeat = opts.repeat || this.repeat;
19815
19843
  this.action = opts.action || this.action;
@@ -20319,12 +20347,11 @@ class SystemManager {
20319
20347
  }
20320
20348
  }
20321
20349
  /**
20322
- * Updates all systems
20323
- * @param type whether this is an update or draw system
20324
- * @param context context reference
20325
- * @param delta time in milliseconds
20350
+ * Initialize all systems in the manager
20351
+ *
20352
+ * Systems added after initialize() will be initialized on add
20326
20353
  */
20327
- updateSystems(type, context, delta) {
20354
+ initialize() {
20328
20355
  if (!this.initialized) {
20329
20356
  this.initialized = true;
20330
20357
  for (const s of this.systems) {
@@ -20333,6 +20360,14 @@ class SystemManager {
20333
20360
  }
20334
20361
  }
20335
20362
  }
20363
+ }
20364
+ /**
20365
+ * Updates all systems
20366
+ * @param type whether this is an update or draw system
20367
+ * @param context context reference
20368
+ * @param delta time in milliseconds
20369
+ */
20370
+ updateSystems(type, context, delta) {
20336
20371
  const systems = this.systems.filter((s) => s.systemType === type);
20337
20372
  for (const s of systems) {
20338
20373
  if (s.preupdate) {
@@ -21128,7 +21163,13 @@ class Animation extends Graphic {
21128
21163
  this.goToFrame(0);
21129
21164
  }
21130
21165
  clone() {
21131
- return new Animation(Object.assign({ frames: this.frames.map((f) => (Object.assign({}, f))), frameDuration: this.frameDuration, reverse: this._reversed, strategy: this.strategy }, this.cloneGraphicOptions()));
21166
+ return new Animation({
21167
+ frames: this.frames.map((f) => ({ ...f })),
21168
+ frameDuration: this.frameDuration,
21169
+ reverse: this._reversed,
21170
+ strategy: this.strategy,
21171
+ ...this.cloneGraphicOptions()
21172
+ });
21132
21173
  }
21133
21174
  /**
21134
21175
  * Create an Animation from a [[SpriteSheet]], a list of indices into the sprite sheet, a duration per frame
@@ -21374,7 +21415,10 @@ class GraphicsGroup extends Graphic {
21374
21415
  this._updateDimensions();
21375
21416
  }
21376
21417
  clone() {
21377
- return new GraphicsGroup(Object.assign({ members: [...this.members] }, this.cloneGraphicOptions()));
21418
+ return new GraphicsGroup({
21419
+ members: [...this.members],
21420
+ ...this.cloneGraphicOptions()
21421
+ });
21378
21422
  }
21379
21423
  _updateDimensions() {
21380
21424
  let bb = new BoundingBox();
@@ -21715,7 +21759,7 @@ class ParticleEmitter extends Actor {
21715
21759
  * Indicates whether particles should start with a random rotation
21716
21760
  */
21717
21761
  this.randomRotation = false;
21718
- const { x, y, pos, isEmitting, minVel, maxVel, acceleration, minAngle, maxAngle, emitRate, particleLife, opacity, fadeFlag, focus, focusAccel, startSize, endSize, minSize, maxSize, beginColor, endColor, particleSprite, emitterType, radius, particleRotationalVelocity, randomRotation, random } = Object.assign({}, config);
21762
+ const { x, y, pos, isEmitting, minVel, maxVel, acceleration, minAngle, maxAngle, emitRate, particleLife, opacity, fadeFlag, focus, focusAccel, startSize, endSize, minSize, maxSize, beginColor, endColor, particleSprite, emitterType, radius, particleRotationalVelocity, randomRotation, random } = { ...config };
21719
21763
  this.pos = pos !== null && pos !== void 0 ? pos : vec(x !== null && x !== void 0 ? x : 0, y !== null && y !== void 0 ? y : 0);
21720
21764
  this.isEmitting = isEmitting !== null && isEmitting !== void 0 ? isEmitting : this.isEmitting;
21721
21765
  this.minVel = minVel !== null && minVel !== void 0 ? minVel : this.minVel;
@@ -22785,6 +22829,7 @@ class Scene extends Class {
22785
22829
  this.engine = engine;
22786
22830
  // Initialize camera first
22787
22831
  this.camera._initialize(engine);
22832
+ this.world.systemManager.initialize();
22788
22833
  // This order is important! we want to be sure any custom init that add actors
22789
22834
  // fire before the actor init
22790
22835
  this.onInitialize.call(this, engine);
@@ -23374,6 +23419,41 @@ class Debug {
23374
23419
  this._engine = engine;
23375
23420
  this.colorBlindMode = new ColorBlindFlags(this._engine);
23376
23421
  }
23422
+ /**
23423
+ * Switch the current excalibur clock with the [[TestClock]] and return
23424
+ * it in the same running state.
23425
+ *
23426
+ * This is useful when you need to debug frame by frame.
23427
+ */
23428
+ useTestClock() {
23429
+ const clock = this._engine.clock;
23430
+ const wasRunning = clock.isRunning();
23431
+ clock.stop();
23432
+ const testClock = clock.toTestClock();
23433
+ if (wasRunning) {
23434
+ testClock.start();
23435
+ }
23436
+ this._engine.clock = testClock;
23437
+ return testClock;
23438
+ }
23439
+ /**
23440
+ * Switch the current excalibur clock with the [[StandardClock]] and
23441
+ * return it in the same runnign state.
23442
+ *
23443
+ * This is useful when you need to switch back to normal mode after
23444
+ * debugging.
23445
+ */
23446
+ useStandardClock() {
23447
+ const currentClock = this._engine.clock;
23448
+ const wasRunning = currentClock.isRunning();
23449
+ currentClock.stop();
23450
+ const standardClock = currentClock.toStandardClock();
23451
+ if (wasRunning) {
23452
+ standardClock.start();
23453
+ }
23454
+ this._engine.clock = standardClock;
23455
+ return standardClock;
23456
+ }
23377
23457
  }
23378
23458
  /**
23379
23459
  * Implementation of a frame's stats. Meant to have values copied via [[FrameStats.reset]], avoid
@@ -25048,6 +25128,264 @@ class PointerEventReceiver extends Class {
25048
25128
  }
25049
25129
  }
25050
25130
 
25131
+ ;// CONCATENATED MODULE: ./Util/Fps.ts
25132
+ class FpsSampler {
25133
+ constructor(options) {
25134
+ var _a;
25135
+ this._samplePeriod = 100;
25136
+ this._currentFrameTime = 0;
25137
+ this._frames = 0;
25138
+ this._previousSampleTime = 0;
25139
+ this._beginFrameTime = 0;
25140
+ this._fps = options.initialFps;
25141
+ this._samplePeriod = (_a = options.samplePeriod) !== null && _a !== void 0 ? _a : this._samplePeriod;
25142
+ this._currentFrameTime = 1000 / options.initialFps;
25143
+ this._nowFn = options.nowFn;
25144
+ this._previousSampleTime = this._nowFn();
25145
+ }
25146
+ /**
25147
+ * Start of code block to sample FPS for
25148
+ */
25149
+ start() {
25150
+ this._beginFrameTime = this._nowFn();
25151
+ }
25152
+ /**
25153
+ * End of code block to sample FPS for
25154
+ */
25155
+ end() {
25156
+ this._frames++;
25157
+ const time = this._nowFn();
25158
+ this._currentFrameTime = time - this._beginFrameTime;
25159
+ if (time >= this._previousSampleTime + this._samplePeriod) {
25160
+ this._fps = (this._frames * 1000) / (time - this._previousSampleTime);
25161
+ this._previousSampleTime = time;
25162
+ this._frames = 0;
25163
+ }
25164
+ }
25165
+ /**
25166
+ * Return the currenty sampled fps over the last sample period, by default every 100ms
25167
+ */
25168
+ get fps() {
25169
+ return this._fps;
25170
+ }
25171
+ /**
25172
+ * Return the instantanteous fps, this can be less useful because it will fluctuate given the current frames time
25173
+ */
25174
+ get instant() {
25175
+ return 1000 / this._currentFrameTime;
25176
+ }
25177
+ }
25178
+
25179
+ ;// CONCATENATED MODULE: ./Util/Clock.ts
25180
+
25181
+
25182
+ /**
25183
+ * Abstract Clock is the base type of all Clocks
25184
+ *
25185
+ * It has a few opinions
25186
+ * 1. It manages the calculation of what "elapsed" time means and thus maximum fps
25187
+ * 2. The default timing api is implemented in now()
25188
+ *
25189
+ * To implement your own clock, extend Clock and override start/stop to start and stop the clock, then call update() with whatever
25190
+ * method is unique to your clock implementation.
25191
+ */
25192
+ class Clock {
25193
+ constructor(options) {
25194
+ var _a, _b, _c;
25195
+ this._onFatalException = () => { };
25196
+ this._maxFps = Infinity;
25197
+ this._lastTime = 0;
25198
+ this._elapsed = 1;
25199
+ this._scheduledCbs = [];
25200
+ this._totalElapsed = 0;
25201
+ this._options = options;
25202
+ this.tick = options.tick;
25203
+ this._lastTime = (_a = this.now()) !== null && _a !== void 0 ? _a : 0;
25204
+ this._maxFps = (_b = options.maxFps) !== null && _b !== void 0 ? _b : this._maxFps;
25205
+ this._onFatalException = (_c = options.onFatalException) !== null && _c !== void 0 ? _c : this._onFatalException;
25206
+ this.fpsSampler = new FpsSampler({
25207
+ initialFps: 60,
25208
+ nowFn: () => this.now()
25209
+ });
25210
+ }
25211
+ /**
25212
+ * Get the elapsed time for the last completed frame
25213
+ */
25214
+ elapsed() {
25215
+ return this._elapsed;
25216
+ }
25217
+ /**
25218
+ * Get the current time in milliseconds
25219
+ */
25220
+ now() {
25221
+ return performance.now();
25222
+ }
25223
+ toTestClock() {
25224
+ const testClock = new TestClock({
25225
+ ...this._options,
25226
+ defaultUpdateMs: 16.6
25227
+ });
25228
+ return testClock;
25229
+ }
25230
+ toStandardClock() {
25231
+ const clock = new StandardClock({
25232
+ ...this._options
25233
+ });
25234
+ return clock;
25235
+ }
25236
+ /**
25237
+ * Schedule a callback to fire given a timeout in milliseconds using the excalibur [[Clock]]
25238
+ *
25239
+ * This is useful to use over the built in browser `setTimeout` because callbacks will be tied to the
25240
+ * excalibur update clock, instead of browser time, this means that callbacks wont fire if the game is
25241
+ * stopped or paused.
25242
+ *
25243
+ * @param cb callback to fire
25244
+ * @param timeoutMs Optionally specify a timeout in milliseconds from now, default is 0ms which means the next possible tick
25245
+ */
25246
+ schedule(cb, timeoutMs = 0) {
25247
+ const scheduledTime = this.now() + timeoutMs;
25248
+ this._scheduledCbs.push([cb, scheduledTime]);
25249
+ }
25250
+ _runScheduledCbs() {
25251
+ // walk backwards to delete items as we loop
25252
+ for (let i = this._scheduledCbs.length - 1; i > -1; i--) {
25253
+ if (this._scheduledCbs[i][1] <= this._totalElapsed) {
25254
+ this._scheduledCbs[i][0]();
25255
+ this._scheduledCbs.splice(i, 1);
25256
+ }
25257
+ }
25258
+ }
25259
+ update(overrideUpdateMs) {
25260
+ try {
25261
+ this.fpsSampler.start();
25262
+ // Get the time to calculate time-elapsed
25263
+ const now = this.now();
25264
+ let elapsed = now - this._lastTime || 1; // first frame
25265
+ // Constrain fps
25266
+ const fpsInterval = this._maxFps === Infinity ? 0 : 1000 / this._maxFps;
25267
+ if (elapsed <= fpsInterval) {
25268
+ return; // too fast 😎 skip this frame
25269
+ }
25270
+ // Resolves issue #138 if the game has been paused, or blurred for
25271
+ // more than a 200 milliseconds, reset elapsed time to 1. This improves reliability
25272
+ // and provides more expected behavior when the engine comes back
25273
+ // into focus
25274
+ if (elapsed > 200) {
25275
+ elapsed = 1;
25276
+ }
25277
+ // tick the mainloop and run scheduled callbacks
25278
+ this._elapsed = overrideUpdateMs || elapsed;
25279
+ this._totalElapsed += this._elapsed;
25280
+ this._runScheduledCbs();
25281
+ this.tick(overrideUpdateMs || elapsed);
25282
+ // if fps interval is not a multple
25283
+ if (fpsInterval > 0) {
25284
+ this._lastTime = now - (elapsed % fpsInterval);
25285
+ }
25286
+ else {
25287
+ this._lastTime = now;
25288
+ }
25289
+ this.fpsSampler.end();
25290
+ }
25291
+ catch (e) {
25292
+ this._onFatalException(e);
25293
+ this.stop();
25294
+ }
25295
+ }
25296
+ }
25297
+ /**
25298
+ * The [[StandardClock]] implements the requestAnimationFrame browser api to run the tick()
25299
+ */
25300
+ class StandardClock extends Clock {
25301
+ constructor(options) {
25302
+ super(options);
25303
+ this._running = false;
25304
+ }
25305
+ isRunning() {
25306
+ return this._running;
25307
+ }
25308
+ start() {
25309
+ this._running = true;
25310
+ const mainloop = () => {
25311
+ // stop the loop
25312
+ if (!this._running) {
25313
+ return;
25314
+ }
25315
+ try {
25316
+ // request next loop
25317
+ this._requestId = window.requestAnimationFrame(mainloop);
25318
+ this.update();
25319
+ }
25320
+ catch (e) {
25321
+ window.cancelAnimationFrame(this._requestId);
25322
+ throw e;
25323
+ }
25324
+ };
25325
+ // begin the first frame
25326
+ mainloop();
25327
+ }
25328
+ stop() {
25329
+ this._running = false;
25330
+ }
25331
+ }
25332
+ /**
25333
+ * The TestClock is meant for debugging interactions in excalibur that require precise timing to replicate or test
25334
+ */
25335
+ class TestClock extends Clock {
25336
+ constructor(options) {
25337
+ super({
25338
+ ...options
25339
+ });
25340
+ this._logger = Logger.getInstance();
25341
+ this._running = false;
25342
+ this._currentTime = 0;
25343
+ this._updateMs = options.defaultUpdateMs;
25344
+ }
25345
+ /**
25346
+ * Get the current time in milliseconds
25347
+ */
25348
+ now() {
25349
+ var _a;
25350
+ return (_a = this._currentTime) !== null && _a !== void 0 ? _a : 0;
25351
+ }
25352
+ isRunning() {
25353
+ return this._running;
25354
+ }
25355
+ start() {
25356
+ this._running = true;
25357
+ }
25358
+ stop() {
25359
+ this._running = false;
25360
+ }
25361
+ /**
25362
+ * Manually step the clock forward 1 tick, optionally specify an elapsed time in milliseconds
25363
+ * @param overrideUpdateMs
25364
+ */
25365
+ step(overrideUpdateMs) {
25366
+ const time = overrideUpdateMs !== null && overrideUpdateMs !== void 0 ? overrideUpdateMs : this._updateMs;
25367
+ if (this._running) {
25368
+ // to be comparable to RAF this needs to be a full blown Task
25369
+ // For example, images cannot decode syncronously in a single step
25370
+ this.update(time);
25371
+ this._currentTime += time;
25372
+ }
25373
+ else {
25374
+ this._logger.warn('The clock is not running, no step will be performed');
25375
+ }
25376
+ }
25377
+ /**
25378
+ * Run a number of steps that tick the clock, optionally specify an elapsed time in milliseconds
25379
+ * @param numberOfSteps
25380
+ * @param overrideUpdateMs
25381
+ */
25382
+ run(numberOfSteps, overrideUpdateMs) {
25383
+ for (let i = 0; i < numberOfSteps; i++) {
25384
+ this.step(overrideUpdateMs !== null && overrideUpdateMs !== void 0 ? overrideUpdateMs : this._updateMs);
25385
+ }
25386
+ }
25387
+ }
25388
+
25051
25389
  ;// CONCATENATED MODULE: ./Engine.ts
25052
25390
  var Engine_decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
25053
25391
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -25074,6 +25412,8 @@ polyfill();
25074
25412
 
25075
25413
 
25076
25414
 
25415
+
25416
+
25077
25417
  /**
25078
25418
  * Enum representing the different mousewheel event bubble prevention
25079
25419
  */
@@ -25125,8 +25465,15 @@ class Engine extends Class {
25125
25465
  * ```
25126
25466
  */
25127
25467
  constructor(options) {
25128
- var _a, _b, _c;
25468
+ var _a, _b, _c, _d;
25129
25469
  super();
25470
+ /**
25471
+ * Optionally set the maximum fps if not set Excalibur will go as fast as the device allows.
25472
+ *
25473
+ * You may want to constrain max fps if your game cannot maintain fps consistenly, it can look and feel better to have a 30fps game than
25474
+ * one that bounces between 30fps and 60fps
25475
+ */
25476
+ this.maxFps = Number.POSITIVE_INFINITY;
25130
25477
  this._hasStarted = false;
25131
25478
  /**
25132
25479
  * Gets or sets the list of post processors to apply at the end of drawing a frame (such as [[ColorBlindCorrector]])
@@ -25162,11 +25509,14 @@ class Engine extends Class {
25162
25509
  Logger.getInstance().fatal(e);
25163
25510
  };
25164
25511
  this._timescale = 1.0;
25165
- this._isLoading = false;
25166
25512
  this._isInitialized = false;
25167
25513
  this._deferredGoTo = null;
25168
25514
  this._loadingComplete = false;
25169
- options = Object.assign(Object.assign({}, Engine._DEFAULT_ENGINE_OPTIONS), options);
25515
+ this._isReady = false;
25516
+ this._isReadyPromise = new Promise(resolve => {
25517
+ this._isReadyResolve = resolve;
25518
+ });
25519
+ options = { ...Engine._DEFAULT_ENGINE_OPTIONS, ...options };
25170
25520
  Flags.freeze();
25171
25521
  // Initialize browser events facade
25172
25522
  this.browser = new BrowserEvents(window, document);
@@ -25275,6 +25625,12 @@ O|===|* >________________>\n\
25275
25625
  if (options.backgroundColor) {
25276
25626
  this.backgroundColor = options.backgroundColor.clone();
25277
25627
  }
25628
+ this.maxFps = (_d = options.maxFps) !== null && _d !== void 0 ? _d : this.maxFps;
25629
+ this.clock = new StandardClock({
25630
+ maxFps: this.maxFps,
25631
+ tick: this._mainloop.bind(this),
25632
+ onFatalException: (e) => this.onFatalException(e)
25633
+ });
25278
25634
  this.enableCanvasTransparency = options.enableCanvasTransparency;
25279
25635
  this._loader = new Loader();
25280
25636
  this.debug = new Debug(this);
@@ -25628,7 +25984,7 @@ O|===|* >________________>\n\
25628
25984
  * @param delta Number of milliseconds elapsed since the last update.
25629
25985
  */
25630
25986
  _update(delta) {
25631
- if (this._isLoading) {
25987
+ if (!this.ready) {
25632
25988
  // suspend updates until loading is finished
25633
25989
  this._loader.update(this, delta);
25634
25990
  // Update input listeners
@@ -25636,7 +25992,6 @@ O|===|* >________________>\n\
25636
25992
  this.input.gamepads.update();
25637
25993
  return;
25638
25994
  }
25639
- this._overrideInitialize(this);
25640
25995
  // Publish preupdate events
25641
25996
  this._preupdate(delta);
25642
25997
  // process engine level events
@@ -25679,10 +26034,10 @@ O|===|* >________________>\n\
25679
26034
  _draw(delta) {
25680
26035
  const ctx = this.ctx;
25681
26036
  this._predraw(ctx, delta);
25682
- if (this._isLoading) {
26037
+ // Drawing nothing else while loading
26038
+ if (!this._isReady) {
25683
26039
  this._loader.canvas.draw(this.graphicsContext, 0, 0);
25684
26040
  this.graphicsContext.flush();
25685
- // Drawing nothing else while loading
25686
26041
  return;
25687
26042
  }
25688
26043
  // TODO move to graphics systems?
@@ -25751,64 +26106,105 @@ O|===|* >________________>\n\
25751
26106
  get loadingComplete() {
25752
26107
  return this._loadingComplete;
25753
26108
  }
26109
+ get ready() {
26110
+ return this._isReady;
26111
+ }
26112
+ isReady() {
26113
+ return this._isReadyPromise;
26114
+ }
25754
26115
  /**
25755
26116
  * Starts the internal game loop for Excalibur after loading
25756
26117
  * any provided assets.
25757
26118
  * @param loader Optional [[Loader]] to use to load resources. The default loader is [[Loader]], override to provide your own
25758
26119
  * custom loader.
26120
+ *
26121
+ * Note: start() only resolves AFTER the user has clicked the play button
25759
26122
  */
25760
- start(loader) {
26123
+ async start(loader) {
25761
26124
  if (!this._compatible) {
25762
- return Promise.reject('Excalibur is incompatible with your browser');
25763
- }
25764
- let loadingComplete;
25765
- // Push the current user entered resolution/viewport
25766
- this.screen.pushResolutionAndViewport();
25767
- // Configure resolution for loader
25768
- this.screen.resolution = this.screen.viewport;
25769
- this.screen.applyResolutionAndViewport();
25770
- this.graphicsContext.updateViewport();
26125
+ throw new Error('Excalibur is incompatible with your browser');
26126
+ }
26127
+ // Wire loader if we have it
25771
26128
  if (loader) {
26129
+ // Push the current user entered resolution/viewport
26130
+ this.screen.pushResolutionAndViewport();
26131
+ // Configure resolution for loader, it expects resolution === viewport
26132
+ this.screen.resolution = this.screen.viewport;
26133
+ this.screen.applyResolutionAndViewport();
26134
+ this.graphicsContext.updateViewport();
25772
26135
  this._loader = loader;
25773
26136
  this._loader.suppressPlayButton = this._suppressPlayButton || this._loader.suppressPlayButton;
25774
26137
  this._loader.wireEngine(this);
25775
- loadingComplete = this.load(this._loader);
25776
26138
  }
25777
- else {
25778
- loadingComplete = Promise.resolve();
25779
- }
25780
- loadingComplete.then(() => {
26139
+ // Start the excalibur clock which drives the mainloop
26140
+ // has started is a slight misnomer, it's really mainloop started
26141
+ this._logger.debug('Starting game clock...');
26142
+ this.browser.resume();
26143
+ this.clock.start();
26144
+ this._logger.debug('Game clock started');
26145
+ if (loader) {
26146
+ await this.load(this._loader);
26147
+ this._loadingComplete = true;
26148
+ // reset back to previous user resolution/viewport
25781
26149
  this.screen.popResolutionAndViewport();
25782
26150
  this.screen.applyResolutionAndViewport();
25783
26151
  this.graphicsContext.updateViewport();
25784
- this.emit('start', new GameStartEvent(this));
25785
- this._loadingComplete = true;
25786
- });
25787
- if (!this._hasStarted) {
25788
- // has started is a slight misnomer, it's really mainloop started
25789
- this._hasStarted = true;
25790
- this._logger.debug('Starting game...');
25791
- this.browser.resume();
25792
- Engine.createMainLoop(this, window.requestAnimationFrame, Date.now)();
25793
- this._logger.debug('Game started');
25794
- }
25795
- else {
25796
- // Game already started;
25797
26152
  }
25798
- return loadingComplete;
26153
+ this._loadingComplete = true;
26154
+ // Initialize before ready
26155
+ this._overrideInitialize(this);
26156
+ this._isReady = true;
26157
+ this._isReadyResolve();
26158
+ this.emit('start', new GameStartEvent(this));
26159
+ return this._isReadyPromise;
26160
+ }
26161
+ _mainloop(elapsed) {
26162
+ this.emit('preframe', new PreFrameEvent(this, this.stats.prevFrame));
26163
+ const delta = elapsed * this.timescale;
26164
+ // reset frame stats (reuse existing instances)
26165
+ const frameId = this.stats.prevFrame.id + 1;
26166
+ this.stats.currFrame.reset();
26167
+ this.stats.currFrame.id = frameId;
26168
+ this.stats.currFrame.delta = delta;
26169
+ this.stats.currFrame.fps = this.clock.fpsSampler.fps;
26170
+ const beforeUpdate = this.clock.now();
26171
+ this._update(delta);
26172
+ const afterUpdate = this.clock.now();
26173
+ this._draw(delta);
26174
+ const afterDraw = this.clock.now();
26175
+ this.stats.currFrame.duration.update = afterUpdate - beforeUpdate;
26176
+ this.stats.currFrame.duration.draw = afterDraw - afterUpdate;
26177
+ this.emit('postframe', new PostFrameEvent(this, this.stats.currFrame));
25799
26178
  }
26179
+ /**
26180
+ *
26181
+ * @param game
26182
+ * @param raf
26183
+ * @param nowFn
26184
+ * @deprecated Use [[Clock]] to run the mainloop, will be removed in v0.26.0
26185
+ */
25800
26186
  static createMainLoop(game, raf, nowFn) {
25801
26187
  let lastTime = nowFn();
26188
+ const fpsSampler = new FpsSampler({
26189
+ nowFn,
26190
+ initialFps: game.maxFps === Infinity ? 60 : game.maxFps
26191
+ });
25802
26192
  return function mainloop() {
25803
26193
  if (!game._hasStarted) {
25804
26194
  return;
25805
26195
  }
25806
26196
  try {
25807
26197
  game._requestId = raf(mainloop);
26198
+ fpsSampler.start();
25808
26199
  game.emit('preframe', new PreFrameEvent(game, game.stats.prevFrame));
25809
26200
  // Get the time to calculate time-elapsed
25810
26201
  const now = nowFn();
25811
- let elapsed = Math.floor(now - lastTime) || 1;
26202
+ let elapsed = now - lastTime || 1; // first frame
26203
+ // Constrain fps
26204
+ const fpsInterval = game.maxFps === Number.POSITIVE_INFINITY ? 0 : 1000 / game.maxFps;
26205
+ if (elapsed <= fpsInterval) {
26206
+ return; // too fast 😎 skip this frame
26207
+ }
25812
26208
  // Resolves issue #138 if the game has been paused, or blurred for
25813
26209
  // more than a 200 milliseconds, reset elapsed time to 1. This improves reliability
25814
26210
  // and provides more expected behavior when the engine comes back
@@ -25822,7 +26218,7 @@ O|===|* >________________>\n\
25822
26218
  game.stats.currFrame.reset();
25823
26219
  game.stats.currFrame.id = frameId;
25824
26220
  game.stats.currFrame.delta = delta;
25825
- game.stats.currFrame.fps = 1.0 / (delta / 1000);
26221
+ game.stats.currFrame.fps = fpsSampler.fps;
25826
26222
  const beforeUpdate = nowFn();
25827
26223
  game._update(delta);
25828
26224
  const afterUpdate = nowFn();
@@ -25830,8 +26226,15 @@ O|===|* >________________>\n\
25830
26226
  const afterDraw = nowFn();
25831
26227
  game.stats.currFrame.duration.update = afterUpdate - beforeUpdate;
25832
26228
  game.stats.currFrame.duration.draw = afterDraw - afterUpdate;
25833
- lastTime = now;
26229
+ // if fps interval is not a multple
26230
+ if (fpsInterval > 0) {
26231
+ lastTime = now - (elapsed % fpsInterval);
26232
+ }
26233
+ else {
26234
+ lastTime = now;
26235
+ }
25834
26236
  game.emit('postframe', new PostFrameEvent(game, game.stats.currFrame));
26237
+ fpsSampler.end();
25835
26238
  game.stats.prevFrame.reset(game.stats.currFrame);
25836
26239
  }
25837
26240
  catch (e) {
@@ -25845,10 +26248,10 @@ O|===|* >________________>\n\
25845
26248
  * Stops Excalibur's main loop, useful for pausing the game.
25846
26249
  */
25847
26250
  stop() {
25848
- if (this._hasStarted) {
26251
+ if (this.clock.isRunning()) {
25849
26252
  this.emit('stop', new GameStopEvent(this));
25850
26253
  this.browser.pause();
25851
- this._hasStarted = false;
26254
+ this.clock.stop();
25852
26255
  this._logger.debug('Game stopped');
25853
26256
  }
25854
26257
  }
@@ -25856,7 +26259,7 @@ O|===|* >________________>\n\
25856
26259
  * Returns the Engine's Running status, Useful for checking whether engine is running or paused.
25857
26260
  */
25858
26261
  isPaused() {
25859
- return !this._hasStarted;
26262
+ return !this.clock.isRunning();
25860
26263
  }
25861
26264
  /**
25862
26265
  * Takes a screen shot of the current viewport and returns it as an
@@ -25874,24 +26277,13 @@ O|===|* >________________>\n\
25874
26277
  * will appear.
25875
26278
  * @param loader Some [[Loadable]] such as a [[Loader]] collection, [[Sound]], or [[Texture]].
25876
26279
  */
25877
- load(loader) {
25878
- const complete = new Promise((resolve) => {
25879
- this._isLoading = true;
25880
- loader.load().then(() => {
25881
- if (this._suppressPlayButton) {
25882
- setTimeout(() => {
25883
- this._isLoading = false;
25884
- resolve();
25885
- // Delay is to give the logo a chance to show, otherwise don't delay
25886
- }, 500);
25887
- }
25888
- else {
25889
- this._isLoading = false;
25890
- resolve();
25891
- }
25892
- });
25893
- });
25894
- return complete;
26280
+ async load(loader) {
26281
+ try {
26282
+ await loader.load();
26283
+ }
26284
+ catch (_a) {
26285
+ await Promise.resolve();
26286
+ }
25895
26287
  }
25896
26288
  }
25897
26289
  /**
@@ -26070,13 +26462,25 @@ class Font extends Raster {
26070
26462
  this.flagDirty();
26071
26463
  }
26072
26464
  clone() {
26073
- return new Font(Object.assign(Object.assign(Object.assign({}, this.cloneGraphicOptions()), this.cloneRasterOptions()), { size: this.size, unit: this.unit, family: this.family, style: this.style, bold: this.bold, textAlign: this.textAlign, baseAlign: this.baseAlign, direction: this.direction, shadow: this.shadow
26465
+ return new Font({
26466
+ ...this.cloneGraphicOptions(),
26467
+ ...this.cloneRasterOptions(),
26468
+ size: this.size,
26469
+ unit: this.unit,
26470
+ family: this.family,
26471
+ style: this.style,
26472
+ bold: this.bold,
26473
+ textAlign: this.textAlign,
26474
+ baseAlign: this.baseAlign,
26475
+ direction: this.direction,
26476
+ shadow: this.shadow
26074
26477
  ? {
26075
26478
  blur: this.shadow.blur,
26076
26479
  offset: this.shadow.offset,
26077
26480
  color: this.shadow.color
26078
26481
  }
26079
- : null }));
26482
+ : null
26483
+ });
26080
26484
  }
26081
26485
  get fontString() {
26082
26486
  return `${this.style} ${this.bold ? 'bold' : ''} ${this.size}${this.unit} ${this.family}`;
@@ -26766,7 +27170,17 @@ let Polygon = class Polygon {
26766
27170
  }
26767
27171
  _drawWithOptions(options) {
26768
27172
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
26769
- const { ctx, x, y, rotation, drawWidth, drawHeight, anchor, offset, opacity, flipHorizontal, flipVertical } = Object.assign(Object.assign({}, options), { rotation: (_a = options.rotation) !== null && _a !== void 0 ? _a : this.rotation, drawWidth: (_b = options.drawWidth) !== null && _b !== void 0 ? _b : this.drawWidth, drawHeight: (_c = options.drawHeight) !== null && _c !== void 0 ? _c : this.drawHeight, flipHorizontal: (_d = options.flipHorizontal) !== null && _d !== void 0 ? _d : this.flipHorizontal, flipVertical: (_e = options.flipVertical) !== null && _e !== void 0 ? _e : this.flipVertical, anchor: (_f = options.anchor) !== null && _f !== void 0 ? _f : this.anchor, offset: (_g = options.offset) !== null && _g !== void 0 ? _g : this.offset, opacity: ((_h = options.opacity) !== null && _h !== void 0 ? _h : 1) * ((_j = this.opacity) !== null && _j !== void 0 ? _j : 1) });
27173
+ const { ctx, x, y, rotation, drawWidth, drawHeight, anchor, offset, opacity, flipHorizontal, flipVertical } = {
27174
+ ...options,
27175
+ rotation: (_a = options.rotation) !== null && _a !== void 0 ? _a : this.rotation,
27176
+ drawWidth: (_b = options.drawWidth) !== null && _b !== void 0 ? _b : this.drawWidth,
27177
+ drawHeight: (_c = options.drawHeight) !== null && _c !== void 0 ? _c : this.drawHeight,
27178
+ flipHorizontal: (_d = options.flipHorizontal) !== null && _d !== void 0 ? _d : this.flipHorizontal,
27179
+ flipVertical: (_e = options.flipVertical) !== null && _e !== void 0 ? _e : this.flipVertical,
27180
+ anchor: (_f = options.anchor) !== null && _f !== void 0 ? _f : this.anchor,
27181
+ offset: (_g = options.offset) !== null && _g !== void 0 ? _g : this.offset,
27182
+ opacity: ((_h = options.opacity) !== null && _h !== void 0 ? _h : 1) * ((_j = this.opacity) !== null && _j !== void 0 ? _j : 1)
27183
+ };
26770
27184
  const xpoint = drawWidth * anchor.x + offset.x + x;
26771
27185
  const ypoint = drawHeight * anchor.y + offset.y + y;
26772
27186
  ctx.save();
@@ -27088,15 +27502,6 @@ function canPlayFile(file) {
27088
27502
  }
27089
27503
 
27090
27504
  ;// CONCATENATED MODULE: ./Resources/Sound/Sound.ts
27091
- var Sound_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
27092
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27093
- return new (P || (P = Promise))(function (resolve, reject) {
27094
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
27095
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
27096
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
27097
- step((generator = generator.apply(thisArg, _arguments || [])).next());
27098
- });
27099
- };
27100
27505
 
27101
27506
 
27102
27507
 
@@ -27187,30 +27592,26 @@ class Sound extends Class {
27187
27592
  isLoaded() {
27188
27593
  return !!this.data;
27189
27594
  }
27190
- load() {
27191
- return Sound_awaiter(this, void 0, void 0, function* () {
27192
- if (this.data) {
27193
- return this.data;
27194
- }
27195
- const arraybuffer = yield this._resource.load();
27196
- const audiobuffer = yield this.decodeAudio(arraybuffer.slice(0));
27197
- this._duration = typeof audiobuffer === 'object' ? audiobuffer.duration : undefined;
27198
- this.emit('processed', new NativeSoundProcessedEvent(this, audiobuffer));
27199
- return this.data = audiobuffer;
27200
- });
27595
+ async load() {
27596
+ if (this.data) {
27597
+ return this.data;
27598
+ }
27599
+ const arraybuffer = await this._resource.load();
27600
+ const audiobuffer = await this.decodeAudio(arraybuffer.slice(0));
27601
+ this._duration = typeof audiobuffer === 'object' ? audiobuffer.duration : undefined;
27602
+ this.emit('processed', new NativeSoundProcessedEvent(this, audiobuffer));
27603
+ return this.data = audiobuffer;
27201
27604
  }
27202
- decodeAudio(data) {
27203
- return Sound_awaiter(this, void 0, void 0, function* () {
27204
- try {
27205
- return yield this._audioContext.decodeAudioData(data.slice(0));
27206
- }
27207
- catch (e) {
27208
- this.logger.error('Unable to decode ' +
27209
- ' this browser may not fully support this format, or the file may be corrupt, ' +
27210
- 'if this is an mp3 try removing id3 tags and album art from the file.');
27211
- return yield Promise.reject();
27212
- }
27213
- });
27605
+ async decodeAudio(data) {
27606
+ try {
27607
+ return await this._audioContext.decodeAudioData(data.slice(0));
27608
+ }
27609
+ catch (e) {
27610
+ this.logger.error('Unable to decode ' +
27611
+ ' this browser may not fully support this format, or the file may be corrupt, ' +
27612
+ 'if this is an mp3 try removing id3 tags and album art from the file.');
27613
+ return await Promise.reject();
27614
+ }
27214
27615
  }
27215
27616
  wireEngine(engine) {
27216
27617
  if (engine) {
@@ -27302,38 +27703,34 @@ class Sound extends Class {
27302
27703
  getTrackId(track) {
27303
27704
  return this._tracks.indexOf(track);
27304
27705
  }
27305
- _resumePlayback() {
27306
- return Sound_awaiter(this, void 0, void 0, function* () {
27307
- if (this._isPaused) {
27308
- const resumed = [];
27309
- // ensure we resume *current* tracks (if paused)
27310
- for (const track of this._tracks) {
27311
- resumed.push(track.play());
27312
- }
27313
- this._isPaused = false;
27314
- this.emit('resume', new NativeSoundEvent(this));
27315
- this.logger.debug('Resuming paused instances for sound', this.path, this._tracks);
27316
- // resolve when resumed tracks are done
27317
- yield Promise.all(resumed);
27706
+ async _resumePlayback() {
27707
+ if (this._isPaused) {
27708
+ const resumed = [];
27709
+ // ensure we resume *current* tracks (if paused)
27710
+ for (const track of this._tracks) {
27711
+ resumed.push(track.play());
27318
27712
  }
27319
- return true;
27320
- });
27713
+ this._isPaused = false;
27714
+ this.emit('resume', new NativeSoundEvent(this));
27715
+ this.logger.debug('Resuming paused instances for sound', this.path, this._tracks);
27716
+ // resolve when resumed tracks are done
27717
+ await Promise.all(resumed);
27718
+ }
27719
+ return true;
27321
27720
  }
27322
27721
  /**
27323
27722
  * Starts playback, returns a promise that resolves when playback is complete
27324
27723
  */
27325
- _startPlayback() {
27326
- return Sound_awaiter(this, void 0, void 0, function* () {
27327
- const track = yield this._getTrackInstance(this.data);
27328
- const complete = yield track.play(() => {
27329
- this.emit('playbackstart', new NativeSoundEvent(this, track));
27330
- this.logger.debug('Playing new instance for sound', this.path);
27331
- });
27332
- // when done, remove track
27333
- this.emit('playbackend', new NativeSoundEvent(this, track));
27334
- this._tracks.splice(this.getTrackId(track), 1);
27335
- return complete;
27724
+ async _startPlayback() {
27725
+ const track = await this._getTrackInstance(this.data);
27726
+ const complete = await track.play(() => {
27727
+ this.emit('playbackstart', new NativeSoundEvent(this, track));
27728
+ this.logger.debug('Playing new instance for sound', this.path);
27336
27729
  });
27730
+ // when done, remove track
27731
+ this.emit('playbackend', new NativeSoundEvent(this, track));
27732
+ this._tracks.splice(this.getTrackId(track), 1);
27733
+ return complete;
27337
27734
  }
27338
27735
  _getTrackInstance(data) {
27339
27736
  const newTrack = new WebAudioInstance(data);
@@ -27351,15 +27748,6 @@ class Sound extends Class {
27351
27748
 
27352
27749
 
27353
27750
  ;// CONCATENATED MODULE: ./Resources/Gif.ts
27354
- var Gif_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
27355
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27356
- return new (P || (P = Promise))(function (resolve, reject) {
27357
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
27358
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
27359
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
27360
- step((generator = generator.apply(thisArg, _arguments || [])).next());
27361
- });
27362
- };
27363
27751
 
27364
27752
 
27365
27753
 
@@ -27393,16 +27781,14 @@ class Gif {
27393
27781
  /**
27394
27782
  * Begins loading the texture and returns a promise to be resolved on completion
27395
27783
  */
27396
- load() {
27397
- return Gif_awaiter(this, void 0, void 0, function* () {
27398
- const arraybuffer = yield this._resource.load();
27399
- this._stream = new Stream(arraybuffer);
27400
- this._gif = new ParseGif(this._stream, this._transparentColor);
27401
- const images = this._gif.images.map(i => new ImageSource(i.src, false));
27402
- // Load all textures
27403
- yield Promise.all(images.map(t => t.load()));
27404
- return this.data = this._textures = images;
27405
- });
27784
+ async load() {
27785
+ const arraybuffer = await this._resource.load();
27786
+ this._stream = new Stream(arraybuffer);
27787
+ this._gif = new ParseGif(this._stream, this._transparentColor);
27788
+ const images = this._gif.images.map(i => new ImageSource(i.src, false));
27789
+ // Load all textures
27790
+ await Promise.all(images.map(t => t.load()));
27791
+ return this.data = this._textures = images;
27406
27792
  }
27407
27793
  isLoaded() {
27408
27794
  return !!this.data;
@@ -27886,7 +28272,11 @@ class Polygon_Polygon extends Raster {
27886
28272
  return vec(minX, minY);
27887
28273
  }
27888
28274
  clone() {
27889
- return new Polygon_Polygon(Object.assign(Object.assign({ points: this.points.map((p) => p.clone()) }, this.cloneGraphicOptions()), this.cloneRasterOptions()));
28275
+ return new Polygon_Polygon({
28276
+ points: this.points.map((p) => p.clone()),
28277
+ ...this.cloneGraphicOptions(),
28278
+ ...this.cloneRasterOptions()
28279
+ });
27890
28280
  }
27891
28281
  execute(ctx) {
27892
28282
  if (this.points && this.points.length) {
@@ -28446,7 +28836,7 @@ Promises_Promise = Promise_1 = Promises_decorate([
28446
28836
  * The current Excalibur version string
28447
28837
  * @description `process.env.__EX_VERSION` gets replaced by Webpack on build
28448
28838
  */
28449
- const EX_VERSION = "0.26.0-alpha.310+5f94c2f";
28839
+ const EX_VERSION = "0.26.0-alpha.311+c19e8da";
28450
28840
 
28451
28841
  polyfill();
28452
28842
  // This file is used as the bundle entry point and exports everything
@@ -28508,6 +28898,9 @@ polyfill();
28508
28898
 
28509
28899
 
28510
28900
 
28901
+
28902
+
28903
+
28511
28904
  // ex.Deprecated
28512
28905
 
28513
28906
  // import * as deprecated from './Deprecated';