diff --git a/examples/math sincos.html b/examples/math sincos.html
index e7eb48a0..061282ff 100644
--- a/examples/math sincos.html
+++ b/examples/math sincos.html
@@ -3,13 +3,18 @@
phaser.js - a(nother) new beginning
+
+
+
+
+
@@ -25,14 +30,15 @@
var game = new Phaser.Game(this, '', 800, 600);
-var data = Phaser.Math.sinCosGenerator(10);
+var data = game.math.sinCosGenerator(10);
console.log('Sin', data.sin);
console.log('Cos', data.cos);
-console.log('Shift value 1', Phaser.Math.shift(data.sin));
-console.log('Shift value 2', Phaser.Math.shift(data.sin));
-console.log('Shift value 3', Phaser.Math.shift(data.sin));
+console.log('Shift value 1', game.math.shift(data.sin));
+console.log('Shift value 2', game.math.shift(data.sin));
+console.log('Shift value 3', game.math.shift(data.sin));
+console.log('Shift value 4', game.math.shift(data.sin));
console.log('Sin', data.sin);
diff --git a/examples/pixi 1.html b/examples/pixi 1.html
new file mode 100644
index 00000000..4bd70188
--- /dev/null
+++ b/examples/pixi 1.html
@@ -0,0 +1,139 @@
+
+
+
+ phaser.js - a(nother) new beginning
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/raf.html b/examples/raf.html
new file mode 100644
index 00000000..939844a7
--- /dev/null
+++ b/examples/raf.html
@@ -0,0 +1,45 @@
+
+
+
+ phaser.js - a(nother) new beginning
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+?
+Game Time:
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/wip1.html b/examples/wip1.html
index 225755e9..aa95919c 100644
--- a/examples/wip1.html
+++ b/examples/wip1.html
@@ -3,9 +3,51 @@
phaser.js - a(nother) new beginning
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -29,17 +71,70 @@
var game = new Phaser.Game(this, '', 800, 600);
-var test = { x: 0 };
+// PIXI it
+var stage = new PIXI.Stage(0x000044);
+var renderer = PIXI.autoDetectRenderer(800, 600);
+document.body.appendChild(renderer.view);
-var tween = game.tweens.create(test);
+game.load.image('cockpit', 'assets/pics/cockpit.png');
+game.load.image('rememberMe', 'assets/pics/remember-me.jpg');
+game.load.image('overdose', 'assets/pics/lance-overdose-loader_eye.png');
-tween.onComplete.add(onComplete, this);
-tween.to({x: 100}, 1000, Phaser.Easing.Linear.None, true);
+game.load.onLoadStart.add(loadStarted, this);
+game.load.onFileComplete.add(fileLoaded, this);
+game.load.onLoadComplete.add(loadCompleted, this);
-function onComplete() {
- console.log('tween finished, new data: ', test);
+game.load.start();
+
+function loadStarted(size) {
+ console.log('Loader started, queue size:', size);
}
+// this.progress, previousKey, success, this.queueSize - this._keys.length, this.queueSize
+function fileLoaded(progress, key, success, remaining, total) {
+ console.log('File Loaded:', key);
+ console.log('Progress: ' + progress + '%');
+ console.log('File: ' + remaining + ' out of ' + total);
+}
+
+var bunny;
+
+function loadCompleted() {
+
+ console.log('Loader finished, creating base textures');
+
+ // Create a basetexture
+ var base = new PIXI.BaseTexture(game.cache.getImage('overdose'));
+ var texture = new PIXI.Texture(base);
+ bunny = new PIXI.Sprite(texture);
+
+ // center the sprites anchor point
+ bunny.anchor.x = 0.5;
+ bunny.anchor.y = 0.5;
+
+ // move the sprite t the center of the screen
+ bunny.position.x = 200;
+ bunny.position.y = 150;
+
+ stage.addChild(bunny);
+
+ requestAnimFrame(animate);
+}
+
+function animate() {
+
+ requestAnimFrame( animate );
+
+ // just for fun, lets rotate mr rabbit a little
+ bunny.rotation += 0.1;
+ bunny.scale.x += 0.01;
+ bunny.scale.y += 0.01;
+
+ // render the stage
+ renderer.render(stage);
+}
+
+
diff --git a/src/Game.js b/src/Game.js
index 8f2e6fab..15bdf7d7 100644
--- a/src/Game.js
+++ b/src/Game.js
@@ -33,18 +33,14 @@ Phaser.Game = function (callbackContext, parent, width, height, preloadCallback,
this.onRenderCallback = renderCallback;
this.onDestroyCallback = destroyCallback;
- var _this = this;
-
if (document.readyState === 'complete' || document.readyState === 'interactive')
{
- setTimeout(function () {
- return Phaser.GAMES[_this.id].boot(parent, width, height);
- });
+ setTimeout(Phaser.GAMES[this.id].boot(parent, width, height), 0);
}
else
{
- document.addEventListener('DOMContentLoaded', Phaser.GAMES[_this.id].boot(parent, width, height), false);
- window.addEventListener('load', Phaser.GAMES[_this.id].boot(parent, width, height), false);
+ document.addEventListener('DOMContentLoaded', Phaser.GAMES[this.id].boot(parent, width, height), false);
+ window.addEventListener('load', Phaser.GAMES[this.id].boot(parent, width, height), false);
}
};
@@ -147,6 +143,95 @@ Phaser.Game.prototype = {
*/
isRunning: false,
+ /**
+ * Automatically handles the core game loop via requestAnimationFrame or setTimeout
+ */
+ raf: null,
+
+ /**
+ * Reference to the GameObject Factory.
+ * @type {Phaser.GameObjectFactory}
+ */
+ add: null,
+
+ /**
+ * Reference to the assets cache.
+ * @type {Phaser.Cache}
+ */
+ cache: null,
+
+ /**
+ * Reference to the input manager
+ * @type {Phaser.InputManager}
+ */
+ input: null,
+
+ /**
+ * Reference to the assets loader.
+ * @type {Phaser.Loader}
+ */
+ load: null,
+
+ /**
+ * Reference to the math helper.
+ * @type {Phaser.GameMath}
+ */
+ math: null,
+
+ /**
+ * Reference to the network class.
+ * @type {Phaser.Net}
+ */
+ net: null,
+
+ /**
+ * Reference to the sound manager.
+ * @type {Phaser.SoundManager}
+ */
+ sound: null,
+
+ /**
+ * Reference to the stage.
+ * @type {Phaser.Stage}
+ */
+ stage: null,
+
+ /**
+ * Reference to game clock.
+ * @type {Phaser.TimeManager}
+ */
+ time: null,
+
+ /**
+ * Reference to the tween manager.
+ * @type {Phaser.TweenManager}
+ */
+ tweens: null,
+
+ /**
+ * Reference to the world.
+ * @type {Phaser.World}
+ */
+ world: null,
+
+ /**
+ * Reference to the physics manager.
+ * @type {Phaser.Physics.PhysicsManager}
+ */
+ physics: null,
+
+ /**
+ * Instance of repeatable random data generator helper.
+ * @type {Phaser.RandomDataGenerator}
+ */
+ rnd: null,
+
+ /**
+ * Contains device information and capabilities.
+ * @type {Phaser.Device}
+ */
+ device: null,
+
/**
* Initialize engine sub modules and start the game.
* @param parent {string} ID of parent Dom element.
@@ -155,29 +240,24 @@ Phaser.Game.prototype = {
*/
boot: function (parent, width, height) {
- var _this = this;
-
if (this.isBooted) {
return;
}
if (!document.body) {
- setTimeout(function () {
- return Phaser.GAMES[_this.id].boot(parent, width, height);
- }, 13);
+ setTimeout(Phaser.GAMES[this.id].boot(parent, width, height), 13);
}
else
{
- document.removeEventListener('DOMContentLoaded', Phaser.GAMES[_this.id].boot);
- window.removeEventListener('load', Phaser.GAMES[_this.id].boot);
+ document.removeEventListener('DOMContentLoaded', Phaser.GAMES[this.id].boot);
+ window.removeEventListener('load', Phaser.GAMES[this.id].boot);
- console.log('Phaser', Phaser.VERSION, 'alive');
+ this.onPause = new Phaser.Signal();
+ this.onResume = new Phaser.Signal();
- // this.onPause = new Phaser.Signal();
- // this.onResume = new Phaser.Signal();
this.device = new Phaser.Device();
this.net = new Phaser.Net(this);
- // this.math = new Phaser.GameMath(this);
+ this.math = Phaser.Math;
// this.stage = new Phaser.Stage(this, parent, width, height);
// this.world = new Phaser.World(this, width, height);
// this.add = new Phaser.GameObjectFactory(this);
@@ -189,16 +269,275 @@ Phaser.Game.prototype = {
// this.sound = new Phaser.SoundManager(this);
this.rnd = new Phaser.RandomDataGenerator([(Date.now() * Math.random()).toString()]);
// this.physics = new Phaser.Physics.PhysicsManager(this);
- // this.plugins = new Phaser.PluginManager(this, this);
- // this.load.onLoadComplete.add(this.loadComplete, this);
+ this.plugins = new Phaser.PluginManager(this, this);
+
+ this.load.onLoadComplete.add(this.loadComplete, this);
+
// this.setRenderer(Phaser.Types.RENDERER_CANVAS);
// this.world.boot();
// this.stage.boot();
// this.input.boot();
this.isBooted = true;
+
+ if (this.onPreloadCallback == null && this.onCreateCallback == null && this.onUpdateCallback == null && this.onRenderCallback == null && this._pendingState == null) {
+ console.warn("Phaser update loop cannot start: No preload, create, update or render functions given and no pending State found");
+ }
+ else
+ {
+ console.log('Phaser', Phaser.VERSION, 'alive');
+ this.isRunning = true;
+ this._loadComplete = false;
+
+ this.raf = new Phaser.RequestAnimationFrame(this);
+ this.raf.start();
+
+ if (this._pendingState)
+ {
+ this.switchState(this._pendingState, false, false);
+ }
+ else
+ {
+ this.startState();
+ }
+ }
+
}
},
+ /**
+ * Called when the load has finished after preload was run.
+ */
+ loadComplete: function () {
+
+ this._loadComplete = true;
+ this.onCreateCallback.call(this.callbackContext);
+
+ },
+
+ /**
+ * Start the current state
+ */
+ startState: function () {
+
+ if (this.onPreloadCallback !== null)
+ {
+ this.load.reset();
+ this.onPreloadCallback.call(this.callbackContext);
+
+ // Is the loader empty?
+ if (this.load.queueSize == 0)
+ {
+ if (this.onCreateCallback !== null)
+ {
+ this.onCreateCallback.call(this.callbackContext);
+ }
+
+ this._loadComplete = true;
+
+ }
+ else
+ {
+ // Start the loader going as we have something in the queue
+ this.load.onLoadComplete.add(this.loadComplete, this);
+ this.load.start();
+ }
+ }
+ else
+ {
+ // No init? Then there was nothing to load either
+ if (this.onCreateCallback !== null) {
+ this.onCreateCallback.call(this.callbackContext);
+ }
+
+ this._loadComplete = true;
+
+ }
+
+ },
+
+ /**
+ * Set the most common state callbacks (init, create, update, render).
+ * @param preloadCallback {function} Init callback invoked when init state.
+ * @param createCallback {function} Create callback invoked when create state.
+ * @param updateCallback {function} Update callback invoked when update state.
+ * @param renderCallback {function} Render callback invoked when render state.
+ * @param destroyCallback {function} Destroy callback invoked when state is destroyed.
+ */
+ setCallbacks: function (preloadCallback, createCallback, updateCallback, renderCallback, destroyCallback) {
+
+ if (typeof preloadCallback === "undefined") { preloadCallback = null; }
+ if (typeof createCallback === "undefined") { createCallback = null; }
+ if (typeof updateCallback === "undefined") { updateCallback = null; }
+ if (typeof renderCallback === "undefined") { renderCallback = null; }
+ if (typeof destroyCallback === "undefined") { destroyCallback = null; }
+
+ this.onPreloadCallback = preloadCallback;
+ this.onCreateCallback = createCallback;
+ this.onUpdateCallback = updateCallback;
+ this.onRenderCallback = renderCallback;
+ this.onDestroyCallback = destroyCallback;
+
+ },
+
+ update: function (time) {
+
+ this.time.update(time);
+
+ this.plugins.preUpdate();
+
+ this.tweens.update();
+ this.input.update();
+ this.stage.update();
+ this.sound.update();
+ this.physics.update();
+ this.world.update();
+
+ this.plugins.update();
+
+ if (this._loadComplete)
+ {
+ if (this.onUpdateCallback)
+ {
+ this.onUpdateCallback.call(this.callbackContext);
+ }
+
+ this.world.postUpdate();
+ this.plugins.postUpdate();
+ this.plugins.preRender();
+
+ if (this.onPreRenderCallback)
+ {
+ this.onPreRenderCallback.call(this.callbackContext);
+ }
+
+ this.renderer.render();
+ this.plugins.render();
+
+ if (this.onRenderCallback)
+ {
+ this.onRenderCallback.call(this.callbackContext);
+ }
+
+ this.plugins.postRender();
+ }
+ else
+ {
+ // Still loading assets
+ if (this.onLoadUpdateCallback)
+ {
+ this.onLoadUpdateCallback.call(this.callbackContext);
+ }
+
+ this.world.postUpdate();
+ this.plugins.postUpdate();
+ this.plugins.preRender();
+ this.renderer.render();
+ this.plugins.render();
+
+ if (this.onLoadRenderCallback)
+ {
+ this.onLoadRenderCallback.call(this.callbackContext);
+ }
+
+ this.plugins.postRender();
+ }
+
+ },
+
+ /**
+ * Switch to a new State.
+ * @param state {State} The state you want to switch to.
+ * @param [clearWorld] {bool} clear everything in the world? (Default to true)
+ * @param [clearCache] {bool} clear asset cache? (Default to false and ONLY available when clearWorld=true)
+ */
+ switchState: function (state, clearWorld, clearCache) {
+
+ if (typeof clearWorld === "undefined") { clearWorld = true; }
+ if (typeof clearCache === "undefined") { clearCache = false; }
+
+ if (this.isBooted == false) {
+ this._pendingState = state;
+ return;
+ }
+
+ // Destroy current state?
+ if (this.onDestroyCallback !== null) {
+ this.onDestroyCallback.call(this.callbackContext);
+ }
+
+ this.input.reset(true);
+
+ // Prototype?
+ if (typeof state === 'function')
+ {
+ this.state = new state(this);
+ }
+ else
+ {
+ this.state = state;
+ }
+
+ // Ok, have we got at least a create or update function?
+ if (this.state['create'] || this.state['update']) {
+
+ this.callbackContext = this.state;
+
+ // Bingo, let's set them up
+ this.onPreloadCallback = this.state['preload'] || null;
+ this.onLoadRenderCallback = this.state['loadRender'] || null;
+ this.onLoadUpdateCallback = this.state['loadUpdate'] || null;
+ this.onCreateCallback = this.state['create'] || null;
+ this.onUpdateCallback = this.state['update'] || null;
+ this.onPreRenderCallback = this.state['preRender'] || null;
+ this.onRenderCallback = this.state['render'] || null;
+ this.onPausedCallback = this.state['paused'] || null;
+ this.onDestroyCallback = this.state['destroy'] || null;
+
+ if (clearWorld) {
+
+ //this.world.destroy();
+
+ if (clearCache == true) {
+ this.cache.destroy();
+ }
+ }
+
+ this._loadComplete = false;
+
+ this.startState();
+
+ }
+ else
+ {
+ console.warn("Invalid Phaser State object given. Must contain at least a create or update function.");
+ }
+ },
+
+ /**
+ * Nuke the entire game from orbit
+ */
+ destroy: function () {
+
+ this.callbackContext = null;
+ this.onPreloadCallback = null;
+ this.onLoadRenderCallback = null;
+ this.onLoadUpdateCallback = null;
+ this.onCreateCallback = null;
+ this.onUpdateCallback = null;
+ this.onRenderCallback = null;
+ this.onPausedCallback = null;
+ this.onDestroyCallback = null;
+ this.cache = null;
+ this.input = null;
+ this.load = null;
+ this.sound = null;
+ this.stage = null;
+ this.time = null;
+ this.world = null;
+ this.isBooted = false;
+
+ }
+
};
diff --git a/src/core/Plugin.js b/src/core/Plugin.js
new file mode 100644
index 00000000..568a8375
--- /dev/null
+++ b/src/core/Plugin.js
@@ -0,0 +1,79 @@
+/**
+* Phaser - Plugin
+*
+* This is a base Plugin template to use for any Phaser plugin development
+*/
+Phaser.Plugin = function (game, parent) {
+
+ this.game = game;
+ this.parent = parent;
+
+ this.active = false;
+ this.visible = false;
+
+ this.hasPreUpdate = false;
+ this.hasUpdate = false;
+ this.hasPostUpdate = false;
+ this.hasPreRender = false;
+ this.hasRender = false;
+ this.hasPostRender = false;
+
+};
+
+Phaser.Plugin.prototype = {,
+
+ /**
+ * Pre-update is called at the start of the update cycle, before any other updates have taken place.
+ * It is only called if active is set to true.
+ */
+ preUpdate: function () {
+ },
+
+ /**
+ * Pre-update is called at the start of the update cycle, before any other updates have taken place.
+ * It is only called if active is set to true.
+ */
+ update: function () {
+ },
+
+ /**
+ * Post-update is called at the end of the objects update cycle, after other update logic has taken place.
+ * It is only called if active is set to true.
+ */
+ postUpdate: function () {
+ },
+
+ /**
+ * Pre-render is called right before the Game Renderer starts and before any custom preRender callbacks have been run.
+ * It is only called if visible is set to true.
+ */
+ preRender: function () {
+ },
+
+ /**
+ * Pre-render is called right before the Game Renderer starts and before any custom preRender callbacks have been run.
+ * It is only called if visible is set to true.
+ */
+ render: function () {
+ },
+
+ /**
+ * Post-render is called after every camera and game object has been rendered, also after any custom postRender callbacks have been run.
+ * It is only called if visible is set to true.
+ */
+ postRender: function () {
+ },
+
+ /**
+ * Clear down this Plugin and null out references
+ */
+ destroy: function () {
+
+ this.game = null;
+ this.parent = null;
+ this.active = false;
+ this.visible = false;
+
+ }
+
+};
diff --git a/src/core/PluginManager.js b/src/core/PluginManager.js
new file mode 100644
index 00000000..4509c289
--- /dev/null
+++ b/src/core/PluginManager.js
@@ -0,0 +1,199 @@
+/**
+* Phaser - PluginManager
+*
+* TODO: We can optimise this a lot by using separate hashes per function (update, render, etc)
+*/
+
+Phaser.PluginManager = function(game, parent) {
+
+ this.game = game;
+ this._parent = parent;
+ this.plugins = [];
+ this._pluginsLength = 0;
+
+};
+
+Phaser.PluginManager.prototype = {,
+
+ /**
+ * Add a new Plugin to the PluginManager.
+ * The plugins game and parent reference are set to this game and pluginmanager parent.
+ * @type {Phaser.Plugin}
+ */
+ add: function (plugin) {
+
+ var result = false;
+
+ // Prototype?
+ if (typeof plugin === 'function')
+ {
+ plugin = new plugin(this.game, this._parent);
+ }
+ else
+ {
+ plugin.game = this.game;
+ plugin.parent = this._parent;
+ }
+
+ // Check for methods now to avoid having to do this every loop
+ if (typeof plugin['preUpdate'] === 'function') {
+ plugin.hasPreUpdate = true;
+ result = true;
+ }
+
+ if (typeof plugin['update'] === 'function') {
+ plugin.hasUpdate = true;
+ result = true;
+ }
+
+ if (typeof plugin['postUpdate'] === 'function') {
+ plugin.hasPostUpdate = true;
+ result = true;
+ }
+
+ if (typeof plugin['preRender'] === 'function') {
+ plugin.hasPreRender = true;
+ result = true;
+ }
+
+ if (typeof plugin['render'] === 'function') {
+ plugin.hasRender = true;
+ result = true;
+ }
+
+ if (typeof plugin['postRender'] === 'function') {
+ plugin.hasPostRender = true;
+ result = true;
+ }
+
+ // The plugin must have at least one of the above functions to be added to the PluginManager.
+ if (result) {
+
+ if (plugin.hasPreUpdate || plugin.hasUpdate || plugin.hasPostUpdate)
+ {
+ plugin.active = true;
+ }
+
+ if (plugin.hasPreRender || plugin.hasRender || plugin.hasPostRender)
+ {
+ plugin.visible = true;
+ }
+
+ this._pluginsLength = this.plugins.push(plugin);
+ return plugin;
+
+ }
+ else
+ {
+ return null;
+ }
+ },
+
+ remove: function (plugin) {
+
+ // TODO
+ this._pluginsLength--;
+
+ },
+
+ preUpdate: function () {
+
+ if (this._pluginsLength == 0)
+ {
+ return;
+ }
+
+ for (this._p = 0; this._p < this._pluginsLength; this._p++) {
+ if (this.plugins[this._p].active && this.plugins[this._p].hasPreUpdate) {
+ this.plugins[this._p].preUpdate();
+ }
+ }
+
+ },
+
+ update: function () {
+
+ if (this._pluginsLength == 0)
+ {
+ return;
+ }
+
+ for (this._p = 0; this._p < this._pluginsLength; this._p++) {
+ if (this.plugins[this._p].active && this.plugins[this._p].hasUpdate) {
+ this.plugins[this._p].update();
+ }
+ }
+
+ },
+
+ postUpdate: function () {
+
+ if (this._pluginsLength == 0)
+ {
+ return;
+ }
+
+ for (this._p = 0; this._p < this._pluginsLength; this._p++) {
+ if (this.plugins[this._p].active && this.plugins[this._p].hasPostUpdate) {
+ this.plugins[this._p].postUpdate();
+ }
+ }
+
+ },
+
+ preRender: function () {
+
+ if (this._pluginsLength == 0)
+ {
+ return;
+ }
+
+ for (this._p = 0; this._p < this._pluginsLength; this._p++) {
+ if (this.plugins[this._p].visible && this.plugins[this._p].hasPreRender) {
+ this.plugins[this._p].preRender();
+ }
+ }
+
+ },
+
+ render: function () {
+
+ if (this._pluginsLength == 0)
+ {
+ return;
+ }
+
+ for (this._p = 0; this._p < this._pluginsLength; this._p++) {
+ if (this.plugins[this._p].visible && this.plugins[this._p].hasRender) {
+ this.plugins[this._p].render();
+ }
+ }
+
+ },
+
+ postRender: function () {
+
+ if (this._pluginsLength == 0)
+ {
+ return;
+ }
+
+ for (this._p = 0; this._p < this._pluginsLength; this._p++) {
+
+ if (this.plugins[this._p].visible && this.plugins[this._p].hasPostRender) {
+ this.plugins[this._p].postRender();
+ }
+ }
+
+ },
+
+ destroy: function () {
+
+ this.plugins.length = 0;
+ this._pluginsLength = 0;
+ this.game = null;
+ this._parent = null;
+
+ }
+
+};
diff --git a/src/system/RequestAnimationFrame.js b/src/system/RequestAnimationFrame.js
new file mode 100644
index 00000000..de24c67e
--- /dev/null
+++ b/src/system/RequestAnimationFrame.js
@@ -0,0 +1,111 @@
+/**
+* Phaser - RequestAnimationFrame
+*
+* Abstracts away the use of RAF or setTimeOut for the core game update loop.
+*/
+Phaser.RequestAnimationFrame = function(game) {
+
+ this.game = game;
+
+ this._isSetTimeOut = false;
+ this.isRunning = false;
+
+ var vendors = [
+ 'ms',
+ 'moz',
+ 'webkit',
+ 'o'
+ ];
+
+ for (var x = 0; x < vendors.length && !window.requestAnimationFrame; x++) {
+ window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
+ window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'];
+ }
+
+};
+
+Phaser.RequestAnimationFrame.prototype = {
+
+ /**
+ * Starts the requestAnimatioFrame running or setTimeout if unavailable in browser
+ * @method start
+ **/
+ start: function () {
+
+ this.isRunning = true;
+
+ if (!window.requestAnimationFrame)
+ {
+ this._isSetTimeOut = true;
+ this._timeOutID = window.setTimeout(Phaser.GAMES[this.game.id].raf.updateSetTimeout, 0);
+ }
+ else
+ {
+ this._isSetTimeOut = false;
+ window.requestAnimationFrame(Phaser.GAMES[this.game.id].raf.updateRAF);
+ }
+
+ },
+
+ /**
+ * The update method for the requestAnimationFrame
+ * @method RAFUpdate
+ **/
+ updateRAF: function (time) {
+
+ this.game.update(time);
+
+ window.requestAnimationFrame(Phaser.GAMES[this.game.id].raf.updateRAF);
+
+ },
+
+ /**
+ * The update method for the setTimeout
+ * @method SetTimeoutUpdate
+ **/
+ updateSetTimeout: function () {
+
+ this.game.update(Date.now());
+
+ this._timeOutID = window.setTimeout(Phaser.GAMES[this.game.id].raf.updateSetTimeout, this.game.time.timeToCall);
+
+ },
+
+ /**
+ * Stops the requestAnimationFrame from running
+ * @method stop
+ **/
+ stop: function () {
+
+ if (this._isSetTimeOut)
+ {
+ clearTimeout(this._timeOutID);
+ }
+ else
+ {
+ window.cancelAnimationFrame;
+ }
+
+ this.isRunning = false;
+
+ },
+
+ /**
+ * Is the browser using setTimeout?
+ * @method isSetTimeOut
+ * @return bool
+ **/
+ isSetTimeOut: function () {
+ return this._isSetTimeOut;
+ },
+
+ /**
+ * Is the browser using requestAnimationFrame?
+ * @method isRAF
+ * @return bool
+ **/
+ isRAF: function () {
+ return (this._isSetTimeOut === false);
+ }
+
+};
\ No newline at end of file
diff --git a/src/time/Time.js b/src/time/Time.js
index d46600fc..23d4df1e 100644
--- a/src/time/Time.js
+++ b/src/time/Time.js
@@ -6,7 +6,7 @@
*/
/**
-* This is the core internal game clock. It manages the elapsed time and calculation of delta values,
+* This is the core internal game clock. It manages the elapsed time and calculation of elapsed values,
* used for game object motion and tweens.
*
* @class Time
@@ -89,11 +89,11 @@ Phaser.Time.prototype = {
/**
* Elapsed time since the last frame.
- * @property delta
+ * @property elapsed
* @public
* @type {Number}
*/
- delta: 0,
+ elapsed: 0,
/**
* Frames per second.
@@ -151,6 +151,22 @@ Phaser.Time.prototype = {
*/
pauseDuration: 0,
+ /**
+ * The value that setTimeout needs to work out when to next update
+ * @property timeToCall
+ * @public
+ * @type {Number}
+ */
+ timeToCall: 0,
+
+ /**
+ * Internal value used by timeToCall as part of the setTimeout loop
+ * @property lastTime
+ * @public
+ * @type {Number}
+ */
+ lastTime: 0,
+
/**
* The number of seconds that have elapsed since the game was started.
* @method totalElapsedSeconds
@@ -161,18 +177,20 @@ Phaser.Time.prototype = {
},
/**
- * Update clock and calculate the fps.
- * This is called automatically by Game._raf
+ * Updates the game clock and calculate the fps.
+ * This is called automatically by Phaser.Game
* @method update
- * @param {Number} raf The current timestamp, either performance.now or Date.now
+ * @param {Number} time The current timestamp, either performance.now or Date.now depending on the browser
*/
- update: function (raf) {
+ update: function (time) {
- this.now = raf;
- this.delta = this.now - this.time;
+ this.now = time;
+ this.timeToCall = Math.max(0, 16 - (time - this.lastTime));
- this.msMin = Math.min(this.msMin, this.delta);
- this.msMax = Math.max(this.msMax, this.delta);
+ this.elapsed = this.now - this.time;
+
+ this.msMin = Math.min(this.msMin, this.elapsed);
+ this.msMax = Math.max(this.msMax, this.elapsed);
this.frames++;
@@ -186,7 +204,8 @@ Phaser.Time.prototype = {
}
this.time = this.now;
- this.physicsElapsed = 1.0 * (this.delta / 1000);
+ this.lastTime = time + this.timeToCall;
+ this.physicsElapsed = 1.0 * (this.elapsed / 1000);
// Paused?
if (this.game.paused) {
@@ -211,8 +230,8 @@ Phaser.Time.prototype = {
*/
gameResumed: function () {
- // Level out the delta timer to avoid spikes
- this.delta = 0;
+ // Level out the elapsed timer to avoid spikes
+ this.elapsed = 0;
this.physicsElapsed = 0;
this.time = Date.now();
this.pauseDuration = this.pausedTime;