melonjs 9.1.0 → 10.0.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.
- package/{LICENSE → LICENSE.md} +0 -0
- package/README.md +93 -57
- package/dist/melonjs.js +10334 -11179
- package/dist/melonjs.min.js +4 -10
- package/dist/melonjs.module.d.ts +13206 -0
- package/dist/melonjs.module.js +9913 -10872
- package/package.json +19 -14
- package/src/audio/audio.js +477 -553
- package/src/camera/camera2d.js +67 -65
- package/src/entity/draggable.js +26 -35
- package/src/entity/droptarget.js +17 -14
- package/src/entity/entity.js +59 -79
- package/src/game.js +194 -204
- package/src/index.js +12 -30
- package/src/input/gamepad.js +8 -19
- package/src/input/keyboard.js +4 -4
- package/src/input/pointer.js +14 -12
- package/src/input/pointerevent.js +15 -13
- package/src/lang/deprecated.js +2 -887
- package/src/level/level.js +3 -3
- package/src/level/tiled/TMXGroup.js +7 -11
- package/src/level/tiled/TMXLayer.js +33 -32
- package/src/level/tiled/TMXTileMap.js +15 -19
- package/src/level/tiled/TMXTileset.js +5 -5
- package/src/level/tiled/TMXUtils.js +3 -3
- package/src/level/tiled/renderer/TMXRenderer.js +4 -0
- package/src/loader/loader.js +8 -23
- package/src/loader/loadingscreen.js +51 -60
- package/src/math/matrix3.js +1 -1
- package/src/particles/emitter.js +36 -39
- package/src/particles/particle.js +27 -12
- package/src/particles/particlecontainer.js +17 -16
- package/src/physics/body.js +80 -118
- package/src/physics/collision.js +5 -235
- package/src/physics/detector.js +235 -0
- package/src/physics/quadtree.js +14 -14
- package/src/physics/world.js +84 -18
- package/src/plugin/plugin.js +26 -24
- package/src/polyfill/console.js +9 -14
- package/src/renderable/GUI.js +48 -62
- package/src/renderable/collectable.js +11 -4
- package/src/renderable/colorlayer.js +28 -26
- package/src/renderable/container.js +120 -96
- package/src/renderable/imagelayer.js +94 -93
- package/src/renderable/renderable.js +164 -138
- package/src/renderable/sprite.js +42 -44
- package/src/renderable/trigger.js +24 -17
- package/src/shapes/ellipse.js +27 -27
- package/src/shapes/line.js +12 -8
- package/src/shapes/poly.js +77 -49
- package/src/shapes/rectangle.js +193 -268
- package/src/state/stage.js +23 -25
- package/src/state/state.js +35 -86
- package/src/system/device.js +233 -285
- package/src/system/event.js +485 -432
- package/src/system/pooling.js +61 -54
- package/src/system/save.js +17 -16
- package/src/system/timer.js +34 -38
- package/src/text/bitmaptext.js +44 -46
- package/src/text/text.js +39 -34
- package/src/tweens/easing.js +0 -2
- package/src/tweens/interpolation.js +3 -8
- package/src/tweens/tween.js +332 -351
- package/src/utils/function.js +6 -8
- package/src/utils/utils.js +34 -30
- package/src/video/canvas/canvas_renderer.js +13 -8
- package/src/video/renderer.js +8 -7
- package/src/video/texture.js +8 -8
- package/src/video/texture_cache.js +5 -5
- package/src/video/video.js +373 -403
- package/src/video/webgl/glshader.js +2 -2
- package/src/video/webgl/webgl_compositor.js +14 -8
- package/src/video/webgl/webgl_renderer.js +21 -19
- package/plugins/debug/debugPanel.js +0 -770
- package/plugins/debug/font/PressStart2P.fnt +0 -100
- package/plugins/debug/font/PressStart2P.ltr +0 -1
- package/plugins/debug/font/PressStart2P.png +0 -0
- package/plugins/debug/particleDebugPanel.js +0 -303
package/src/video/video.js
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import Vector2d from "./../math/vector2.js";
|
|
2
|
-
import {warning} from "./../lang/deprecated";
|
|
3
2
|
import WebGLRenderer from "./webgl/webgl_renderer.js";
|
|
4
3
|
import CanvasRenderer from "./canvas/canvas_renderer.js";
|
|
5
4
|
import utils from "./../utils/utils.js";
|
|
6
|
-
import event from "./../system/event.js";
|
|
7
|
-
import
|
|
5
|
+
import * as event from "./../system/event.js";
|
|
6
|
+
import { repaint } from "./../game.js";
|
|
8
7
|
import device from "./../system/device.js";
|
|
9
8
|
import { initialized, version } from "./../index.js";
|
|
10
9
|
|
|
10
|
+
/**
|
|
11
|
+
* video functions
|
|
12
|
+
* @namespace me.video
|
|
13
|
+
* @memberOf me
|
|
14
|
+
*/
|
|
15
|
+
|
|
11
16
|
var designRatio = 1;
|
|
12
17
|
var designWidth = 0;
|
|
13
18
|
var designHeight = 0;
|
|
@@ -47,437 +52,402 @@ function autoDetectRenderer(options) {
|
|
|
47
52
|
};
|
|
48
53
|
|
|
49
54
|
/**
|
|
50
|
-
*
|
|
51
|
-
* @
|
|
52
|
-
* @memberOf me
|
|
55
|
+
* callback for window resize event
|
|
56
|
+
* @ignore
|
|
53
57
|
*/
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
* Select the HTML5 Canvas renderer
|
|
58
|
-
* @public
|
|
59
|
-
* @name CANVAS
|
|
60
|
-
* @memberOf me.video
|
|
61
|
-
* @enum {Number}
|
|
62
|
-
*/
|
|
63
|
-
CANVAS : 0,
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Select the WebGL renderer
|
|
67
|
-
* @public
|
|
68
|
-
* @name WEBGL
|
|
69
|
-
* @memberOf me.video
|
|
70
|
-
* @enum {Number}
|
|
71
|
-
*/
|
|
72
|
-
WEBGL : 1,
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Auto-select the renderer (Attempt WebGL first, with fallback to Canvas)
|
|
76
|
-
* @public
|
|
77
|
-
* @name AUTO
|
|
78
|
-
* @memberOf me.video
|
|
79
|
-
* @enum {Number}
|
|
80
|
-
*/
|
|
81
|
-
AUTO : 2,
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* the parent container of the main canvas element
|
|
85
|
-
* @ignore
|
|
86
|
-
* @type {HTMLElement}
|
|
87
|
-
* @readonly
|
|
88
|
-
* @name parent
|
|
89
|
-
* @memberOf me.video
|
|
90
|
-
*/
|
|
91
|
-
parent : null,
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* the scaling ratio to be applied to the display canvas
|
|
95
|
-
* @type {me.Vector2d}
|
|
96
|
-
* @default <1,1>
|
|
97
|
-
* @memberOf me.video
|
|
98
|
-
*/
|
|
99
|
-
scaleRatio : new Vector2d(1, 1),
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Initialize the "video" system (create a canvas based on the given arguments, and the related renderer). <br>
|
|
103
|
-
* melonJS support various scaling mode, that can be enabled <u>once the scale option is set to <b>`auto`</b></u> : <br>
|
|
104
|
-
* - <i><b>`fit`</b></i> : Letterboxed; content is scaled to design aspect ratio <br>
|
|
105
|
-
* <center><img src="images/scale-fit.png"/></center><br>
|
|
106
|
-
* - <i><b>`fill-min`</b></i> : Canvas is resized to fit minimum design resolution; content is scaled to design aspect ratio <br>
|
|
107
|
-
* <center><img src="images/scale-fill-min.png"/></center><br>
|
|
108
|
-
* - <i><b>`fill-max`</b></i> : Canvas is resized to fit maximum design resolution; content is scaled to design aspect ratio <br>
|
|
109
|
-
* <center><img src="images/scale-fill-max.png"/></center><br>
|
|
110
|
-
* - <i><b>`flex`</b><</i> : Canvas width & height is resized to fit; content is scaled to design aspect ratio <br>
|
|
111
|
-
* <center><img src="images/scale-flex.png"/></center><br>
|
|
112
|
-
* - <i><b>`flex-width`</b></i> : Canvas width is resized to fit; content is scaled to design aspect ratio <br>
|
|
113
|
-
* <center><img src="images/scale-flex-width.png"/></center><br>
|
|
114
|
-
* - <i><b>`flex-height`</b></i> : Canvas height is resized to fit; content is scaled to design aspect ratio <br>
|
|
115
|
-
* <center><img src="images/scale-flex-height.png"/></center><br>
|
|
116
|
-
* - <i><b>`stretch`</b></i> : Canvas is resized to fit; content is scaled to screen aspect ratio
|
|
117
|
-
* <center><img src="images/scale-stretch.png"/></center><br>
|
|
118
|
-
* @name init
|
|
119
|
-
* @memberOf me.video
|
|
120
|
-
* @function
|
|
121
|
-
* @param {Number} width The width of the canvas viewport
|
|
122
|
-
* @param {Number} height The height of the canvas viewport
|
|
123
|
-
* @param {Object} [options] The optional video/renderer parameters.<br> (see Renderer(s) documentation for further specific options)
|
|
124
|
-
* @param {String|HTMLElement} [options.parent=document.body] the DOM parent element to hold the canvas in the HTML file
|
|
125
|
-
* @param {Number} [options.renderer=me.video.AUTO] renderer to use (me.video.CANVAS, me.video.WEBGL, me.video.AUTO)
|
|
126
|
-
* @param {Boolean} [options.doubleBuffering=false] enable/disable double buffering
|
|
127
|
-
* @param {Number|String} [options.scale=1.0] enable scaling of the canvas ('auto' for automatic scaling)
|
|
128
|
-
* @param {String} [options.scaleMethod="fit"] screen scaling modes ('fit','fill-min','fill-max','flex','flex-width','flex-height','stretch')
|
|
129
|
-
* @param {Boolean} [options.preferWebGL1=false] if true the renderer will only use WebGL 1
|
|
130
|
-
* @param {String} [options.powerPreference="default"] a hint to the user agent indicating what configuration of GPU is suitable for the WebGL context ("default", "high-performance", "low-power"). To be noted that Safari and Chrome (since version 80) both default to "low-power" to save battery life and improve the user experience on these dual-GPU machines.
|
|
131
|
-
* @param {Boolean} [options.transparent=false] whether to allow transparent pixels in the front buffer (screen).
|
|
132
|
-
* @param {Boolean} [options.antiAlias=false] whether to enable or not video scaling interpolation
|
|
133
|
-
* @param {Boolean} [options.consoleHeader=true] whether to display melonJS version and basic device information in the console
|
|
134
|
-
* @return {Boolean} false if initialization failed (canvas not supported)
|
|
135
|
-
* @see me.CanvasRenderer
|
|
136
|
-
* @see me.WebGLRenderer
|
|
137
|
-
* @example
|
|
138
|
-
* // init the video with a 640x480 canvas
|
|
139
|
-
* me.video.init(640, 480, {
|
|
140
|
-
* parent : "screen",
|
|
141
|
-
* renderer : me.video.AUTO,
|
|
142
|
-
* scale : "auto",
|
|
143
|
-
* scaleMethod : "fit",
|
|
144
|
-
* doubleBuffering : true
|
|
145
|
-
* });
|
|
146
|
-
*/
|
|
147
|
-
init : function (game_width, game_height, options) {
|
|
148
|
-
|
|
149
|
-
// ensure melonjs has been properly initialized
|
|
150
|
-
if (!initialized) {
|
|
151
|
-
throw new Error("me.video.init() called before engine initialization.");
|
|
152
|
-
}
|
|
58
|
+
function onresize() {
|
|
59
|
+
var settings = renderer.settings;
|
|
60
|
+
var scaleX = 1, scaleY = 1;
|
|
153
61
|
|
|
154
|
-
|
|
155
|
-
settings = Object.assign(settings, options || {});
|
|
156
|
-
|
|
157
|
-
// sanitize potential given parameters
|
|
158
|
-
settings.width = game_width;
|
|
159
|
-
settings.height = game_height;
|
|
160
|
-
settings.doubleBuffering = !!(settings.doubleBuffering);
|
|
161
|
-
settings.transparent = !!(settings.transparent);
|
|
162
|
-
settings.antiAlias = !!(settings.antiAlias);
|
|
163
|
-
settings.failIfMajorPerformanceCaveat = !!(settings.failIfMajorPerformanceCaveat);
|
|
164
|
-
settings.subPixel = !!(settings.subPixel);
|
|
165
|
-
settings.verbose = !!(settings.verbose);
|
|
166
|
-
if (settings.scaleMethod.search(/^(fill-(min|max)|fit|flex(-(width|height))?|stretch)$/) !== -1) {
|
|
167
|
-
settings.autoScale = (settings.scale === "auto") || true;
|
|
168
|
-
} else {
|
|
169
|
-
// default scaling method
|
|
170
|
-
settings.scaleMethod = "fit";
|
|
171
|
-
settings.autoScale = (settings.scale === "auto") || false;
|
|
172
|
-
}
|
|
62
|
+
if (settings.autoScale) {
|
|
173
63
|
|
|
174
|
-
//
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
settings.parent = settings.wrapper;
|
|
178
|
-
}
|
|
64
|
+
// set max the canvas max size if CSS values are defined
|
|
65
|
+
var canvasMaxWidth = Infinity;
|
|
66
|
+
var canvasMaxHeight = Infinity;
|
|
179
67
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
68
|
+
if (window.getComputedStyle) {
|
|
69
|
+
var style = window.getComputedStyle(renderer.getScreenCanvas(), null);
|
|
70
|
+
canvasMaxWidth = parseInt(style.maxWidth, 10) || Infinity;
|
|
71
|
+
canvasMaxHeight = parseInt(style.maxHeight, 10) || Infinity;
|
|
184
72
|
}
|
|
185
73
|
|
|
186
|
-
//
|
|
187
|
-
var
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
74
|
+
// get the maximum canvas size within the parent div containing the canvas container
|
|
75
|
+
var nodeBounds = device.getParentBounds(getParent());
|
|
76
|
+
|
|
77
|
+
var _max_width = Math.min(canvasMaxWidth, nodeBounds.width);
|
|
78
|
+
var _max_height = Math.min(canvasMaxHeight, nodeBounds.height);
|
|
79
|
+
|
|
80
|
+
// calculate final canvas width & height
|
|
81
|
+
var screenRatio = _max_width / _max_height;
|
|
82
|
+
|
|
83
|
+
if ((settings.scaleMethod === "fill-min" && screenRatio > designRatio) ||
|
|
84
|
+
(settings.scaleMethod === "fill-max" && screenRatio < designRatio) ||
|
|
85
|
+
(settings.scaleMethod === "flex-width")
|
|
86
|
+
) {
|
|
87
|
+
// resize the display canvas to fill the parent container
|
|
88
|
+
var sWidth = Math.min(canvasMaxWidth, designHeight * screenRatio);
|
|
89
|
+
scaleX = scaleY = _max_width / sWidth;
|
|
90
|
+
renderer.resize(Math.floor(sWidth), designHeight);
|
|
91
|
+
}
|
|
92
|
+
else if ((settings.scaleMethod === "fill-min" && screenRatio < designRatio) ||
|
|
93
|
+
(settings.scaleMethod === "fill-max" && screenRatio > designRatio) ||
|
|
94
|
+
(settings.scaleMethod === "flex-height")
|
|
95
|
+
) {
|
|
96
|
+
// resize the display canvas to fill the parent container
|
|
97
|
+
var sHeight = Math.min(canvasMaxHeight, designWidth * (_max_height / _max_width));
|
|
98
|
+
scaleX = scaleY = _max_height / sHeight;
|
|
99
|
+
renderer.resize(designWidth, Math.floor(sHeight));
|
|
100
|
+
}
|
|
101
|
+
else if (settings.scaleMethod === "flex") {
|
|
102
|
+
// resize the display canvas to fill the parent container
|
|
103
|
+
renderer.resize(Math.floor(_max_width), Math.floor(_max_height));
|
|
104
|
+
}
|
|
105
|
+
else if (settings.scaleMethod === "stretch") {
|
|
106
|
+
// scale the display canvas to fit with the parent container
|
|
107
|
+
scaleX = _max_width / designWidth;
|
|
108
|
+
scaleY = _max_height / designHeight;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
// scale the display canvas to fit the parent container
|
|
112
|
+
// make sure we maintain the original aspect ratio
|
|
113
|
+
if (screenRatio < designRatio) {
|
|
114
|
+
scaleX = scaleY = _max_width / designWidth;
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
scaleX = scaleY = _max_height / designHeight;
|
|
192
118
|
}
|
|
193
119
|
}
|
|
194
120
|
|
|
195
|
-
//
|
|
196
|
-
|
|
197
|
-
|
|
121
|
+
// adjust scaling ratio based on the new scaling ratio
|
|
122
|
+
scale(scaleX, scaleY);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
198
125
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
126
|
+
/**
|
|
127
|
+
* Select the HTML5 Canvas renderer
|
|
128
|
+
* @name CANVAS
|
|
129
|
+
* @memberOf me.video
|
|
130
|
+
* @constant
|
|
131
|
+
*/
|
|
132
|
+
export const CANVAS = 0;
|
|
203
133
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
settings.zoomY = game_height * this.scaleRatio.y;
|
|
212
|
-
|
|
213
|
-
//add a channel for the onresize/onorientationchange event
|
|
214
|
-
window.addEventListener(
|
|
215
|
-
"resize",
|
|
216
|
-
utils.function.throttle(
|
|
217
|
-
function (e) {
|
|
218
|
-
event.publish(event.WINDOW_ONRESIZE, [ e ]);
|
|
219
|
-
}, 100
|
|
220
|
-
), false
|
|
221
|
-
);
|
|
134
|
+
/**
|
|
135
|
+
* Select the WebGL renderer
|
|
136
|
+
* @name WEBGL
|
|
137
|
+
* @memberOf me.video
|
|
138
|
+
* @constant
|
|
139
|
+
*/
|
|
140
|
+
export const WEBGL = 1;
|
|
222
141
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
142
|
+
/**
|
|
143
|
+
* Auto-select the renderer (Attempt WebGL first, with fallback to Canvas)
|
|
144
|
+
* @name AUTO
|
|
145
|
+
* @memberOf me.video
|
|
146
|
+
* @constant
|
|
147
|
+
*/
|
|
148
|
+
export const AUTO = 2;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* the parent container of the main canvas element
|
|
152
|
+
* @ignore
|
|
153
|
+
* @type {HTMLElement}
|
|
154
|
+
* @readonly
|
|
155
|
+
* @name parent
|
|
156
|
+
* @memberOf me.video
|
|
157
|
+
*/
|
|
158
|
+
export let parent = null;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* the scaling ratio to be applied to the display canvas
|
|
162
|
+
* @name scaleRatio
|
|
163
|
+
* @type {me.Vector2d}
|
|
164
|
+
* @default <1,1>
|
|
165
|
+
* @memberOf me.video
|
|
166
|
+
*/
|
|
167
|
+
export let scaleRatio = new Vector2d(1, 1);
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* A reference to the active Canvas or WebGL active renderer renderer
|
|
171
|
+
* @name renderer
|
|
172
|
+
* @type {me.CanvasRenderer|me.WebGLRenderer}
|
|
173
|
+
* @memberOf me.video
|
|
174
|
+
*/
|
|
175
|
+
export let renderer = null;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Initialize the "video" system (create a canvas based on the given arguments, and the related renderer). <br>
|
|
179
|
+
* melonJS support various scaling mode, that can be enabled <u>once the scale option is set to <b>`auto`</b></u> : <br>
|
|
180
|
+
* - <i><b>`fit`</b></i> : Letterboxed; content is scaled to design aspect ratio <br>
|
|
181
|
+
* <center><img src="images/scale-fit.png"/></center><br>
|
|
182
|
+
* - <i><b>`fill-min`</b></i> : Canvas is resized to fit minimum design resolution; content is scaled to design aspect ratio <br>
|
|
183
|
+
* <center><img src="images/scale-fill-min.png"/></center><br>
|
|
184
|
+
* - <i><b>`fill-max`</b></i> : Canvas is resized to fit maximum design resolution; content is scaled to design aspect ratio <br>
|
|
185
|
+
* <center><img src="images/scale-fill-max.png"/></center><br>
|
|
186
|
+
* - <i><b>`flex`</b><</i> : Canvas width & height is resized to fit; content is scaled to design aspect ratio <br>
|
|
187
|
+
* <center><img src="images/scale-flex.png"/></center><br>
|
|
188
|
+
* - <i><b>`flex-width`</b></i> : Canvas width is resized to fit; content is scaled to design aspect ratio <br>
|
|
189
|
+
* <center><img src="images/scale-flex-width.png"/></center><br>
|
|
190
|
+
* - <i><b>`flex-height`</b></i> : Canvas height is resized to fit; content is scaled to design aspect ratio <br>
|
|
191
|
+
* <center><img src="images/scale-flex-height.png"/></center><br>
|
|
192
|
+
* - <i><b>`stretch`</b></i> : Canvas is resized to fit; content is scaled to screen aspect ratio
|
|
193
|
+
* <center><img src="images/scale-stretch.png"/></center><br>
|
|
194
|
+
* @function me.video.init
|
|
195
|
+
* @param {Number} width The width of the canvas viewport
|
|
196
|
+
* @param {Number} height The height of the canvas viewport
|
|
197
|
+
* @param {Object} [options] The optional video/renderer parameters.<br> (see Renderer(s) documentation for further specific options)
|
|
198
|
+
* @param {String|HTMLElement} [options.parent=document.body] the DOM parent element to hold the canvas in the HTML file
|
|
199
|
+
* @param {Number} [options.renderer=me.video.AUTO] renderer to use (me.video.CANVAS, me.video.WEBGL, me.video.AUTO)
|
|
200
|
+
* @param {Boolean} [options.doubleBuffering=false] enable/disable double buffering
|
|
201
|
+
* @param {Number|String} [options.scale=1.0] enable scaling of the canvas ('auto' for automatic scaling)
|
|
202
|
+
* @param {String} [options.scaleMethod="fit"] screen scaling modes ('fit','fill-min','fill-max','flex','flex-width','flex-height','stretch')
|
|
203
|
+
* @param {Boolean} [options.preferWebGL1=false] if true the renderer will only use WebGL 1
|
|
204
|
+
* @param {String} [options.powerPreference="default"] a hint to the user agent indicating what configuration of GPU is suitable for the WebGL context ("default", "high-performance", "low-power"). To be noted that Safari and Chrome (since version 80) both default to "low-power" to save battery life and improve the user experience on these dual-GPU machines.
|
|
205
|
+
* @param {Boolean} [options.transparent=false] whether to allow transparent pixels in the front buffer (screen).
|
|
206
|
+
* @param {Boolean} [options.antiAlias=false] whether to enable or not video scaling interpolation
|
|
207
|
+
* @param {Boolean} [options.consoleHeader=true] whether to display melonJS version and basic device information in the console
|
|
208
|
+
* @return {Boolean} false if initialization failed (canvas not supported)
|
|
209
|
+
* @example
|
|
210
|
+
* // init the video with a 640x480 canvas
|
|
211
|
+
* me.video.init(640, 480, {
|
|
212
|
+
* parent : "screen",
|
|
213
|
+
* renderer : me.video.AUTO,
|
|
214
|
+
* scale : "auto",
|
|
215
|
+
* scaleMethod : "fit",
|
|
216
|
+
* doubleBuffering : true
|
|
217
|
+
* });
|
|
218
|
+
*/
|
|
219
|
+
export function init(game_width, game_height, options) {
|
|
220
|
+
|
|
221
|
+
// ensure melonjs has been properly initialized
|
|
222
|
+
if (!initialized) {
|
|
223
|
+
throw new Error("me.video.init() called before engine initialization.");
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// revert to default options if not defined
|
|
227
|
+
settings = Object.assign(settings, options || {});
|
|
228
|
+
|
|
229
|
+
// sanitize potential given parameters
|
|
230
|
+
settings.width = game_width;
|
|
231
|
+
settings.height = game_height;
|
|
232
|
+
settings.doubleBuffering = !!(settings.doubleBuffering);
|
|
233
|
+
settings.transparent = !!(settings.transparent);
|
|
234
|
+
settings.antiAlias = !!(settings.antiAlias);
|
|
235
|
+
settings.failIfMajorPerformanceCaveat = !!(settings.failIfMajorPerformanceCaveat);
|
|
236
|
+
settings.subPixel = !!(settings.subPixel);
|
|
237
|
+
settings.verbose = !!(settings.verbose);
|
|
238
|
+
if (settings.scaleMethod.search(/^(fill-(min|max)|fit|flex(-(width|height))?|stretch)$/) !== -1) {
|
|
239
|
+
settings.autoScale = (settings.scale === "auto") || true;
|
|
240
|
+
} else {
|
|
241
|
+
// default scaling method
|
|
242
|
+
settings.scaleMethod = "fit";
|
|
243
|
+
settings.autoScale = (settings.scale === "auto") || false;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// display melonJS version
|
|
247
|
+
if (settings.consoleHeader !== false) {
|
|
248
|
+
// output video information in the console
|
|
249
|
+
console.log("melonJS 2 (v" + version + ") | http://melonjs.org" );
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// override renderer settings if &webgl is defined in the URL
|
|
253
|
+
var uriFragment = utils.getUriFragment();
|
|
254
|
+
if (uriFragment.webgl === true || uriFragment.webgl1 === true || uriFragment.webgl2 === true) {
|
|
255
|
+
settings.renderer = WEBGL;
|
|
256
|
+
if (uriFragment.webgl1 === true) {
|
|
257
|
+
settings.preferWebGL1 = true;
|
|
244
258
|
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// normalize scale
|
|
262
|
+
settings.scale = (settings.autoScale) ? 1.0 : (+settings.scale || 1.0);
|
|
263
|
+
scaleRatio.set(settings.scale, settings.scale);
|
|
264
|
+
|
|
265
|
+
// force double buffering if scaling is required
|
|
266
|
+
if (settings.autoScale || (settings.scale !== 1.0)) {
|
|
267
|
+
settings.doubleBuffering = true;
|
|
268
|
+
}
|
|
245
269
|
|
|
246
|
-
|
|
247
|
-
|
|
270
|
+
// hold the requested video size ratio
|
|
271
|
+
designRatio = game_width / game_height;
|
|
272
|
+
designWidth = game_width;
|
|
273
|
+
designHeight = game_height;
|
|
274
|
+
|
|
275
|
+
// default scaled size value
|
|
276
|
+
settings.zoomX = game_width * scaleRatio.x;
|
|
277
|
+
settings.zoomY = game_height * scaleRatio.y;
|
|
278
|
+
|
|
279
|
+
//add a channel for the onresize/onorientationchange event
|
|
280
|
+
window.addEventListener(
|
|
281
|
+
"resize",
|
|
282
|
+
utils.function.throttle(
|
|
248
283
|
function (e) {
|
|
249
|
-
event.
|
|
284
|
+
event.emit(event.WINDOW_ONRESIZE, e);
|
|
250
285
|
}, 100
|
|
251
|
-
), false
|
|
286
|
+
), false
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
// Screen Orientation API
|
|
290
|
+
window.addEventListener(
|
|
291
|
+
"orientationchange",
|
|
292
|
+
function (e) {
|
|
293
|
+
event.emit(event.WINDOW_ONORIENTATION_CHANGE, e);
|
|
294
|
+
},
|
|
295
|
+
false
|
|
296
|
+
);
|
|
297
|
+
// pre-fixed implementation on mozzila
|
|
298
|
+
window.addEventListener(
|
|
299
|
+
"onmozorientationchange",
|
|
300
|
+
function (e) {
|
|
301
|
+
event.emit(event.WINDOW_ONORIENTATION_CHANGE, e);
|
|
302
|
+
},
|
|
303
|
+
false
|
|
304
|
+
);
|
|
305
|
+
if (typeof window.screen !== "undefined") {
|
|
306
|
+
// is this one required ?
|
|
307
|
+
window.screen.onorientationchange = function (e) {
|
|
308
|
+
event.emit(event.WINDOW_ONORIENTATION_CHANGE, e);
|
|
309
|
+
};
|
|
310
|
+
}
|
|
252
311
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
312
|
+
// Automatically update relative canvas position on scroll
|
|
313
|
+
window.addEventListener("scroll", utils.function.throttle(
|
|
314
|
+
function (e) {
|
|
315
|
+
event.emit(event.WINDOW_ONSCROLL, e);
|
|
316
|
+
}, 100
|
|
317
|
+
), false);
|
|
318
|
+
|
|
319
|
+
// register to the channel
|
|
320
|
+
event.on(event.WINDOW_ONRESIZE, onresize, this);
|
|
321
|
+
event.on(event.WINDOW_ONORIENTATION_CHANGE, onresize, this);
|
|
322
|
+
|
|
323
|
+
try {
|
|
324
|
+
switch (settings.renderer) {
|
|
325
|
+
case AUTO:
|
|
326
|
+
case WEBGL:
|
|
327
|
+
renderer = autoDetectRenderer(settings);
|
|
328
|
+
break;
|
|
329
|
+
default:
|
|
330
|
+
renderer = new CanvasRenderer(settings);
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
333
|
+
} catch (e) {
|
|
334
|
+
console(e.message);
|
|
335
|
+
// me.video.init() returns false if failing at creating/using a HTML5 canvas
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// add our canvas (default to document.body if settings.parent is undefined)
|
|
340
|
+
parent = device.getElement(settings.parent);
|
|
341
|
+
parent.appendChild(renderer.getScreenCanvas());
|
|
342
|
+
|
|
343
|
+
// trigger an initial resize();
|
|
344
|
+
onresize();
|
|
345
|
+
|
|
346
|
+
// add an observer to detect when the dom tree is modified
|
|
347
|
+
if ("MutationObserver" in window) {
|
|
348
|
+
// Create an observer instance linked to the callback function
|
|
349
|
+
var observer = new MutationObserver(onresize.bind(this));
|
|
350
|
+
|
|
351
|
+
// Start observing the target node for configured mutations
|
|
352
|
+
observer.observe(parent, {
|
|
353
|
+
attributes: false, childList: true, subtree: true
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (settings.consoleHeader !== false) {
|
|
358
|
+
var renderType = (renderer instanceof CanvasRenderer) ? "CANVAS" : "WebGL" + renderer.WebGLVersion;
|
|
359
|
+
var audioType = device.hasWebAudio ? "Web Audio" : "HTML5 Audio";
|
|
360
|
+
var gpu_renderer = (typeof renderer.GPURenderer === "string") ? " (" + renderer.GPURenderer + ")" : "";
|
|
361
|
+
// output video information in the console
|
|
362
|
+
console.log(
|
|
363
|
+
renderType + " renderer" + gpu_renderer + " | " +
|
|
364
|
+
audioType + " | " +
|
|
365
|
+
"pixel ratio " + device.devicePixelRatio + " | " +
|
|
366
|
+
(device.isMobile ? "mobile" : "desktop") + " | " +
|
|
367
|
+
device.getScreenOrientation() + " | " +
|
|
368
|
+
device.language
|
|
257
369
|
);
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
this.onresize.bind(this)
|
|
370
|
+
console.log( "resolution: " + "requested " + game_width + "x" + game_height +
|
|
371
|
+
", got " + renderer.getWidth() + "x" + renderer.getHeight()
|
|
261
372
|
);
|
|
373
|
+
}
|
|
262
374
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
* A reference to the current video renderer
|
|
266
|
-
* @public
|
|
267
|
-
* @memberOf me.video
|
|
268
|
-
* @name renderer
|
|
269
|
-
* @type {me.Renderer|me.CanvasRenderer|me.WebGLRenderer}
|
|
270
|
-
*/
|
|
271
|
-
switch (settings.renderer) {
|
|
272
|
-
case this.AUTO:
|
|
273
|
-
case this.WEBGL:
|
|
274
|
-
this.renderer = autoDetectRenderer(settings);
|
|
275
|
-
break;
|
|
276
|
-
default:
|
|
277
|
-
this.renderer = new CanvasRenderer(settings);
|
|
278
|
-
break;
|
|
279
|
-
}
|
|
280
|
-
} catch (e) {
|
|
281
|
-
console(e.message);
|
|
282
|
-
// me.video.init() returns false if failing at creating/using a HTML5 canvas
|
|
283
|
-
return false;
|
|
284
|
-
}
|
|
375
|
+
// notify the video has been initialized
|
|
376
|
+
event.emit(event.VIDEO_INIT);
|
|
285
377
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
this.parent.appendChild(this.renderer.getScreenCanvas());
|
|
378
|
+
return true;
|
|
379
|
+
};
|
|
289
380
|
|
|
290
|
-
|
|
291
|
-
|
|
381
|
+
/**
|
|
382
|
+
* Create and return a new Canvas element
|
|
383
|
+
* @function me.video.createCanvas
|
|
384
|
+
* @param {Number} width width
|
|
385
|
+
* @param {Number} height height
|
|
386
|
+
* @param {Boolean} [offscreen=false] will returns an OffscreenCanvas if supported
|
|
387
|
+
* @return {HTMLCanvasElement|OffscreenCanvas}
|
|
388
|
+
*/
|
|
389
|
+
export function createCanvas(width, height, offscreen) {
|
|
390
|
+
var _canvas;
|
|
292
391
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
var observer = new MutationObserver(this.onresize.bind(this));
|
|
392
|
+
if (width === 0 || height === 0) {
|
|
393
|
+
throw new Error("width or height was zero, Canvas could not be initialized !");
|
|
394
|
+
}
|
|
297
395
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
396
|
+
if (device.OffscreenCanvas === true && offscreen === true) {
|
|
397
|
+
_canvas = new OffscreenCanvas(0, 0);
|
|
398
|
+
// stubbing style for compatibility,
|
|
399
|
+
// as OffscreenCanvas is detached from the DOM
|
|
400
|
+
if (typeof _canvas.style === "undefined") {
|
|
401
|
+
_canvas.style = {};
|
|
302
402
|
}
|
|
403
|
+
} else {
|
|
404
|
+
// "else" create a "standard" canvas
|
|
405
|
+
_canvas = document.createElement("canvas");
|
|
406
|
+
}
|
|
407
|
+
_canvas.width = width;
|
|
408
|
+
_canvas.height = height;
|
|
303
409
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
var audioType = device.hasWebAudio ? "Web Audio" : "HTML5 Audio";
|
|
307
|
-
var gpu_renderer = (typeof this.renderer.GPURenderer === "string") ? " (" + this.renderer.GPURenderer + ")" : "";
|
|
308
|
-
// output video information in the console
|
|
309
|
-
console.log(
|
|
310
|
-
renderType + " renderer" + gpu_renderer + " | " +
|
|
311
|
-
audioType + " | " +
|
|
312
|
-
"pixel ratio " + device.devicePixelRatio + " | " +
|
|
313
|
-
(device.isMobile ? "mobile" : "desktop") + " | " +
|
|
314
|
-
device.getScreenOrientation() + " | " +
|
|
315
|
-
device.language
|
|
316
|
-
);
|
|
317
|
-
console.log( "resolution: " + "requested " + game_width + "x" + game_height +
|
|
318
|
-
", got " + this.renderer.getWidth() + "x" + this.renderer.getHeight()
|
|
319
|
-
);
|
|
320
|
-
}
|
|
410
|
+
return _canvas;
|
|
411
|
+
};
|
|
321
412
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
* @name createCanvas
|
|
331
|
-
* @memberOf me.video
|
|
332
|
-
* @function
|
|
333
|
-
* @param {Number} width width
|
|
334
|
-
* @param {Number} height height
|
|
335
|
-
* @param {Boolean} [offscreen=false] will returns an OffscreenCanvas if supported
|
|
336
|
-
* @return {HTMLCanvasElement|OffscreenCanvas}
|
|
337
|
-
*/
|
|
338
|
-
createCanvas : function (width, height, offscreen) {
|
|
339
|
-
var _canvas;
|
|
340
|
-
|
|
341
|
-
if (width === 0 || height === 0) {
|
|
342
|
-
throw new Error("width or height was zero, Canvas could not be initialized !");
|
|
343
|
-
}
|
|
413
|
+
/**
|
|
414
|
+
* return a reference to the parent DOM element holding the main canvas
|
|
415
|
+
* @function me.video.getParent
|
|
416
|
+
* @return {HTMLElement}
|
|
417
|
+
*/
|
|
418
|
+
export function getParent() {
|
|
419
|
+
return parent;
|
|
420
|
+
};
|
|
344
421
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
return _canvas;
|
|
360
|
-
},
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* return a reference to the parent DOM element holding the main canvas
|
|
364
|
-
* @name getParent
|
|
365
|
-
* @memberOf me.video
|
|
366
|
-
* @function
|
|
367
|
-
* @return {HTMLElement}
|
|
368
|
-
*/
|
|
369
|
-
getParent : function () {
|
|
370
|
-
return this.parent;
|
|
371
|
-
},
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
* callback for window resize event
|
|
375
|
-
* @ignore
|
|
376
|
-
*/
|
|
377
|
-
onresize : function () {
|
|
378
|
-
var renderer = this.renderer;
|
|
379
|
-
var settings = renderer.settings;
|
|
380
|
-
var scaleX = 1, scaleY = 1;
|
|
381
|
-
|
|
382
|
-
if (settings.autoScale) {
|
|
383
|
-
|
|
384
|
-
// set max the canvas max size if CSS values are defined
|
|
385
|
-
var canvasMaxWidth = Infinity;
|
|
386
|
-
var canvasMaxHeight = Infinity;
|
|
387
|
-
|
|
388
|
-
if (window.getComputedStyle) {
|
|
389
|
-
var style = window.getComputedStyle(renderer.getScreenCanvas(), null);
|
|
390
|
-
canvasMaxWidth = parseInt(style.maxWidth, 10) || Infinity;
|
|
391
|
-
canvasMaxHeight = parseInt(style.maxHeight, 10) || Infinity;
|
|
392
|
-
}
|
|
422
|
+
/**
|
|
423
|
+
* scale the "displayed" canvas by the given scalar.
|
|
424
|
+
* this will modify the size of canvas element directly.
|
|
425
|
+
* Only use this if you are not using the automatic scaling feature.
|
|
426
|
+
* @function me.video.scale
|
|
427
|
+
* @see me.video.init
|
|
428
|
+
* @param {Number} x x scaling multiplier
|
|
429
|
+
* @param {Number} y y scaling multiplier
|
|
430
|
+
*/
|
|
431
|
+
export function scale(x, y) {
|
|
432
|
+
var canvas = renderer.getScreenCanvas();
|
|
433
|
+
var context = renderer.getScreenContext();
|
|
434
|
+
var settings = renderer.settings;
|
|
435
|
+
var pixelRatio = device.devicePixelRatio;
|
|
393
436
|
|
|
394
|
-
|
|
395
|
-
|
|
437
|
+
var w = settings.zoomX = canvas.width * x * pixelRatio;
|
|
438
|
+
var h = settings.zoomY = canvas.height * y * pixelRatio;
|
|
396
439
|
|
|
397
|
-
|
|
398
|
-
|
|
440
|
+
// update the global scale variable
|
|
441
|
+
scaleRatio.set(x * pixelRatio, y * pixelRatio);
|
|
399
442
|
|
|
400
|
-
|
|
401
|
-
|
|
443
|
+
// adjust CSS style based on device pixel ratio
|
|
444
|
+
canvas.style.width = (w / pixelRatio) + "px";
|
|
445
|
+
canvas.style.height = (h / pixelRatio) + "px";
|
|
402
446
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
) {
|
|
407
|
-
// resize the display canvas to fill the parent container
|
|
408
|
-
var sWidth = Math.min(canvasMaxWidth, designHeight * screenRatio);
|
|
409
|
-
scaleX = scaleY = _max_width / sWidth;
|
|
410
|
-
renderer.resize(Math.floor(sWidth), designHeight);
|
|
411
|
-
}
|
|
412
|
-
else if ((settings.scaleMethod === "fill-min" && screenRatio < designRatio) ||
|
|
413
|
-
(settings.scaleMethod === "fill-max" && screenRatio > designRatio) ||
|
|
414
|
-
(settings.scaleMethod === "flex-height")
|
|
415
|
-
) {
|
|
416
|
-
// resize the display canvas to fill the parent container
|
|
417
|
-
var sHeight = Math.min(canvasMaxHeight, designWidth * (_max_height / _max_width));
|
|
418
|
-
scaleX = scaleY = _max_height / sHeight;
|
|
419
|
-
renderer.resize(designWidth, Math.floor(sHeight));
|
|
420
|
-
}
|
|
421
|
-
else if (settings.scaleMethod === "flex") {
|
|
422
|
-
// resize the display canvas to fill the parent container
|
|
423
|
-
renderer.resize(Math.floor(_max_width), Math.floor(_max_height));
|
|
424
|
-
}
|
|
425
|
-
else if (settings.scaleMethod === "stretch") {
|
|
426
|
-
// scale the display canvas to fit with the parent container
|
|
427
|
-
scaleX = _max_width / designWidth;
|
|
428
|
-
scaleY = _max_height / designHeight;
|
|
429
|
-
}
|
|
430
|
-
else {
|
|
431
|
-
// scale the display canvas to fit the parent container
|
|
432
|
-
// make sure we maintain the original aspect ratio
|
|
433
|
-
if (screenRatio < designRatio) {
|
|
434
|
-
scaleX = scaleY = _max_width / designWidth;
|
|
435
|
-
}
|
|
436
|
-
else {
|
|
437
|
-
scaleX = scaleY = _max_height / designHeight;
|
|
438
|
-
}
|
|
439
|
-
}
|
|
447
|
+
// if anti-alias and blend mode were resetted (e.g. Canvas mode)
|
|
448
|
+
renderer.setAntiAlias(context, settings.antiAlias);
|
|
449
|
+
renderer.setBlendMode(settings.blendMode, context);
|
|
440
450
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
}
|
|
444
|
-
},
|
|
445
|
-
|
|
446
|
-
/**
|
|
447
|
-
* scale the "displayed" canvas by the given scalar.
|
|
448
|
-
* this will modify the size of canvas element directly.
|
|
449
|
-
* Only use this if you are not using the automatic scaling feature.
|
|
450
|
-
* @name scale
|
|
451
|
-
* @memberOf me.video
|
|
452
|
-
* @function
|
|
453
|
-
* @see me.video.init
|
|
454
|
-
* @param {Number} x x scaling multiplier
|
|
455
|
-
* @param {Number} y y scaling multiplier
|
|
456
|
-
*/
|
|
457
|
-
scale : function (x, y) {
|
|
458
|
-
var renderer = this.renderer;
|
|
459
|
-
var canvas = renderer.getScreenCanvas();
|
|
460
|
-
var context = renderer.getScreenContext();
|
|
461
|
-
var settings = renderer.settings;
|
|
462
|
-
var pixelRatio = device.devicePixelRatio;
|
|
463
|
-
|
|
464
|
-
var w = settings.zoomX = canvas.width * x * pixelRatio;
|
|
465
|
-
var h = settings.zoomY = canvas.height * y * pixelRatio;
|
|
466
|
-
|
|
467
|
-
// update the global scale variable
|
|
468
|
-
this.scaleRatio.set(x * pixelRatio, y * pixelRatio);
|
|
469
|
-
|
|
470
|
-
// adjust CSS style based on device pixel ratio
|
|
471
|
-
canvas.style.width = (w / pixelRatio) + "px";
|
|
472
|
-
canvas.style.height = (h / pixelRatio) + "px";
|
|
473
|
-
|
|
474
|
-
// if anti-alias and blend mode were resetted (e.g. Canvas mode)
|
|
475
|
-
renderer.setAntiAlias(context, settings.antiAlias);
|
|
476
|
-
renderer.setBlendMode(settings.blendMode, context);
|
|
477
|
-
|
|
478
|
-
// force repaint
|
|
479
|
-
game.repaint();
|
|
480
|
-
}
|
|
451
|
+
// force repaint
|
|
452
|
+
repaint();
|
|
481
453
|
};
|
|
482
|
-
|
|
483
|
-
export default video;
|