Timer has removed all use of local temporary vars in the core update loop.

Timer.clearPendingEvents will purge any events marked for deletion, this is run automatically at the start of the update loop.
The main Timer loop could incorrectly remove TimeEvent if a new one was added specifically during an event callback (thanks @garyyeap, fix #710)
This commit is contained in:
photonstorm 2014-04-14 11:51:50 +01:00
parent 286882b1ee
commit f33ba5dcc7
3 changed files with 70 additions and 46 deletions

View file

@ -56,14 +56,22 @@ There is also an [un-official Getting Started Guide](http://www.antonoffplus.com
Version 2.0.4 - "Mos Shirare" - in development Version 2.0.4 - "Mos Shirare" - in development
### Updates ### Updates
* TypeScript definitions fixes and updates (thanks @clark-stevenson)
* Timer has removed all use of local temporary vars in the core update loop.
### New Features ### New Features
* Loader now has an onFileStart event you can listen for (thanks @codevinsky, #705)
* Timer.clearPendingEvents will purge any events marked for deletion, this is run automatically at the start of the update loop.
### Bug Fixes ### Bug Fixes
* The main Timer loop could incorrectly remove TimeEvent if a new one was added specifically during an event callback (thanks @garyyeap, fix #710)
There is an extensive [Migration Guide](https://github.com/photonstorm/phaser/blob/master/resources/Migration%20Guide.md) available for those converting from Phaser 1.x to 2.x. In the guide we detail the API breaking changes and approach to our new physics system. There is an extensive [Migration Guide](https://github.com/photonstorm/phaser/blob/master/resources/Migration%20Guide.md) available for those converting from Phaser 1.x to 2.x. In the guide we detail the API breaking changes and approach to our new physics system.

View file

@ -94,29 +94,28 @@ Phaser.Loader = function (game) {
*/ */
this.baseURL = ''; this.baseURL = '';
/** /**
* @property {Phaser.Signal} onFileStart - Event signal. * @property {Phaser.Signal} onLoadStart - This event is dispatched when the loading process starts, before the first file has been requested.
*/
this.onFileStart = new Phaser.Signal();
/**
* @property {Phaser.Signal} onFileComplete - Event signal.
*/
this.onFileComplete = new Phaser.Signal();
/**
* @property {Phaser.Signal} onFileError - Event signal.
*/
this.onFileError = new Phaser.Signal();
/**
* @property {Phaser.Signal} onLoadStart - Event signal.
*/ */
this.onLoadStart = new Phaser.Signal(); this.onLoadStart = new Phaser.Signal();
/** /**
* @property {Phaser.Signal} onLoadComplete - Event signal. * @property {Phaser.Signal} onFileStart - This event is dispatched immediately before a file starts loading. It's possible the file may still error (404, etc) after this event is sent.
*/
this.onFileStart = new Phaser.Signal();
/**
* @property {Phaser.Signal} onFileComplete - This event is dispatched when a file completes loading successfully.
*/
this.onFileComplete = new Phaser.Signal();
/**
* @property {Phaser.Signal} onFileError - This event is dispatched when a file errors as a result of the load request.
*/
this.onFileError = new Phaser.Signal();
/**
* @property {Phaser.Signal} onLoadComplete - This event is dispatched when the final file in the load queue has either loaded or failed.
*/ */
this.onLoadComplete = new Phaser.Signal(); this.onLoadComplete = new Phaser.Signal();
@ -886,11 +885,11 @@ Phaser.Loader.prototype = {
return; return;
} }
this.onFileStart.dispatch(this.progress, this._fileList[this._fileIndex]);
var file = this._fileList[this._fileIndex]; var file = this._fileList[this._fileIndex];
var _this = this; var _this = this;
this.onFileStart.dispatch(this.progress, file.key);
// Image or Data? // Image or Data?
switch (file.type) switch (file.type)
{ {

View file

@ -109,6 +109,18 @@ Phaser.Timer = function (game, autoDestroy) {
*/ */
this._i = 0; this._i = 0;
/**
* @property {number} _diff - Internal cache var.
* @private
*/
this._diff = 0;
/**
* @property {number} _newTick - Internal cache var.
* @private
*/
this._newTick = 0;
}; };
/** /**
@ -325,6 +337,28 @@ Phaser.Timer.prototype = {
}, },
/**
* Clears any events from the Timer which have pendingDelete set to true and then resets the private _len and _i values.
*
* @method Phaser.Timer#clearPendingEvents
*/
clearPendingEvents: function () {
this._i = this.events.length;
while (this._i--)
{
if (this.events[this._i].pendingDelete)
{
this.events.splice(this._i, 1);
}
}
this._len = this.events.length;
this._i = 0;
},
/** /**
* The main Timer update event, called automatically by the Game clock. * The main Timer update event, called automatically by the Game clock.
* @method Phaser.Timer#update * @method Phaser.Timer#update
@ -341,55 +375,38 @@ Phaser.Timer.prototype = {
this._now = time; this._now = time;
this._len = this.events.length; // Clears events marked for deletion and resets _len and _i to 0.
this.clearPendingEvents();
this._i = 0;
while (this._i < this._len)
{
if (this.events[this._i].pendingDelete)
{
this.events.splice(this._i, 1);
this._len--;
}
this._i++;
}
this._len = this.events.length;
if (this.running && this._now >= this.nextTick && this._len > 0) if (this.running && this._now >= this.nextTick && this._len > 0)
{ {
this._i = 0;
while (this._i < this._len && this.running) while (this._i < this._len && this.running)
{ {
if (this._now >= this.events[this._i].tick) if (this._now >= this.events[this._i].tick)
{ {
var diff = this._now - this.events[this._i].tick; // (now + delay) - (time difference from last tick to now)
var newTick = (this._now + this.events[this._i].delay) - diff; this._newTick = (this._now + this.events[this._i].delay) - (this._now - this.events[this._i].tick);
if (newTick < 0) if (this._newTick < 0)
{ {
newTick = this._now + this.events[this._i].delay; this._newTick = this._now + this.events[this._i].delay;
} }
if (this.events[this._i].loop === true) if (this.events[this._i].loop === true)
{ {
this.events[this._i].tick = newTick; this.events[this._i].tick = this._newTick;
this.events[this._i].callback.apply(this.events[this._i].callbackContext, this.events[this._i].args); this.events[this._i].callback.apply(this.events[this._i].callbackContext, this.events[this._i].args);
} }
else if (this.events[this._i].repeatCount > 0) else if (this.events[this._i].repeatCount > 0)
{ {
this.events[this._i].repeatCount--; this.events[this._i].repeatCount--;
this.events[this._i].tick = newTick; this.events[this._i].tick = this._newTick;
this.events[this._i].callback.apply(this.events[this._i].callbackContext, this.events[this._i].args); this.events[this._i].callback.apply(this.events[this._i].callbackContext, this.events[this._i].args);
} }
else else
{ {
this.events[this._i].callback.apply(this.events[this._i].callbackContext, this.events[this._i].args); this.events[this._i].callback.apply(this.events[this._i].callbackContext, this.events[this._i].args);
this.events.splice(this._i, 1); this.events[this._i].pendingDelete = true;
this._len--;
} }
this._i++; this._i++;