Skip to content

Commit 3852592

Browse files
committed
[#1139] allows specifying a custom renderer
1 parent 3e04b7f commit 3852592

File tree

5 files changed

+64
-10
lines changed

5 files changed

+64
-10
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## [14.3.0] (melonJS 2) - _2022-12-XX_
44

5+
### Added
6+
- Core: its now possible to specify a custom renderer (that extends the default Renderer class)
7+
58
### Changed
69
- General: further code revamping to make melonJS more modular and allow instantiation of different app/games
710
- Physic: new `Detector` class instantiated by each physic world instance to detect and solve collisions

src/application/application.js

+8-7
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,15 @@ const AUTO = 2;
3939
* @param {number} height - The height of the canvas viewport
4040
* @param {object} [options] - The optional video/renderer parameters.<br> (see Renderer(s) documentation for further specific options)
4141
* @param {string|HTMLElement} [options.parent=document.body] - the DOM parent element to hold the canvas in the HTML file
42-
* @param {number} [options.renderer=video.AUTO] - renderer to use (me.video.CANVAS, me.video.WEBGL, me.video.AUTO)
42+
* @param {number|Renderer} [options.renderer=video.AUTO] - renderer to use (me.video.CANVAS, me.video.WEBGL, me.video.AUTO), or a custom renderer class
4343
* @param {number|string} [options.scale=1.0] - enable scaling of the canvas ('auto' for automatic scaling)
4444
* @param {string} [options.scaleMethod="fit"] - screen scaling modes ('fit','fill-min','fill-max','flex','flex-width','flex-height','stretch')
4545
* @param {boolean} [options.preferWebGL1=false] - if true the renderer will only use WebGL 1
4646
* @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.
4747
* @param {boolean} [options.transparent=false] - whether to allow transparent pixels in the front buffer (screen).
4848
* @param {boolean} [options.antiAlias=false] - whether to enable or not video scaling interpolation
4949
* @param {boolean} [options.consoleHeader=true] - whether to display melonJS version and basic device information in the console
50+
* @throws Will throw an exception if it fails to instantiate a renderer
5051
*/
5152
constructor(width, height, options) {
5253

@@ -183,7 +184,7 @@ const AUTO = 2;
183184
this.settings.zoomX = width * this.settings.scale;
184185
this.settings.zoomY = height * this.settings.scale;
185186

186-
try {
187+
if (typeof this.settings.renderer === "number") {
187188
switch (this.settings.renderer) {
188189
case AUTO:
189190
case WEBGL:
@@ -193,10 +194,10 @@ const AUTO = 2;
193194
this.renderer = new CanvasRenderer(this.settings);
194195
break;
195196
}
196-
} catch (e) {
197-
console(e.message);
198-
// me.video.init() returns false if failing at creating/using a HTML5 canvas
199-
return false;
197+
} else {
198+
var CustomRenderer = this.settings.renderer;
199+
// a renderer class
200+
this.renderer = new CustomRenderer(this.settings);
200201
}
201202

202203
// register to the channel
@@ -228,7 +229,7 @@ const AUTO = 2;
228229
}
229230

230231
if (this.settings.consoleHeader !== false) {
231-
var renderType = (this.renderer instanceof CanvasRenderer) ? "CANVAS" : "WebGL" + this.renderer.WebGLVersion;
232+
var renderType = typeof this.settings.renderer === "number" ? (this.renderer instanceof CanvasRenderer ? "CANVAS" : "WebGL" + this.renderer.WebGLVersion) : "Custom";
232233
var audioType = device.hasWebAudio ? "Web Audio" : "HTML5 Audio";
233234
var gpu_renderer = (typeof this.renderer.GPURenderer === "string") ? " (" + this.renderer.GPURenderer + ")" : "";
234235
// output video information in the console

src/video/video.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export let renderer = null;
5757
* @param {number} height - The height of the canvas viewport
5858
* @param {object} [options] - The optional video/renderer parameters.<br> (see Renderer(s) documentation for further specific options)
5959
* @param {string|HTMLElement} [options.parent=document.body] - the DOM parent element to hold the canvas in the HTML file
60-
* @param {number} [options.renderer=video.AUTO] - renderer to use (me.video.CANVAS, me.video.WEBGL, me.video.AUTO)
60+
* @param {number|Renderer} [options.renderer=video.AUTO] - renderer to use (me.video.CANVAS, me.video.WEBGL, me.video.AUTO), or a custom renderer class
6161
* @param {number|string} [options.scale=1.0] - enable scaling of the canvas ('auto' for automatic scaling)
6262
* @param {string} [options.scaleMethod="fit"] - screen scaling modes ('fit','fill-min','fill-max','flex','flex-width','flex-height','stretch')
6363
* @param {boolean} [options.preferWebGL1=false] - if true the renderer will only use WebGL 1
@@ -81,8 +81,14 @@ export function init(width, height, options) {
8181
throw new Error("me.video.init() called before engine initialization.");
8282
}
8383

84-
// initialize the default game Application with the given options
85-
game.init(width, height, options);
84+
try {
85+
// initialize the default game Application with the given options
86+
game.init(width, height, options);
87+
} catch (e) {
88+
console(e.message);
89+
// me.video.init() historically returns false if failing at creating/using a HTML5 canvas
90+
return false;
91+
}
8692

8793
// assign the default renderer
8894
renderer = game.renderer;
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Puppeteer Mocha</title>
5+
</head>
6+
<body>
7+
<!-- Canvas placeholder -->
8+
<div id="screen"></div>
9+
<script type="module">
10+
import * as me from './lib/melonjs.module.js';
11+
12+
// a custom renderer extending the default canvas one with one `isCustom` property
13+
class CustomRenderer extends me.CanvasRenderer {
14+
constructor(options) {
15+
super(options);
16+
this.isCustom = true;
17+
}
18+
}
19+
20+
me.boot();
21+
me.video.init(800, 600, {parent : "screen", scale : "auto", renderer : CustomRenderer});
22+
23+
// a global reference that we can check later in the corresponding test
24+
globalThis.isCustomRenderer = me.game.renderer.isCustom;
25+
</script>
26+
</body>
27+
</html>

tests/browser/spec/renderer-spec.js

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { expect } from "expect";
2+
3+
describe("Renderer test", function () {
4+
var page;
5+
6+
before(async () => {
7+
page = await browser.newPage();
8+
await page.goto("http://localhost:8042/renderer_test.html", {'waitUntil':'load'});
9+
10+
});
11+
12+
describe("Custom Renderer", async () => {
13+
it("should create a custom renderer", async () => {
14+
expect(await page.evaluate(() => globalThis.isCustomRenderer)).toEqual(true);
15+
});
16+
});
17+
});

0 commit comments

Comments
 (0)