Updated TimerEvent and Clock

Swapped to Class format. Added timeScale, startAt and more robust loop handling.
This commit is contained in:
Richard Davey 2017-06-28 22:19:41 +01:00
parent 755fa260c0
commit 5cef085eb5
4 changed files with 167 additions and 120 deletions

View file

@ -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 ()

View file

@ -135,6 +135,7 @@ Systems.prototype = {
list[i].preUpdate(time, delta);
}
// preUpdate TimerEvents
this.time.update(time, delta);
this.tweens.update(time, delta);

View file

@ -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;

View file

@ -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;