The Headless render mode has been implemented. You can now set HEADLESS as the renderType in the Game Config and it will run a special game step that skips rendering. It will still create a Canvas element, as lots of internal systems (like input) rely on it, but it will not draw anything to it. Fix #3256

This commit is contained in:
Richard Davey 2018-02-28 21:57:32 +00:00
parent a223b35ccf
commit 252a76f416
5 changed files with 83 additions and 14 deletions

View file

@ -9,6 +9,7 @@
* Game.Config.roundPixels property added to prevent sub-pixel interpolation during rendering of Game Objects in WebGL and Canvas.
* Load.plugin now accepts a class as an argument as well as a URL string (thanks @nkholski)
* Tween.complete will allow you to flag a tween as being complete, no matter what stage it is at. If an onComplete callback has been defined it will be invoked. You can set an optional delay before this happens (thanks @Jerenaux for the idea)
* The Headless render mode has been implemented. You can now set HEADLESS as the `renderType` in the Game Config and it will run a special game step that skips rendering. It will still create a Canvas element, as lots of internal systems (like input) rely on it, but it will not draw anything to it. Fix #3256 (thanks @rgk)
### Bug Fixes

View file

@ -25,23 +25,27 @@ var CreateRenderer = function (game)
// Game either requested Canvas,
// or requested AUTO or WEBGL but the browser doesn't support it, so fall back to Canvas
if (config.renderType === CONST.CANVAS || (config.renderType !== CONST.CANVAS && !Features.webGL))
if (config.renderType !== CONST.HEADLESS)
{
if (Features.canvas)
if (config.renderType === CONST.CANVAS || (config.renderType !== CONST.CANVAS && !Features.webGL))
{
// They requested Canvas and their browser supports it
config.renderType = CONST.CANVAS;
if (Features.canvas)
{
// They requested Canvas and their browser supports it
config.renderType = CONST.CANVAS;
}
else
{
throw new Error('Cannot create Canvas or WebGL context, aborting.');
}
}
else
{
throw new Error('Cannot create Canvas or WebGL context, aborting.');
// Game requested WebGL and browser says it supports it
config.renderType = CONST.WEBGL;
}
}
else
{
// Game requested WebGL and browser says it supports it
config.renderType = CONST.WEBGL;
}
// Pixel Art mode?
if (config.pixelArt)
@ -78,6 +82,12 @@ var CreateRenderer = function (game)
game.canvas.style.height = (config.height * config.zoom).toString() + 'px';
}
if (config.renderType === CONST.HEADLESS)
{
// Nothing more to do here
return;
}
var CanvasRenderer;
var WebGLRenderer;

View file

@ -25,7 +25,16 @@ var DebugHeader = function (game)
return;
}
var renderType = (config.renderType === CONST.CANVAS) ? 'Canvas' : 'WebGL';
var renderType = 'WebGL';
if (config.renderType === CONST.CANVAS)
{
renderType = 'Canvas';
}
else if (config.renderType === CONST.HEADLESS)
{
renderType = 'Headless';
}
var audioConfig = config.audio;
var deviceAudio = game.device.audio;

View file

@ -294,7 +294,14 @@ var Game = new Class({
this.config.postBoot();
this.loop.start(this.step.bind(this));
if (this.renderer)
{
this.loop.start(this.step.bind(this));
}
else
{
this.loop.start(this.headlessStep.bind(this));
}
VisibilityHandler(this.events);
@ -370,6 +377,45 @@ var Game = new Class({
this.events.emit('postrender', renderer);
},
/**
* A special version of the Game Step for the HEADLESS renderer only.
*
* The main Game Step. Called automatically by the Time Step, once per browser frame (typically as a result of
* Request Animation Frame, or Set Timeout on very old browsers.)
*
* The step will update the global managers first, then proceed to update each Scene in turn, via the Scene Manager.
*
* This process emits `prerender` and `postrender` events, even though nothing actually displays.
*
* @method Phaser.Game#headlessStep
* @fires Phaser.Game#prerenderEvent
* @fires Phaser.Game#postrenderEvent
* @since 3.2.0
*
* @param {integer} time - The current timestamp as generated by the Request Animation Frame or SetTimeout.
* @param {number} delta - The delta time elapsed since the last frame.
*/
headlessStep: function (time, delta)
{
// Global Managers
this.input.update(time, delta);
this.sound.update(time, delta);
// Scenes
this.onStepCallback();
this.scene.update(time, delta);
// Render
this.events.emit('prerender');
this.events.emit('postrender');
},
/**
* Game Pause event.
*

View file

@ -52,10 +52,11 @@ var Pipeline = {
{
var renderer = this.scene.sys.game.renderer;
if (renderer.gl && renderer.hasPipeline(pipelineName))
if (renderer && renderer.gl && renderer.hasPipeline(pipelineName))
{
this.defaultPipeline = renderer.getPipeline(pipelineName);
this.pipeline = this.defaultPipeline;
return true;
}
@ -77,9 +78,10 @@ var Pipeline = {
{
var renderer = this.scene.sys.game.renderer;
if (renderer.gl && renderer.hasPipeline(pipelineName))
if (renderer && renderer.gl && renderer.hasPipeline(pipelineName))
{
this.pipeline = renderer.getPipeline(pipelineName);
return true;
}
@ -98,6 +100,7 @@ var Pipeline = {
resetPipeline: function ()
{
this.pipeline = this.defaultPipeline;
return (this.pipeline !== null);
},