melonjs 12.0.0 → 13.1.1

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 (54) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +4 -6
  3. package/dist/melonjs.js +22648 -22478
  4. package/dist/melonjs.min.js +5 -6
  5. package/dist/melonjs.module.d.ts +289 -264
  6. package/dist/melonjs.module.js +21979 -21804
  7. package/package.json +15 -16
  8. package/src/application/application.js +231 -0
  9. package/src/audio/audio.js +8 -2
  10. package/src/camera/camera2d.js +6 -6
  11. package/src/game.js +9 -232
  12. package/src/index.js +3 -3
  13. package/src/input/keyboard.js +2 -2
  14. package/src/input/pointer.js +4 -5
  15. package/src/input/pointerevent.js +10 -10
  16. package/src/lang/deprecated.js +27 -30
  17. package/src/level/level.js +2 -2
  18. package/src/level/tiled/TMXGroup.js +10 -0
  19. package/src/level/tiled/TMXLayer.js +11 -2
  20. package/src/level/tiled/TMXObject.js +13 -2
  21. package/src/level/tiled/TMXTileMap.js +15 -3
  22. package/src/level/tiled/TMXTileset.js +8 -0
  23. package/src/loader/loader.js +64 -28
  24. package/src/loader/loadingscreen.js +27 -28
  25. package/src/math/color.js +62 -42
  26. package/src/math/observable_vector2.js +26 -2
  27. package/src/math/observable_vector3.js +32 -4
  28. package/src/math/vector2.js +23 -0
  29. package/src/math/vector3.js +26 -0
  30. package/src/physics/body.js +27 -51
  31. package/src/physics/detector.js +3 -3
  32. package/src/physics/quadtree.js +58 -29
  33. package/src/physics/world.js +32 -3
  34. package/src/renderable/container.js +2 -2
  35. package/src/renderable/imagelayer.js +8 -8
  36. package/src/renderable/nineslicesprite.js +27 -1
  37. package/src/renderable/trigger.js +4 -4
  38. package/src/state/stage.js +1 -1
  39. package/src/state/state.js +50 -3
  40. package/src/system/device.js +814 -981
  41. package/src/system/event.js +2 -1
  42. package/src/system/platform.js +32 -0
  43. package/src/system/save.js +23 -14
  44. package/src/system/timer.js +12 -35
  45. package/src/text/text.js +9 -12
  46. package/src/tweens/tween.js +6 -6
  47. package/src/utils/string.js +13 -0
  48. package/src/video/canvas/canvas_renderer.js +30 -65
  49. package/src/video/renderer.js +23 -30
  50. package/src/video/texture/canvas_texture.js +39 -3
  51. package/src/video/video.js +27 -25
  52. package/src/video/webgl/glshader.js +1 -1
  53. package/src/video/webgl/webgl_compositor.js +2 -2
  54. package/src/video/webgl/webgl_renderer.js +8 -20
@@ -399,7 +399,8 @@ export const CANVAS_ONRESIZE = "canvas.onresize";
399
399
  * Event for when the viewport is resized <br>
400
400
  * (this usually follows a WINDOW_ONRESIZE event, when using the `flex` scaling mode is used and after the viewport was updated).<br>
401
401
  * Data passed : {number} viewport width <br>
402
- * Data passed : {number} viewport height
402
+ * Data passed : {number} viewport height <br>
403
+ * Data passed : {Camera2d} a reference to the camera viewport being resized
403
404
  * @public
404
405
  * @constant
405
406
  * @type {string}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The device platform type
