Phaser.ArrayList is a new iterative object, similar in principal to a linked list but operating on a single array without modifying the object structure.

Input and Pointer now use the new ArrayList instead of a LinkedList, which resolve list item removable during callback issues.
Input.reset no longer resets every interactive item it knows of, because they are removed during the destroy phase and can now persist between States if needed.
This commit is contained in:
photonstorm 2014-04-25 15:11:54 +01:00
parent 45aa486e27
commit 54b71ddc23
10 changed files with 212 additions and 35 deletions

View file

@ -77,6 +77,8 @@ Version 2.0.4 - "Mos Shirare" - in development
* RandomDataGenerator.integerInRange uses a new method of rounding the value to an integer to avoid distribution probability issues (thanks PhaserFan)
* Updated the Device little / big endianess check.
* Time has been updated so that physicsElapsed can never be zero (falls back to 1/60), also fixes p2 elapsed time bug (thanks @georgiee, fix #758)
* Input and Pointer now use the new ArrayList instead of a LinkedList, which resolve list item removable during callback issues.
* Input.reset no longer resets every interactive item it knows of, because they are removed during the destroy phase and can now persist between States if needed.
### New Features
@ -94,6 +96,8 @@ Version 2.0.4 - "Mos Shirare" - in development
* Device.support32bit is a new boolean that sets if the context supports 32bit pixel manipulation using array buffer views or not.
* BitmapData.processPixelRGB lets you perform a custom callback on every pixel in the BitmapData.
* P2.World now has its own pause and resume methods, so you can pause the physics simulation independent of your game (thanks @georgiee)
* Phaser.ArrayList is a new iterative object, similar in principal to a linked list but operating on a single array without modifying the object structure.
### Bug Fixes

View file

@ -80,6 +80,7 @@
<script src="$path/src/core/Camera.js"></script>
<script src="$path/src/core/State.js"></script>
<script src="$path/src/core/StateManager.js"></script>
<script src="$path/src/core/ArrayList.js"></script>
<script src="$path/src/core/LinkedList.js"></script>
<script src="$path/src/core/Signal.js"></script>
<script src="$path/src/core/SignalBinding.js"></script>

View file

@ -25,7 +25,7 @@ Phaser.Plugin.Webcam.prototype.constructor = Phaser.Plugin.Webcam;
Phaser.Plugin.Webcam.prototype.start = function (width, height, context) {
console.log('Webcam start', width, height);
// console.log('Webcam start', width, height);
this.context = context;

191
src/core/ArrayList.js Normal file
View file

@ -0,0 +1,191 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2014 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
/**
* A basic linked list data structure.
*
* @class Phaser.ArrayList
* @constructor
*/
Phaser.ArrayList = function () {
/**
* @property {number} total - Number of objects in the list.
* @default
*/
this.total = 0;
/**
* @property {number} position - Current cursor position.
* @default
*/
this.position = 0;
/**
* @property {array} list - The list.
*/
this.list = [];
};
Phaser.ArrayList.prototype = {
/**
* Adds a new element to this linked list.
*
* @method Phaser.ArrayList#add
* @param {object} child - The element to add to this list. Can be a Phaser.Sprite or any other object you need to quickly iterate through.
* @return {object} The child that was added.
*/
add: function (child) {
if (!this.exists(child))
{
this.list.push(child);
this.total++;
}
return child;
},
getIndex: function (child) {
var i = this.list.length;
while (i--)
{
if (this.list[i] === child)
{
return i;
}
}
return -1;
},
exists: function (child) {
var i = this.list.length;
while (i--)
{
if (this.list[i] === child)
{
return true;
}
}
return false;
},
/**
* Resets the first, last, next and previous node pointers in this list.
*
* @method Phaser.ArrayList#reset
*/
reset: function () {
this.list.length = 0;
this.total = 0;
},
/**
* Removes the given element from this linked list if it exists.
*
* @method Phaser.ArrayList#remove
* @param {object} child - The child to be removed from the list.
*/
remove: function (child) {
var idx = this.getIndex(child);
if (idx > -1)
{
this.list.splice(idx, 1);
this.total--;
return child;
}
},
/**
* Calls a function on all members of this list, using the member as the context for the callback.
* The function must exist on the member.
*
* @method Phaser.ArrayList#callAll
* @param {function} callback - The function to call.
* @param {...*} parameter - Additional parameters that will be passed to the callback.
*/
callAll: function (callback) {
var args = Array.prototype.splice.call(arguments, 1);
var i = this.list.length;
while (i--)
{
this.list[i][callback].apply(this.list[i], args);
}
}
};
/**
*
*
* @name Phaser.ArrayList#first
* @property {object} first - The first item in the list.
*/
Object.defineProperty(Phaser.ArrayList.prototype, "first", {
get: function () {
this.position = 0;
if (this.total > 0)
{
return this.list[0];
}
else
{
return null;
}
}
});
/**
*
*
* @name Phaser.ArrayList#next
* @property {object} next - Advanced the cursor and return.
*/
Object.defineProperty(Phaser.ArrayList.prototype, "next", {
get: function () {
if (this.position < this.total)
{
this.position++;
return this.list[this.position];
}
else
{
return null;
}
}
});
Phaser.ArrayList.prototype.constructor = Phaser.ArrayList;

View file

@ -37,7 +37,7 @@ Phaser.LinkedList = function () {
this.last = null;
/**
* @property {object} game - Number of elements in the list.
* @property {number} total - Number of elements in the list.
* @default
*/
this.total = 0;

View file

@ -198,11 +198,11 @@ Phaser.BitmapData.prototype = {
* @param {number} r - The red color value, between 0 and 0xFF (255).
* @param {number} g - The green color value, between 0 and 0xFF (255).
* @param {number} b - The blue color value, between 0 and 0xFF (255).
* @param {number} [a=255] - The alpha color value, between 0 and 0xFF (255).
* @param {number} [a=1] - The alpha color value, between 0 and 1.
*/
fill: function (r, g, b, a) {
if (typeof a === 'undefined') { a = 255; }
if (typeof a === 'undefined') { a = 1; }
this.context.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
this.context.fillRect(0, 0, this.width, this.height);

View file

@ -268,10 +268,10 @@ Phaser.Input = function (game) {
this.onHold = null;
/**
* A linked list of interactive objects; the InputHandler components (belonging to Sprites) register themselves with this.
* @property {Phaser.LinkedList} interactiveItems
* A list of interactive objects. Te InputHandler components add and remove themselves from this.
* @property {Phaser.ArrayList} interactiveItems
*/
this.interactiveItems = new Phaser.LinkedList();
this.interactiveItems = new Phaser.ArrayList();
/**
* @property {Phaser.Point} _localPoint - Internal cache var.
@ -521,8 +521,6 @@ Phaser.Input.prototype = {
this.onUp = new Phaser.Signal();
this.onTap = new Phaser.Signal();
this.onHold = new Phaser.Signal();
this.interactiveItems.callAll('reset');
}
this._pollCounter = 0;

View file

@ -213,7 +213,7 @@ Phaser.InputHandler.prototype = {
start: function (priority, useHandCursor) {
priority = priority || 0;
if (typeof useHandCursor == 'undefined') { useHandCursor = false; }
if (typeof useHandCursor === 'undefined') { useHandCursor = false; }
// Turning on
if (this.enabled === false)

View file

@ -364,15 +364,15 @@ Phaser.Pointer.prototype = {
this._highestRenderObject = null;
this._highestInputPriorityID = -1;
// Just run through the linked list
// Run through the list
if (this.game.input.interactiveItems.total > 0)
{
var currentNode = this.game.input.interactiveItems.next;
var currentNode = this.game.input.interactiveItems.first;
do
{
// If the object is using pixelPerfect checks, or has a higher InputManager.PriorityID OR if the priority ID is the same as the current highest AND it has a higher renderOrderID, then set it to the top
if (currentNode.validForInput(this._highestInputPriorityID, this._highestRenderOrderID))
if (currentNode && currentNode.validForInput(this._highestInputPriorityID, this._highestRenderOrderID))
{
if ((!fromClick && currentNode.checkPointerOver(this)) || (fromClick && currentNode.checkPointerDown(this)))
{
@ -381,9 +381,9 @@ Phaser.Pointer.prototype = {
this._highestRenderObject = currentNode;
}
}
currentNode = currentNode.next;
currentNode = this.game.input.interactiveItems.next;
}
while (currentNode != null);
while (currentNode !== null);
}
if (this._highestRenderObject === null)
@ -502,28 +502,10 @@ Phaser.Pointer.prototype = {
this.game.input.currentPointers--;
}
if (this.game.input.interactiveItems.total > 0)
{
var currentNode = this.game.input.interactiveItems.next;
do
{
if (currentNode)
{
currentNode._releasedHandler(this);
}
currentNode = currentNode.next;
}
while (currentNode != null);
}
if (this.targetObject)
{
this.targetObject._releasedHandler(this);
}
this.game.input.interactiveItems.callAll('_releasedHandler', this);
this.targetObject = null;
return this;
},

View file

@ -14,6 +14,7 @@
"src/core/State.js",
"src/core/StateManager.js",
"src/core/LinkedList.js",
"src/core/ArrayList.js",
"src/core/Signal.js",
"src/core/SignalBinding.js",
"src/core/Filter.js",