diff --git a/v3/src/boot/Game.js b/v3/src/boot/Game.js index dd8674fff..73dbac5ed 100644 --- a/v3/src/boot/Game.js +++ b/v3/src/boot/Game.js @@ -149,11 +149,25 @@ Game.prototype = { onHidden: function () { this.loop.pause(); + + // var active = this.state.active; + + // for (var i = 0; i < active.length; i++) + // { + // active[i].state.sys.pause(); + // } }, onVisible: function () { this.loop.resume(); + + // var active = this.state.active; + + // for (var i = 0; i < active.length; i++) + // { + // active[i].state.sys.resume(); + // } }, onBlur: function () diff --git a/v3/src/state/Systems.js b/v3/src/state/Systems.js index 037e28f47..065a5352b 100644 --- a/v3/src/state/Systems.js +++ b/v3/src/state/Systems.js @@ -135,6 +135,7 @@ Systems.prototype = { list[i].preUpdate(time, delta); } + // preUpdate TimerEvents this.time.update(time, delta); this.tweens.update(time, delta); diff --git a/v3/src/time/Clock.js b/v3/src/time/Clock.js index 7c6c80859..6906f2107 100644 --- a/v3/src/time/Clock.js +++ b/v3/src/time/Clock.js @@ -1,42 +1,22 @@ +var Class = require('../utils/Class'); var TimerEvent = require('./TimerEvent'); -// There is only ever one instance of a MasterClock per game, and it belongs to the Game. +var Clock = new Class({ -var Clock = function (state, masterclock) -{ - this.state = state; + initialize: - /** - * The `performance.now()` value when the time was last updated. - * @property {float} time - * @protected - */ - this.time = 0; + function Clock (state) + { + this.state = state; - /** - * The `now` when the previous update occurred. - * @property {float} prevTime - * @protected - */ - this.prevTime = 0; + this.now = Date.now(); - /** - * Elapsed time since the last time update, in milliseconds, based on `now`. - * - * This value _may_ include time that the game is paused/inactive. - * - * @property {number} elapsed - * @see Lazer.Time.time - * @protected - */ - this.elapsed = 0; + this.paused = false; - this._pendingInsertion = []; - this._active = []; - this._pendingRemoval = []; -}; - -Clock.prototype = { + this._active = []; + this._pendingInsertion = []; + this._pendingRemoval = []; + }, addEvent: function (config) { @@ -52,10 +32,33 @@ Clock.prototype = { return this.addEvent({ delay: delay, callback: callback, args: args, callbackScope: callbackScope }); }, - begin: function (time) + clearPendingEvents: function () { + this._pendingInsertion = []; + }, + + removeAllEvents: function () + { + this._pendingRemoval = this._pendingRemoval.concat(this._active); + + return this; + }, + + begin: function () + { + var toRemove = this._pendingRemoval.length; + var toInsert = this._pendingInsertion.length; + + if (toRemove === 0 && toInsert === 0) + { + // Quick bail + return; + } + + var i; + // Delete old events - for (var i = 0; i < this._pendingRemoval.length; i++) + for (i = 0; i < toRemove; i++) { var event = this._pendingRemoval[i]; @@ -70,8 +73,17 @@ Clock.prototype = { event.destroy(); } + for (i = 0; i < toInsert; i++) + { + var event = this._pendingInsertion[i]; + + event.elapsed = event.startAt * event.timeScale; + + this._active.push(event); + } + // Move pending events to the active list - this._active = this._active.concat(this._pendingInsertion.splice(0)); + // this._active = this._active.concat(this._pendingInsertion.splice(0)); // Clear the lists this._pendingRemoval.length = 0; @@ -80,20 +92,13 @@ Clock.prototype = { update: function (time, delta) { - this.prevTime = this.time; + this.now = time; - this.time = time; - - this.elapsed = time - this.prevTime; - - if (this._active.length) + if (this.paused) { - this.processEvents(time, this.elapsed); + return; } - }, - processEvents: function (time, elapsed) - { for (var i = 0; i < this._active.length; i++) { var event = this._active[i]; @@ -103,9 +108,11 @@ Clock.prototype = { continue; } - event.elapsed += elapsed; - - // console.log(event.elapsed); + // Use delta time to increase elapsed. + // Avoids needing to adjust for pause / resume. + // Automatically smoothed by TimeStep class. + // In testing accurate to +- 1ms! + event.elapsed += delta * event.timeScale; if (event.elapsed >= event.delay) { @@ -115,7 +122,7 @@ Clock.prototype = { event.elapsed = event.delay; // Process the event - if (!event.hasDispatched) + if (!event.hasDispatched && event.callback) { event.hasDispatched = true; event.callback.apply(event.callbackScope, event.args); @@ -134,10 +141,20 @@ Clock.prototype = { } } } + }, + + destroy: function () + { + for (var i = 0; i < this._active.length; i++) + { + this._active[i].destroy(); + } + + this._active.length = 0; + this._pendingRemoval.length = 0; + this._pendingInsertion.length = 0; } -}; - -Clock.prototype.constructor = Clock; +}); module.exports = Clock; diff --git a/v3/src/time/TimerEvent.js b/v3/src/time/TimerEvent.js index c2820d681..e1a9f1226 100644 --- a/v3/src/time/TimerEvent.js +++ b/v3/src/time/TimerEvent.js @@ -1,85 +1,102 @@ -var GetValue = require('../utils/object/GetValue'); +var Class = require('../utils/Class'); +var GetFastValue = require('../utils/object/GetFastValue'); -/** -* A TimerEvent is a single event that is processed by a Phaser.Clock -* -* It consists of a delay, which is a value in milliseconds after which the event will fire. -* When the event fires it calls a specific callback with the specified arguments. -* -* TimerEvents are removed by their parent timer once finished firing or repeating. -* -* Use {@link Phaser.Clock#add}, {@link Phaser.Clock#repeat}, or {@link Phaser.Clock#loop} methods to create a new event. -* -* @class Phaser.TimerEvent -* @constructor -* @param {number} delay - The delay in ms at which this TimerEvent fires. -* @param {number} tick - The tick is the next game clock time that this event will fire at. -* @param {number} repeatCount - If this TimerEvent repeats it will do so this many times. -* @param {boolean} loop - True if this TimerEvent loops, otherwise false. -* @param {function} callback - The callback that will be called when the TimerEvent occurs. -* @param {object} callbackContext - The context in which the callback will be called. -* @param {any[]} arguments - Additional arguments to be passed to the callback. -*/ -var TimerEvent = function (config) -{ - /** - * @property {number} delay - The delay in ms at which this TimerEvent fires. - */ - this.delay = GetValue(config, 'delay', 0); +var TimerEvent = new Class({ - /** - * @property {number} repeatCount - If this TimerEvent repeats it will do so this many times. - */ - this.repeatCount = GetValue(config, 'repeat', 0); + initialize: - /** - * @property {boolean} loop - True if this TimerEvent loops, otherwise false. - */ - this.loop = GetValue(config, 'loop', false); - - /** - * @property {function} callback - The callback that will be called when the TimerEvent occurs. - */ - this.callback = GetValue(config, 'callback', null); - - /** - * @property {object} callbackContext - The context in which the callback will be called. - */ - this.callbackScope = GetValue(config, 'callbackScope', null); - - /** - * @property {any[]} arguments - Additional arguments to be passed to the callback. - */ - this.args = GetValue(config, 'args', []); - - // This works for setting an infinite repeat too - if (this.repeatCount === -1) + function TimerEvent (config) { - this.loop = true; - } + /** + * @property {number} delay - The delay in ms at which this TimerEvent fires. + */ + this.delay = 0; - this.elapsed = 0; - this.hasDispatched = false; + /** + * @property {number} repeatCount - If this TimerEvent repeats it will do so this many times. + */ + this.repeatCount = 0; - // Swap for a getter / setter - this.paused = false; -}; + /** + * @property {boolean} loop - True if this TimerEvent loops, otherwise false. + */ + this.loop = false; -TimerEvent.prototype = { + /** + * @property {function} callback - The callback that will be called when the TimerEvent occurs. + */ + this.callback; + + /** + * @property {object} callbackContext - The context in which the callback will be called. + */ + this.callbackScope; + + /** + * @property {any[]} arguments - Additional arguments to be passed to the callback. + */ + this.args; + + // Scale the time causing this TimerEvent to update + this.timeScale = 1; + + // Start this many MS into the elapsed (useful if you want a long duration with repeat, but for the first loop to fire quickly) + this.startAt = 0; + + this.elapsed = 0; + + this.paused = false; + + this.hasDispatched = false; + + this.reset(config); + }, + + reset: function (config) + { + this.delay = GetFastValue(config, 'delay', 0); + + this.repeatCount = GetFastValue(config, 'repeat', 0); + + this.loop = GetFastValue(config, 'loop', false); + + this.callback = GetFastValue(config, 'callback', undefined); + + this.callbackScope = GetFastValue(config, 'callbackScope', this.callback); + + this.args = GetFastValue(config, 'args', []); + + this.timeScale = GetFastValue(config, 'timeScale', 1); + + this.startAt = GetFastValue(config, 'startAt', 0); + + this.paused = GetFastValue(config, 'paused', false); + + // This works for setting an infinite repeat too + if (this.repeatCount === -1) + { + this.loop = true; + } + + this.elapsed = 0; + this.hasDispatched = false; + + return this; + }, getProgress: function () { return (this.elapsed / this.delay); }, - pause: function () + getElapsed: function () { - this.paused = true; + return this.elapsed; }, - resume: function () + getElapsedSeconds: function () { - this.paused = false; + return this.elapsed * 0.001; }, remove: function (dispatchCallback) @@ -102,8 +119,6 @@ TimerEvent.prototype = { this.args.length = 0; } -}; - -TimerEvent.prototype.constructor = TimerEvent; +}); module.exports = TimerEvent;