melonjs 10.5.2 → 10.7.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 (67) hide show
  1. package/README.md +4 -6
  2. package/dist/melonjs.js +37470 -36394
  3. package/dist/melonjs.min.js +22 -22
  4. package/dist/melonjs.module.d.ts +606 -426
  5. package/dist/melonjs.module.js +8114 -7033
  6. package/package.json +15 -13
  7. package/src/camera/camera2d.js +11 -10
  8. package/src/game.js +5 -5
  9. package/src/geometries/ellipse.js +1 -1
  10. package/src/geometries/poly.js +1 -1
  11. package/src/geometries/rectangle.js +15 -0
  12. package/src/index.js +5 -5
  13. package/src/input/gamepad.js +12 -10
  14. package/src/input/keyboard.js +5 -3
  15. package/src/input/pointer.js +1 -1
  16. package/src/input/pointerevent.js +3 -4
  17. package/src/level/tiled/TMXLayer.js +1 -1
  18. package/src/level/tiled/TMXTileMap.js +1 -1
  19. package/src/level/tiled/TMXUtils.js +1 -1
  20. package/src/level/tiled/renderer/TMXHexagonalRenderer.js +1 -1
  21. package/src/level/tiled/renderer/TMXIsometricRenderer.js +1 -1
  22. package/src/level/tiled/renderer/TMXOrthogonalRenderer.js +1 -1
  23. package/src/level/tiled/renderer/TMXRenderer.js +1 -1
  24. package/src/level/tiled/renderer/TMXStaggeredRenderer.js +1 -1
  25. package/src/loader/loader.js +1 -1
  26. package/src/loader/loadingscreen.js +1 -1
  27. package/src/math/color.js +1 -1
  28. package/src/math/matrix2.js +2 -2
  29. package/src/math/matrix3.js +67 -66
  30. package/src/math/observable_vector2.js +1 -1
  31. package/src/math/observable_vector3.js +1 -1
  32. package/src/math/vector2.js +1 -1
  33. package/src/math/vector3.js +1 -1
  34. package/src/particles/emitter.js +120 -429
  35. package/src/particles/particle.js +51 -52
  36. package/src/particles/settings.js +310 -0
  37. package/src/physics/body.js +7 -7
  38. package/src/polyfill/console.js +7 -7
  39. package/src/polyfill/index.js +7 -0
  40. package/src/polyfill/performance.js +20 -0
  41. package/src/polyfill/requestAnimationFrame.js +10 -10
  42. package/src/renderable/colorlayer.js +1 -1
  43. package/src/renderable/container.js +11 -1
  44. package/src/renderable/imagelayer.js +3 -3
  45. package/src/renderable/nineslicesprite.js +6 -3
  46. package/src/renderable/renderable.js +18 -1
  47. package/src/renderable/sprite.js +2 -2
  48. package/src/state/state.js +13 -13
  49. package/src/system/device.js +141 -128
  50. package/src/system/event.js +10 -10
  51. package/src/system/pooling.js +150 -155
  52. package/src/system/timer.js +1 -1
  53. package/src/text/bitmaptext.js +35 -91
  54. package/src/text/text.js +82 -145
  55. package/src/text/textmetrics.js +168 -0
  56. package/src/text/textstyle.js +14 -0
  57. package/src/utils/agent.js +4 -4
  58. package/src/utils/function.js +2 -2
  59. package/src/utils/utils.js +10 -5
  60. package/src/video/canvas/canvas_renderer.js +34 -4
  61. package/src/video/renderer.js +3 -5
  62. package/src/video/texture.js +1 -1
  63. package/src/video/video.js +11 -11
  64. package/src/video/webgl/buffer/vertex.js +0 -3
  65. package/src/video/webgl/glshader.js +1 -3
  66. package/src/video/webgl/webgl_renderer.js +50 -22
  67. package/src/particles/particlecontainer.js +0 -95