3
+ * @namespace platform
4
+ * @memberof device
5
+ * @property {string} ua the user agent string for the current device
6
+ * @property {boolean} iOS `true` if the device is an iOS platform
7
+ * @property {boolean} android `true` if the device is an Android platform
8
+ * @property {boolean} android2 `true` if the device is an Android 2.x platform
9
+ * @property {boolean} linux `true` if the device is a Linux platform
10
+ * @property {boolean} chromeOS `true` if the device is running on ChromeOS.
11
+ * @property {boolean} wp `true` if the device is a Windows Phone platform
12
+ * @property {boolean} BlackBerry`true` if the device is a BlackBerry platform
13
+ * @property {boolean} Kindle`true` if the device is a Kindle platform
14
+ * @property {boolean} ejecta `true` if running under Ejecta
15
+ * @property {boolean} isWeixin `true` if running under Wechat
16
+ * @property {boolean} nodeJS `true` if running under node.js
17
+ * @property {boolean} isMobile `true` if a mobile device
18
+ */
19
+
20
+ export const ua = typeof globalThis.navigator !== "undefined" ? globalThis.navigator.userAgent : "";
21
+ export const iOS = /iPhone|iPad|iPod/i.test(ua);
22
+ export const android = /Android/i.test(ua);
23
+ export const android2 = /Android 2/i.test(ua);
24
+ export const linux = /Linux/i.test(ua);
25
+ export const chromeOS = /CrOS/.test(ua);
26
+ export const wp = /Windows Phone/i.test(ua);
27
+ export const BlackBerry = /BlackBerry/i.test(ua);
28
+ export const Kindle = /Kindle|Silk.*Mobile Safari/i.test(ua);
29
+ export const ejecta = (typeof globalThis.ejecta !== "undefined");
30
+ export const isWeixin = /MicroMessenger/i.test(ua);
31
+ export const nodeJS = (typeof globalThis.process !== "undefined") && (typeof globalThis.process.release !== "undefined") && (globalThis.process.release.name === "node");
32
+ export const isMobile = /Mobi/i.test(ua) || iOS || android || wp || BlackBerry || Kindle || false;
@@ -1,4 +1,3 @@
1
- import device from "./device.js";
2
1
  import * as event from "./event.js";
3
2
 
4
3
  /**
@@ -32,22 +31,32 @@ import * as event from "./event.js";
32
31
  * @namespace save
33
32
  */
34
33
 
35
- // Variable to hold the object data
36
- var data = {};
34
+ // Variable to hold the object data
35
+ var data = {};
37
36
 
38
- /**
39
- * a function to check if the given key is a reserved word
40
- * @ignore
41
- */
42
- function isReserved(key) {
43
- return (key === "add" || key === "remove");
44
- }
37
+ let hasLocalStorage = false;
38
+
39
+ try {
40
+ // true if localStorage is supported
41
+ hasLocalStorage = typeof globalThis !== "undefined" && typeof globalThis.localStorage !== "undefined";
42
+ } catch (e) {
43
+ // the above generates an exception when cookies are blocked
44
+ hasLocalStorage = false;
45
+ }
46
+
47
+ /**
48
+ * a function to check if the given key is a reserved word
49
+ * @ignore
50
+ */
51
+ function isReserved(key) {
52
+ return (key === "add" || key === "remove");
53
+ }
45
54
 
46
55
 
47
56
  // Initialize me.save on Boot event
