melonjs 10.11.0 → 12.0.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 (39) hide show
  1. package/README.md +2 -0
  2. package/dist/melonjs.js +2949 -2795
  3. package/dist/melonjs.min.js +4 -4
  4. package/dist/melonjs.module.d.ts +208 -135
  5. package/dist/melonjs.module.js +2917 -2772
  6. package/package.json +11 -10
  7. package/src/audio/audio.js +5 -5
  8. package/src/entity/entity.js +5 -7
  9. package/src/geometries/ellipse.js +1 -1
  10. package/src/geometries/path2d.js +4 -4
  11. package/src/geometries/poly.js +1 -2
  12. package/src/geometries/rectangle.js +1 -1
  13. package/src/loader/loadingscreen.js +17 -103
  14. package/src/loader/melonjs_logo.png +0 -0
  15. package/src/physics/body.js +3 -4
  16. package/src/physics/collision.js +1 -12
  17. package/src/physics/detector.js +6 -52
  18. package/src/physics/response.js +48 -0
  19. package/src/physics/sat.js +1 -1
  20. package/src/polyfill/index.js +4 -0
  21. package/src/renderable/GUI.js +6 -4
  22. package/src/renderable/colorlayer.js +9 -7
  23. package/src/renderable/container.js +12 -10
  24. package/src/renderable/dragndrop.js +1 -1
  25. package/src/renderable/imagelayer.js +5 -5
  26. package/src/renderable/light2d.js +47 -14
  27. package/src/renderable/renderable.js +6 -6
  28. package/src/renderable/sprite.js +4 -4
  29. package/src/renderable/trigger.js +9 -2
  30. package/src/state/state.js +19 -3
  31. package/src/system/device.js +3 -67
  32. package/src/system/dom.js +69 -0
  33. package/src/system/event.js +11 -0
  34. package/src/system/pooling.js +1 -1
  35. package/src/text/bitmaptext.js +1 -2
  36. package/src/text/text.js +7 -5
  37. package/src/text/textmetrics.js +1 -2
  38. package/src/utils/string.js +0 -24
  39. package/src/video/texture/atlas.js +2 -0