@@ -103,12 +103,17 @@ var utils = {
103
103
  var hash = {};
104
104
 
105
105
  if (typeof url === "undefined") {
106
- var location = document.location;
107
-
108
- if (location && location.hash) {
109
- url = location.hash;
106
+ if (typeof globalThis.document !== "undefined") {
107
+ var location = globalThis.document.location;
108
+
109
+ if (location && location.hash) {
110
+ url = location.hash;
111
+ } else {
112
+ // No "document.location" exist for Wechat mini game platform.
113
+ return hash;
114
+ }
110
115
  } else {
111
- // No "document.location" exist for Wechat mini game platform.
116
+ // "document" undefined on node.js
112
117
  return hash;
113
118
  }
114
119
  } else {
@@ -55,7 +55,18 @@ class CanvasRenderer extends Renderer {
55
55
  this.uvOffset = 1;
56
56
  }
57
57
 
58
- return this;
58
+ // context lost & restore event for canvas
59
+ this.getScreenCanvas().addEventListener("contextlost", (e) => {
60
+ e.preventDefault();
61
+ this.isContextValid = false;
62
+ event.emit(event.ONCONTEXT_LOST, this);
63
+ }, false );
64
+ // ctx.restoreContext()
65
+ this.getScreenCanvas().addEventListener("contextrestored", () => {
66
+ this.isContextValid = true;
67
+ event.emit(event.ONCONTEXT_RESTORED, this);
68
+ me.game.repaint();
69
+ }, false );
59
70
  }
60
71
 
61
72
  /**
@@ -80,17 +91,36 @@ class CanvasRenderer extends Renderer {
80
91
  }
81
92
 
82
93
  /**
83
- * Set a blend mode for the given context
94
+ * set a blend mode for the given context. <br>
95
+ * Supported blend mode between Canvas and WebGL remderer : <br>
96
+ * - "normal" : this is the default mode and draws new content on top of the existing content <br>
97
+ * <img src="images/normal-blendmode.png" width="510"/> <br>
98
+ * - "multiply" : the pixels of the top layer are multiplied with the corresponding pixel of the bottom layer. A darker picture is the result. <br>
99
+ * <img src="images/multiply-blendmode.png" width="510"/> <br>
100
+ * - "additive or lighter" : where both content overlap the color is determined by adding color values. <br>
101
+ * <img src="images/lighter-blendmode.png" width="510"/> <br>
102
+ * - "screen" : The pixels are inverted, multiplied, and inverted again. A lighter picture is the result (opposite of multiply) <br>
103
+ * <img src="images/screen-blendmode.png" width="510"/> <br>
84
104
  * @name setBlendMode
105
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
85
106
  * @memberof CanvasRenderer.prototype
86
107
  * @function
87
- * @param {string} [mode="normal"] blend mode : "normal", "multiply"
108
+ * @param {string} [mode="normal"] blend mode : "normal", "multiply", "lighter, "additive", "screen"
88
109
  * @param {CanvasRenderingContext2D} [context]
89
110
  */
90
- setBlendMode(mode, context) {
111
+ setBlendMode(mode = "normal", context) {
91
112
  context = context || this.getContext();
92
113
  this.currentBlendMode = mode;
93
114
  switch (mode) {
115
+ case "screen" :
116
+ context.globalCompositeOperation = "screen";
117
+ break;
118
+
119
+ case "lighter" :
120
+ case "additive" :
121
+ context.globalCompositeOperation = "lighter";
122
+ break;
123
+
94
124
  case "multiply" :
95
125
  context.globalCompositeOperation = "multiply";
96
126
  break;
@@ -57,15 +57,15 @@ class Renderer {
57
57
  /**
58
58
  * @ignore
59
59
  */
60
- this.currentBlendMode = "normal";
60
+ this.currentBlendMode = "none";
61
61
 
62
62
  // create the main screen canvas
63
63
  if (device.ejecta === true) {
64
64
  // a main canvas is already automatically created by Ejecta
65
65
  this.canvas = document.getElementById("canvas");
66
- } else if (typeof window.canvas !== "undefined") {
66
+ } else if (typeof globalThis.canvas !== "undefined") {
67
67
  // a global canvas is available, e.g. webapp adapter for wechat
68
- this.canvas = window.canvas;
68
+ this.canvas = globalThis.canvas;
69
69
  } else if (typeof this.settings.canvas !== "undefined") {
70
70
  this.canvas = this.settings.canvas;
71
71
  } else {
@@ -92,8 +92,6 @@ class Renderer {
92
92
  event.on(event.GAME_RESET, () => {
93
93
  renderer.reset();
94
94
  });
95
-
96
- return this;
97
95
  }
98
96
 
99
97
  /**
@@ -3,7 +3,7 @@ import WebGLRenderer from "./webgl/webgl_renderer.js";
3
3
  import TextureCache from "./texture_cache.js";
4
4
  import Sprite from "./../renderable/sprite.js";
5
5
  import { renderer } from "./video.js";
6
- import pool from "./../system/pooling.js";
6
+ import * as pool from "./../system/pooling.js";
7
7
  import loader from "./../loader/loader.js";
8
8
  import { ETA } from "./../math/math.js";
9
9
 
@@ -18,7 +18,7 @@ var designHeight = 0;
18
18
 
19
19
  // default video settings
20
20
  var settings = {
21
- parent : document.body,
21
+ parent : undefined,
22
22
  renderer : 2, // AUTO
23
23
  doubleBuffering : false,
24
24
  autoScale : false,
@@ -64,8 +64,8 @@ function onresize() {
64
64
  var canvasMaxWidth = Infinity;
65
65
  var canvasMaxHeight = Infinity;
66
66
 
67
- if (window.getComputedStyle) {
68
- var style = window.getComputedStyle(renderer.getScreenCanvas(), null);
67
+ if (globalThis.getComputedStyle) {
68
+ var style = globalThis.getComputedStyle(renderer.getScreenCanvas(), null);
69
69
  canvasMaxWidth = parseInt(style.maxWidth, 10) || Infinity;
70
70
  canvasMaxHeight = parseInt(style.maxHeight, 10) || Infinity;
71
71
  }
@@ -276,7 +276,7 @@ export function init(width, height, options) {
276
276
  settings.zoomY = height * scaleRatio.y;
277
277
 
278
278
  //add a channel for the onresize/onorientationchange event
279
- window.addEventListener(
279
+ globalThis.addEventListener(
280
280
  "resize",
281
281
  utils.function.throttle(
282
282
  function (e) {
@@ -286,7 +286,7 @@ export function init(width, height, options) {
286
286
  );
287
287
 
288
288
  // Screen Orientation API
289
- window.addEventListener(
289
+ globalThis.addEventListener(
290
290
  "orientationchange",
291
291
  function (e) {
292
292
  event.emit(event.WINDOW_ONORIENTATION_CHANGE, e);
@@ -294,7 +294,7 @@ export function init(width, height, options) {
294
294
  false
295
295
  );
296
296
  // pre-fixed implementation on mozzila
297
- window.addEventListener(
297
+ globalThis.addEventListener(
298
298
  "onmozorientationchange",
299
299
  function (e) {
300
300
  event.emit(event.WINDOW_ONORIENTATION_CHANGE, e);
@@ -303,13 +303,13 @@ export function init(width, height, options) {
303
303
  );
304
304
 
305
305
  if (device.ScreenOrientation === true) {
306
- window.screen.orientation.onchange = function (e) {
306
+ globalThis.screen.orientation.onchange = function (e) {
307
307
  event.emit(event.WINDOW_ONORIENTATION_CHANGE, e);
308
308
  };
309
309
  }
310
310
 
311
311
  // Automatically update relative canvas position on scroll
312
- window.addEventListener("scroll", utils.function.throttle(
312
+ globalThis.addEventListener("scroll", utils.function.throttle(
313
313
  function (e) {
314
314
  event.emit(event.WINDOW_ONSCROLL, e);
315
315
  }, 100
@@ -336,14 +336,14 @@ export function init(width, height, options) {
336
336
  }
337
337
 
338
338
  // add our canvas (default to document.body if settings.parent is undefined)
339
- parent = device.getElement(settings.parent);
339
+ parent = device.getElement(typeof settings.parent !== "undefined" ? settings.parent : document.body);
340
340
  parent.appendChild(renderer.getScreenCanvas());
341
341
 
342
342
  // trigger an initial resize();
343
343
  onresize();
344
344
 
345
345
  // add an observer to detect when the dom tree is modified
346
- if ("MutationObserver" in window) {
346
+ if ("MutationObserver" in globalThis) {
347
347
  // Create an observer instance linked to the callback function
348
348
  var observer = new MutationObserver(onresize.bind(this));
349
349
 
@@ -362,7 +362,7 @@ export function init(width, height, options) {
362
362
  renderType + " renderer" + gpu_renderer + " | " +
363
363
  audioType + " | " +
364
364
  "pixel ratio " + device.devicePixelRatio + " | " +
365
- (device.isMobile ? "mobile" : "desktop") + " | " +
365
+ (device.nodeJS ? "node.js" : device.isMobile ? "mobile" : "desktop") + " | " +
366
366
  device.getScreenOrientation() + " | " +
367
367
  device.language
368
368
  );
@@ -22,9 +22,6 @@ class VertexArrayBuffer {
22
22
  // Float32 and Uint32 view of the vertex data array buffer
23
23
  this.bufferF32 = new Float32Array(this.buffer);
24
24
  this.bufferU32 = new Uint32Array(this.buffer);
25
-
26
-
27
- return this;
28
25
  }
29
26
 
30
27
  /**
@@ -284,9 +284,7 @@ class GLShader {
284
284
  this.uniforms = extractUniforms(this.gl, this);
285
285
 
286
286
  // destroy the shader on context lost (will be recreated on context restore)
287
- event.on(event.WEBGL_ONCONTEXT_LOST, this.destroy, this);
288
-
289
- return this;
287
+ event.on(event.ONCONTEXT_LOST, this.destroy, this);
290
288
  }
291
289
 
292
290
  /**
@@ -7,7 +7,7 @@ import TextureCache from "./../texture_cache.js";
7
7
  import { TextureAtlas, createAtlas } from "./../texture.js";
8
8
  import { createCanvas, renderer } from "./../video.js";
9
9
  import * as event from "./../../system/event.js";
10
- import pool from "./../../system/pooling.js";
10
+ import * as pool from "./../../system/pooling.js";
11
11
  import { isPowerOfTwo, nextPowerOfTwo, TAU } from "./../../math/math.js";
12
12
 
13
13
 
@@ -100,6 +100,11 @@ class WebGLRenderer extends Renderer {
100
100
  */
101
101
  this._scissorStack = [];
102
102
 
103
+ /**
104
+ * @ignore
105
+ */
106
+ this._blendStack = [];
107
+
103
108
  /**
104
109
  * @ignore
105
110
  */
@@ -158,22 +163,20 @@ class WebGLRenderer extends Renderer {
158
163
  // Create a texture cache
159
164
  this.cache = new TextureCache(this.maxTextures);
160
165
 
161
- // to simulate context lost and restore :
166
+ // to simulate context lost and restore in WebGL:
162
167
  // var ctx = me.video.renderer.context.getExtension('WEBGL_lose_context');
163
168
  // ctx.loseContext()
164
169
  this.getScreenCanvas().addEventListener("webglcontextlost", (e) => {
165
170
  e.preventDefault();
166
171
  this.isContextValid = false;
167
- event.emit(event.WEBGL_ONCONTEXT_LOST, this);
172
+ event.emit(event.ONCONTEXT_LOST, this);
168
173
  }, false );
169
174
  // ctx.restoreContext()
170
175
  this.getScreenCanvas().addEventListener("webglcontextrestored", () => {
171
176
  this.reset();
172
177
  this.isContextValid = true;
173
- event.emit(event.WEBGL_ONCONTEXT_RESTORED, this);
178
+ event.emit(event.ONCONTEXT_RESTORED, this);
174
179
  }, false );
175
-
176
- return this;
177
180
  }
178
181
 
179
182
  /**
@@ -561,28 +564,49 @@ class WebGLRenderer extends Renderer {
561
564
  }
562
565
 
563
566
  /**
564
- * set a blend mode for the given context
567
+ * set a blend mode for the given context. <br>
568
+ * Supported blend mode between Canvas and WebGL remderer : <br>
569
+ * - "normal" : this is the default mode and draws new content on top of the existing content <br>
570
+ * <img src="images/normal-blendmode.png" width="510"/> <br>
571
+ * - "multiply" : the pixels of the top layer are multiplied with the corresponding pixel of the bottom layer. A darker picture is the result. <br>
572
+ * <img src="images/multiply-blendmode.png" width="510"/> <br>
573
+ * - "additive or lighter" : where both content overlap the color is determined by adding color values. <br>
574
+ * <img src="images/lighter-blendmode.png" width="510"/> <br>
575
+ * - "screen" : The pixels are inverted, multiplied, and inverted again. A lighter picture is the result (opposite of multiply) <br>
576
+ * <img src="images/screen-blendmode.png" width="510"/> <br>
565
577
  * @name setBlendMode
578
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
566
579
  * @memberof WebGLRenderer.prototype
567
580
  * @function
568
- * @param {string} [mode="normal"] blend mode : "normal", "multiply"
581
+ * @param {string} [mode="normal"] blend mode : "normal", "multiply", "lighter", "additive", "screen"
569
582
  * @param {WebGLRenderingContext} [gl]
570
583
  */
571
- setBlendMode(mode, gl) {
572
- gl = gl || this.gl;
573
-
584
+ setBlendMode(mode = "normal", gl = this.gl) {
574
585
 
575
- gl.enable(gl.BLEND);
576
- switch (mode) {
577
- case "multiply" :
578
- gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
579
- this.currentBlendMode = mode;
580
- break;
581
-
582
- default :
583
- gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
584
- this.currentBlendMode = "normal";
585
- break;
586
+ if (this.currentBlendMode !== mode) {
587
+ this.flush();
588
+ gl.enable(gl.BLEND);
589
+ this.currentBlendMode = mode;
590
+
591
+ switch (mode) {
592
+ case "screen" :
593
+ gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_COLOR);
594
+ break;
595
+
596
+ case "lighter" :
597
+ case "additive" :
598
+ gl.blendFunc(gl.ONE, gl.ONE);
599
+ break;
600
+
601
+ case "multiply" :
602
+ gl.blendFunc(gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA);
603
+ break;
604
+
605
+ default :
606
+ gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
607
+ this.currentBlendMode = "normal";
608
+ break;
609
+ }
586
610
  }
587
611
  }
588
612
 
@@ -616,6 +640,8 @@ class WebGLRenderer extends Renderer {
616
640
  this.currentColor.copy(color);
617
641
  this.currentTransform.copy(matrix);
618
642
 
643
+ this.setBlendMode(this._blendStack.pop());
644
+
619
645
  // recycle objects
620
646
  pool.push(color);
621
647
  pool.push(matrix);
@@ -648,6 +674,8 @@ class WebGLRenderer extends Renderer {
648
674
  // FIXME avoid slice and object realloc
649
675
  this._scissorStack.push(this.currentScissor.slice());
650
676
  }
677
+
678
+ this._blendStack.push(this.getBlendMode());
651
679
  }
652
680
 
653
681
  /**
@@ -1,95 +0,0 @@
1
- import Container from "./../renderable/container.js";
2
- import { viewport } from "./../game.js";
3
-
4
- /**
5
- * @classdesc
6
- * Particle Container Object.
7
- * @class ParticleContainer
8
- * @augments Container
9
- * @param {ParticleEmitter} emitter the emitter which owns this container
10
- */
11
-
12
- class ParticleContainer extends Container {
13
-
14
- /**
15
- * @ignore
16
- */
17
- constructor(emitter) {
18
- // call the super constructor
19
- super(
20
- viewport.pos.x,
21
- viewport.pos.y,
22
- viewport.width,
23
- viewport.height
24
- );
25
-
26
- // don't sort the particles by z-index
27
- this.autoSort = false;
28
-
29
- // count the updates
30
- this._updateCount = 0;
31
-
32
- // internally store how much time was skipped when frames are skipped
33
- this._dt = 0;
34
-
35
- // cache the emitter for later use
36
- this._emitter = emitter;
37
-
38
- this.autoTransform = false;
39
-
40
- this.anchorPoint.set(0, 0);
41
-
42
- this.isKinematic = true;
43
- }
44
-
45
- /**
46
- * @ignore
47
- */
48
- update(dt) {
49
- // skip frames if necessary
50
- if (++this._updateCount > this._emitter.framesToSkip) {
51
- this._updateCount = 0;
52
- }
53
- if (this._updateCount > 0) {
54
- this._dt += dt;
55
- return false;
56
- }
57
-
58
- // apply skipped delta time
59
- dt += this._dt;
60
- this._dt = 0;
61
-
62
- // Update particles and remove them if they are dead
63
- for (var i = this.children.length - 1; i >= 0; --i) {
64
- var particle = this.children[i];
65
- particle.inViewport = viewport.isVisible(particle, this.floating);
66
- if (!particle.update(dt)) {
67
- this.removeChildNow(particle);
68
- }
69
- }
70
- return true;
71
- }
72
-
73
- /**
74
- * @ignore
75
- */
76
- draw(renderer, rect) {
77
- if (this.children.length > 0) {
78
- var context = renderer.getContext(),
79
- gco;
80
- // Check for additive draw
81
- if (this._emitter.textureAdditive) {
82
- gco = context.globalCompositeOperation;
83
- context.globalCompositeOperation = "lighter";
84
- }
85
-
86
- super.draw(renderer, rect);
87
-
88
- // Restore globalCompositeOperation
89
- if (this._emitter.textureAdditive) {
90
- context.globalCompositeOperation = gco;
91
- }
92
- }
93
- }
94
- };
95
- export default ParticleContainer;