diff --git a/examples/js.php b/examples/js.php index 7a6cc3849..faf156c24 100644 --- a/examples/js.php +++ b/examples/js.php @@ -62,6 +62,7 @@ + diff --git a/examples/linkedlist1.php b/examples/linkedlist1.php index a54b5da17..c877264f8 100644 --- a/examples/linkedlist1.php +++ b/examples/linkedlist1.php @@ -46,11 +46,11 @@ list = new Phaser.LinkedList(); list.add(a.input); - // list.add(b.input); - // list.add(c.input); - // list.add(d.input); - // list.add(e.input); - // list.add(f.input); + list.add(b.input); + list.add(c.input); + list.add(d.input); + list.add(e.input); + list.add(f.input); list.dump(); diff --git a/examples/touch1.php b/examples/touch1.php new file mode 100644 index 000000000..120b6e4d4 --- /dev/null +++ b/examples/touch1.php @@ -0,0 +1,62 @@ + + + + phaser.js - a new beginning + + + + + + + + \ No newline at end of file diff --git a/src/core/LinkedList.js b/src/core/LinkedList.js index 675099a37..84e3d0a35 100644 --- a/src/core/LinkedList.js +++ b/src/core/LinkedList.js @@ -7,17 +7,19 @@ Phaser.LinkedList.prototype = { prev: null, first: null, last: null, + total: 0, sprite: { name: 'HD' }, add: function (child) { // If the list is empty - if (this.first == null && this.last == null) + if (this.total == 0 && this.first == null && this.last == null) { this.first = child; this.last = child; this.next = child; child.prev = this; + this.total++; return; } @@ -28,6 +30,10 @@ Phaser.LinkedList.prototype = { this.last = child; + this.total++; + + return child; + }, remove: function (child) { @@ -38,6 +44,8 @@ Phaser.LinkedList.prototype = { return; } + this.total--; + // The only node? if (this.first == child && this.last == child) { diff --git a/src/gameobjects/Events.js b/src/gameobjects/Events.js new file mode 100644 index 000000000..e92e3bbb6 --- /dev/null +++ b/src/gameobjects/Events.js @@ -0,0 +1,21 @@ +/** +* The Events component is a collection of events fired by the parent game object and its components. +* @param parent The game object using this Input component +*/ +Phaser.Events = function (sprite) { + + this.parent = sprite; + this.onAddedToGroup = new Phaser.Signal; + this.onRemovedFromGroup = new Phaser.Signal; + this.onKilled = new Phaser.Signal; + this.onRevived = new Phaser.Signal; + this.onOutOfBounds = new Phaser.Signal; + + this.onInputOver = null; + this.onInputOut = null; + this.onInputDown = null; + this.onInputUp = null; + this.onDragStart = null; + this.onDragStop = null; + +}; \ No newline at end of file diff --git a/src/gameobjects/Sprite.js b/src/gameobjects/Sprite.js index 2be8a5d24..863abd856 100644 --- a/src/gameobjects/Sprite.js +++ b/src/gameobjects/Sprite.js @@ -29,7 +29,7 @@ Phaser.Sprite = function (game, x, y, key, frame) { PIXI.Sprite.call(this); } - // this.events = new Phaser.Components.Events(this); + this.events = new Phaser.Events(this); /** * This manages animations of the sprite. You can modify animations through it. (see AnimationManager) @@ -102,6 +102,9 @@ Phaser.Sprite = function (game, x, y, key, frame) { // Transform cache a00: 1, a01: 0, a02: x, a10: 0, a11: 1, a12: y, id: 1, + // Input specific transform cache + i01: 0, i10: 0, idi: 1, + // Bounds check left: null, right: null, top: null, bottom: null, @@ -188,6 +191,7 @@ Phaser.Sprite.prototype.update = function() { { this._cache.a00 = this.worldTransform[0]; // scaleX a this._cache.a01 = this.worldTransform[1]; // skewY c + this._cache.i01 = this.worldTransform[1]; // skewY c this._cache.scaleX = Math.sqrt((this._cache.a00 * this._cache.a00) + (this._cache.a01 * this._cache.a01)); // round this off a bit? this._cache.a01 *= -1; this._cache.dirty = true; @@ -197,6 +201,7 @@ Phaser.Sprite.prototype.update = function() { if (this.worldTransform[3] != this._cache.a10 || this.worldTransform[4] != this._cache.a11) { this._cache.a10 = this.worldTransform[3]; // skewX b + this._cache.i10 = this.worldTransform[3]; // skewX b this._cache.a11 = this.worldTransform[4]; // scaleY d this._cache.scaleY = Math.sqrt((this._cache.a10 * this._cache.a10) + (this._cache.a11 * this._cache.a11)); // round this off a bit? this._cache.a10 *= -1; @@ -227,6 +232,7 @@ Phaser.Sprite.prototype.update = function() { this._cache.halfHeight = Math.floor(this._cache.height / 2); this._cache.id = 1 / (this._cache.a00 * this._cache.a11 + this._cache.a01 * -this._cache.a10); + this._cache.idi = 1 / (this._cache.a00 * this._cache.a11 + this._cache.i01 * -this._cache.i10); this.updateBounds(); } @@ -262,11 +268,6 @@ Phaser.Sprite.prototype.update = function() { this.body.update(); - if (this.input.enabled) - { - this.input.update(); - } - } Phaser.Sprite.prototype.postUpdate = function() { @@ -309,6 +310,15 @@ Phaser.Sprite.prototype.getLocalPosition = function(p, x, y) { } +Phaser.Sprite.prototype.getLocalUnmodifiedPosition = function(p, x, y) { + + p.x = this._cache.a11 * this._cache.idi * x + -this._cache.i01 * this._cache.idi * y + (this._cache.a12 * this._cache.i01 - this._cache.a02 * this._cache.a11) * this._cache.idi; + p.y = this._cache.a00 * this._cache.idi * y + -this._cache.i10 * this._cache.idi * x + (-this._cache.a12 * this._cache.a00 + this._cache.a02 * this._cache.i10) * this._cache.idi; + + return p; + +} + Phaser.Sprite.prototype.getBounds = function(rect) { rect = rect || new Phaser.Rectangle; diff --git a/src/input/Input.js b/src/input/Input.js index c3c16386d..3d9f2cff2 100644 --- a/src/input/Input.js +++ b/src/input/Input.js @@ -370,7 +370,7 @@ Phaser.Input.prototype = { **/ reset: function (hard) { - if (typeof hard === "undefined") { hard = false; } + hard = hard || false; this.keyboard.reset(); this.mousePointer.reset(); @@ -428,7 +428,8 @@ Phaser.Input.prototype = { **/ startPointer: function (event) { - if (this.maxPointers < 10 && this.totalActivePointers == this.maxPointers) { + if (this.maxPointers < 10 && this.totalActivePointers == this.maxPointers) + { return null; } @@ -525,7 +526,7 @@ Phaser.Input.prototype = { **/ getPointer: function (state) { - if (typeof state === "undefined") { state = false; } + state = state || false; if (this.pointer1.active == state) { @@ -599,10 +600,7 @@ Phaser.Input.prototype = { **/ getAngle: function (pointer1, pointer2) { // return Phaser.Vec2Utils.angle(pointer1.position, pointer2.position); - }, - - addGameObject: function() {}, - removeGameObject: function() {}, + } }; diff --git a/src/input/InputHandler.js b/src/input/InputHandler.js index b562e7a63..c6a31d3fb 100644 --- a/src/input/InputHandler.js +++ b/src/input/InputHandler.js @@ -104,7 +104,7 @@ Phaser.InputHandler.prototype = { this.enabled = true; // Create the signals the Input component will emit - if (this.sprites.events && this.sprite.events.onInputOver == null) + if (this.sprite.events && this.sprite.events.onInputOver == null) { this.sprite.events.onInputOver = new Phaser.Signal; this.sprite.events.onInputOut = new Phaser.Signal; @@ -316,13 +316,13 @@ Phaser.InputHandler.prototype = { }, /** - * Checks if the given pointer is over this Sprite. All checks are done in world coordinates. + * Checks if the given pointer is over this Sprite. */ checkPointerOver: function (pointer) { if (this.enabled && this.sprite.visible) { - this.sprite.getLocalPosition(this._tempPoint, pointer.x, pointer.y); + this.sprite.getLocalUnmodifiedPosition(this._tempPoint, pointer.x, pointer.y); // Check against bounds var width = this.sprite.texture.frame.width, @@ -330,11 +330,11 @@ Phaser.InputHandler.prototype = { x1 = -width * this.sprite.anchor.x, y1; - if(x > x1 && x < x1 + width) + if (this._tempPoint.x > x1 && this._tempPoint.x < x1 + width) { y1 = -height * this.sprite.anchor.y; - if(y > y1 && y < y1 + height) + if (this._tempPoint.y > y1 && this._tempPoint.y < y1 + height) { return true; } @@ -364,7 +364,7 @@ Phaser.InputHandler.prototype = { } else if (this._pointerData[pointer.id].isOver == true) { - if (Phaser.SpriteUtils.overlapsPointer(this.sprite, pointer)) + if (this.checkPointerOver(pointer)) { this._pointerData[pointer.id].x = pointer.x - this.sprite.x; this._pointerData[pointer.id].y = pointer.y - this.sprite.y; @@ -449,7 +449,7 @@ Phaser.InputHandler.prototype = { this._pointerData[pointer.id].downDuration = this._pointerData[pointer.id].timeUp - this._pointerData[pointer.id].timeDown; // Only release the InputUp signal if the pointer is still over this sprite - if (Phaser.SpriteUtils.overlapsPointer(this.sprite, pointer)) + if (this.checkPointerOver(pointer)) { //console.log('releasedHandler: ' + Date.now()); this.sprite.events.onInputUp.dispatch(this.sprite, pointer); diff --git a/src/input/Pointer.js b/src/input/Pointer.js index 895e88f0a..a388d486b 100644 --- a/src/input/Pointer.js +++ b/src/input/Pointer.js @@ -259,7 +259,7 @@ Phaser.Pointer.prototype = { if (this.targetObject !== null) { - this.targetObject.input._touchedHandler(this); + this.targetObject._touchedHandler(this); } return this; @@ -349,9 +349,9 @@ Phaser.Pointer.prototype = { } // Easy out if we're dragging something and it still exists - if (this.targetObject !== null && this.targetObject.input && this.targetObject.input.isDragged == true) + if (this.targetObject !== null && this.targetObject.isDragged == true) { - if (this.targetObject.input.update(this) == false) + if (this.targetObject.update(this) == false) { this.targetObject = null; } @@ -366,47 +366,36 @@ Phaser.Pointer.prototype = { this._highestInputPriorityID = -1; // Just run through the linked list - if (this.game.input.interactiveItems.next) + if (this.game.input.interactiveItems.total > 0) { var currentNode = this.game.input.interactiveItems.next; - + do { // If the object 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.priorityID > this._highestInputPriorityID || (currentNode.priorityID == this._highestInputPriorityID && currentNode.sprite.renderOrderID > this._highestRenderOrderID) && currentNode.checkPointerOver(this)) + if (currentNode.priorityID > this._highestInputPriorityID || (currentNode.priorityID == this._highestInputPriorityID && currentNode.sprite.renderOrderID > this._highestRenderOrderID)) { - this._highestRenderOrderID = currentNode.sprite.renderOrderID; - this._highestInputPriorityID = currentNode.priorityID; - this._highestRenderObject = currentNode; + if (currentNode.checkPointerOver(this)) + { + // console.log('HRO set', currentNode.sprite.name); + this._highestRenderOrderID = currentNode.sprite.renderOrderID; + this._highestInputPriorityID = currentNode.priorityID; + this._highestRenderObject = currentNode; + } } - currentNode = currentNode.next; } - while (currentNode != this.game.input.interactiveItems.next) + while (currentNode != null) } - -/* - for (var i = 0; i < this.game.input.totalTrackedObjects; i++) - { - if (this.game.input.inputObjects[i] && this.game.input.inputObjects[i].input && this.game.input.inputObjects[i].input.checkPointerOver(this)) - { - // If the object 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 (this.game.input.inputObjects[i].input.priorityID > this._highestInputPriorityID || (this.game.input.inputObjects[i].input.priorityID == this._highestInputPriorityID && this.game.input.inputObjects[i].renderOrderID > this._highestRenderOrderID)) - { - this._highestRenderOrderID = this.game.input.inputObjects[i].renderOrderID; - this._highestRenderObject = i; - this._highestInputPriorityID = this.game.input.inputObjects[i].input.priorityID; - } - } - } -*/ - if (this._highestRenderObject == null) { + // console.log("HRO null"); + // The pointer isn't currently over anything, check if we've got a lingering previous target if (this.targetObject) { + // console.log("The pointer isn't currently over anything, check if we've got a lingering previous target"); this.targetObject._pointerOutHandler(this); this.targetObject = null; } @@ -416,15 +405,18 @@ Phaser.Pointer.prototype = { if (this.targetObject == null) { // And now set the new one + // console.log('And now set the new one'); this.targetObject = this._highestRenderObject; this._highestRenderObject._pointerOverHandler(this); } else { // We've got a target from the last update + // console.log("We've got a target from the last update"); if (this.targetObject == this._highestRenderObject) { // Same target as before, so update it + // console.log("Same target as before, so update it"); if (this._highestRenderObject.update(this) == false) { this.targetObject = null; @@ -433,6 +425,7 @@ Phaser.Pointer.prototype = { else { // The target has changed, so tell the old one we've left it + // console.log("The target has changed, so tell the old one we've left it"); this.targetObject._pointerOutHandler(this); // And now set the new one @@ -511,17 +504,20 @@ Phaser.Pointer.prototype = { this.game.input.currentPointers--; } - if (this.game.input.interactiveItems.next) + if (this.game.input.interactiveItems.total > 0) { var currentNode = this.game.input.interactiveItems.next; do { - currentNode._releasedHandler(this); + if (currentNode) + { + currentNode._releasedHandler(this); + } currentNode = currentNode.next; } - while (currentNode != this.game.input.interactiveItems.next) + while (currentNode != null) } if (this.targetObject) @@ -631,7 +627,7 @@ Object.defineProperty(Phaser.Pointer.prototype, "worldX", { */ get: function () { - return this.game.world.camera.worldView.x + this.x; + return this.game.world.camera.x + this.x; }, @@ -647,7 +643,7 @@ Object.defineProperty(Phaser.Pointer.prototype, "worldY", { */ get: function () { - return this.game.world.camera.worldView.y + this.y; + return this.game.world.camera.y + this.y; }, diff --git a/src/utils/Debug.js b/src/utils/Debug.js index f571c9e6e..600e4298d 100644 --- a/src/utils/Debug.js +++ b/src/utils/Debug.js @@ -246,21 +246,22 @@ Phaser.Utils.Debug.prototype = { */ renderPointer: function (pointer, hideIfUp, downColor, upColor, color) { - if (this.context == null) + if (this.context == null || pointer == null) { return; } - if (typeof hideIfUp === "undefined") { hideIfUp = false; } - if (typeof downColor === "undefined") { downColor = 'rgba(0,255,0,0.5)'; } - if (typeof upColor === "undefined") { upColor = 'rgba(255,0,0,0.5)'; } - if (typeof color === "undefined") { color = 'rgb(255,255,255)'; } + hideIfUp = hideIfUp || false; + downColor = downColor || 'rgba(0,255,0,0.5)'; + upColor = upColor || 'rgba(255,0,0,0.5)'; + color = color || 'rgb(255,255,255)'; if (hideIfUp == true && pointer.isUp == true) { return; } + this.start(pointer.x, pointer.y - 100, color); this.context.beginPath(); this.context.arc(pointer.x, pointer.y, pointer.circle.radius, 0, Math.PI * 2); @@ -285,11 +286,32 @@ Phaser.Utils.Debug.prototype = { this.context.closePath(); // Render the text - this.start(pointer.x, pointer.y - 100, color); + // this.start(pointer.x, pointer.y - 100, color); this.line('ID: ' + pointer.id + " Active: " + pointer.active); this.line('World X: ' + pointer.worldX + " World Y: " + pointer.worldY); this.line('Screen X: ' + pointer.x + " Screen Y: " + pointer.y); this.line('Duration: ' + pointer.duration + " ms"); + this.stop(); + + }, + + /** + * Render Sprite Input Debug information + * @param x {number} X position of the debug info to be rendered. + * @param y {number} Y position of the debug info to be rendered. + * @param [color] {number} color of the debug info to be rendered. (format is css color string) + */ + renderSpriteInputInfo: function (sprite, x, y, color) { + + color = color || 'rgb(255,255,255)'; + + this.start(x, y, color); + this.line('Sprite Input: (' + sprite.width + ' x ' + sprite.height + ')'); + this.line('x: ' + sprite.input.pointerX().toFixed(1) + ' y: ' + sprite.input.pointerY().toFixed(1)); + this.line('over: ' + sprite.input.pointerOver() + ' duration: ' + sprite.input.overDuration().toFixed(0)); + this.line('down: ' + sprite.input.pointerDown() + ' duration: ' + sprite.input.downDuration().toFixed(0)); + this.line('just over: ' + sprite.input.justOver() + ' just out: ' + sprite.input.justOut()); + this.stop(); },