Timer class overhaul.

This commit is contained in:
photonstorm 2014-01-04 02:53:32 +00:00
parent 7aa45b5872
commit aa3a86df6e
4 changed files with 312 additions and 79 deletions

View file

@ -0,0 +1,45 @@
var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render });
function preload() {
game.load.image('mushroom', 'assets/sprites/mushroom2.png');
}
var timer;
function create() {
game.stage.backgroundColor = '#007236';
timer = game.time.create(1000, false);
timer.repeat(1, 10);
timer.onEvent.add(addSprite, this);
timer.start();
// text = game.add.text(0, 0, "Text Above Sprites", { font: "64px Arial", fill: "#00bff3", align: "center" });
}
function addSprite() {
game.add.sprite(game.world.randomX, game.world.randomY, 'mushroom');
}
function update() {
}
function render() {
game.debug.renderText(timer.ms, 32, 32);
// game.debug.renderCameraInfo(game.camera, 32, 32);
}

View file

@ -118,10 +118,55 @@ Phaser.Time = function (game) {
*/
this._justResumed = false;
/**
* @property {array} _timers - Internal store of Phaser.Timer objects.
* @private
*/
this._timers = [];
};
Phaser.Time.prototype = {
/**
* Creates a new Phaser.Timer object.
* @method Phaser.Time#create
* @param {number} [timeUnit=1000] - The number of ms that represent 1 unit of time. For example a timer that ticks every second would have a timeUnit value of 1000.
* @param {boolean} [autoDestroy=true] - A Timer that is set to automatically destroy itself will do so after all of its events have been dispatched (assuming no looping events).
* @return {Phaser.Timer} The Timer object that was created.
*/
create: function (timeUnit, autoDestroy) {
if (typeof autoDestroy === 'undefined') { autoDestroy = true; }
var timer = new Phaser.Timer(this.game, timeUnit, autoDestroy);
if (typeof delay !== 'undefined')
{
timer.add(delay);
}
this._timers.push(timer);
return timer;
},
/**
* Remove all Timer objects, regardless of their state.
* @method Phaser.Time#removeAll
*/
removeAll: function () {
for (var i = 0; i < this._timers.length; i++)
{
this._timers[i].destroy();
}
this._timers = [];
},
/**
* Updates the game clock and calculate the fps. This is called automatically by Phaser.Game.
* @method Phaser.Time#update
@ -171,6 +216,23 @@ Phaser.Time.prototype = {
this.pausedTime = this.now - this._pauseStarted;
}
var i = 0;
var len = this._timers.length;
while (i < len)
{
if (this._timers[i].update(this.now))
{
i++;
}
else
{
this._timers.splice(i, 1);
len--;
}
}
},
/**

View file

@ -5,14 +5,21 @@
*/
/**
* Timer constructor.
* A Timer is a way to create small re-usable or disposable objects that do nothing but wait for a specific moment in time, and then dispatch an event.
* You can add as many events to a Timer as you like, each with their own delays. A Timer uses its own timeUnit, which directly correlates to milliseconds.
* For example a Timer with a timeUnit of 250 would fire an event every quarter of a second.
*
* @class Phaser.Timer
* @classdesc A Timer
* @classdesc A Timer is a way to create small re-usable or disposable objects that do nothing but wait for a specific moment in time, and then dispatch an event.
* @constructor
* @param {Phaser.Game} game A reference to the currently running game.
* @param {number} [timeUnit=1000] - The number of ms that represent 1 unit of time. For example a timer that ticks every second would have a timeUnit value of 1000.
* @param {boolean} [autoDestroy=true] - A Timer that is set to automatically destroy itself will do so after all of its events have been dispatched (assuming no looping events).
*/
Phaser.Timer = function (game) {
Phaser.Timer = function (game, timeUnit, autoDestroy) {
if (typeof timeUnit === 'undefined') { timeUnit = Phaser.Timer.SECOND; }
if (typeof autoDestroy === 'undefined') { autoDestroy = true; }
/**
* @property {Phaser.Game} game - Local reference to game.
@ -20,92 +27,154 @@ Phaser.Timer = function (game) {
this.game = game;
/**
* The time at which this Timer instance started.
* @property {number} _started
* @property {number} _started - The time at which this Timer instance started.
* @private
* @default
*/
this._started = 0;
/**
* The time (in ms) that the last second counter ticked over.
* @property {number} _timeLastSecond
* @private
* @property {boolean} running - True if the Timer is actively running.
* @default
*/
this._timeLastSecond = 0;
this.running = false;
/**
* @property {boolean} pauseWithGame - If true then the timer will update itself automatically if the game pauses, otherwise it will carry on dispatching regardless.
* @default
*/
this.pauseWithGame = true;
/**
* @property {boolean} autoDestroy - A Timer that is set to automatically destroy itself will do so after all of its events have been dispatched (assuming no looping events).
*/
this.autoDestroy = autoDestroy;
/**
* @property {boolean} expired - An expired Timer is one in which all of its events have been dispatched and none are pending.
* @default
*/
this.expired = false;
/**
* @property {array} events - An array holding the event data.
*/
this.events = [];
/**
* This is the event you should listen for. It will be dispatched whenever one of your events is triggered.
* It will pass whatever properties you set-up for the event as parameters.
* @property {Phaser.Signal} onEvent
*/
this.onEvent = new Phaser.Signal();
// Need to add custom FPS rate, for now we'll just use seconds
/**
* @property {number} timeUnit - The unit of time being used by this Timer.
*/
this.timeUnit = timeUnit;
};
/**
* @constant
* @type {number}
*/
Phaser.Timer.MINUTE = 60000;
/**
* @constant
* @type {number}
*/
Phaser.Timer.SECOND = 1000;
/**
* @constant
* @type {number}
*/
Phaser.Timer.HALF = 500;
/**
* @constant
* @type {number}
*/
Phaser.Timer.QUARTER = 250;
Phaser.Timer.prototype = {
// delay could be from now, when the timer is created, or relative to an already running timer
/**
* Creates a new Event on this Timer.
* @method Phaser.Timer#_create
* @private
*/
_create: function (delay, loop, repeatCount, args) {
// add: function (delay, callback, callbackContext) {
this.events.push({
delay: delay,
tick: delay,
expired: false,
repeatCount: repeatCount,
loop: loop,
args: args
});
this.expired = false;
},
/**
* Adds a new Event to this Timer. The event will fire after the given amount of 'delay' has passed if the Timer is running.
* Call Timer.start() once you have added all of the Events you require for this Timer.
* @method Phaser.Timer#add
* @param {number} [delay] - The number of timeUnits before the Timer will dispatch its onEvent signal.
*/
add: function (delay) {
this.events.push({
delay: delay,
dispatched: false,
repeatCount: 0,
loop: false,
args: Array.prototype.splice.call(arguments, 1)
});
// this.events.push({
// delay: delay,
// dispatched: false,
// callback: callback,
// callbackContext: callbackContext,
// args: Array.prototype.splice.call(arguments, 3)
// });
this._create(delay, false, 0, Array.prototype.splice.call(arguments, 1));
},
/**
* Adds a new Event to this Timer that will repeat for the given number of iterations.
* The event will fire after the given amount of 'delay' has passed if the Timer is running.
* Call Timer.start() once you have added all of the Events you require for this Timer.
* @method Phaser.Timer#repeat
* @param {number} [delay] - The number of timeUnits before the Timer will dispatch its onEvent signal.
* @param {number} [count] - The number of times to repeat this Event.
*/
repeat: function (delay, count) {
this.events.push({
delay: delay,
dispatched: false,
repeatCount: count,
loop: false,
args: Array.prototype.splice.call(arguments, 2)
});
this._create(delay, false, count, Array.prototype.splice.call(arguments, 2));
},
/**
* Adds a new looped Event to this Timer that will repeat forever or until the Timer is stopped.
* The event will fire after the given amount of 'delay' has passed if the Timer is running.
* Call Timer.start() once you have added all of the Events you require for this Timer.
* @method Phaser.Timer#loop
* @param {number} [delay] - The number of timeUnits before the Timer will dispatch its onEvent signal.
*/
loop: function (delay) {
this.events.push({
delay: delay,
dispatched: false,
loop: true,
args: Array.prototype.splice.call(arguments, 2)
});
this._create(delay, true, 0, Array.prototype.splice.call(arguments, 1));
},
/**
* Starts this Timer running.
* @method Phaser.Timer#start
*/
start: function() {
this._started = this.game.time.now;
this.running = true;
// sort the events based on delay here, also don't run unless events is populated
// add ability to auto-stop once all events are done
// add support for maximum duration
// add support for delay before starting
// add signals?
},
/**
* Stops this Timer from running. Does not cause it to be destroyed if autoDestroy is set to true.
* @method Phaser.Timer#stop
*/
stop: function() {
this.running = false;
@ -113,46 +182,104 @@ Phaser.Timer.prototype = {
},
update: function() {
// TODO: Game Paused support
/**
* The main Timer update event.
* @method Phaser.Timer#update
* @protected
* @param {number} time - The time from the core game clock.
* @return {boolean} True if there are still events waiting to be dispatched, otherwise false if this Timer can be deleted.
*/
update: function(time) {
if (this.running)
{
var seconds = this.seconds();
var now = (time - this._started) / this.timeUnit;
var expired = 0;
for (var i = 0, len = this.events.length; i < len; i++)
{
if (this.events[i].dispatched === false && seconds >= this.events[i].delay)
if (this.events[i].expired === false && now >= this.events[i].tick)
{
if (this.events[i].loop)
{
this.events[i].tick += this.events[i].delay - (now - this.events[i].tick);
this.onEvent.dispatch.apply(this, this.events[i].args);
this.events[i].delay = seconds + this.events[i].delay;
}
else if (this.events[i].repeatCount > 0)
{
this.events[i].repeatCount--;
this.events[i].tick += this.events[i].delay - (now - this.events[i].tick);
this.onEvent.dispatch.apply(this, this.events[i].args);
this.events[i].delay = seconds + this.events[i].delay;
}
else
{
this.events[i].dispatched = true;
// this.events[i].callback.apply(this.events[i].callbackContext, this.events[i].args);
this.events[i].expired = true;
this.onEvent.dispatch.apply(this, this.events[i].args);
// ought to slice it now
}
}
if (this.events[i].expired)
{
expired++;
}
}
// There are no events left at all
if (expired === this.events.length)
{
this.expired = true;
}
}
if (this.expired && this.autoDestroy)
{
return false;
}
else
{
return true;
}
},
seconds: function() {
return (this.game.time.now - this._started) * 0.001;
/**
* Destroys this Timer. Events are not dispatched.
* @method Phaser.Timer#destroy
*/
destroy: function() {
this.onEvent.removeAll();
this.running = false;
this.events = [];
}
};
/**
* @name Phaser.Timer#ms
* @property {number} ms - The duration in milliseconds that this Timer has been running for.
* @readonly
*/
Object.defineProperty(Phaser.Timer.prototype, "ms", {
get: function () {
return this.game.time.now - this._started;
}
});
/**
* @name Phaser.Timer#seconds
* @property {number} seconds - The duration in seconds that this Timer has been running for.
* @readonly
*/
Object.defineProperty(Phaser.Timer.prototype, "seconds", {
get: function () {
return (this.game.time.now - this._started) * 0.001;
}
});
Phaser.Timer.prototype.constructor = Phaser.Timer;

View file

@ -81,9 +81,9 @@ Phaser.TweenManager.prototype = {
* @param {Phaser.Tween} tween - The tween object you want to add.
* @returns {Phaser.Tween} The tween object you added to the manager.
*/
add: function ( tween ) {
add: function (tween) {
this._add.push( tween );
this._add.push(tween);
},
@ -106,14 +106,13 @@ Phaser.TweenManager.prototype = {
* @method Phaser.TweenManager#remove
* @param {Phaser.Tween} tween - The tween object you want to remove.
*/
remove: function ( tween ) {
remove: function (tween) {
var i = this._tweens.indexOf( tween );
if ( i !== -1 ) {
var i = this._tweens.indexOf(tween);
if (i !== -1)
{
this._tweens[i].pendingDelete = true;
}
},
@ -126,7 +125,7 @@ Phaser.TweenManager.prototype = {
*/
update: function () {
if ( this._tweens.length === 0 && this._add.length === 0 )
if (this._tweens.length === 0 && this._add.length === 0)
{
return false;
}
@ -134,20 +133,18 @@ Phaser.TweenManager.prototype = {
var i = 0;
var numTweens = this._tweens.length;
while ( i < numTweens ) {
if ( this._tweens[ i ].update( this.game.time.now ) ) {
while (i < numTweens)
{
if (this._tweens[i].update(this.game.time.now))
{
i++;
} else {
this._tweens.splice( i, 1 );
}
else
{
this._tweens.splice(i, 1);
numTweens--;
}
}
// If there are any new tweens to be added, do so now - otherwise they can be spliced out of the array before ever running
@ -183,7 +180,8 @@ Phaser.TweenManager.prototype = {
*/
pauseAll: function () {
for (var i = this._tweens.length - 1; i >= 0; i--) {
for (var i = this._tweens.length - 1; i >= 0; i--)
{
this._tweens[i].pause();
}
@ -196,7 +194,8 @@ Phaser.TweenManager.prototype = {
*/
resumeAll: function () {
for (var i = this._tweens.length - 1; i >= 0; i--) {
for (var i = this._tweens.length - 1; i >= 0; i--)
{
this._tweens[i].resume();
}