48
57
  event.on(event.BOOT, () => {
49
58
  // Load previous data if local Storage is supported
50
- if (typeof globalThis.localStorage !== "undefined") {
59
+ if (hasLocalStorage === true) {
51
60
  var me_save_content = globalThis.localStorage.getItem("me.save");
52
61
 
53
62
  if (typeof me_save_content === "string" && me_save_content.length > 0) {
@@ -95,7 +104,7 @@ var save = {
95
104
  */
96
105
  set (value) {
97
106
  data[prop] = value;
98
- if (device.localStorage === true) {
107
+ if (hasLocalStorage === true) {
99
108
  globalThis.localStorage.setItem("me.save." + prop, JSON.stringify(value));
100
109
  }
101
110
  }
@@ -109,7 +118,7 @@ var save = {
109
118
  });
110
119
 
111
120
  // Save keys
112
- if (device.localStorage === true) {
121
+ if (hasLocalStorage === true) {
113
122
  globalThis.localStorage.setItem("me.save", JSON.stringify(Object.keys(data)));
114
123
  }
115
124
  },
@@ -127,7 +136,7 @@ var save = {
127
136
  if (!isReserved(key)) {
128
137
  if (typeof data[key] !== "undefined") {
129
138
  delete data[key];
130
- if (device.localStorage === true) {
139
+ if (hasLocalStorage === true) {
131
140
  globalThis.localStorage.removeItem("me.save." + key);
132
141
  globalThis.localStorage.setItem("me.save", JSON.stringify(Object.keys(data)));
133
142
  }
@@ -6,53 +6,46 @@ import { clamp } from "./../math/math.js";
6
6
  /**
7
7
  * @classdesc
8
8
  * a Timer class to manage timing related function (FPS, Game Tick, Time...)
9
- * @see {@link timer} the default global timer instance
9
+ * @see {@link timer} the default global timer instance
10
10
  */
11
11
  class Timer {
12
12
 
13
13
  constructor() {
14
14
  /**
15
- * Last game tick value.<br/>
16
- * Use this value to scale velocities during frame drops due to slow
17
- * hardware or when setting an FPS limit. (See {@link timer.maxfps})
18
- * This feature is disabled by default. Enable me.timer.interpolation to
19
- * use it.
15
+ * Last game tick value. <br>
16
+ * Use this value to scale velocities during frame drops due to slow hardware or when setting an FPS limit.
17
+ * This feature is disabled by default (Enable interpolation to use it).
20
18
  * @public
21
- * @see timer.interpolation
19
+ * @see interpolation
20
+ * @See maxfps
22
21
  * @type {number}
23
22
  * @name tick
24
- * @memberof timer
25
23
  */
26
24
  this.tick = 1.0;
27
25
 
28
26
  /**
29
- * Last measured fps rate.<br/>
30
- * This feature is disabled by default, unless the debugPanel is enabled/visible
27
+ * Last measured fps rate.<br>
28
+ * This feature is disabled by default, unless the debugPanel is enabled/visible.
31
29
  * @public
32
30
  * @type {number}
33
31
  * @name fps
34
- * @memberof timer
35
32
  */
36
33
  this.fps = 0;
37
34
 
38
35
  /**
39
36
  * Set the maximum target display frame per second
40
37
  * @public
41
- * @see timer.tick
38
+ * @see tick
42
39
  * @type {number}
43
- * @name maxfps
44
40
  * @default 60
45
- * @memberof timer
46
41
  */
47
42
  this.maxfps = 60;
48
43
 
49
44
  /**
50
45
  * Enable/disable frame interpolation
51
- * @see timer.tick
46
+ * @see tick
52
47
  * @type {boolean}
53
48
  * @default false
54
- * @name interpolation
55
- * @memberof timer
56
49
  */
57
50
  this.interpolation = false;
58
51
 
@@ -96,8 +89,6 @@ class Timer {
96
89
 
97
90
  /**
98
91
  * reset time (e.g. usefull in case of pause)
99
- * @name reset
100
- * @memberof timer
101
92
  * @ignore
102
93
  */
103
94
  reset() {
@@ -114,8 +105,6 @@ class Timer {
114
105
 
115
106
  /**
116
107
  * Calls a function once after a specified delay. See me.timer.setInterval to repeativly call a function.
117
- * @name setTimeout
118
- * @memberof timer
119
108
  * @param {Function} fn the function you want to execute after delay milliseconds.
120
109
  * @param {number} delay the number of milliseconds (thousandths of a second) that the function call should be delayed by.
121
110
  * @param {boolean} [pauseable=true] respects the pause state of the engine.
@@ -142,8 +131,6 @@ class Timer {
142
131
 
143
132
  /**
144
133
  * Calls a function continously at the specified interval. See setTimeout to call function a single time.
145
- * @name setInterval
146
- * @memberof timer
147
134
  * @param {Function} fn the function to execute
148
135
  * @param {number} delay the number of milliseconds (thousandths of a second) on how often to execute the function
149
136
  * @param {boolean} [pauseable=true] respects the pause state of the engine.
@@ -170,8 +157,6 @@ class Timer {
170
157
 
171
158
  /**
172
159
  * Clears the delay set by me.timer.setTimeout().
173
- * @name clearTimeout
174
- * @memberof timer
175
160
  * @param {number} timeoutID ID of the timeout to be cleared
176
161
  */
177
162
  clearTimeout(timeoutID) {
@@ -180,8 +165,6 @@ class Timer {
180
165
 
181
166
  /**
182
167
  * Clears the Interval set by me.timer.setInterval().
183
- * @name clearInterval
184
- * @memberof timer
185
168
  * @param {number} intervalID ID of the interval to be cleared
186
169
  */
187
170
  clearInterval(intervalID) {
@@ -191,8 +174,6 @@ class Timer {
191
174
  /**
192
175
  * Return the current timestamp in milliseconds <br>
193
176
  * since the game has started or since linux epoch (based on browser support for High Resolution Timer)
194
- * @name getTime
195
- * @memberof timer
196
177
  * @returns {number}
197
178
  */
198
179
  getTime() {
@@ -201,8 +182,6 @@ class Timer {
201
182
 
202
183
  /**
203
184
  * Return elapsed time in milliseconds since the last update
204
- * @name getDelta
205
- * @memberof timer
206
185
  * @returns {number}
207
186
  */
208
187
  getDelta() {
@@ -211,9 +190,7 @@ class Timer {
211
190
 
212
191
  /**
213
192
  * compute the actual frame time and fps rate
214
- * @name computeFPS
215
193
  * @ignore
216
- * @memberof timer
217
194
  */
218
195
  countFPS() {
219
196
  this.framecount++;
@@ -281,6 +258,8 @@ class Timer {
281
258
  }
282
259
  };
283
260
 
261
+ const timer = new Timer();
262
+
284
263
  /**
285
264
  * the default global Timer instance
286
265
  * @namespace timer
@@ -295,6 +274,4 @@ class Timer {
295
274
  * // set a timer to call "myFunction" every 1000ms (respecting the pause state) and passing param1 and param2
296
275
  * timer.setInterval(myFunction, 1000, true, param1, param2);
297
276
  */
298
- const timer = new Timer();
299
-
300
277
  export default timer;
package/src/text/text.js CHANGED
@@ -204,18 +204,6 @@ class Text extends Renderable {
204
204
  this.setText(settings.text);
205
205
  }
206
206
 
207
- /** @ignore */
208
- onDeactivateEvent() {
209
- // free the canvas and potential corresponding texture when deactivated
210
- if (this.offScreenCanvas === true) {
211
- globalRenderer.currentCompositor.deleteTexture2D(globalRenderer.currentCompositor.getTexture2D(this.glTextureUnit));
212
- globalRenderer.cache.delete(this.canvasTexture.canvas);
213
- pool.push(this.canvasTexture);
214
- this.canvasTexture = undefined;
215
- this.glTextureUnit = undefined;
216
- }
217
- }
218
-
219
207
  /**
220
208
  * make the font bold
221
209
  * @returns {Text} this object for chaining
@@ -436,6 +424,15 @@ class Text extends Renderable {
436
424
  * @ignore
437
425
  */
438
426
  destroy() {
427
+ if (this.offScreenCanvas === true) {
428
+ if (globalRenderer instanceof WebGLRenderer) {
429
+ globalRenderer.currentCompositor.deleteTexture2D(globalRenderer.currentCompositor.getTexture2D(this.glTextureUnit));
430
+ this.glTextureUnit = undefined;
431
+ }
432
+ globalRenderer.cache.delete(this.canvasTexture.canvas);
433
+ pool.push(this.canvasTexture);
434
+ this.canvasTexture = undefined;
435
+ }
439
436
  pool.push(this.fillStyle);
440
437
  pool.push(this.strokeStyle);
441
438
  this.fillStyle = this.strokeStyle = undefined;
@@ -1,6 +1,6 @@
1
1
  import timer from "./../system/timer.js";
2
2
  import * as event from "./../system/event.js";
3
- import { world, lastUpdate } from "./../game.js";
3
+ import game from "./../game.js";
4
4
  import { Easing } from "./easing.js";
5
5
  import { Interpolation } from "./interpolation.js";
6
6
 
@@ -72,7 +72,7 @@ class Tween {
72
72
  this._onUpdateCallback = null;
73
73
  this._onCompleteCallback = null;
74
74
  // tweens are synchronized with the game update loop
75
- this._tweenTimeTracker = lastUpdate;
75
+ this._tweenTimeTracker = game.lastUpdate;
76
76
 
77
77
  // reset flags to default value
78
78
  this.isPersistent = false;
@@ -170,7 +170,7 @@ class Tween {
170
170
  this._onStartCallbackFired = false;
171
171
 
172
172
  // add the tween to the object pool on start
173
- world.addChild(this);
173
+ game.world.addChild(this);
174
174
 
175
175
  this._startTime = time + this._delayTime;
176
176
 
@@ -212,7 +212,7 @@ class Tween {
212
212
  */
213
213
  stop() {
214
214
  // remove the tween from the world container
215
- world.removeChildNow(this);
215
+ game.world.removeChildNow(this);
216
216
  return this;
217
217
  }
218
218
 
@@ -349,7 +349,7 @@ class Tween {
349
349
 
350
350
  // the original Tween implementation expect
351
351
  // a timestamp and not a time delta
352
- this._tweenTimeTracker = (lastUpdate > this._tweenTimeTracker) ? lastUpdate : this._tweenTimeTracker + dt;
352
+ this._tweenTimeTracker = (game.lastUpdate > this._tweenTimeTracker) ? game.lastUpdate : this._tweenTimeTracker + dt;
353
353
  var time = this._tweenTimeTracker;
354
354
 
355
355
  var property;
@@ -442,7 +442,7 @@ class Tween {
442
442
 
443
443
  } else {
444
444
  // remove the tween from the world container
445
- world.removeChildNow(this);
445
+ game.world.removeChildNow(this);
446
446
 
447
447
  if ( this._onCompleteCallback !== null ) {
448
448
 
@@ -58,3 +58,16 @@ export function toHex(str) {
58
58
  }
59
59
  return res;
60
60
  };
61
+
62
+ /**
63
+ * returns true if the given string is a data url in the `data:[<mediatype>][;base64],<data>` format.
64
+ * (this will not test the validity of the Data or Base64 encoding)
65
+ * @public
66
+ * @memberof utils.string
67
+ * @name isDataUrl
68
+ * @param {string} str the string (url) to be tested
69
+ * @returns {boolean} true if the string is a data url
70
+ */
71
+ export function isDataUrl(str) {
72
+ return /^data:(.+);base64,(.+)$/.test(str);
73
+ };
@@ -5,7 +5,6 @@ import Ellipse from "./../../geometries/ellipse.js";
5
5
  import RoundRect from "./../../geometries/roundrect.js";
6
6
  import Rect from "./../../geometries/rectangle.js";
7
7
  import Bounds from "./../../physics/bounds.js";
8
- import { createCanvas } from "./../video.js";
9
8
  import * as event from "./../../system/event.js";
10
9
 
11
10
  /**
@@ -19,7 +18,6 @@ class CanvasRenderer extends Renderer {
19
18
  * @param {number} options.width The width of the canvas without scaling
20
19
  * @param {number} options.height The height of the canvas without scaling
21
20
  * @param {HTMLCanvasElement} [options.canvas] The html canvas to draw to on screen
22
- * @param {boolean} [options.doubleBuffering=false] Whether to enable double buffering
23
21
  * @param {boolean} [options.antiAlias=false] Whether to enable anti-aliasing
24
22
  * @param {boolean} [options.transparent=false] Whether to enable transparency on the canvas (performance hit when enabled)
25
23
  * @param {boolean} [options.subPixel=false] Whether to enable subpixel renderering (performance hit when enabled)
@@ -32,17 +30,7 @@ class CanvasRenderer extends Renderer {
32
30
  super(options);
33
31
 
34
32
  // defined the 2d context
35
- this.context = this.getContext2d(this.getScreenCanvas(), this.settings.transparent);
36
-
37
- // create the back buffer if we use double buffering
38
- if (this.settings.doubleBuffering) {
39
- this.backBufferCanvas = createCanvas(this.settings.width, this.settings.height, true);
40
- this.backBufferContext2D = this.getContext2d(this.backBufferCanvas);
41
- }
42
- else {
43
- this.backBufferCanvas = this.getScreenCanvas();
44
- this.backBufferContext2D = this.context;
45
- }
33
+ this.context = this.getContext2d(this.getCanvas(), this.settings.transparent);
46
34
 
47
35
  this.setBlendMode(this.settings.blendMode);
48
36
 
@@ -58,13 +46,13 @@ class CanvasRenderer extends Renderer {
58
46
  }
59
47
 
60
48
  // context lost & restore event for canvas
61
- this.getScreenCanvas().addEventListener("contextlost", (e) => {
49
+ this.getCanvas().addEventListener("contextlost", (e) => {
62
50
  e.preventDefault();
63
51
  this.isContextValid = false;
64
52
  event.emit(event.ONCONTEXT_LOST, this);
65
53
  }, false );
66
54
  // ctx.restoreContext()
67
- this.getScreenCanvas().addEventListener("contextrestored", () => {
55
+ this.getCanvas().addEventListener("contextrestored", () => {
68
56
  this.isContextValid = true;
69
57
  event.emit(event.ONCONTEXT_RESTORED, this);
70
58
  }, false );
@@ -86,7 +74,7 @@ class CanvasRenderer extends Renderer {
86
74
  * @memberof CanvasRenderer
87
75
  */
88
76
  resetTransform() {
89
- this.backBufferContext2D.setTransform(1, 0, 0, 1, 0, 0);
77
+ this.getContext().setTransform(1, 0, 0, 1, 0, 0);
90
78
  }
91
79
 
92
80
  /**
@@ -128,12 +116,6 @@ class CanvasRenderer extends Renderer {
128
116
  this.currentBlendMode = "normal";
129
117
  break;
130
118
  }
131
-
132
- // transparent setting will override the given blendmode for this.context
133
- if (this.settings.doubleBuffering && this.settings.transparent) {
134
- // Clears the front buffer for each frame blit
135
- this.context.globalCompositeOperation = "copy";
136
- }
137
119
  }
138
120
 
139
121
  /**
@@ -147,17 +129,6 @@ class CanvasRenderer extends Renderer {
147
129
  }
148
130
  }
149
131
 
150
- /**
151
- * render the main framebuffer on screen
152
- * @name flush
153
- * @memberof CanvasRenderer
154
- */
155
- flush() {
156
- if (this.settings.doubleBuffering) {
157
- this.context.drawImage(this.backBufferCanvas, 0, 0);
158
- }
159
- }
160
-
161
132
  /**
162
133
  * Clears the main framebuffer with the given color
163
134
  * @name clearColor
@@ -166,11 +137,14 @@ class CanvasRenderer extends Renderer {
166
137
  * @param {boolean} [opaque=false] Allow transparency [default] or clear the surface completely [true]
167
138
  */
168
139
  clearColor(color = "#000000", opaque) {
140
+ var canvas = this.getCanvas();
141
+ var context = this.getContext();
142
+
169
143
  this.save();
170
144
  this.resetTransform();
171
- this.backBufferContext2D.globalCompositeOperation = opaque ? "copy" : "source-over";
172
- this.backBufferContext2D.fillStyle = (color instanceof Color) ? color.toRGBA() : color;
173
- this.fillRect(0, 0, this.backBufferCanvas.width, this.backBufferCanvas.height);
145
+ context.globalCompositeOperation = opaque ? "copy" : "source-over";
146
+ context.fillStyle = (color instanceof Color) ? color.toRGBA() : color;
147
+ this.fillRect(0, 0, canvas.width, canvas.height);
174
148
  this.restore();
175
149
  }
176
150
 
@@ -530,17 +504,6 @@ class CanvasRenderer extends Renderer {
530
504
  this.strokeRoundRect(x, y, width, height, radius, true);
531
505
  }
532
506
 
533
-
534
- /**
535
- * return a reference to the system 2d Context
536
- * @name getContext
537
- * @memberof CanvasRenderer
538
- * @returns {CanvasRenderingContext2D}
539
- */
540
- getContext() {
541
- return this.backBufferContext2D;
542
- }
543
-
544
507
  /**
545
508
  * return a reference to the font 2d Context
546
509
  * @ignore
@@ -556,7 +519,7 @@ class CanvasRenderer extends Renderer {
556
519
  * @memberof CanvasRenderer
557
520
  */
558
521
  save() {
559
- this.backBufferContext2D.save();
522
+ this.getContext().save();
560
523
  }
561
524
 
562
525
  /**
@@ -565,12 +528,12 @@ class CanvasRenderer extends Renderer {
565
528
  * @memberof CanvasRenderer
566
529
  */
567
530
  restore() {
568
- this.backBufferContext2D.restore();
531
+ this.getContext().restore();
569
532
  this.currentColor.glArray[3] = this.getGlobalAlpha();
570
533
  this.currentScissor[0] = 0;
571
534
  this.currentScissor[1] = 0;
572
- this.currentScissor[2] = this.backBufferCanvas.width;
573
- this.currentScissor[3] = this.backBufferCanvas.height;
535
+ this.currentScissor[2] = this.getCanvas().width;
536
+ this.currentScissor[3] = this.getCanvas().height;
574
537
  }
575
538
 
576
539
  /**
@@ -580,7 +543,7 @@ class CanvasRenderer extends Renderer {
580
543
  * @param {number} angle in radians
581
544
  */
582
545
  rotate(angle) {
583
- this.backBufferContext2D.rotate(angle);
546
+ this.getContext().rotate(angle);
584
547
  }
585
548
 
586
549
  /**
@@ -591,7 +554,7 @@ class CanvasRenderer extends Renderer {
591
554
  * @param {number} y
592
555
  */
593
556
  scale(x, y) {
594
- this.backBufferContext2D.scale(x, y);
557
+ this.getContext().scale(x, y);
595
558
  }
596
559
 
597
560
  /**
@@ -602,8 +565,9 @@ class CanvasRenderer extends Renderer {
602
565
  * @param {Color|string} color css color value
603
566
  */
604
567
  setColor(color) {
605
- this.backBufferContext2D.strokeStyle =
606
- this.backBufferContext2D.fillStyle = (
568
+ var context = this.getContext();
569
+ context.strokeStyle =
570
+ context.fillStyle = (
607
571
  color instanceof Color ?
608
572
  color.toRGBA() :
609
573
  color
@@ -617,7 +581,7 @@ class CanvasRenderer extends Renderer {
617
581
  * @param {number} alpha 0.0 to 1.0 values accepted.
618
582
  */
619
583
  setGlobalAlpha(alpha) {
620
- this.backBufferContext2D.globalAlpha = this.currentColor.glArray[3] = alpha;
584
+ this.getContext().globalAlpha = this.currentColor.glArray[3] = alpha;
621
585
  }
622
586
 
623
587
  /**
@@ -627,7 +591,7 @@ class CanvasRenderer extends Renderer {
627
591
  * @returns {number} global alpha value
628
592
  */
629
593
  getGlobalAlpha() {
630
- return this.backBufferContext2D.globalAlpha;
594
+ return this.getContext().globalAlpha;
631
595
  }
632
596
 
633
597
  /**
@@ -637,7 +601,7 @@ class CanvasRenderer extends Renderer {
637
601
  * @param {number} width Line width
638
602
  */
639
603
  setLineWidth(width) {
640
- this.backBufferContext2D.lineWidth = width;
604
+ this.getContext().lineWidth = width;
641
605
  }
642
606
 
643
607
  /**
@@ -672,7 +636,7 @@ class CanvasRenderer extends Renderer {
672
636
  f |= 0;
673
637
  }
674
638
 
675
- this.backBufferContext2D.transform(a, b, c, d, e, f);
639
+ this.getContext().transform(a, b, c, d, e, f);
676
640
  }
677
641
 
678
642
  /**
@@ -684,9 +648,9 @@ class CanvasRenderer extends Renderer {
684
648
  */
685
649
  translate(x, y) {
686
650
  if (this.settings.subPixel === false) {
687
- this.backBufferContext2D.translate(~~x, ~~y);
651
+ this.getContext().translate(~~x, ~~y);
688
652
  } else {
689
- this.backBufferContext2D.translate(x, y);
653
+ this.getContext().translate(x, y);
690
654
  }
691
655
  }
692
656
 
@@ -704,14 +668,14 @@ class CanvasRenderer extends Renderer {
704
668
  * @param {number} height
705
669
  */
706
670
  clipRect(x, y, width, height) {
707
- var canvas = this.backBufferCanvas;
671
+ var canvas = this.getCanvas();
708
672
  // if requested box is different from the current canvas size;
709
673
  if (x !== 0 || y !== 0 || width !== canvas.width || height !== canvas.height) {
710
674
  var currentScissor = this.currentScissor;
711
675
  // if different from the current scissor box
712
676
  if (currentScissor[0] !== x || currentScissor[1] !== y ||
713
677
  currentScissor[2] !== width || currentScissor[3] !== height) {
714
- var context = this.backBufferContext2D;
678
+ var context = this.getContext();
715
679
  context.beginPath();
716
680
  context.rect(x, y, width, height);
717
681
  context.clip();
@@ -743,11 +707,11 @@ class CanvasRenderer extends Renderer {
743
707
  }
744
708
 
745
709
  // https://github.com/melonjs/melonJS/issues/648
746
- else if (mask instanceof RoundRect) {
710
+ if (mask instanceof RoundRect) {
747
711
  context.roundRect(mask.top, mask.left, mask.width, mask.height, mask.radius);
748
712
  } else if (mask instanceof Rect || mask instanceof Bounds) {
749
713
  context.rect(mask.top, mask.left, mask.width, mask.height);
750
- } else if (mask instanceof Ellipse) {
714
+ } else if (mask instanceof Ellipse) {
751
715
  const _x = mask.pos.x, _y = mask.pos.y,
752
716
  hw = mask.radiusV.x,
753
717
  hh = mask.radiusV.y,
@@ -769,6 +733,7 @@ class CanvasRenderer extends Renderer {
769
733
  context.bezierCurveTo(xmin, by, lx, ymax, lx, _y);
770
734
  context.bezierCurveTo(lx, ymin, xmin, ty, _x, ty);
771
735
  } else {
736
+ // polygon
772
737
  const _x = mask.pos.x, _y = mask.pos.y;
773
738
  var point;
774
739