@@ -198,7 +198,7 @@ export class DropTarget extends Renderable {
198
198
  * @memberof DropTarget
199
199
  * @param {Draggable} draggable the draggable object that is dropped
200
200
  */
201
- drop() {
201
+ drop(draggable) { // eslint-disable-line no-unused-vars
202
202
 
203
203
  }
204
204
 
@@ -164,7 +164,7 @@ class ImageLayer extends Sprite {
164
164
  * @param {number} h new height
165
165
  */
166
166
  resize(w, h) {
167
- super.resize(
167
+ return super.resize(
168
168
  this.repeatX ? Infinity : w,
169
169
  this.repeatY ? Infinity : h
170
170
  );
@@ -243,14 +243,14 @@ class ImageLayer extends Sprite {
243
243
  }
244
244
 
245
245
  /**
246
- * draw the ImageLayer. <br>
247
- * automatically called by the game manager {@link game}
246
+ * draw this ImageLayer (automatically called by melonJS)
248
247
  * @name draw
249
248
  * @memberof ImageLayer
250
249
  * @protected
251
- * @param {CanvasRenderer|WebGLRenderer} renderer a renderer object
250
+ * @param {CanvasRenderer|WebGLRenderer} renderer a renderer instance
251
+ * @param {Camera2d} [viewport] the viewport to (re)draw
252
252
  */
253
- draw(renderer) {
253
+ draw(renderer, viewport) {
254
254
  var width = this.width,
255
255
  height = this.height,
256
256
  bw = viewport.bounds.width,
@@ -4,19 +4,41 @@ import Renderable from "./renderable.js";
4
4
  /** @ignore */
5
5
  function createGradient(light) {
6
6
  var context = light.texture.context;
7
- var x1 = light.texture.width / 2;
8
- var y1 = light.texture.height / 2;
9
- var gradient = context.createRadialGradient(x1, y1, 0, x1, y1, light.radius);
7
+
8
+ var x1 = light.texture.width / 2,
9
+ y1 = light.texture.height / 2;
10
+
11
+ var radiusX = light.radiusX,
12
+ radiusY = light.radiusY;
13
+
14
+ var scaleX, scaleY, invScaleX, invScaleY;
15
+ var gradient;
16
+
10
17
 
11
18
  light.texture.clear();
12
19
 
20
+ if (radiusX >= radiusY) {
21
+ scaleX = 1;
22
+ invScaleX = 1;
23
+ scaleY = radiusY/radiusX;
24
+ invScaleY = radiusX/radiusY;
25
+ gradient = context.createRadialGradient(x1, y1 * invScaleY, 0, x1, radiusY * invScaleY, radiusX);
26
+ }
27
+ else {
28
+ scaleY = 1;
29
+ invScaleY = 1;
30
+ scaleX = radiusX/radiusY;
31
+ invScaleX = radiusY/radiusX;
32
+ gradient = context.createRadialGradient(x1 * invScaleX, y1, 0, x1 * invScaleX, y1, radiusY);
33
+ }
34
+
13
35
  gradient.addColorStop( 0, light.color.toRGBA(light.intensity));
14
36
  gradient.addColorStop( 1, light.color.toRGBA(0.0));
15
37
 
16
- context.beginPath();
17
38
  context.fillStyle = gradient;
18
- context.arc(x1, y1, light.radius, 0, Math.PI * 2, false);
19
- context.fill();
39
+
40
+ context.setTransform(scaleX, 0, 0, scaleY, 0, 0);
41
+ context.fillRect(0, 0, light.texture.width * invScaleX, light.texture.height * invScaleY);
20
42
  }
21
43
 
22
44
  /**
@@ -31,13 +53,14 @@ class Light2d extends Renderable {
31
53
  /**
32
54
  * @param {number} x - The horizontal position of the light.
33
55
  * @param {number} y - The vertical position of the light.
34
- * @param {number} radius - The radius of the light.
56
+ * @param {number} radiusX - The horizontal radius of the light.
57
+ * @param {number} [radiusY=radiusX] - The vertical radius of the light.
35
58
  * @param {Color|string} [color="#FFF"] the color of the light
36
59
  * @param {number} [intensity=0.7] - The intensity of the light.
37
60
  */
38
- constructor(x, y, radius, color = "#FFF", intensity = 0.7) {
61
+ constructor(x, y, radiusX, radiusY = radiusX, color = "#FFF", intensity = 0.7) {
39
62
  // call the parent constructor
40
- super(x, y, radius * 2, radius * 2);
63
+ super(x, y, radiusX * 2, radiusY * 2);
41
64
 
42
65
  /**
43
66
  * the color of the light
@@ -47,10 +70,16 @@ class Light2d extends Renderable {
47
70
  this.color = pool.pull("Color").parseCSS(color);
48
71
 
49
72
  /**
50
- * The radius of the light
73
+ * The horizontal radius of the light
51
74
  * @type {number}
52
75
  */
53
- this.radius = radius;
76
+ this.radiusX = radiusX;
77
+
78
+ /**
79
+ * The vertical radius of the light
80
+ * @type {number}
81
+ */
82
+ this.radiusY = radiusY;
54
83
 
55
84
  /**
56
85
  * The intensity of the light
@@ -90,10 +119,14 @@ class Light2d extends Renderable {
90
119
  }
91
120
 
92
121
  /**
93
- * object draw (Called internally by the engine).
94
- * @ignore
122
+ * draw this Light2d (automatically called by melonJS)
123
+ * @name draw
124
+ * @memberof Light2d
125
+ * @protected
126
+ * @param {CanvasRenderer|WebGLRenderer} renderer a renderer instance
127
+ * @param {Camera2d} [viewport] the viewport to (re)draw
95
128
  */
96
- draw(renderer) {
129
+ draw(renderer, viewport) { // eslint-disable-line no-unused-vars
97
130
  renderer.drawImage(this.texture.canvas, this.getBounds().x, this.getBounds().y);
98
131
  }
99
132
 
@@ -735,14 +735,14 @@ class Renderable extends Rect {
735
735
  }
736
736
 
737
737
  /**
738
- * object draw. <br>
739
- * automatically called by the game manager {@link game}
738
+ * draw this renderable (automatically called by melonJS)
740
739
  * @name draw
741
740
  * @memberof Renderable
742
741
  * @protected
743
- * @param {CanvasRenderer|WebGLRenderer} renderer a renderer object
742
+ * @param {CanvasRenderer|WebGLRenderer} renderer a renderer instance
743
+ * @param {Camera2d} [viewport] the viewport to (re)draw
744
744
  */
745
- draw(renderer) { // eslint-disable-line no-unused-vars
745
+ draw(renderer, viewport) { // eslint-disable-line no-unused-vars
746
746
  // empty one !
747
747
  }
748
748
 
@@ -775,7 +775,7 @@ class Renderable extends Rect {
775
775
  * when this renderable body is colliding with another one
776
776
  * @name onCollision
777
777
  * @memberof Renderable
778
- * @param {collision.ResponseObject} response the collision response object
778
+ * @param {ResponseObject} response the collision response object
779
779
  * @param {Renderable} other the other renderable touching this one (a reference to response.a or response.b)
780
780
  * @returns {boolean} true if the object should respond to the collision (its position and velocity will be corrected)
781
781
  * @example
@@ -792,7 +792,7 @@ class Renderable extends Rect {
792
792
  * return true;
793
793
  * },
794
794
  */
795
- onCollision() {
795
+ onCollision(response, other) { // eslint-disable-line no-unused-vars
796
796
  return false;
797
797
  }
798
798
 
@@ -586,14 +586,14 @@ class Sprite extends Renderable {
586
586
  }
587
587
 
588
588
  /**
589
- * sprite draw. <br>
590
- * automatically called by the game manager {@link game}
589
+ * draw this srite (automatically called by melonJS)
591
590
  * @name draw
592
591
  * @memberof Sprite
593
592
  * @protected
594
- * @param {CanvasRenderer|WebGLRenderer} renderer a renderer object
593
+ * @param {CanvasRenderer|WebGLRenderer} renderer a renderer instance
594
+ * @param {Camera2d} [viewport] the viewport to (re)draw
595
595
  */
596
- draw(renderer) {
596
+ draw(renderer, viewport) { // eslint-disable-line no-unused-vars
597
597
  // do nothing if we are flickering
598
598
  if (this._flicker.isFlickering) {
599
599
  this._flicker.state = !this._flicker.state;
@@ -129,8 +129,15 @@ class Trigger extends Renderable {
129
129
  }
130
130
  }
131
131
 
132
- /** @ignore */
133
- onCollision() {
132
+ /**
133
+ * onCollision callback, triggered in case of collision with this trigger
134
+ * @name onCollision
135
+ * @memberof Trigger
136
+ * @param {ResponseObject} response the collision response object
137
+ * @param {Renderable} other the other renderable touching this one (a reference to response.a or response.b)
138
+ * @returns {boolean} true if the object should respond to the collision (its position and velocity will be corrected)
139
+ */
140
+ onCollision(response, other) { // eslint-disable-line no-unused-vars
134
141
  if (this.name === "Trigger") {
135
142
  this.triggerEvent.apply(this);
136
143
  }
@@ -426,6 +426,24 @@ var state = {
426
426
  }
427
427
  },
428
428
 
429
+ /**
430
+ * returns the stage associated with the specified state
431
+ * (or the current one if none is specified)
432
+ * @name set
433
+ * @memberof state
434
+ * @public
435
+ * @param {number} [state] State ID (see constants)
436
+ * @returns {Stage}
437
+ */
438
+ get(state = _state) {
439
+ if (typeof _stages[state] !== "undefined") {
440
+ return _stages[state].stage;
441
+ } else {
442
+ return undefined;
443
+ }
444
+
445
+ },
446
+
429
447
  /**
430
448
  * return a reference to the current stage<br>
431
449
  * useful to call a object specific method
@@ -435,9 +453,7 @@ var state = {
435
453
  * @returns {Stage}
436
454
  */
437
455
  current() {
438
- if (typeof _stages[_state] !== "undefined") {
439
- return _stages[_state].stage;
440
- }
456
+ return this.get();
441
457
  },
442
458
 
443
459
  /**
@@ -4,6 +4,7 @@ import save from "./save.js";
4
4
  import { prefixed } from "./../utils/agent.js";
5
5
  import state from "./../state/state.js";
6
6
  import * as event from "./event.js";
7
+ import { DOMContentLoaded } from "./dom.js";
7
8
 
8
9
  // private properties
9
10
  let accelInitialized = false;
@@ -23,45 +24,6 @@ function _disableSwipeFn(e) {
23
24
  return false;
24
25
  };
25
26
 
26
- // DOM loading stuff
27
- let readyBound = false, isReady = false, readyList = [];
28
-
29
- /**
30
- * // called to check if the device is ready
31
- * @ignore
32
- */
33
- function _domReady() {
34
- // Make sure that the DOM is not already loaded
35
- if (!isReady) {
36
- // be sure document.body is there
37
- if (typeof globalThis.document !== "undefined" && !globalThis.document.body) {
38
- return setTimeout(_domReady, 13);
39
- }
40
-
41
- // clean up loading event
42
- if (typeof globalThis.document !== "undefined" && typeof globalThis.document.removeEventListener === "function") {
43
- globalThis.document.removeEventListener(
44
- "DOMContentLoaded",
45
- this._domReady,
46
- false
47
- );
48
- }
49
-
50
- if (typeof globalThis.removeEventListener === "function") {
51
- // remove the event on globalThis.onload (always added in `onReady`)
52
- globalThis.removeEventListener("load", _domReady, false);
53
- }
54
-
55
- // execute all callbacks
56
- while (readyList.length) {
57
- readyList.shift().call(globalThis, []);
58
- }
59
-
60
- // Remember that the DOM is ready
61
- isReady = true;
62
- }
63
- };
64
-
65
27
  // a cache DOMRect object
66
28
  let _domRect = {left: 0, top: 0, x: 0, y: 0, width: 0, height: 0, right: 0, bottom: 0};
67
29
 
@@ -418,7 +380,7 @@ let device = {
418
380
  * @readonly
419
381
  * @name nodeJS
420
382
  */
421
- nodeJS : (typeof process !== "undefined") && (process.release.name === "node"),
383
+ nodeJS : (typeof globalThis.process !== "undefined") && (typeof globalThis.process.release !== "undefined") && (globalThis.process.release.name === "node"),
422
384
 
423
385
  /**
424
386
  * equals to true if the device is running on ChromeOS.
@@ -606,33 +568,7 @@ let device = {
606
568
  * });
607
569
  */
608
570
  onReady(fn) {
609
- // If the DOM is already ready
610
- if (isReady) {
611
- // Execute the function immediately
612
- fn.call(globalThis, []);
613
- }
614
- else {
615
- // Add the function to the wait list
616
- readyList.push(fn);
617
-
618
- // attach listeners if not yet done
619
- if (!readyBound) {
620
- // directly call domReady if document is already "ready"
621
- if (device.nodeJS === true || (typeof globalThis.document !== "undefined" && globalThis.document.readyState === "complete")) {
622
- // defer the fn call to ensure our script is fully loaded
623
- globalThis.setTimeout(_domReady, 0);
624
- }
625
- else {
626
- if (typeof globalThis.document !== "undefined" && typeof globalThis.document.addEventListener === "function") {
627
- // Use the handy event callback
628
- globalThis.document.addEventListener("DOMContentLoaded", _domReady, false);
629
- }
630
- // A fallback to globalThis.onload, that will always work
631
- globalThis.addEventListener("load", _domReady, false);
632
- }
633
- readyBound = true;
634
- }
635
- }
571
+ DOMContentLoaded(fn);
636
572
  },
637
573
 
638
574
  /**
@@ -0,0 +1,69 @@
1
+ import * as event from "./event.js";
2
+
3
+ // track if DOMContentLoaded was called already
4
+ let readyBound = false;
5
+
6
+ // is the DOM ready ?
7
+ let isDOMReady = false;
8
+
9
+ // check if the dom is ready
10
+ function _domReady() {
11
+
12
+ // Make sure that the DOM is not already loaded
13
+ if (!isDOMReady) {
14
+ // be sure document.body is there
15
+ if (typeof globalThis.document !== "undefined" && !globalThis.document.body) {
16
+ return setTimeout(_domReady, 13);
17
+ }
18
+
19
+ // clean up loading event
20
+ if (typeof globalThis.document !== "undefined" && typeof globalThis.document.removeEventListener === "function") {
21
+ globalThis.document.removeEventListener(
22
+ "DOMContentLoaded",
23
+ _domReady,
24
+ false
25
+ );
26
+ }
27
+
28
+ if (typeof globalThis.removeEventListener === "function") {
29
+ // remove the event on globalThis.onload (always added in `onReady`)
30
+ globalThis.removeEventListener("load", _domReady, false);
31
+ }
32
+
33
+ // execute all callbacks
34
+ event.emit(event.DOM_READY);
35
+
36
+ // Remember that the DOM is ready
37
+ isDOMReady = true;
38
+ }
39
+ };
40
+
41
+ // https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded_event
42
+ export function DOMContentLoaded(fn) {
43
+ // If the DOM is already ready
44
+ if (isDOMReady) {
45
+ // Execute the function immediately
46
+ fn.call(globalThis, []);
47
+ }
48
+ else {
49
+ // else add the function to the DOM_READY event
50
+ event.once(event.DOM_READY, fn, globalThis);
51
+ // bind dom load event if not done yet
52
+ if (!readyBound) {
53
+ // directly call domReady if document is already "ready"
54
+ if (((typeof process !== "undefined") && (process.release.name === "node")) || (typeof globalThis.document !== "undefined" && globalThis.document.readyState === "complete")) {
55
+ // defer the fn call to ensure our script is fully loaded
56
+ globalThis.setTimeout(_domReady, 0);
57
+ }
58
+ else {
59
+ if (typeof globalThis.document !== "undefined" && typeof globalThis.document.addEventListener === "function") {
60
+ // Use the handy event callback
61
+ globalThis.document.addEventListener("DOMContentLoaded", _domReady, false);
62
+ }
63
+ // A fallback to globalThis.onload, that will always work
64
+ globalThis.addEventListener("load", _domReady, false);
65
+ }
66
+ readyBound = true;
67
+ }
68
+ }
69
+ }
@@ -8,6 +8,17 @@ import EventEmitter from "eventemitter3";
8
8
  // internal instance of the event emiter
9
9
  var eventEmitter = new EventEmitter();
10
10
 
11
+ /**
12
+ * event when the DOM is Ready is booting
13
+ * @public
14
+ * @constant
15
+ * @type {string}
16
+ * @name DOM_READY
17
+ * @memberof event
18
+ * @see event.on
19
+ */
20
+ export const DOM_READY = "dom_ready";
21
+
11
22
  /**
12
23
  * event when the system is booting
13
24
  * @public
@@ -167,7 +167,7 @@ class ObjectPool {
167
167
  return (typeof className !== "undefined") &&
168
168
  (typeof obj.onResetEvent === "function") &&
169
169
  (className in this.objectClass) &&
170
- (this.objectClass[className].pool !== "undefined");
170
+ (typeof this.objectClass[className].pool !== "undefined");
171
171
 
172
172
  }
173
173
 
@@ -1,5 +1,4 @@
1
1
  import Color from "./../math/color.js";
2
- import * as stringUtil from "./../utils/string.js";
3
2
  import pool from "./../system/pooling.js";
4
3
  import loader from "./../loader/loader.js";
5
4
  import Renderable from "./../renderable/renderable.js";
@@ -254,7 +253,7 @@ class BitmapText extends Renderable {
254
253
 
255
254
  for (var i = 0; i < this._text.length; i++) {
256
255
  x = lX;
257
- var string = stringUtil.trimRight(this._text[i]);
256
+ var string = this._text[i].trimRight();
258
257
  // adjust x pos based on alignment value
259
258
  var stringWidth = this.metrics.lineWidth(string);
260
259
  switch (this.textAlign) {
package/src/text/text.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import Color from "./../math/color.js";
2
2
  import WebGLRenderer from "./../video/webgl/webgl_renderer.js";
3
3
  import { renderer as globalRenderer } from "./../video/video.js";
4
- import { trimRight } from "./../utils/string.js";
5
4
  import pool from "./../system/pooling.js";
6
5
  import Renderable from "./../renderable/renderable.js";
7
6
  import { nextPowerOfTwo } from "./../math/math.js";
@@ -25,6 +24,9 @@ var getContext2d = function (renderer, text) {
25
24
  if (text.offScreenCanvas === true) {
26
25
  return text.canvasTexture.context;
27
26
  } else {
27
+ if (typeof renderer === "undefined") {
28
+ renderer = globalRenderer;
29
+ }
28
30
  return renderer.getFontContext();
29
31
  }
30
32
  };
@@ -333,11 +335,11 @@ class Text extends Renderable {
333
335
 
334
336
  /**
335
337
  * measure the given text size in pixels
336
- * @param {CanvasRenderer|WebGLRenderer} [renderer] reference to the active renderer
338
+ * @param {CanvasRenderer|WebGLRenderer} renderer reference to the active renderer
337
339
  * @param {string} [text] the text to be measured
338
340
  * @returns {TextMetrics} a TextMetrics object defining the dimensions of the given piece of text
339
341
  */
340
- measureText(renderer = globalRenderer, text = this._text) {
342
+ measureText(renderer, text = this._text) {
341
343
  return this.metrics.measureText(text, getContext2d(renderer, this));
342
344
  }
343
345
 
@@ -350,7 +352,7 @@ class Text extends Renderable {
350
352
  * @param {number} [y]
351
353
  * @param {boolean} [stroke=false] draw stroke the the text if true
352
354
  */
353
- draw(renderer, text, x, y, stroke) {
355
+ draw(renderer, text, x = this.pos.x, y = this.pos.y, stroke = false) {
354
356
  // "hacky patch" for backward compatibilty
355
357
  if (typeof this.ancestor === "undefined") {
356
358
 
@@ -420,7 +422,7 @@ class Text extends Renderable {
420
422
  setContextStyle(context, this, stroke);
421
423
 
422
424
  for (var i = 0; i < text.length; i++) {
423
- var string = trimRight(text[i]);
425
+ var string = text[i].trimRight();
424
426
  // draw the string
425
427
  context[stroke ? "strokeText" : "fillText"](string, x, y);
426
428
  // add leading space
@@ -1,5 +1,4 @@
1
1
  import Bounds from "./../physics/bounds.js";
2
- import { trimRight } from "./../utils/string.js";
3
2
  import Text from "./text.js";
4
3
  import setContextStyle from "./textstyle.js";
5
4
 
@@ -92,7 +91,7 @@ class TextMetrics extends Bounds {
92
91
  this.width = this.height = 0;
93
92
 
94
93
  for (var i = 0; i < strings.length; i++) {
95
- this.width = Math.max(this.lineWidth(trimRight(strings[i]), context), this.width);
94
+ this.width = Math.max(this.lineWidth(strings[i].trimRight(), context), this.width);
96
95
  this.height += this.lineHeight();
97
96
  }
98
97
  this.width = Math.ceil(this.width);
@@ -15,30 +15,6 @@ export function capitalize(str) {
15
15
  return str.charAt(0).toUpperCase() + str.slice(1);
16
16
  };
17
17
 
18
- /**
19
- * returns the string stripped of whitespace from the left.
20
- * @public
21
- * @memberof utils.string
22
- * @name trimLeft
23
- * @param {string} str the string to be trimmed
24
- * @returns {string} trimmed string
25
- */
26
- export function trimLeft(str) {
27
- return str.replace(/^\s+/, "");
28
- };
29
-
30
- /**
31
- * returns the string stripped of whitespace from the right.
32
- * @public
33
- * @memberof utils.string
34
- * @name trimRight
35
- * @param {string} str the string to be trimmed
36
- * @returns {string} trimmed string
37
- */
38
- export function trimRight(str) {
39
- return str.replace(/\s+$/, "");
40
- };
41
-
42
18
  /**
43
19
  * returns true if the given string contains a numeric integer or float value
44
20
  * @public
@@ -381,6 +381,8 @@ export class TextureAtlas {
381
381
  * add uvs mapping for the given region
382
382
  * @param {object} atlas the atlas dictionnary where the region is define
383
383
  * @param {object} name region (or frame) name
384
+ * @param {number} w the width of the region
385
+ * @param {number} h the height of the region
384
386
  * @returns {Float32Array} the created region UVs
385
387
  */
386
388
  addUVs(atlas, name, w, h) {