melonjs 10.12.0 → 13.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.
- package/LICENSE.md +1 -1
- package/README.md +6 -6
- package/dist/melonjs.js +22651 -22529
- package/dist/melonjs.min.js +5 -6
- package/dist/melonjs.module.d.ts +195 -195
- package/dist/melonjs.module.js +22107 -21977
- package/package.json +14 -14
- package/src/application/application.js +231 -0
- package/src/audio/audio.js +13 -7
- package/src/camera/camera2d.js +6 -6
- package/src/game.js +9 -232
- package/src/index.js +3 -3
- package/src/input/keyboard.js +2 -2
- package/src/input/pointer.js +4 -5
- package/src/input/pointerevent.js +8 -8
- package/src/lang/deprecated.js +0 -29
- package/src/level/level.js +2 -2
- package/src/level/tiled/TMXLayer.js +2 -2
- package/src/level/tiled/TMXTileMap.js +3 -3
- package/src/loader/loader.js +64 -28
- package/src/loader/loadingscreen.js +28 -115
- package/src/loader/melonjs_logo.png +0 -0
- package/src/physics/body.js +27 -51
- package/src/physics/detector.js +3 -3
- package/src/physics/quadtree.js +58 -29
- package/src/physics/world.js +32 -3
- package/src/polyfill/index.js +4 -0
- package/src/renderable/container.js +2 -2
- package/src/renderable/imagelayer.js +8 -8
- package/src/renderable/light2d.js +40 -11
- package/src/renderable/trigger.js +4 -4
- package/src/state/stage.js +1 -1
- package/src/state/state.js +50 -3
- package/src/system/device.js +808 -1039
- package/src/system/dom.js +69 -0
- package/src/system/event.js +13 -1
- package/src/system/platform.js +32 -0
- package/src/system/save.js +23 -14
- package/src/system/timer.js +12 -35
- package/src/text/bitmaptext.js +1 -2
- package/src/text/text.js +10 -14
- package/src/text/textmetrics.js +1 -2
- package/src/tweens/tween.js +6 -6
- package/src/utils/string.js +13 -24
- package/src/video/canvas/canvas_renderer.js +3 -2
- package/src/video/renderer.js +2 -2
- package/src/video/texture/canvas_texture.js +36 -2
- package/src/video/video.js +15 -9
- package/src/video/webgl/glshader.js +1 -1
- package/src/video/webgl/webgl_renderer.js +1 -1
|
@@ -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
|
+
}
|
package/src/system/event.js
CHANGED
|
@@ -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
|
|
@@ -388,7 +399,8 @@ export const CANVAS_ONRESIZE = "canvas.onresize";
|
|
|
388
399
|
* Event for when the viewport is resized <br>
|
|
389
400
|
* (this usually follows a WINDOW_ONRESIZE event, when using the `flex` scaling mode is used and after the viewport was updated).<br>
|
|
390
401
|
* Data passed : {number} viewport width <br>
|
|
391
|
-
* Data passed : {number} viewport height
|
|
402
|
+
* Data passed : {number} viewport height <br>
|
|
403
|
+
* Data passed : {Camera2d} a reference to the camera viewport being resized
|
|
392
404
|
* @public
|
|
393
405
|
* @constant
|
|
394
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;
|
package/src/system/save.js
CHANGED
|
@@ -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
|
-
|
|
36
|
-
|
|
34
|
+
// Variable to hold the object data
|
|
35
|
+
var data = {};
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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
|
}
|
package/src/system/timer.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
16
|
-
* Use this value to scale velocities during frame drops due to slow
|
|
17
|
-
*
|
|
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
|
|
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
|
|
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
|
|
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/bitmaptext.js
CHANGED
|
@@ -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 =
|
|
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";
|
|
@@ -205,18 +204,6 @@ class Text extends Renderable {
|
|
|
205
204
|
this.setText(settings.text);
|
|
206
205
|
}
|
|
207
206
|
|
|
208
|
-
/** @ignore */
|
|
209
|
-
onDeactivateEvent() {
|
|
210
|
-
// free the canvas and potential corresponding texture when deactivated
|
|
211
|
-
if (this.offScreenCanvas === true) {
|
|
212
|
-
globalRenderer.currentCompositor.deleteTexture2D(globalRenderer.currentCompositor.getTexture2D(this.glTextureUnit));
|
|
213
|
-
globalRenderer.cache.delete(this.canvasTexture.canvas);
|
|
214
|
-
pool.push(this.canvasTexture);
|
|
215
|
-
this.canvasTexture = undefined;
|
|
216
|
-
this.glTextureUnit = undefined;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
207
|
/**
|
|
221
208
|
* make the font bold
|
|
222
209
|
* @returns {Text} this object for chaining
|
|
@@ -423,7 +410,7 @@ class Text extends Renderable {
|
|
|
423
410
|
setContextStyle(context, this, stroke);
|
|
424
411
|
|
|
425
412
|
for (var i = 0; i < text.length; i++) {
|
|
426
|
-
var string =
|
|
413
|
+
var string = text[i].trimRight();
|
|
427
414
|
// draw the string
|
|
428
415
|
context[stroke ? "strokeText" : "fillText"](string, x, y);
|
|
429
416
|
// add leading space
|
|
@@ -437,6 +424,15 @@ class Text extends Renderable {
|
|
|
437
424
|
* @ignore
|
|
438
425
|
*/
|
|
439
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
|
+
}
|
|
440
436
|
pool.push(this.fillStyle);
|
|
441
437
|
pool.push(this.strokeStyle);
|
|
442
438
|
this.fillStyle = this.strokeStyle = undefined;
|
package/src/text/textmetrics.js
CHANGED
|
@@ -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(
|
|
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);
|
package/src/tweens/tween.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import timer from "./../system/timer.js";
|
|
2
2
|
import * as event from "./../system/event.js";
|
|
3
|
-
import
|
|
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
|
|
package/src/utils/string.js
CHANGED
|
@@ -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
|
|
@@ -82,3 +58,16 @@ export function toHex(str) {
|
|
|
82
58
|
}
|
|
83
59
|
return res;
|
|
84
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
|
+
};
|
|
@@ -743,11 +743,11 @@ class CanvasRenderer extends Renderer {
|
|
|
743
743
|
}
|
|
744
744
|
|
|
745
745
|
// https://github.com/melonjs/melonJS/issues/648
|
|
746
|
-
|
|
746
|
+
if (mask instanceof RoundRect) {
|
|
747
747
|
context.roundRect(mask.top, mask.left, mask.width, mask.height, mask.radius);
|
|
748
748
|
} else if (mask instanceof Rect || mask instanceof Bounds) {
|
|
749
749
|
context.rect(mask.top, mask.left, mask.width, mask.height);
|
|
750
|
-
}
|
|
750
|
+
} else if (mask instanceof Ellipse) {
|
|
751
751
|
const _x = mask.pos.x, _y = mask.pos.y,
|
|
752
752
|
hw = mask.radiusV.x,
|
|
753
753
|
hh = mask.radiusV.y,
|
|
@@ -769,6 +769,7 @@ class CanvasRenderer extends Renderer {
|
|
|
769
769
|
context.bezierCurveTo(xmin, by, lx, ymax, lx, _y);
|
|
770
770
|
context.bezierCurveTo(lx, ymin, xmin, ty, _x, ty);
|
|
771
771
|
} else {
|
|
772
|
+
// polygon
|
|
772
773
|
const _x = mask.pos.x, _y = mask.pos.y;
|
|
773
774
|
var point;
|
|
774
775
|
|
package/src/video/renderer.js
CHANGED
|
@@ -2,7 +2,7 @@ import Color from "./../math/color.js";
|
|
|
2
2
|
import Matrix3d from "./../math/matrix3.js";
|
|
3
3
|
import { createCanvas, renderer } from "./video.js";
|
|
4
4
|
import * as event from "./../system/event.js";
|
|
5
|
-
import device from "./../system/device.js";
|
|
5
|
+
import * as device from "./../system/device.js";
|
|
6
6
|
import { setPrefixed } from "./../utils/agent.js";
|
|
7
7
|
import Rect from "./../geometries/rectangle.js";
|
|
8
8
|
import RoundRect from "./../geometries/roundrect.js";
|
|
@@ -22,7 +22,7 @@ class Renderer {
|
|
|
22
22
|
* @param {number} options.width The width of the canvas without scaling
|
|
23
23
|
* @param {number} options.height The height of the canvas without scaling
|
|
24
24
|
* @param {HTMLCanvasElement} [options.canvas] The html canvas to draw to on screen
|
|
25
|
-
* @param {boolean} [options.doubleBuffering=false] Whether to enable double buffering
|
|
25
|
+
* @param {boolean} [options.doubleBuffering=false] Whether to enable double buffering (not applicable when using the WebGL Renderer)
|
|
26
26
|
* @param {boolean} [options.antiAlias=false] Whether to enable anti-aliasing, use false (default) for a pixelated effect.
|
|
27
27
|
* @param {boolean} [options.failIfMajorPerformanceCaveat=true] If true, the renderer will switch to CANVAS mode if the performances of a WebGL context would be dramatically lower than that of a native application making equivalent OpenGL calls.
|
|
28
28
|
* @param {boolean} [options.transparent=false] Whether to enable transparency on the canvas (performance hit when enabled)
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { createCanvas } from "./../video.js";
|
|
2
|
+
import { setPrefixed } from "./../../utils/agent.js";
|
|
2
3
|
|
|
3
|
-
// default
|
|
4
|
+
// default canvas settings
|
|
4
5
|
var defaultAttributes = {
|
|
5
6
|
offscreenCanvas : false,
|
|
6
|
-
willReadFrequently : false
|
|
7
|
+
willReadFrequently : false,
|
|
8
|
+
antiAlias : false
|
|
7
9
|
};
|
|
8
10
|
|
|
9
11
|
/**
|
|
@@ -16,6 +18,7 @@ class CanvasTexture {
|
|
|
16
18
|
* @param {object} attributes The attributes to create both the canvas and 2d context
|
|
17
19
|
* @param {boolean} [attributes.offscreenCanvas=false] will create an offscreenCanvas if true instead of a standard canvas
|
|
18
20
|
* @param {boolean} [attributes.willReadFrequently=false] Indicates whether or not a lot of read-back operations are planned
|
|
21
|
+
* @param {boolean} [attributes.antiAlias=false] Whether to enable anti-aliasing, use false (default) for a pixelated effect.
|
|
19
22
|
*/
|
|
20
23
|
constructor(width, height, attributes = defaultAttributes) {
|
|
21
24
|
|
|
@@ -33,6 +36,9 @@ class CanvasTexture {
|
|
|
33
36
|
* @type {CanvasRenderingContext2D}
|
|
34
37
|
*/
|
|
35
38
|
this.context = this.canvas.getContext("2d", { willReadFrequently: attributes.willReadFrequently });
|
|
39
|
+
|
|
40
|
+
// enable or disable antiAlias if specified
|
|
41
|
+
this.setAntiAlias(attributes.antiAlias);
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
/**
|
|
@@ -51,6 +57,34 @@ class CanvasTexture {
|
|
|
51
57
|
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
52
58
|
}
|
|
53
59
|
|
|
60
|
+
/**
|
|
61
|
+
* enable/disable image smoothing (scaling interpolation)
|
|
62
|
+
* @param {boolean} [enable=false]
|
|
63
|
+
*/
|
|
64
|
+
setAntiAlias(enable = false) {
|
|
65
|
+
var canvas = this.canvas;
|
|
66
|
+
|
|
67
|
+
// enable/disable antialias on the given Context2d object
|
|
68
|
+
setPrefixed("imageSmoothingEnabled", enable, this.context);
|
|
69
|
+
|
|
70
|
+
// set antialias CSS property on the main canvas
|
|
71
|
+
if (typeof canvas.style !== "undefined") {
|
|
72
|
+
if (enable !== true) {
|
|
73
|
+
// https://developer.mozilla.org/en-US/docs/Web/CSS/image-rendering
|
|
74
|
+
canvas.style["image-rendering"] = "optimizeSpeed"; // legal fallback
|
|
75
|
+
canvas.style["image-rendering"] = "-moz-crisp-edges"; // Firefox
|
|
76
|
+
canvas.style["image-rendering"] = "-o-crisp-edges"; // Opera
|
|
77
|
+
canvas.style["image-rendering"] = "-webkit-optimize-contrast"; // Safari
|
|
78
|
+
canvas.style["image-rendering"] = "optimize-contrast"; // CSS 3
|
|
79
|
+
canvas.style["image-rendering"] = "crisp-edges"; // CSS 4
|
|
80
|
+
canvas.style["image-rendering"] = "pixelated"; // CSS 4
|
|
81
|
+
canvas.style.msInterpolationMode = "nearest-neighbor"; // IE8+
|
|
82
|
+
} else {
|
|
83
|
+
canvas.style["image-rendering"] = "auto";
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
54
88
|
/**
|
|
55
89
|
* Resizes the canvas texture to the given width and height.
|
|
56
90
|
* @param {number} width the desired width
|