From 19483bafedb9bcd8c2b7ca26c0bcb01213875c6d Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Thu, 29 Aug 2013 17:20:59 +0100 Subject: [PATCH] Canvas and Stage added and starting to merge in Pixi deeply. --- examples/flow.php | 4 +- examples/js.php | 3 +- examples/stage 1.php | 38 ++++++++ src/Game.js | 73 ++++++++++++--- src/Stage.js | 76 +++++++++++++++ src/core/StateManager.js | 1 - src/system/Canvas.js | 193 +++++++++++++++++++++++++++++++++++++++ src/system/Device.js | 2 +- 8 files changed, 372 insertions(+), 18 deletions(-) create mode 100644 examples/stage 1.php create mode 100644 src/Stage.js create mode 100644 src/system/Canvas.js diff --git a/examples/flow.php b/examples/flow.php index 79a23662..285f543c 100644 --- a/examples/flow.php +++ b/examples/flow.php @@ -13,10 +13,8 @@ // Your game will work either from within a closure or not, it doesn't matter (function () { - var game = new Phaser.Game(800, 600, Phaser.RENDERER_AUTO, '', { preload: preload, create: create }); - // In this approach we're simply using functions in the current scope to do what we need - // game.launch(this, preload, create); + var game = new Phaser.Game(800, 600, Phaser.RENDERER_AUTO, '', { preload: preload, create: create }); function preload() { diff --git a/examples/js.php b/examples/js.php index 73b8e9a4..7f8081cf 100644 --- a/examples/js.php +++ b/examples/js.php @@ -37,7 +37,7 @@ - + @@ -65,4 +65,5 @@ + diff --git a/examples/stage 1.php b/examples/stage 1.php new file mode 100644 index 00000000..4e121757 --- /dev/null +++ b/examples/stage 1.php @@ -0,0 +1,38 @@ + + + + phaser.js - a new beginning + + + + + + + + \ No newline at end of file diff --git a/src/Game.js b/src/Game.js index 6bfd5831..a1126e7b 100644 --- a/src/Game.js +++ b/src/Game.js @@ -24,13 +24,15 @@ * @param renderer {number} Which renderer to use (canvas or webgl) * @param parent {string} ID of its parent DOM element. */ -Phaser.Game = function (width, height, renderer, parent, state) { +Phaser.Game = function (width, height, renderer, parent, state, transparent, antialias) { if (typeof width === "undefined") { width = 800; } if (typeof height === "undefined") { height = 600; } if (typeof renderer === "undefined") { renderer = Phaser.RENDERER_AUTO; } if (typeof parent === "undefined") { parent = ''; } if (typeof state === "undefined") { state = null; } + if (typeof transparent === "undefined") { transparent = false; } + if (typeof antialias === "undefined") { antialias = true; } this.id = Phaser.GAMES.push(this) - 1; this.parent = parent; @@ -38,10 +40,12 @@ Phaser.Game = function (width, height, renderer, parent, state) { // Do some more intelligent size parsing here, so they can set "100%" for example, maybe pass the scale mode in here too? this.width = width; this.height = height; + this.transparent = transparent; + this.antialias = antialias; + this.renderType = renderer; + // this.renderer = renderer; - this.renderer = renderer; - - console.log('Phaser.Game', width, height, renderer, parent); + console.log('Phaser.Game', width, height, renderer, parent, transparent, antialias); this.state = new Phaser.StateManager(this, state); @@ -89,6 +93,9 @@ Phaser.Game.prototype = { */ height: 0, + transparent: false, + antialias: true, + /** * The Games DOM parent. * @type {HTMLElement} @@ -99,7 +106,13 @@ Phaser.Game.prototype = { * The Renderer this Phaser.Game will use. Either Phaser.RENDERER_AUTO, Phaser.RENDERER_CANVAS or Phaser.RENDERER_WEBGL * @type {number} */ - renderer: 0, + renderType: 0, + + /** + * The Pixi Renderer + * @type {number} + */ + renderer: null, /** * Whether load complete loading or not. @@ -108,10 +121,10 @@ Phaser.Game.prototype = { _loadComplete: false, /** - * Game is paused? + * Is game paused? * @type {bool} */ - _paused: false, + paused: false, /** * Whether the game engine is booted, aka available. @@ -243,15 +256,18 @@ Phaser.Game.prototype = { document.removeEventListener('DOMContentLoaded', this._onBoot); window.removeEventListener('load', this._onBoot); - this.onPause = new Phaser.Signal(); - this.onResume = new Phaser.Signal(); + this.onPause = new Phaser.Signal; + this.onResume = new Phaser.Signal; this.isBooted = true; this.device = new Phaser.Device(); + + this.setUpRenderer(); + this.net = new Phaser.Net(this); this.math = Phaser.Math; - // this.stage = new Phaser.Stage(this, parent, width, height); + this.stage = new Phaser.Stage(this); // this.world = new Phaser.World(this, width, height); // this.add = new Phaser.GameObjectFactory(this); this.cache = new Phaser.Cache(this); @@ -268,10 +284,17 @@ Phaser.Game.prototype = { this.state.boot(); // this.world.boot(); - // this.stage.boot(); + this.stage.boot(); // this.input.boot(); - console.log('Phaser', Phaser.VERSION, 'initialized'); + if (this.renderType == Phaser.RENDERER_CANVAS) + { + console.log('Phaser', Phaser.VERSION, 'initialized. Rendering to Canvas'); + } + else + { + console.log('Phaser', Phaser.VERSION, 'initialized. Rendering to WebGL'); + } this.isRunning = true; this._loadComplete = false; @@ -283,6 +306,32 @@ Phaser.Game.prototype = { }, + setUpRenderer: function () { + + if (this.renderType == Phaser.RENDERER_CANVAS || (this.renderer == Phaser.RENDERER_AUTO && this.device.webGL == false)) + { + if (this.device.canvas) + { + this.renderType = Phaser.RENDERER_CANVAS; + this.renderer = new PIXI.CanvasRenderer(this.width, this.height, null, this.transparent); + Phaser.Canvas.setSmoothingEnabled(this.renderer.view, this.antialias); + } + else + { + throw new Error('Phaser.Game - cannot create Canvas or WebGL context, aborting.'); + } + } + else + { + // They must have requested WebGL and their browser supports it + this.renderer = new PIXI.WebGLRenderer(this.width, this.height, null, this.transparent, this.antialias); + } + + Phaser.Canvas.addToDOM(this.renderer.view, this.parent, true); + Phaser.Canvas.setTouchAction(this.renderer.view); + + }, + /** * Called when the load has finished, after preload was run. */ diff --git a/src/Stage.js b/src/Stage.js new file mode 100644 index 00000000..70a015e5 --- /dev/null +++ b/src/Stage.js @@ -0,0 +1,76 @@ +/** + * Stage + * + * The Stage controls the canvas on which everything is displayed. It handles display within the browser, + * focus handling, game resizing, scaling and the pause, boot and orientation screens. + * + * @package Phaser.Stage + * @author Richard Davey + * @copyright 2013 Photon Storm Ltd. + * @license https://github.com/photonstorm/phaser/blob/master/license.txt MIT License + */ +Phaser.Stage = function (game) { + + this.game = game; + + this.bounds = new Phaser.Rectangle; + this.offset = new Phaser.Point; + +}; + +Phaser.Stage.prototype = { + + _onChange: null, + _s: null, + + bounds: null, + offset: null, + + boot: function () { + + // Get the offset values (for input and other things) + Phaser.Canvas.getOffset(this.game.renderer.view, this.offset); + this.bounds.setTo(this.offset.x, this.offset.y, this.game.width, this.game.height); + + this._s = new PIXI.Stage(0x000000); + + var _this = this; + + this._onChange = function (event) { + return _this.visibilityChange(event); + } + + document.addEventListener('visibilitychange', this._onChange, false); + document.addEventListener('webkitvisibilitychange', this._onChange, false); + document.addEventListener('pagehide', this._onChange, false); + document.addEventListener('pageshow', this._onChange, false); + + window.onblur = this._onChange; + window.onfocus = this._onChange; + + }, + + /** + * This method is called when the document visibility is changed. + */ + visibilityChange: function (event) { + + if (this.disableVisibilityChange) + { + return; + } + + if (event.type == 'pagehide' || event.type == 'blur' || document['hidden'] == true || document['webkitHidden'] == true) + { + console.log('visibilityChange - hidden', event); + this.game.paused = true; + } + else + { + console.log('visibilityChange - shown', event); + this.game.paused = false; + } + + }, + +}; \ No newline at end of file diff --git a/src/core/StateManager.js b/src/core/StateManager.js index df495a7e..e901a8b2 100644 --- a/src/core/StateManager.js +++ b/src/core/StateManager.js @@ -349,7 +349,6 @@ Phaser.StateManager.prototype = { if (this.onCreateCallback) { console.log('Create callback found'); this.onCreateCallback.call(this.callbackContext); - // this.onCreateCallback.call(this.onCreateCallback); } }, diff --git a/src/system/Canvas.js b/src/system/Canvas.js new file mode 100644 index 00000000..b6c8f7d2 --- /dev/null +++ b/src/system/Canvas.js @@ -0,0 +1,193 @@ +/** +* @author Richard Davey +* @copyright 2013 Photon Storm Ltd. +* @license https://github.com/photonstorm/phaser/blob/master/license.txt MIT License +* @module Phaser.Canvas +*/ + +Phaser.Canvas = { + + /** + * Get the DOM offset values of any given element + */ + getOffset: function (element, point) { + + if (typeof point === "undefined") { point = new Phaser.Point; } + + var box = element.getBoundingClientRect(); + var clientTop = element.clientTop || document.body.clientTop || 0; + var clientLeft = element.clientLeft || document.body.clientLeft || 0; + var scrollTop = window.pageYOffset || element.scrollTop || document.body.scrollTop; + var scrollLeft = window.pageXOffset || element.scrollLeft || document.body.scrollLeft; + + point.x = box.left + scrollLeft - clientLeft; + point.y = box.top + scrollTop - clientTop; + + return point; + + }, + + /** + * Returns the aspect ratio of the given canvas. + * + * @method getAspectRatio + * @param {HTMLCanvasElement} canvas The canvas to get the aspect ratio from. + * @return {Number} Returns true on success + */ + getAspectRatio: function (canvas) { + return canvas.width / canvas.height; + }, + + /** + * Sets the background color behind the canvas. This changes the canvas style property. + * + * @method setBackgroundColor + * @param {HTMLCanvasElement} canvas The canvas to set the background color on. + * @param {String} color The color to set. Can be in the format 'rgb(r,g,b)', or '#RRGGBB' or any valid CSS color. + * @return {HTMLCanvasElement} Returns the source canvas. + */ + setBackgroundColor: function (canvas, color) { + + if (typeof color === "undefined") { color = 'rgb(0,0,0)'; } + + canvas.style.backgroundColor = color; + + return canvas; + + }, + + /** + * Sets the touch-action property on the canvas style. Can be used to disable default browser touch actions. + * + * @method setTouchAction + * @param {HTMLCanvasElement} canvas The canvas to set the touch action on. + * @param {String} value The touch action to set. Defaults to 'none'. + * @return {HTMLCanvasElement} Returns the source canvas. + */ + setTouchAction: function (canvas, value) { + + if (typeof value === "undefined") { value = 'none'; } + + canvas.style.msTouchAction = value; + canvas.style['ms-touch-action'] = value; + canvas.style['touch-action'] = value; + + return canvas; + + }, + + /** + * Adds the given canvas element to the DOM. The canvas will be added as a child of the given parent. + * If no parent is given it will be added as a child of the document.body. + * + * @method addToDOM + * @param {HTMLCanvasElement} canvas The canvas to set the touch action on. + * @param {String} parent The DOM element to add the canvas to. Defaults to ''. + * @param {bool} overflowHidden If set to true it will add the overflow='hidden' style to the parent DOM element. + * @return {HTMLCanvasElement} Returns the source canvas. + */ + addToDOM: function (canvas, parent, overflowHidden) { + + if (typeof parent === "undefined") { parent = ''; } + if (typeof overflowHidden === "undefined") { overflowHidden = true; } + + if ((parent !== '' || parent !== null) && document.getElementById(parent)) + { + document.getElementById(parent).appendChild(canvas); + + if (overflowHidden) + { + document.getElementById(parent).style.overflow = 'hidden'; + } + } + else + { + document.body.appendChild(canvas); + } + + return canvas; + + }, + + /** + * Sets the transform of the given canvas to the matrix values provided. + * + * @method setTransform + * @param {CanvasRenderingContext2D} context The context to set the transform on. + * @param {Number} translateX The value to translate horizontally by. + * @param {Number} translateY The value to translate vertically by. + * @param {Number} scaleX The value to scale horizontally by. + * @param {Number} scaleY The value to scale vertically by. + * @param {Number} skewX The value to skew horizontaly by. + * @param {Number} skewY The value to skew vertically by. + * @return {CanvasRenderingContext2D} Returns the source context. + */ + setTransform: function (context, translateX, translateY, scaleX, scaleY, skewX, skewY) { + + context.setTransform(scaleX, skewX, skewY, scaleY, translateX, translateY); + + return context; + + }, + + /** + * Sets the Image Smoothing property on the given context. Set to false to disable image smoothing. + * By default browsers have image smoothing enabled, which isn't always what you visually want, especially + * when using pixel art in a game. Note that this sets the property on the context itself, so that any image + * drawn to the context will be affected. This sets the property across all current browsers but support is + * patchy on earlier browsers, especially on mobile. + * + * @method setSmoothingEnabled + * @param {CanvasRenderingContext2D} context The context to enable or disable the image smoothing on. + * @param {bool} value If set to true it will enable image smoothing, false will disable it. + * @return {CanvasRenderingContext2D} Returns the source context. + */ + setSmoothingEnabled: function (context, value) { + + context['imageSmoothingEnabled'] = value; + context['mozImageSmoothingEnabled'] = value; + context['oImageSmoothingEnabled'] = value; + context['webkitImageSmoothingEnabled'] = value; + context['msImageSmoothingEnabled'] = value; + + return context; + + }, + + /** + * Sets the CSS image-rendering property on the given canvas to be 'crisp' (aka 'optimize contrast on webkit'). + * Note that if this doesn't given the desired result then see the setSmoothingEnabled. + * + * @method setImageRenderingCrisp + * @param {HTMLCanvasElement} canvas The canvas to set image-rendering crisp on. + * @return {HTMLCanvasElement} Returns the source canvas. + */ + setImageRenderingCrisp: function (canvas) { + + canvas.style['image-rendering'] = 'crisp-edges'; + canvas.style['image-rendering'] = '-moz-crisp-edges'; + canvas.style['image-rendering'] = '-webkit-optimize-contrast'; + canvas.style.msInterpolationMode = 'nearest-neighbor'; + + return canvas; + + }, + + /** + * Sets the CSS image-rendering property on the given canvas to be 'bicubic' (aka 'auto'). + * Note that if this doesn't given the desired result then see the CanvasUtils.setSmoothingEnabled method. + * + * @method setImageRenderingBicubic + * @param {HTMLCanvasElement} canvas The canvas to set image-rendering bicubic on. + * @return {HTMLCanvasElement} Returns the source canvas. + */ + setImageRenderingBicubic: function (canvas) { + + canvas.style['image-rendering'] = 'auto'; + canvas.style.msInterpolationMode = 'bicubic'; + + return canvas; + + } + +}; diff --git a/src/system/Device.js b/src/system/Device.js index 0f11e28c..1702c6b0 100644 --- a/src/system/Device.js +++ b/src/system/Device.js @@ -308,7 +308,7 @@ Phaser.Device.prototype = { this.file = !!window['File'] && !!window['FileReader'] && !!window['FileList'] && !!window['Blob']; this.fileSystem = !!window['requestFileSystem']; - this.webGL = !!window['WebGLRenderingContext']; + this.webGL = ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(); this.worker = !!window['Worker']; if ('ontouchstart' in document.documentElement || window.navigator.msPointerEnabled) {