diff --git a/Phaser/CameraManager.ts b/Phaser/CameraManager.ts index 24b454bd..fa8a7af2 100644 --- a/Phaser/CameraManager.ts +++ b/Phaser/CameraManager.ts @@ -38,10 +38,12 @@ module Phaser { * Local private reference to Game. */ private _game: Game; + /** - * Local container for storing camera. + * Local container for storing cameras. */ private _cameras: Camera[]; + /** * Local helper stores index of next created camera. */ diff --git a/Phaser/Group.ts b/Phaser/Group.ts index 25654daa..bf61020c 100644 --- a/Phaser/Group.ts +++ b/Phaser/Group.ts @@ -5,7 +5,6 @@ * Phaser - Group * * This class is used for organising, updating and sorting game objects. -* */ module Phaser { @@ -179,7 +178,7 @@ module Phaser { } /** - * Adds a new Basic subclass (Basic, Basic, Enemy, etc) to the group. + * Adds a new Basic subclass (Basic, GameObject, Sprite, etc) to the group. * Group will try to replace a null member of the array first. * Failing that, Group will add it to the end of the member array, * assuming there is room for it, and doubling the size of the array if necessary. @@ -188,7 +187,6 @@ module Phaser { * the object will NOT be added to the group!

* * @param {Basic} Object The object you want to add to the group. - * * @return {Basic} The same Basic object that was passed in. */ public add(Object: Basic) { diff --git a/Phaser/gameobjects/Tilemap.ts b/Phaser/gameobjects/Tilemap.ts index d768c963..a04f0419 100644 --- a/Phaser/gameobjects/Tilemap.ts +++ b/Phaser/gameobjects/Tilemap.ts @@ -339,7 +339,7 @@ module Phaser { public getTileFromInputXY(layer?: number = 0):Tile { - return this.tiles[this.layers[layer].getTileFromWorldXY(this._game.input.worldX, this._game.input.worldY)]; + return this.tiles[this.layers[layer].getTileFromWorldXY(this._game.input.getWorldX(), this._game.input.getWorldY())]; } diff --git a/Phaser/system/input/Input.ts b/Phaser/system/input/Input.ts index e451e326..c1f158d4 100644 --- a/Phaser/system/input/Input.ts +++ b/Phaser/system/input/Input.ts @@ -19,6 +19,7 @@ module Phaser { this._game = game; + this.mousePointer = new Pointer(this._game, 0); this.pointer1 = new Pointer(this._game, 1); this.pointer2 = new Pointer(this._game, 2); this.pointer3 = new Pointer(this._game, 3); @@ -38,6 +39,11 @@ module Phaser { this.onDown = new Phaser.Signal(); this.onUp = new Phaser.Signal(); + this.onTap = new Phaser.Signal(); + this.onDoubleTap = new Phaser.Signal(); + this.onHold = new Phaser.Signal(); + + this.currentPointers = 0; } @@ -53,6 +59,29 @@ module Phaser { */ public disabled: bool = false; + /** + * Controls the expected behaviour when using a mouse and touch together on a multi-input device + */ + public multiInputOverride: number = Input.MOUSE_TOUCH_COMBINE; + + /** + * Static defining the behaviour expected on a multi-input device system. + * With this setting when the mouse is used it updates the Input.x/y globals regardless if another pointer is active or not + */ + public static MOUSE_OVERRIDES_TOUCH: number = 0; + + /** + * Static defining the behaviour expected on a multi-input device system. + * With this setting when the mouse is used it only updates the Input.x/y globals if no other pointer is active + */ + public static TOUCH_OVERRIDES_MOUSE: number = 1; + + /** + * Static defining the behaviour expected on a multi-input device system. + * With this setting when the mouse is used it updates the Input.x/y globals at the same time as any active Pointer objects might + */ + public static MOUSE_TOUCH_COMBINE: number = 2; + /** * Phaser.Mouse handler * @type {Mouse} @@ -109,18 +138,6 @@ module Phaser { */ public scaleY: number = 1; - /** - * - * @type {Number} - */ - public worldX: number = 0; - - /** - * - * @type {Number} - */ - public worldY: number = 0; - /** * The maximum number of Pointers allowed to be active at any one time. * For lots of games it's useful to set this to 1 @@ -128,6 +145,12 @@ module Phaser { */ public maxPointers: number = 10; + /** + * The current number of active Pointers. + * @type {Number} + */ + public currentPointers: number = 0; + /** * A Signal dispatched when a mouse/Pointer object is pressed * @type {Phaser.Signal} @@ -158,6 +181,72 @@ module Phaser { */ public onHold: Phaser.Signal; + /** + * The number of milliseconds that the Pointer has to be pressed down and then released to be considered a tap or click + * @property tapRate + * @type {Number} + **/ + public tapRate: number = 200; + + /** + * The number of milliseconds between taps of the same Pointer for it to be considered a double tap / click + * @property doubleTapRate + * @type {Number} + **/ + public doubleTapRate: number = 250; + + /** + * The number of milliseconds that the Pointer has to be pressed down for it to fire a onHold event + * @property holdRate + * @type {Number} + **/ + public holdRate: number = 2000; + + /** + * The number of milliseconds below which the Pointer is considered justPressed + * @property justPressedRate + * @type {Number} + **/ + public justPressedRate: number = 200; + + /** + * The number of milliseconds below which the Pointer is considered justReleased + * @property justReleasedRate + * @type {Number} + **/ + public justReleasedRate: number = 200; + + /** + * Sets if the Pointer objects should record a history of x/y coordinates they have passed through. + * The history is cleared each time the Pointer is pressed down. + * The history is updated at the rate specified in Input.pollRate + * @property recordPointerHistory + * @type {Boolean} + **/ + public recordPointerHistory: bool = true; + + /** + * The rate in milliseconds at which the Pointer objects should update their tracking history + * @property recordRate + * @type {Number} + */ + public recordRate: number = 100; + + /** + * The total number of entries that can be recorded into the Pointer objects tracking history. + * The the Pointer is tracking one event every 100ms, then a trackLimit of 100 would store the last 10 seconds worth of history. + * @property recordLimit + * @type {Number} + */ + public recordLimit: number = 100; + + /** + * A Pointer object specifically used by the Mouse + * @property mousePointer + * @type {Pointer} + **/ + public mousePointer: Pointer; + /** * A Pointer object * @property pointer1 @@ -274,16 +363,22 @@ module Phaser { public update() { - //this.worldX = this._game.camera.worldView.x + this.x; - //this.worldY = this._game.camera.worldView.y + this.y; - - this.mouse.update(); + this.mousePointer.update(); + this.pointer1.update(); + this.pointer2.update(); + this.pointer3.update(); + this.pointer4.update(); + this.pointer5.update(); + this.pointer6.update(); + this.pointer7.update(); + this.pointer8.update(); + this.pointer9.update(); + this.pointer10.update(); } public reset() { - this.mouse.reset(); this.keyboard.reset(); this.pointer1.reset(); @@ -299,6 +394,11 @@ module Phaser { this.onDown = new Phaser.Signal(); this.onUp = new Phaser.Signal(); + this.onTap = new Phaser.Signal(); + this.onDoubleTap = new Phaser.Signal(); + this.onHold = new Phaser.Signal(); + + this.currentPointers = 0; } @@ -309,61 +409,61 @@ module Phaser { **/ public get totalInactivePointers(): number { - return 10 - this.totalActivePointers; + return 10 - this.currentPointers; } /** - * Get the total number of active Pointers + * Recalculates the total number of active Pointers * @method totalActivePointers * @return {Number} The number of Pointers currently active **/ public get totalActivePointers(): number { - var result: number = 0; + this.currentPointers = 0; if (this.pointer1.active == true) { - result++; + this.currentPointers++; } else if (this.pointer2.active == true) { - result++; + this.currentPointers++; } else if (this.pointer3.active == true) { - result++; + this.currentPointers++; } else if (this.pointer4.active == true) { - result++; + this.currentPointers++; } else if (this.pointer5.active == true) { - result++; + this.currentPointers++; } else if (this.pointer6.active == true) { - result++; + this.currentPointers++; } else if (this.pointer7.active == true) { - result++; + this.currentPointers++; } else if (this.pointer8.active == true) { - result++; + this.currentPointers++; } else if (this.pointer9.active == true) { - result++; + this.currentPointers++; } else if (this.pointer10.active == true) { - result++; + this.currentPointers++; } - return result; + return this.currentPointers; } @@ -671,7 +771,7 @@ module Phaser { this._game.stage.context.fillStyle = color; this._game.stage.context.fillText('Input', x, y); this._game.stage.context.fillText('Screen X: ' + this.x + ' Screen Y: ' + this.y, x, y + 14); - this._game.stage.context.fillText('World X: ' + this.worldX + ' World Y: ' + this.worldY, x, y + 28); + this._game.stage.context.fillText('World X: ' + this.getWorldX() + ' World Y: ' + this.getWorldY(), x, y + 28); this._game.stage.context.fillText('Scale X: ' + this.scaleX.toFixed(1) + ' Scale Y: ' + this.scaleY.toFixed(1), x, y + 42); } diff --git a/Phaser/system/input/MSPointer.ts b/Phaser/system/input/MSPointer.ts index eae1597d..a23d76bf 100644 --- a/Phaser/system/input/MSPointer.ts +++ b/Phaser/system/input/MSPointer.ts @@ -25,7 +25,7 @@ module Phaser { } /** - * + * Local private reference to game. * @property _game * @type Game * @private @@ -39,7 +39,7 @@ module Phaser { public disabled: bool = false; /** - * + * Starts the event listeners running * @method start */ public start() { @@ -111,11 +111,18 @@ module Phaser { } /** - * + * Stop the event listeners * @method stop */ public stop() { + if (this._game.device.mspointer == true) + { + //this._game.stage.canvas.addEventListener('MSPointerDown', (event) => this.onPointerDown(event), false); + //this._game.stage.canvas.addEventListener('MSPointerMove', (event) => this.onPointerMove(event), false); + //this._game.stage.canvas.addEventListener('MSPointerUp', (event) => this.onPointerUp(event), false); + } + } } diff --git a/Phaser/system/input/Mouse.ts b/Phaser/system/input/Mouse.ts index 7042298a..c32a4ee7 100644 --- a/Phaser/system/input/Mouse.ts +++ b/Phaser/system/input/Mouse.ts @@ -16,12 +16,14 @@ module Phaser { } + /** + * Local private reference to game. + * @property _game + * @type {Phaser.Game} + * @private + **/ private _game: Game; - private _x: number = 0; - private _y: number = 0; - - public button: number; public static LEFT_BUTTON: number = 0; public static MIDDLE_BUTTON: number = 1; @@ -34,30 +36,9 @@ module Phaser { public disabled: bool = false; /** - * @type {Boolean} - */ - public isDown: bool = false; - - /** - * @type {Boolean} - */ - public isUp: bool = true; - - /** - * @type {Number} - */ - public timeDown: number = 0; - - /** - * @type {Number} - */ - public duration: number = 0; - - /** - * @type {Number} - */ - public timeUp: number = 0; - + * Starts the event listeners running + * @method start + */ public start() { this._game.stage.canvas.addEventListener('mousedown', (event: MouseEvent) => this.onMouseDown(event), true); @@ -66,13 +47,6 @@ module Phaser { } - public reset() { - - this.isDown = false; - this.isUp = true; - - } - /** * @param {MouseEvent} event */ @@ -83,31 +57,9 @@ module Phaser { return; } - this.button = event.button; + event['identifier'] = 0; - this._x = event.clientX - this._game.stage.x; - this._y = event.clientY - this._game.stage.y; - - this._game.input.x = this._x * this._game.input.scaleX; - this._game.input.y = this._y * this._game.input.scaleY; - - this.isDown = true; - this.isUp = false; - this.timeDown = this._game.time.now; - - this._game.input.onDown.dispatch(this._game.input.x, this._game.input.y, this.timeDown); - - } - - public update() { - - //this._game.input.x = this._x * this._game.input.scaleX; - //this._game.input.y = this._y * this._game.input.scaleY; - - if (this.isDown) - { - this.duration = this._game.time.now - this.timeDown; - } + this._game.input.mousePointer.start(event); } @@ -121,13 +73,9 @@ module Phaser { return; } - this.button = event.button; + event['identifier'] = 0; - this._x = event.clientX - this._game.stage.x; - this._y = event.clientY - this._game.stage.y; - - this._game.input.x = this._x * this._game.input.scaleX; - this._game.input.y = this._y * this._game.input.scaleY; + this._game.input.mousePointer.move(event); } @@ -141,19 +89,21 @@ module Phaser { return; } - this.button = event.button; - this.isDown = false; - this.isUp = true; - this.timeUp = this._game.time.now; - this.duration = this.timeUp - this.timeDown; + event['identifier'] = 0; - this._x = event.clientX - this._game.stage.x; - this._y = event.clientY - this._game.stage.y; + this._game.input.mousePointer.stop(event); - this._game.input.x = this._x * this._game.input.scaleX; - this._game.input.y = this._y * this._game.input.scaleY; + } - this._game.input.onUp.dispatch(this._game.input.x, this._game.input.y, this.timeDown); + /** + * Stop the event listeners + * @method stop + */ + public stop() { + + //this._game.stage.canvas.addEventListener('mousedown', (event: MouseEvent) => this.onMouseDown(event), true); + //this._game.stage.canvas.addEventListener('mousemove', (event: MouseEvent) => this.onMouseMove(event), true); + //this._game.stage.canvas.addEventListener('mouseup', (event: MouseEvent) => this.onMouseUp(event), true); } diff --git a/Phaser/system/input/Pointer.ts b/Phaser/system/input/Pointer.ts index da1eecfc..17085094 100644 --- a/Phaser/system/input/Pointer.ts +++ b/Phaser/system/input/Pointer.ts @@ -25,6 +25,11 @@ module Phaser { this.pointB = new Point(); this.circle = new Circle(0, 0, 44); + if (id == 0) + { + this.isMouse = true; + } + } /** @@ -36,7 +41,31 @@ module Phaser { private _game: Game; /** - * The Pointer ID (a number between 1 and 10) + * Local private variable to store the status of dispatching a hold event + * @property _holdSent + * @type {Boolean} + * @private + */ + private _holdSent: bool = false; + + /** + * Local private variable storing the short-term history of pointer movements + * @property _history + * @type {Array} + * @private + */ + private _history = []; + + /** + * Local private variable storing the time at which the next history drop should occur + * @property _lastDrop + * @type {Number} + * @private + */ + private _nextDrop: number = 0; + + /** + * The Pointer ID (a number between 1 and 10, 0 is reserved for the mouse pointer specifically) * @property id * @type {Number} */ @@ -87,6 +116,13 @@ module Phaser { */ public withinGame: bool = false; + /** + * If this Pointer is a mouse the button property holds the value of which mouse button was pressed down + * @property button + * @type {Number} + */ + public button: number; + /** * The horizontal coordinate of point relative to the viewport in pixels, excluding any scroll offset * @property clientX @@ -151,14 +187,21 @@ module Phaser { public target; /** - * If the Pointer is touching the touchscreen isDown is set to true + * If the Pointer is a mouse this is true, otherwise false + * @property isMouse + * @type {Boolean} + **/ + public isMouse: bool = false; + + /** + * If the Pointer is touching the touchscreen, or the mouse button is held down, isDown is set to true * @property isDown * @type {Boolean} **/ public isDown: bool = false; /** - * If the Pointer is not touching the touchscreen isUp is set to true + * If the Pointer is not touching the touchscreen, or the mouse button is up, isUp is set to true * @property isUp * @type {Boolean} **/ @@ -179,18 +222,11 @@ module Phaser { public timeUp: number = 0; /** - * The number of milliseconds below which the Pointer is considered justPressed - * @property justPressedRate + * A timestamp representing when the Pointer was last tapped or clicked + * @property previousTapTime * @type {Number} **/ - public justPressedRate: number = 200; - - /** - * The number of milliseconds below which the Pointer is considered justReleased - * @property justReleasedRate - * @type {Number} - **/ - public justReleasedRate: number = 200; + public previousTapTime: number = 0; /** * The total number of times this Pointer has been touched to the touchscreen @@ -200,12 +236,17 @@ module Phaser { public totalTouches: number = 0; /** - * How long the Pointer has been depressed on the touchscreen. + * How long the Pointer has been depressed on the touchscreen. If not currently down it returns -1. * @property duration * @type {Number} **/ public get duration(): number { + if (this.isUp) + { + return -1; + } + return this._game.time.now - this.timeDown; } @@ -240,6 +281,13 @@ module Phaser { this.identifier = event.identifier; this.target = event.target; + if (event.button) + { + this.button = event.button; + } + + this._history.length = 0; + this.move(event); this.pointA.setTo(this.x, this.y); @@ -249,17 +297,56 @@ module Phaser { this.isDown = true; this.isUp = false; this.timeDown = this._game.time.now; + this._holdSent = false; - this._game.input.x = this.x * this._game.input.scaleX; - this._game.input.y = this.y * this._game.input.scaleY; - this._game.input.onDown.dispatch(this); + if (this._game.input.multiInputOverride == Input.MOUSE_OVERRIDES_TOUCH || this._game.input.multiInputOverride == Input.MOUSE_TOUCH_COMBINE || (this._game.input.multiInputOverride == Input.TOUCH_OVERRIDES_MOUSE && this._game.input.currentPointers == 0)) + { + this._game.input.x = this.x * this._game.input.scaleX; + this._game.input.y = this.y * this._game.input.scaleY; + this._game.input.onDown.dispatch(this); + } this.totalTouches++; + if (this.isMouse == false) + { + this._game.input.currentPointers++; + } + return this; } + public update() { + + if (this.active) + { + if (this._holdSent == false && this.duration >= this._game.input.holdRate) + { + if (this._game.input.multiInputOverride == Input.MOUSE_OVERRIDES_TOUCH || this._game.input.multiInputOverride == Input.MOUSE_TOUCH_COMBINE || (this._game.input.multiInputOverride == Input.TOUCH_OVERRIDES_MOUSE && this._game.input.currentPointers == 0)) + { + this._game.input.onHold.dispatch(this); + } + + this._holdSent = true; + } + + // Update the droppings history + if (this._game.input.recordPointerHistory && this._game.time.now >= this._nextDrop) + { + this._nextDrop = this._game.time.now + this._game.input.recordRate; + this._history.push({ x: this.pointB.x, y: this.pointB.y }); + + if (this._history.length > this._game.input.recordLimit) + { + this._history.shift(); + } + } + + } + + } + /** * Called when the Pointer is moved on the touchscreen * @method move @@ -267,6 +354,11 @@ module Phaser { */ public move(event): Pointer { + if (event.button) + { + this.button = event.button; + } + this.clientX = event.clientX; this.clientY = event.clientY; this.pageX = event.pageX; @@ -280,10 +372,11 @@ module Phaser { this.pointB.setTo(this.x, this.y); this.circle.setTo(this.x, this.y, 44); - this._game.input.x = this.x * this._game.input.scaleX; - this._game.input.y = this.y * this._game.input.scaleY; - - // Droppings history (used for gestures and motion tracking) + if (this._game.input.multiInputOverride == Input.MOUSE_OVERRIDES_TOUCH || this._game.input.multiInputOverride == Input.MOUSE_TOUCH_COMBINE || (this._game.input.multiInputOverride == Input.TOUCH_OVERRIDES_MOUSE && this._game.input.currentPointers == 0)) + { + this._game.input.x = this.x * this._game.input.scaleX; + this._game.input.y = this.y * this._game.input.scaleY; + } return this; @@ -308,6 +401,29 @@ module Phaser { */ public stop(event): Pointer { + console.log('duration', this.duration); + + if (this._game.input.multiInputOverride == Input.MOUSE_OVERRIDES_TOUCH || this._game.input.multiInputOverride == Input.MOUSE_TOUCH_COMBINE || (this._game.input.multiInputOverride == Input.TOUCH_OVERRIDES_MOUSE && this._game.input.currentPointers == 0)) + { + this._game.input.onUp.dispatch(this); + + // Was it a tap? + if (this.duration >= 0 && this.duration <= this._game.input.tapRate) + { + // Yes, let's dispatch the signal + this._game.input.onTap.dispatch(this); + + // Was it a double-tap? + if (this.timeUp - this.previousTapTime < this._game.input.doubleTapRate) + { + this._game.input.onDoubleTap.dispatch(this); + } + + this.previousTapTime = this.timeUp; + } + + } + this.active = false; this.withinGame = false; @@ -315,19 +431,22 @@ module Phaser { this.isUp = true; this.timeUp = this._game.time.now; - this._game.input.onUp.dispatch(this); + if (this.isMouse == false) + { + this._game.input.currentPointers--; + } return this; } /** - * The Pointer is considered justPressed if the time it was pressed onto the touchscreen is less than justPressedRate + * The Pointer is considered justPressed if the time it was pressed onto the touchscreen or clicked is less than justPressedRate * @method justPressed * @param {Number} [duration]. * @return {Boolean} */ - public justPressed(duration?: number = this.justPressedRate): bool { + public justPressed(duration?: number = this._game.input.justPressedRate): bool { if (this.isDown === true && (this.timeDown + duration) > this._game.time.now) { @@ -346,7 +465,7 @@ module Phaser { * @param {Number} [duration]. * @return {Boolean} */ - public justReleased(duration?: number = this.justReleasedRate): bool { + public justReleased(duration?: number = this._game.input.justReleasedRate): bool { if (this.isUp === true && (this.timeUp + duration) > this._game.time.now) { @@ -359,6 +478,10 @@ module Phaser { } + /** + * Resets the Pointer properties. Called by Input.reset when you perform a State change. + * @method reset + */ public reset() { this.active = false; @@ -366,6 +489,8 @@ module Phaser { this.isDown = false; this.isUp = true; this.totalTouches = 0; + this._holdSent = false; + this._history.length = 0; } diff --git a/Phaser/system/input/Touch.ts b/Phaser/system/input/Touch.ts index 01c53887..71b74c98 100644 --- a/Phaser/system/input/Touch.ts +++ b/Phaser/system/input/Touch.ts @@ -27,9 +27,9 @@ module Phaser { } /** - * + * Local private reference to game. * @property _game - * @type {Game} + * @type {Phaser.Game} * @private **/ private _game: Game; @@ -41,19 +41,22 @@ module Phaser { public disabled: bool = false; /** - * + * Starts the event listeners running * @method start */ public start() { - this._game.stage.canvas.addEventListener('touchstart', (event) => this.onTouchStart(event), false); - this._game.stage.canvas.addEventListener('touchmove', (event) => this.onTouchMove(event), false); - this._game.stage.canvas.addEventListener('touchend', (event) => this.onTouchEnd(event), false); - this._game.stage.canvas.addEventListener('touchenter', (event) => this.onTouchEnter(event), false); - this._game.stage.canvas.addEventListener('touchleave', (event) => this.onTouchLeave(event), false); - this._game.stage.canvas.addEventListener('touchcancel', (event) => this.onTouchCancel(event), false); + if (this._game.device.touch) + { + this._game.stage.canvas.addEventListener('touchstart', (event) => this.onTouchStart(event), false); + this._game.stage.canvas.addEventListener('touchmove', (event) => this.onTouchMove(event), false); + this._game.stage.canvas.addEventListener('touchend', (event) => this.onTouchEnd(event), false); + this._game.stage.canvas.addEventListener('touchenter', (event) => this.onTouchEnter(event), false); + this._game.stage.canvas.addEventListener('touchleave', (event) => this.onTouchLeave(event), false); + this._game.stage.canvas.addEventListener('touchcancel', (event) => this.onTouchCancel(event), false); - document.addEventListener('touchmove', (event) => this.consumeTouchMove(event), false); + document.addEventListener('touchmove', (event) => this.consumeTouchMove(event), false); + } } @@ -192,17 +195,20 @@ module Phaser { } /** - * + * Stop the event listeners * @method stop */ public stop() { - //this._domElement.addEventListener('touchstart', (event) => this.onTouchStart(event), false); - //this._domElement.addEventListener('touchmove', (event) => this.onTouchMove(event), false); - //this._domElement.addEventListener('touchend', (event) => this.onTouchEnd(event), false); - //this._domElement.addEventListener('touchenter', (event) => this.onTouchEnter(event), false); - //this._domElement.addEventListener('touchleave', (event) => this.onTouchLeave(event), false); - //this._domElement.addEventListener('touchcancel', (event) => this.onTouchCancel(event), false); + if (this._game.device.touch) + { + //this._domElement.addEventListener('touchstart', (event) => this.onTouchStart(event), false); + //this._domElement.addEventListener('touchmove', (event) => this.onTouchMove(event), false); + //this._domElement.addEventListener('touchend', (event) => this.onTouchEnd(event), false); + //this._domElement.addEventListener('touchenter', (event) => this.onTouchEnter(event), false); + //this._domElement.addEventListener('touchleave', (event) => this.onTouchLeave(event), false); + //this._domElement.addEventListener('touchcancel', (event) => this.onTouchCancel(event), false); + } } diff --git a/README.md b/README.md index a3bee0b8..e37c1c83 100644 --- a/README.md +++ b/README.md @@ -22,44 +22,47 @@ Latest Update V0.9.6 -* Virtually every class now has documentation - if you spot a typo or something missing please shout (thanks pixelpicosean) -* Grunt file updated to produce the new Special FX JS file (thanks HackManiac) -* Fixed issue stopping Phaser working on iOS 5 (iPad 1) -* Created new mobile test folder, updated index.php to use mobile CSS and made some mobile specific tests -* Fixed a few speed issues on Android 2.x stock browser -* Moved Camera context save/restore back inside parameter checks (sped-up Samsung S3 stock browser) -* Fixed bug with StageScaleMode.checkOrientation not respecting the NO_SCALE value -* Added MSPointer support (thanks Diego Bezerra) -* Added Camera.clear to perform a clearRect instead of a fillRect if needed (default is false) -* Swapped Camera.opaque default from true to false re: performance -* Updated Stage.visibilityChange to avoid pause screen locking in certain situations -* Added StageScaleMode.enterLandscape and enterPortrait signals for easier device orientation change checks -* Added StageScaleMode.isPortrait -* Updated StageScaleMode to check both window.orientationchange and window.resize events -* Updated RequestAnimationFrame to use performance.now for sub-millisecond precision and to drive the Game.time.update loop -* Updated RequestAnimationFrame setTimeout to use fixed timestep and re-ordered callback sequence. Android 2/iOS5 performance much better now -* Removed Stage.ORIENTATION_LANDSCAPE statics because the values should be taken from Stage.scale.isPortrait / isLandscape -* Removed Stage.maxScaleX/Y and moved them into StageScaleMode.minWidth, minHeight, maxWidth and maxHeight -* Fixed Stage.scale so that it resizes without needing an orientation change first -* Added StageScaleMode.startFullscreen(), stopFullScreen() and isFullScreen for making use of the FullScreen API on desktop browsers -* Swapped Stage.offset from Point to MicroPoint -* Swapped Stage.bounds from Rectangle to Quad -* Added State.destroy support. A states destroy function is called when you switch to a new state (thanks JesseFreeman) -* Added Sprite.fillColor, used in the Sprite render if no image is loaded (set via the property or Sprite.makeGraphic) (thanks JesseFreeman) -* Renamed Phaser.Finger to Phaser.Pointer -* Updated all of the Input classes so they now use Input.pointers 1 through 10 -* Updated Touch and MSPointer to allow multi-touch support (when the hardware supports it) and created new tests to show this -* Added Input.getPointer, Input.getPointerFromIdentifier, Input.totalActivePointers and Input.totalInactivePointers -* Added Input.startPointer, Input.updatePointer and Input.stopPointer -* Phaser Input now confirmed working on Windows Phone 8 (Nokia Lumia 920) -* Added Input.maxPointers to allow you to limit the number of fingers your game will listen for on multi-touch systems -* Pointer.totalTouches value keeps a running total of the number of times the Pointer has been pressed -* Added Pointer.pointA and pointB - pointA is placed on touch, pointB is moved on update, useful for tracking distance/direction/gestures -* Added Game.state - now contains a reference to the current state object (if any was given) -* Moved the Input start events from the constructors to a single Input.start method +* Virtually every class now has documentation - if you spot a typo or something missing please shout (thanks pixelpicosean). +* Grunt file updated to produce the new Special FX JS file (thanks HackManiac). +* Fixed issue stopping Phaser working on iOS 5 (iPad 1). +* Created new mobile test folder, updated index.php to use mobile CSS and made some mobile specific tests. +* Fixed a few speed issues on Android 2.x stock browser. +* Moved Camera context save/restore back inside parameter checks (sped-up Samsung S3 stock browser). +* Fixed bug with StageScaleMode.checkOrientation not respecting the NO_SCALE value. +* Added MSPointer support (thanks Diego Bezerra). +* Added Camera.clear to perform a clearRect instead of a fillRect if needed (default is false). +* Swapped Camera.opaque default from true to false re: performance. +* Updated Stage.visibilityChange to avoid pause screen locking in certain situations. +* Added StageScaleMode.enterLandscape and enterPortrait signals for easier device orientation change checks. +* Added StageScaleMode.isPortrait. +* Updated StageScaleMode to check both window.orientationchange and window.resize events. +* Updated RequestAnimationFrame to use performance.now for sub-millisecond precision and to drive the Game.time.update loop. +* Updated RequestAnimationFrame setTimeout to use fixed timestep and re-ordered callback sequence. Android 2/iOS5 performance much better now. +* Removed Stage.ORIENTATION_LANDSCAPE statics because the values should be taken from Stage.scale.isPortrait / isLandscape. +* Removed Stage.maxScaleX/Y and moved them into StageScaleMode.minWidth, minHeight, maxWidth and maxHeight. +* Fixed Stage.scale so that it resizes without needing an orientation change first. +* Added StageScaleMode.startFullscreen(), stopFullScreen() and isFullScreen for making use of the FullScreen API on desktop browsers. +* Swapped Stage.offset from Point to MicroPoint. +* Swapped Stage.bounds from Rectangle to Quad. +* Added State.destroy support. A states destroy function is called when you switch to a new state (thanks JesseFreeman). +* Added Sprite.fillColor, used in the Sprite render if no image is loaded (set via the property or Sprite.makeGraphic) (thanks JesseFreeman). +* Renamed Phaser.Finger to Phaser.Pointer. +* Updated all of the Input classes so they now use Input.pointers 1 through 10. +* Updated Touch and MSPointer to allow multi-touch support (when the hardware supports it) and created new tests to show this. +* Added Input.getPointer, Input.getPointerFromIdentifier, Input.totalActivePointers and Input.totalInactivePointers. +* Added Input.startPointer, Input.updatePointer and Input.stopPointer. +* Phaser Input now confirmed working on Windows Phone 8 (Nokia Lumia 920). +* Added Input.maxPointers to allow you to limit the number of fingers your game will listen for on multi-touch systems. +* Pointer.totalTouches value keeps a running total of the number of times the Pointer has been pressed. +* Added Pointer.pointA and pointB - pointA is placed on touch, pointB is moved on update, useful for tracking distance/direction/gestures. +* Added Game.state - now contains a reference to the current state object (if any was given). +* Moved the Input start events from the constructors to a single Input.start method. * Added Input.disabled boolean to globally turn off all input event processing. -* Added Input.Mouse.disabled, Input.Touch.disabled, Input.MSPointer.disabled and Input.Keyboard.disabled +* Added Input.Mouse.disabled, Input.Touch.disabled, Input.MSPointer.disabled and Input.Keyboard.disabled. * Added Device.mspointer boolean. true if MSPointer is available on the device. +* Added Input.onDown, onUp, onTap, onDoubleTap and onHold signals - all fired by the mouse or touch. +* Added Input.recordPointerHistory to record the x/y coordinates a Pointer tracks through. Also Input.recordRate and Input.recordLimit for fine control. +* Added Input.multiInputOverride which can be MOUSE_OVERRIDES_TOUCH, TOUCH_OVERRIDES_MOUSE or MOUSE_TOUCH_COMBINE. * TODO: Check that tween pausing works with the new performance.now diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 457b8a35..a905a611 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -120,6 +120,10 @@ multitouch.ts + + + single tap.ts + single touch.ts diff --git a/Tests/input/single tap.js b/Tests/input/single tap.js new file mode 100644 index 00000000..08f3911a --- /dev/null +++ b/Tests/input/single tap.js @@ -0,0 +1,42 @@ +/// +(function () { + var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + function init() { + myGame.loader.addImageFile('ball0', 'assets/sprites/yellow_ball.png'); + myGame.loader.addImageFile('ball1', 'assets/sprites/aqua_ball.png'); + myGame.loader.addImageFile('ball2', 'assets/sprites/blue_ball.png'); + myGame.loader.addImageFile('ball3', 'assets/sprites/green_ball.png'); + myGame.loader.addImageFile('ball4', 'assets/sprites/red_ball.png'); + myGame.loader.addImageFile('ball5', 'assets/sprites/purple_ball.png'); + myGame.loader.load(); + } + var balls; + function create() { + balls = myGame.createGroup(); + myGame.input.onTap.add(tapped, this); + myGame.input.onDoubleTap.add(doubleTapped, this); + } + function doubleTapped(pointer) { + var tempBall = new Phaser.Sprite(myGame, pointer.x, pointer.y, 'ball' + Math.round(Math.random() * 5)); + tempBall.outOfBoundsAction = Phaser.GameObject.OUT_OF_BOUNDS_KILL; + tempBall.velocity.y = 100 + Math.random() * 150; + tempBall.elasticity = 0.9; + tempBall.scale.setTo(4, 4); + balls.add(tempBall); + } + function tapped(pointer) { + var tempBall = new Phaser.Sprite(myGame, pointer.x, pointer.y, 'ball' + Math.round(Math.random() * 5)); + tempBall.outOfBoundsAction = Phaser.GameObject.OUT_OF_BOUNDS_KILL; + tempBall.velocity.y = 100 + Math.random() * 150; + tempBall.elasticity = 0.9; + balls.add(tempBall); + } + function update() { + } + function render() { + myGame.input.renderDebugInfo(16, 16); + //myGame.input.pointer1.renderDebug(true); + //myGame.input.pointer2.renderDebug(true); + //myGame.input.pointer3.renderDebug(true); + } +})(); diff --git a/Tests/input/single tap.ts b/Tests/input/single tap.ts new file mode 100644 index 00000000..17e91e36 --- /dev/null +++ b/Tests/input/single tap.ts @@ -0,0 +1,65 @@ +/// + +(function () { + + var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + function init() { + + myGame.loader.addImageFile('ball0', 'assets/sprites/yellow_ball.png'); + myGame.loader.addImageFile('ball1', 'assets/sprites/aqua_ball.png'); + myGame.loader.addImageFile('ball2', 'assets/sprites/blue_ball.png'); + myGame.loader.addImageFile('ball3', 'assets/sprites/green_ball.png'); + myGame.loader.addImageFile('ball4', 'assets/sprites/red_ball.png'); + myGame.loader.addImageFile('ball5', 'assets/sprites/purple_ball.png'); + + myGame.loader.load(); + + } + + var balls: Phaser.Group; + + function create() { + + balls = myGame.createGroup(); + + myGame.input.onTap.add(tapped, this); + myGame.input.onDoubleTap.add(doubleTapped, this); + + } + + function doubleTapped(pointer: Phaser.Pointer) { + + var tempBall: Phaser.Sprite = new Phaser.Sprite(myGame, pointer.x, pointer.y, 'ball' + Math.round(Math.random() * 5)); + tempBall.outOfBoundsAction = Phaser.GameObject.OUT_OF_BOUNDS_KILL; + tempBall.velocity.y = 100 + Math.random() * 150; + tempBall.elasticity = 0.9; + tempBall.scale.setTo(4, 4); + balls.add(tempBall); + + } + + function tapped(pointer: Phaser.Pointer) { + + var tempBall: Phaser.Sprite = new Phaser.Sprite(myGame, pointer.x, pointer.y, 'ball' + Math.round(Math.random() * 5)); + tempBall.outOfBoundsAction = Phaser.GameObject.OUT_OF_BOUNDS_KILL; + tempBall.velocity.y = 100 + Math.random() * 150; + tempBall.elasticity = 0.9; + balls.add(tempBall); + + } + + function update() { + } + + function render() { + + myGame.input.renderDebugInfo(16, 16); + + //myGame.input.pointer1.renderDebug(true); + //myGame.input.pointer2.renderDebug(true); + //myGame.input.pointer3.renderDebug(true); + + } + +})(); diff --git a/Tests/phaser.js b/Tests/phaser.js index c683481c..abdc4db2 100644 --- a/Tests/phaser.js +++ b/Tests/phaser.js @@ -6769,7 +6769,6 @@ var Phaser; * Phaser - Group * * This class is used for organising, updating and sorting game objects. -* */ var Phaser; (function (Phaser) { @@ -6867,7 +6866,7 @@ var Phaser; configurable: true }); Group.prototype.add = /** - * Adds a new Basic subclass (Basic, Basic, Enemy, etc) to the group. + * Adds a new Basic subclass (Basic, GameObject, Sprite, etc) to the group. * Group will try to replace a null member of the array first. * Failing that, Group will add it to the end of the member array, * assuming there is room for it, and doubling the size of the array if necessary. @@ -6876,7 +6875,6 @@ var Phaser; * the object will NOT be added to the group!

* * @param {Basic} Object The object you want to add to the group. - * * @return {Basic} The same Basic object that was passed in. */ function (Object) { @@ -10728,6 +10726,27 @@ var Phaser; * @return {Phaser.Pointer} This object. */ function Pointer(game, id) { + /** + * Local private variable to store the status of dispatching a hold event + * @property _holdSent + * @type {Boolean} + * @private + */ + this._holdSent = false; + /** + * Local private variable storing the short-term history of pointer movements + * @property _history + * @type {Array} + * @private + */ + this._history = []; + /** + * Local private variable storing the time at which the next history drop should occur + * @property _lastDrop + * @type {Number} + * @private + */ + this._nextDrop = 0; /** * A Point object representing the x/y screen coordinates of the Pointer. * @property pointA @@ -10802,13 +10821,19 @@ var Phaser; */ this.y = -1; /** - * If the Pointer is touching the touchscreen isDown is set to true + * If the Pointer is a mouse this is true, otherwise false + * @property isMouse + * @type {Boolean} + **/ + this.isMouse = false; + /** + * If the Pointer is touching the touchscreen, or the mouse button is held down, isDown is set to true * @property isDown * @type {Boolean} **/ this.isDown = false; /** - * If the Pointer is not touching the touchscreen isUp is set to true + * If the Pointer is not touching the touchscreen, or the mouse button is up, isUp is set to true * @property isUp * @type {Boolean} **/ @@ -10826,17 +10851,11 @@ var Phaser; **/ this.timeUp = 0; /** - * The number of milliseconds below which the Pointer is considered justPressed - * @property justPressedRate + * A timestamp representing when the Pointer was last tapped or clicked + * @property previousTapTime * @type {Number} **/ - this.justPressedRate = 200; - /** - * The number of milliseconds below which the Pointer is considered justReleased - * @property justReleasedRate - * @type {Number} - **/ - this.justReleasedRate = 200; + this.previousTapTime = 0; /** * The total number of times this Pointer has been touched to the touchscreen * @property totalTouches @@ -10849,14 +10868,20 @@ var Phaser; this.pointA = new Phaser.Point(); this.pointB = new Phaser.Point(); this.circle = new Phaser.Circle(0, 0, 44); + if(id == 0) { + this.isMouse = true; + } } Object.defineProperty(Pointer.prototype, "duration", { get: /** - * How long the Pointer has been depressed on the touchscreen. + * How long the Pointer has been depressed on the touchscreen. If not currently down it returns -1. * @property duration * @type {Number} **/ function () { + if(this.isUp) { + return -1; + } return this._game.time.now - this.timeDown; }, enumerable: true, @@ -10886,6 +10911,10 @@ var Phaser; function (event) { this.identifier = event.identifier; this.target = event.target; + if(event.button) { + this.button = event.button; + } + this._history.length = 0; this.move(event); this.pointA.setTo(this.x, this.y); this.active = true; @@ -10893,18 +10922,48 @@ var Phaser; this.isDown = true; this.isUp = false; this.timeDown = this._game.time.now; - this._game.input.x = this.x * this._game.input.scaleX; - this._game.input.y = this.y * this._game.input.scaleY; - this._game.input.onDown.dispatch(this); + this._holdSent = false; + if(this._game.input.multiInputOverride == Phaser.Input.MOUSE_OVERRIDES_TOUCH || this._game.input.multiInputOverride == Phaser.Input.MOUSE_TOUCH_COMBINE || (this._game.input.multiInputOverride == Phaser.Input.TOUCH_OVERRIDES_MOUSE && this._game.input.currentPointers == 0)) { + this._game.input.x = this.x * this._game.input.scaleX; + this._game.input.y = this.y * this._game.input.scaleY; + this._game.input.onDown.dispatch(this); + } this.totalTouches++; + if(this.isMouse == false) { + this._game.input.currentPointers++; + } return this; }; + Pointer.prototype.update = function () { + if(this.active) { + if(this._holdSent == false && this.duration >= this._game.input.holdRate) { + if(this._game.input.multiInputOverride == Phaser.Input.MOUSE_OVERRIDES_TOUCH || this._game.input.multiInputOverride == Phaser.Input.MOUSE_TOUCH_COMBINE || (this._game.input.multiInputOverride == Phaser.Input.TOUCH_OVERRIDES_MOUSE && this._game.input.currentPointers == 0)) { + this._game.input.onHold.dispatch(this); + } + this._holdSent = true; + } + // Update the droppings history + if(this._game.input.recordPointerHistory && this._game.time.now >= this._nextDrop) { + this._nextDrop = this._game.time.now + this._game.input.recordRate; + this._history.push({ + x: this.pointB.x, + y: this.pointB.y + }); + if(this._history.length > this._game.input.recordLimit) { + this._history.shift(); + } + } + } + }; Pointer.prototype.move = /** * Called when the Pointer is moved on the touchscreen * @method move * @param {Any} event */ function (event) { + if(event.button) { + this.button = event.button; + } this.clientX = event.clientX; this.clientY = event.clientY; this.pageX = event.pageX; @@ -10915,9 +10974,10 @@ var Phaser; this.y = this.pageY - this._game.stage.offset.y; this.pointB.setTo(this.x, this.y); this.circle.setTo(this.x, this.y, 44); - this._game.input.x = this.x * this._game.input.scaleX; - this._game.input.y = this.y * this._game.input.scaleY; - // Droppings history (used for gestures and motion tracking) + if(this._game.input.multiInputOverride == Phaser.Input.MOUSE_OVERRIDES_TOUCH || this._game.input.multiInputOverride == Phaser.Input.MOUSE_TOUCH_COMBINE || (this._game.input.multiInputOverride == Phaser.Input.TOUCH_OVERRIDES_MOUSE && this._game.input.currentPointers == 0)) { + this._game.input.x = this.x * this._game.input.scaleX; + this._game.input.y = this.y * this._game.input.scaleY; + } return this; }; Pointer.prototype.leave = /** @@ -10935,22 +10995,38 @@ var Phaser; * @param {Any} event */ function (event) { + console.log('duration', this.duration); + if(this._game.input.multiInputOverride == Phaser.Input.MOUSE_OVERRIDES_TOUCH || this._game.input.multiInputOverride == Phaser.Input.MOUSE_TOUCH_COMBINE || (this._game.input.multiInputOverride == Phaser.Input.TOUCH_OVERRIDES_MOUSE && this._game.input.currentPointers == 0)) { + this._game.input.onUp.dispatch(this); + // Was it a tap? + if(this.duration >= 0 && this.duration <= this._game.input.tapRate) { + // Yes, let's dispatch the signal + this._game.input.onTap.dispatch(this); + // Was it a double-tap? + if(this.timeUp - this.previousTapTime < this._game.input.doubleTapRate) { + this._game.input.onDoubleTap.dispatch(this); + } + this.previousTapTime = this.timeUp; + } + } this.active = false; this.withinGame = false; this.isDown = false; this.isUp = true; this.timeUp = this._game.time.now; - this._game.input.onUp.dispatch(this); + if(this.isMouse == false) { + this._game.input.currentPointers--; + } return this; }; Pointer.prototype.justPressed = /** - * The Pointer is considered justPressed if the time it was pressed onto the touchscreen is less than justPressedRate + * The Pointer is considered justPressed if the time it was pressed onto the touchscreen or clicked is less than justPressedRate * @method justPressed * @param {Number} [duration]. * @return {Boolean} */ function (duration) { - if (typeof duration === "undefined") { duration = this.justPressedRate; } + if (typeof duration === "undefined") { duration = this._game.input.justPressedRate; } if(this.isDown === true && (this.timeDown + duration) > this._game.time.now) { return true; } else { @@ -10964,19 +11040,25 @@ var Phaser; * @return {Boolean} */ function (duration) { - if (typeof duration === "undefined") { duration = this.justReleasedRate; } + if (typeof duration === "undefined") { duration = this._game.input.justReleasedRate; } if(this.isUp === true && (this.timeUp + duration) > this._game.time.now) { return true; } else { return false; } }; - Pointer.prototype.reset = function () { + Pointer.prototype.reset = /** + * Resets the Pointer properties. Called by Input.reset when you perform a State change. + * @method reset + */ + function () { this.active = false; this.identifier = null; this.isDown = false; this.isUp = true; this.totalTouches = 0; + this._holdSent = false; + this._history.length = 0; }; Pointer.prototype.renderDebug = /** * Renders the Pointer.circle object onto the stage in green if down or red if up. @@ -11050,7 +11132,7 @@ var Phaser; this._game = game; } MSPointer.prototype.start = /** - * + * Starts the event listeners running * @method start */ function () { @@ -11107,10 +11189,15 @@ var Phaser; this._game.input.stopPointer(event); }; MSPointer.prototype.stop = /** - * + * Stop the event listeners * @method stop */ function () { + if(this._game.device.mspointer == true) { + //this._game.stage.canvas.addEventListener('MSPointerDown', (event) => this.onPointerDown(event), false); + //this._game.stage.canvas.addEventListener('MSPointerMove', (event) => this.onPointerMove(event), false); + //this._game.stage.canvas.addEventListener('MSPointerUp', (event) => this.onPointerUp(event), false); + } }; return MSPointer; })(); @@ -11174,6 +11261,10 @@ var Phaser; */ this.disabled = false; /** + * Controls the expected behaviour when using a mouse and touch together on a multi-input device + */ + this.multiInputOverride = Input.MOUSE_TOUCH_COMBINE; + /** * X coordinate of the most recent Pointer event * @type {Number} * @private @@ -11196,22 +11287,69 @@ var Phaser; */ this.scaleY = 1; /** - * - * @type {Number} - */ - this.worldX = 0; - /** - * - * @type {Number} - */ - this.worldY = 0; - /** * The maximum number of Pointers allowed to be active at any one time. * For lots of games it's useful to set this to 1 * @type {Number} */ this.maxPointers = 10; + /** + * The current number of active Pointers. + * @type {Number} + */ + this.currentPointers = 0; + /** + * The number of milliseconds that the Pointer has to be pressed down and then released to be considered a tap or click + * @property tapRate + * @type {Number} + **/ + this.tapRate = 200; + /** + * The number of milliseconds between taps of the same Pointer for it to be considered a double tap / click + * @property doubleTapRate + * @type {Number} + **/ + this.doubleTapRate = 250; + /** + * The number of milliseconds that the Pointer has to be pressed down for it to fire a onHold event + * @property holdRate + * @type {Number} + **/ + this.holdRate = 2000; + /** + * The number of milliseconds below which the Pointer is considered justPressed + * @property justPressedRate + * @type {Number} + **/ + this.justPressedRate = 200; + /** + * The number of milliseconds below which the Pointer is considered justReleased + * @property justReleasedRate + * @type {Number} + **/ + this.justReleasedRate = 200; + /** + * Sets if the Pointer objects should record a history of x/y coordinates they have passed through. + * The history is cleared each time the Pointer is pressed down. + * The history is updated at the rate specified in Input.pollRate + * @property recordPointerHistory + * @type {Boolean} + **/ + this.recordPointerHistory = true; + /** + * The rate in milliseconds at which the Pointer objects should update their tracking history + * @property recordRate + * @type {Number} + */ + this.recordRate = 100; + /** + * The total number of entries that can be recorded into the Pointer objects tracking history. + * The the Pointer is tracking one event every 100ms, then a trackLimit of 100 would store the last 10 seconds worth of history. + * @property recordLimit + * @type {Number} + */ + this.recordLimit = 100; this._game = game; + this.mousePointer = new Phaser.Pointer(this._game, 0); this.pointer1 = new Phaser.Pointer(this._game, 1); this.pointer2 = new Phaser.Pointer(this._game, 2); this.pointer3 = new Phaser.Pointer(this._game, 3); @@ -11229,7 +11367,14 @@ var Phaser; this.gestures = new Phaser.Gestures(this._game); this.onDown = new Phaser.Signal(); this.onUp = new Phaser.Signal(); + this.onTap = new Phaser.Signal(); + this.onDoubleTap = new Phaser.Signal(); + this.onHold = new Phaser.Signal(); + this.currentPointers = 0; } + Input.MOUSE_OVERRIDES_TOUCH = 0; + Input.TOUCH_OVERRIDES_MOUSE = 1; + Input.MOUSE_TOUCH_COMBINE = 2; Object.defineProperty(Input.prototype, "x", { get: /** * The screen X coordinate @@ -11268,12 +11413,19 @@ var Phaser; this.gestures.start(); }; Input.prototype.update = function () { - //this.worldX = this._game.camera.worldView.x + this.x; - //this.worldY = this._game.camera.worldView.y + this.y; - this.mouse.update(); + this.mousePointer.update(); + this.pointer1.update(); + this.pointer2.update(); + this.pointer3.update(); + this.pointer4.update(); + this.pointer5.update(); + this.pointer6.update(); + this.pointer7.update(); + this.pointer8.update(); + this.pointer9.update(); + this.pointer10.update(); }; Input.prototype.reset = function () { - this.mouse.reset(); this.keyboard.reset(); this.pointer1.reset(); this.pointer2.reset(); @@ -11287,6 +11439,10 @@ var Phaser; this.pointer10.reset(); this.onDown = new Phaser.Signal(); this.onUp = new Phaser.Signal(); + this.onTap = new Phaser.Signal(); + this.onDoubleTap = new Phaser.Signal(); + this.onHold = new Phaser.Signal(); + this.currentPointers = 0; }; Object.defineProperty(Input.prototype, "totalInactivePointers", { get: /** @@ -11295,41 +11451,41 @@ var Phaser; * @return {Number} The number of Pointers currently inactive **/ function () { - return 10 - this.totalActivePointers; + return 10 - this.currentPointers; }, enumerable: true, configurable: true }); Object.defineProperty(Input.prototype, "totalActivePointers", { get: /** - * Get the total number of active Pointers + * Recalculates the total number of active Pointers * @method totalActivePointers * @return {Number} The number of Pointers currently active **/ function () { - var result = 0; + this.currentPointers = 0; if(this.pointer1.active == true) { - result++; + this.currentPointers++; } else if(this.pointer2.active == true) { - result++; + this.currentPointers++; } else if(this.pointer3.active == true) { - result++; + this.currentPointers++; } else if(this.pointer4.active == true) { - result++; + this.currentPointers++; } else if(this.pointer5.active == true) { - result++; + this.currentPointers++; } else if(this.pointer6.active == true) { - result++; + this.currentPointers++; } else if(this.pointer7.active == true) { - result++; + this.currentPointers++; } else if(this.pointer8.active == true) { - result++; + this.currentPointers++; } else if(this.pointer9.active == true) { - result++; + this.currentPointers++; } else if(this.pointer10.active == true) { - result++; + this.currentPointers++; } - return result; + return this.currentPointers; }, enumerable: true, configurable: true @@ -11518,7 +11674,7 @@ var Phaser; this._game.stage.context.fillStyle = color; this._game.stage.context.fillText('Input', x, y); this._game.stage.context.fillText('Screen X: ' + this.x + ' Screen Y: ' + this.y, x, y + 14); - this._game.stage.context.fillText('World X: ' + this.worldX + ' World Y: ' + this.worldY, x, y + 28); + this._game.stage.context.fillText('World X: ' + this.getWorldX() + ' World Y: ' + this.getWorldY(), x, y + 28); this._game.stage.context.fillText('Scale X: ' + this.scaleX.toFixed(1) + ' Scale Y: ' + this.scaleY.toFixed(1), x, y + 42); }; return Input; @@ -11799,39 +11955,21 @@ var Phaser; (function (Phaser) { var Mouse = (function () { function Mouse(game) { - this._x = 0; - this._y = 0; /** * You can disable all Input by setting disabled = true. While set all new input related events will be ignored. * @type {Boolean} */ this.disabled = false; - /** - * @type {Boolean} - */ - this.isDown = false; - /** - * @type {Boolean} - */ - this.isUp = true; - /** - * @type {Number} - */ - this.timeDown = 0; - /** - * @type {Number} - */ - this.duration = 0; - /** - * @type {Number} - */ - this.timeUp = 0; this._game = game; } Mouse.LEFT_BUTTON = 0; Mouse.MIDDLE_BUTTON = 1; Mouse.RIGHT_BUTTON = 2; - Mouse.prototype.start = function () { + Mouse.prototype.start = /** + * Starts the event listeners running + * @method start + */ + function () { var _this = this; this._game.stage.canvas.addEventListener('mousedown', function (event) { return _this.onMouseDown(event); @@ -11843,10 +11981,6 @@ var Phaser; return _this.onMouseUp(event); }, true); }; - Mouse.prototype.reset = function () { - this.isDown = false; - this.isUp = true; - }; Mouse.prototype.onMouseDown = /** * @param {MouseEvent} event */ @@ -11854,22 +11988,8 @@ var Phaser; if(this._game.input.disabled || this.disabled) { return; } - this.button = event.button; - this._x = event.clientX - this._game.stage.x; - this._y = event.clientY - this._game.stage.y; - this._game.input.x = this._x * this._game.input.scaleX; - this._game.input.y = this._y * this._game.input.scaleY; - this.isDown = true; - this.isUp = false; - this.timeDown = this._game.time.now; - this._game.input.onDown.dispatch(this._game.input.x, this._game.input.y, this.timeDown); - }; - Mouse.prototype.update = function () { - //this._game.input.x = this._x * this._game.input.scaleX; - //this._game.input.y = this._y * this._game.input.scaleY; - if(this.isDown) { - this.duration = this._game.time.now - this.timeDown; - } + event['identifier'] = 0; + this._game.input.mousePointer.start(event); }; Mouse.prototype.onMouseMove = /** * @param {MouseEvent} event @@ -11878,11 +11998,8 @@ var Phaser; if(this._game.input.disabled || this.disabled) { return; } - this.button = event.button; - this._x = event.clientX - this._game.stage.x; - this._y = event.clientY - this._game.stage.y; - this._game.input.x = this._x * this._game.input.scaleX; - this._game.input.y = this._y * this._game.input.scaleY; + event['identifier'] = 0; + this._game.input.mousePointer.move(event); }; Mouse.prototype.onMouseUp = /** * @param {MouseEvent} event @@ -11891,17 +12008,18 @@ var Phaser; if(this._game.input.disabled || this.disabled) { return; } - this.button = event.button; - this.isDown = false; - this.isUp = true; - this.timeUp = this._game.time.now; - this.duration = this.timeUp - this.timeDown; - this._x = event.clientX - this._game.stage.x; - this._y = event.clientY - this._game.stage.y; - this._game.input.x = this._x * this._game.input.scaleX; - this._game.input.y = this._y * this._game.input.scaleY; - this._game.input.onUp.dispatch(this._game.input.x, this._game.input.y, this.timeDown); + event['identifier'] = 0; + this._game.input.mousePointer.stop(event); }; + Mouse.prototype.stop = /** + * Stop the event listeners + * @method stop + */ + function () { + //this._game.stage.canvas.addEventListener('mousedown', (event: MouseEvent) => this.onMouseDown(event), true); + //this._game.stage.canvas.addEventListener('mousemove', (event: MouseEvent) => this.onMouseMove(event), true); + //this._game.stage.canvas.addEventListener('mouseup', (event: MouseEvent) => this.onMouseUp(event), true); + }; return Mouse; })(); Phaser.Mouse = Mouse; @@ -11934,32 +12052,34 @@ var Phaser; this._game = game; } Touch.prototype.start = /** - * + * Starts the event listeners running * @method start */ function () { var _this = this; - this._game.stage.canvas.addEventListener('touchstart', function (event) { - return _this.onTouchStart(event); - }, false); - this._game.stage.canvas.addEventListener('touchmove', function (event) { - return _this.onTouchMove(event); - }, false); - this._game.stage.canvas.addEventListener('touchend', function (event) { - return _this.onTouchEnd(event); - }, false); - this._game.stage.canvas.addEventListener('touchenter', function (event) { - return _this.onTouchEnter(event); - }, false); - this._game.stage.canvas.addEventListener('touchleave', function (event) { - return _this.onTouchLeave(event); - }, false); - this._game.stage.canvas.addEventListener('touchcancel', function (event) { - return _this.onTouchCancel(event); - }, false); - document.addEventListener('touchmove', function (event) { - return _this.consumeTouchMove(event); - }, false); + if(this._game.device.touch) { + this._game.stage.canvas.addEventListener('touchstart', function (event) { + return _this.onTouchStart(event); + }, false); + this._game.stage.canvas.addEventListener('touchmove', function (event) { + return _this.onTouchMove(event); + }, false); + this._game.stage.canvas.addEventListener('touchend', function (event) { + return _this.onTouchEnd(event); + }, false); + this._game.stage.canvas.addEventListener('touchenter', function (event) { + return _this.onTouchEnter(event); + }, false); + this._game.stage.canvas.addEventListener('touchleave', function (event) { + return _this.onTouchLeave(event); + }, false); + this._game.stage.canvas.addEventListener('touchcancel', function (event) { + return _this.onTouchCancel(event); + }, false); + document.addEventListener('touchmove', function (event) { + return _this.consumeTouchMove(event); + }, false); + } }; Touch.prototype.consumeTouchMove = /** * Prevent iOS bounce-back (doesn't work?) @@ -12056,17 +12176,19 @@ var Phaser; } }; Touch.prototype.stop = /** - * + * Stop the event listeners * @method stop */ function () { - //this._domElement.addEventListener('touchstart', (event) => this.onTouchStart(event), false); - //this._domElement.addEventListener('touchmove', (event) => this.onTouchMove(event), false); - //this._domElement.addEventListener('touchend', (event) => this.onTouchEnd(event), false); - //this._domElement.addEventListener('touchenter', (event) => this.onTouchEnter(event), false); - //this._domElement.addEventListener('touchleave', (event) => this.onTouchLeave(event), false); - //this._domElement.addEventListener('touchcancel', (event) => this.onTouchCancel(event), false); - }; + if(this._game.device.touch) { + //this._domElement.addEventListener('touchstart', (event) => this.onTouchStart(event), false); + //this._domElement.addEventListener('touchmove', (event) => this.onTouchMove(event), false); + //this._domElement.addEventListener('touchend', (event) => this.onTouchEnd(event), false); + //this._domElement.addEventListener('touchenter', (event) => this.onTouchEnter(event), false); + //this._domElement.addEventListener('touchleave', (event) => this.onTouchLeave(event), false); + //this._domElement.addEventListener('touchcancel', (event) => this.onTouchCancel(event), false); + } + }; return Touch; })(); Phaser.Touch = Touch; @@ -13666,7 +13788,7 @@ var Phaser; }; Tilemap.prototype.getTileFromInputXY = function (layer) { if (typeof layer === "undefined") { layer = 0; } - return this.tiles[this.layers[layer].getTileFromWorldXY(this._game.input.worldX, this._game.input.worldY)]; + return this.tiles[this.layers[layer].getTileFromWorldXY(this._game.input.getWorldX(), this._game.input.getWorldY())]; }; Tilemap.prototype.getTileOverlaps = /** * Get tiles overlaps the given object. diff --git a/Tests/tilemap/map draw.js b/Tests/tilemap/map draw.js index e788a8cc..d99c6ad3 100644 --- a/Tests/tilemap/map draw.js +++ b/Tests/tilemap/map draw.js @@ -32,7 +32,7 @@ map.collide(); marker.x = myGame.math.snapToFloor(myGame.input.worldX, 16); marker.y = myGame.math.snapToFloor(myGame.input.worldY, 16); - if(myGame.input.mouse.isDown) { + if(myGame.input.mousePointer.isDown) { map.putTile(marker.x, marker.y, 32); } } diff --git a/Tests/tilemap/map draw.ts b/Tests/tilemap/map draw.ts index d0b87eb0..d6e82978 100644 --- a/Tests/tilemap/map draw.ts +++ b/Tests/tilemap/map draw.ts @@ -48,7 +48,7 @@ marker.x = myGame.math.snapToFloor(myGame.input.worldX, 16); marker.y = myGame.math.snapToFloor(myGame.input.worldY, 16); - if (myGame.input.mouse.isDown) + if (myGame.input.mousePointer.isDown) { map.putTile(marker.x, marker.y, 32); } diff --git a/build/phaser.d.ts b/build/phaser.d.ts index bb814c6f..54cddf8a 100644 --- a/build/phaser.d.ts +++ b/build/phaser.d.ts @@ -1681,7 +1681,7 @@ module Phaser { */ private _game; /** - * Local container for storing camera. + * Local container for storing cameras. */ private _cameras; /** @@ -4064,7 +4064,6 @@ module Phaser { * Phaser - Group * * This class is used for organising, updating and sorting game objects. -* */ module Phaser { class Group extends Basic { @@ -4125,7 +4124,7 @@ module Phaser { */ public maxSize : number; /** - * Adds a new Basic subclass (Basic, Basic, Enemy, etc) to the group. + * Adds a new Basic subclass (Basic, GameObject, Sprite, etc) to the group. * Group will try to replace a null member of the array first. * Failing that, Group will add it to the end of the member array, * assuming there is room for it, and doubling the size of the array if necessary. @@ -4134,7 +4133,6 @@ module Phaser { * the object will NOT be added to the group!

* * @param {Basic} Object The object you want to add to the group. - * * @return {Basic} The same Basic object that was passed in. */ public add(Object: Basic): Basic; @@ -6165,7 +6163,28 @@ module Phaser { **/ private _game; /** - * The Pointer ID (a number between 1 and 10) + * Local private variable to store the status of dispatching a hold event + * @property _holdSent + * @type {Boolean} + * @private + */ + private _holdSent; + /** + * Local private variable storing the short-term history of pointer movements + * @property _history + * @type {Array} + * @private + */ + private _history; + /** + * Local private variable storing the time at which the next history drop should occur + * @property _lastDrop + * @type {Number} + * @private + */ + private _nextDrop; + /** + * The Pointer ID (a number between 1 and 10, 0 is reserved for the mouse pointer specifically) * @property id * @type {Number} */ @@ -6210,6 +6229,12 @@ module Phaser { */ public withinGame: bool; /** + * If this Pointer is a mouse the button property holds the value of which mouse button was pressed down + * @property button + * @type {Number} + */ + public button: number; + /** * The horizontal coordinate of point relative to the viewport in pixels, excluding any scroll offset * @property clientX * @type {Number} @@ -6264,13 +6289,19 @@ module Phaser { */ public target; /** - * If the Pointer is touching the touchscreen isDown is set to true + * If the Pointer is a mouse this is true, otherwise false + * @property isMouse + * @type {Boolean} + **/ + public isMouse: bool; + /** + * If the Pointer is touching the touchscreen, or the mouse button is held down, isDown is set to true * @property isDown * @type {Boolean} **/ public isDown: bool; /** - * If the Pointer is not touching the touchscreen isUp is set to true + * If the Pointer is not touching the touchscreen, or the mouse button is up, isUp is set to true * @property isUp * @type {Boolean} **/ @@ -6288,17 +6319,11 @@ module Phaser { **/ public timeUp: number; /** - * The number of milliseconds below which the Pointer is considered justPressed - * @property justPressedRate + * A timestamp representing when the Pointer was last tapped or clicked + * @property previousTapTime * @type {Number} **/ - public justPressedRate: number; - /** - * The number of milliseconds below which the Pointer is considered justReleased - * @property justReleasedRate - * @type {Number} - **/ - public justReleasedRate: number; + public previousTapTime: number; /** * The total number of times this Pointer has been touched to the touchscreen * @property totalTouches @@ -6306,7 +6331,7 @@ module Phaser { **/ public totalTouches: number; /** - * How long the Pointer has been depressed on the touchscreen. + * How long the Pointer has been depressed on the touchscreen. If not currently down it returns -1. * @property duration * @type {Number} **/ @@ -6327,6 +6352,7 @@ module Phaser { * @param {Any} event */ public start(event): Pointer; + public update(): void; /** * Called when the Pointer is moved on the touchscreen * @method move @@ -6346,7 +6372,7 @@ module Phaser { */ public stop(event): Pointer; /** - * The Pointer is considered justPressed if the time it was pressed onto the touchscreen is less than justPressedRate + * The Pointer is considered justPressed if the time it was pressed onto the touchscreen or clicked is less than justPressedRate * @method justPressed * @param {Number} [duration]. * @return {Boolean} @@ -6359,6 +6385,10 @@ module Phaser { * @return {Boolean} */ public justReleased(duration?: number): bool; + /** + * Resets the Pointer properties. Called by Input.reset when you perform a State change. + * @method reset + */ public reset(): void; /** * Renders the Pointer.circle object onto the stage in green if down or red if up. @@ -6389,7 +6419,7 @@ module Phaser { */ constructor(game: Game); /** - * + * Local private reference to game. * @property _game * @type Game * @private @@ -6401,7 +6431,7 @@ module Phaser { */ public disabled: bool; /** - * + * Starts the event listeners running * @method start */ public start(): void; @@ -6424,7 +6454,7 @@ module Phaser { **/ private onPointerUp(event); /** - * + * Stop the event listeners * @method stop */ public stop(): void; @@ -6484,6 +6514,25 @@ module Phaser { */ public disabled: bool; /** + * Controls the expected behaviour when using a mouse and touch together on a multi-input device + */ + public multiInputOverride: number; + /** + * Static defining the behaviour expected on a multi-input device system. + * With this setting when the mouse is used it updates the Input.x/y globals regardless if another pointer is active or not + */ + static MOUSE_OVERRIDES_TOUCH: number; + /** + * Static defining the behaviour expected on a multi-input device system. + * With this setting when the mouse is used it only updates the Input.x/y globals if no other pointer is active + */ + static TOUCH_OVERRIDES_MOUSE: number; + /** + * Static defining the behaviour expected on a multi-input device system. + * With this setting when the mouse is used it updates the Input.x/y globals at the same time as any active Pointer objects might + */ + static MOUSE_TOUCH_COMBINE: number; + /** * Phaser.Mouse handler * @type {Mouse} */ @@ -6531,22 +6580,17 @@ module Phaser { */ public scaleY: number; /** - * - * @type {Number} - */ - public worldX: number; - /** - * - * @type {Number} - */ - public worldY: number; - /** * The maximum number of Pointers allowed to be active at any one time. * For lots of games it's useful to set this to 1 * @type {Number} */ public maxPointers: number; /** + * The current number of active Pointers. + * @type {Number} + */ + public currentPointers: number; + /** * A Signal dispatched when a mouse/Pointer object is pressed * @type {Phaser.Signal} */ @@ -6572,6 +6616,63 @@ module Phaser { */ public onHold: Signal; /** + * The number of milliseconds that the Pointer has to be pressed down and then released to be considered a tap or click + * @property tapRate + * @type {Number} + **/ + public tapRate: number; + /** + * The number of milliseconds between taps of the same Pointer for it to be considered a double tap / click + * @property doubleTapRate + * @type {Number} + **/ + public doubleTapRate: number; + /** + * The number of milliseconds that the Pointer has to be pressed down for it to fire a onHold event + * @property holdRate + * @type {Number} + **/ + public holdRate: number; + /** + * The number of milliseconds below which the Pointer is considered justPressed + * @property justPressedRate + * @type {Number} + **/ + public justPressedRate: number; + /** + * The number of milliseconds below which the Pointer is considered justReleased + * @property justReleasedRate + * @type {Number} + **/ + public justReleasedRate: number; + /** + * Sets if the Pointer objects should record a history of x/y coordinates they have passed through. + * The history is cleared each time the Pointer is pressed down. + * The history is updated at the rate specified in Input.pollRate + * @property recordPointerHistory + * @type {Boolean} + **/ + public recordPointerHistory: bool; + /** + * The rate in milliseconds at which the Pointer objects should update their tracking history + * @property recordRate + * @type {Number} + */ + public recordRate: number; + /** + * The total number of entries that can be recorded into the Pointer objects tracking history. + * The the Pointer is tracking one event every 100ms, then a trackLimit of 100 would store the last 10 seconds worth of history. + * @property recordLimit + * @type {Number} + */ + public recordLimit: number; + /** + * A Pointer object specifically used by the Mouse + * @property mousePointer + * @type {Pointer} + **/ + public mousePointer: Pointer; + /** * A Pointer object * @property pointer1 * @type {Pointer} @@ -6653,7 +6754,7 @@ module Phaser { **/ public totalInactivePointers : number; /** - * Get the total number of active Pointers + * Recalculates the total number of active Pointers * @method totalActivePointers * @return {Number} The number of Pointers currently active **/ @@ -6871,10 +6972,13 @@ module Phaser { module Phaser { class Mouse { constructor(game: Game); + /** + * Local private reference to game. + * @property _game + * @type {Phaser.Game} + * @private + **/ private _game; - private _x; - private _y; - public button: number; static LEFT_BUTTON: number; static MIDDLE_BUTTON: number; static RIGHT_BUTTON: number; @@ -6884,32 +6988,14 @@ module Phaser { */ public disabled: bool; /** - * @type {Boolean} + * Starts the event listeners running + * @method start */ - public isDown: bool; - /** - * @type {Boolean} - */ - public isUp: bool; - /** - * @type {Number} - */ - public timeDown: number; - /** - * @type {Number} - */ - public duration: number; - /** - * @type {Number} - */ - public timeUp: number; public start(): void; - public reset(): void; /** * @param {MouseEvent} event */ public onMouseDown(event: MouseEvent): void; - public update(): void; /** * @param {MouseEvent} event */ @@ -6918,6 +7004,11 @@ module Phaser { * @param {MouseEvent} event */ public onMouseUp(event: MouseEvent): void; + /** + * Stop the event listeners + * @method stop + */ + public stop(): void; } } /** @@ -6938,9 +7029,9 @@ module Phaser { */ constructor(game: Game); /** - * + * Local private reference to game. * @property _game - * @type {Game} + * @type {Phaser.Game} * @private **/ private _game; @@ -6950,7 +7041,7 @@ module Phaser { */ public disabled: bool; /** - * + * Starts the event listeners running * @method start */ public start(): void; @@ -7000,7 +7091,7 @@ module Phaser { **/ private onTouchEnd(event); /** - * + * Stop the event listeners * @method stop */ public stop(): void; diff --git a/build/phaser.js b/build/phaser.js index c683481c..abdc4db2 100644 --- a/build/phaser.js +++ b/build/phaser.js @@ -6769,7 +6769,6 @@ var Phaser; * Phaser - Group * * This class is used for organising, updating and sorting game objects. -* */ var Phaser; (function (Phaser) { @@ -6867,7 +6866,7 @@ var Phaser; configurable: true }); Group.prototype.add = /** - * Adds a new Basic subclass (Basic, Basic, Enemy, etc) to the group. + * Adds a new Basic subclass (Basic, GameObject, Sprite, etc) to the group. * Group will try to replace a null member of the array first. * Failing that, Group will add it to the end of the member array, * assuming there is room for it, and doubling the size of the array if necessary. @@ -6876,7 +6875,6 @@ var Phaser; * the object will NOT be added to the group!

* * @param {Basic} Object The object you want to add to the group. - * * @return {Basic} The same Basic object that was passed in. */ function (Object) { @@ -10728,6 +10726,27 @@ var Phaser; * @return {Phaser.Pointer} This object. */ function Pointer(game, id) { + /** + * Local private variable to store the status of dispatching a hold event + * @property _holdSent + * @type {Boolean} + * @private + */ + this._holdSent = false; + /** + * Local private variable storing the short-term history of pointer movements + * @property _history + * @type {Array} + * @private + */ + this._history = []; + /** + * Local private variable storing the time at which the next history drop should occur + * @property _lastDrop + * @type {Number} + * @private + */ + this._nextDrop = 0; /** * A Point object representing the x/y screen coordinates of the Pointer. * @property pointA @@ -10802,13 +10821,19 @@ var Phaser; */ this.y = -1; /** - * If the Pointer is touching the touchscreen isDown is set to true + * If the Pointer is a mouse this is true, otherwise false + * @property isMouse + * @type {Boolean} + **/ + this.isMouse = false; + /** + * If the Pointer is touching the touchscreen, or the mouse button is held down, isDown is set to true * @property isDown * @type {Boolean} **/ this.isDown = false; /** - * If the Pointer is not touching the touchscreen isUp is set to true + * If the Pointer is not touching the touchscreen, or the mouse button is up, isUp is set to true * @property isUp * @type {Boolean} **/ @@ -10826,17 +10851,11 @@ var Phaser; **/ this.timeUp = 0; /** - * The number of milliseconds below which the Pointer is considered justPressed - * @property justPressedRate + * A timestamp representing when the Pointer was last tapped or clicked + * @property previousTapTime * @type {Number} **/ - this.justPressedRate = 200; - /** - * The number of milliseconds below which the Pointer is considered justReleased - * @property justReleasedRate - * @type {Number} - **/ - this.justReleasedRate = 200; + this.previousTapTime = 0; /** * The total number of times this Pointer has been touched to the touchscreen * @property totalTouches @@ -10849,14 +10868,20 @@ var Phaser; this.pointA = new Phaser.Point(); this.pointB = new Phaser.Point(); this.circle = new Phaser.Circle(0, 0, 44); + if(id == 0) { + this.isMouse = true; + } } Object.defineProperty(Pointer.prototype, "duration", { get: /** - * How long the Pointer has been depressed on the touchscreen. + * How long the Pointer has been depressed on the touchscreen. If not currently down it returns -1. * @property duration * @type {Number} **/ function () { + if(this.isUp) { + return -1; + } return this._game.time.now - this.timeDown; }, enumerable: true, @@ -10886,6 +10911,10 @@ var Phaser; function (event) { this.identifier = event.identifier; this.target = event.target; + if(event.button) { + this.button = event.button; + } + this._history.length = 0; this.move(event); this.pointA.setTo(this.x, this.y); this.active = true; @@ -10893,18 +10922,48 @@ var Phaser; this.isDown = true; this.isUp = false; this.timeDown = this._game.time.now; - this._game.input.x = this.x * this._game.input.scaleX; - this._game.input.y = this.y * this._game.input.scaleY; - this._game.input.onDown.dispatch(this); + this._holdSent = false; + if(this._game.input.multiInputOverride == Phaser.Input.MOUSE_OVERRIDES_TOUCH || this._game.input.multiInputOverride == Phaser.Input.MOUSE_TOUCH_COMBINE || (this._game.input.multiInputOverride == Phaser.Input.TOUCH_OVERRIDES_MOUSE && this._game.input.currentPointers == 0)) { + this._game.input.x = this.x * this._game.input.scaleX; + this._game.input.y = this.y * this._game.input.scaleY; + this._game.input.onDown.dispatch(this); + } this.totalTouches++; + if(this.isMouse == false) { + this._game.input.currentPointers++; + } return this; }; + Pointer.prototype.update = function () { + if(this.active) { + if(this._holdSent == false && this.duration >= this._game.input.holdRate) { + if(this._game.input.multiInputOverride == Phaser.Input.MOUSE_OVERRIDES_TOUCH || this._game.input.multiInputOverride == Phaser.Input.MOUSE_TOUCH_COMBINE || (this._game.input.multiInputOverride == Phaser.Input.TOUCH_OVERRIDES_MOUSE && this._game.input.currentPointers == 0)) { + this._game.input.onHold.dispatch(this); + } + this._holdSent = true; + } + // Update the droppings history + if(this._game.input.recordPointerHistory && this._game.time.now >= this._nextDrop) { + this._nextDrop = this._game.time.now + this._game.input.recordRate; + this._history.push({ + x: this.pointB.x, + y: this.pointB.y + }); + if(this._history.length > this._game.input.recordLimit) { + this._history.shift(); + } + } + } + }; Pointer.prototype.move = /** * Called when the Pointer is moved on the touchscreen * @method move * @param {Any} event */ function (event) { + if(event.button) { + this.button = event.button; + } this.clientX = event.clientX; this.clientY = event.clientY; this.pageX = event.pageX; @@ -10915,9 +10974,10 @@ var Phaser; this.y = this.pageY - this._game.stage.offset.y; this.pointB.setTo(this.x, this.y); this.circle.setTo(this.x, this.y, 44); - this._game.input.x = this.x * this._game.input.scaleX; - this._game.input.y = this.y * this._game.input.scaleY; - // Droppings history (used for gestures and motion tracking) + if(this._game.input.multiInputOverride == Phaser.Input.MOUSE_OVERRIDES_TOUCH || this._game.input.multiInputOverride == Phaser.Input.MOUSE_TOUCH_COMBINE || (this._game.input.multiInputOverride == Phaser.Input.TOUCH_OVERRIDES_MOUSE && this._game.input.currentPointers == 0)) { + this._game.input.x = this.x * this._game.input.scaleX; + this._game.input.y = this.y * this._game.input.scaleY; + } return this; }; Pointer.prototype.leave = /** @@ -10935,22 +10995,38 @@ var Phaser; * @param {Any} event */ function (event) { + console.log('duration', this.duration); + if(this._game.input.multiInputOverride == Phaser.Input.MOUSE_OVERRIDES_TOUCH || this._game.input.multiInputOverride == Phaser.Input.MOUSE_TOUCH_COMBINE || (this._game.input.multiInputOverride == Phaser.Input.TOUCH_OVERRIDES_MOUSE && this._game.input.currentPointers == 0)) { + this._game.input.onUp.dispatch(this); + // Was it a tap? + if(this.duration >= 0 && this.duration <= this._game.input.tapRate) { + // Yes, let's dispatch the signal + this._game.input.onTap.dispatch(this); + // Was it a double-tap? + if(this.timeUp - this.previousTapTime < this._game.input.doubleTapRate) { + this._game.input.onDoubleTap.dispatch(this); + } + this.previousTapTime = this.timeUp; + } + } this.active = false; this.withinGame = false; this.isDown = false; this.isUp = true; this.timeUp = this._game.time.now; - this._game.input.onUp.dispatch(this); + if(this.isMouse == false) { + this._game.input.currentPointers--; + } return this; }; Pointer.prototype.justPressed = /** - * The Pointer is considered justPressed if the time it was pressed onto the touchscreen is less than justPressedRate + * The Pointer is considered justPressed if the time it was pressed onto the touchscreen or clicked is less than justPressedRate * @method justPressed * @param {Number} [duration]. * @return {Boolean} */ function (duration) { - if (typeof duration === "undefined") { duration = this.justPressedRate; } + if (typeof duration === "undefined") { duration = this._game.input.justPressedRate; } if(this.isDown === true && (this.timeDown + duration) > this._game.time.now) { return true; } else { @@ -10964,19 +11040,25 @@ var Phaser; * @return {Boolean} */ function (duration) { - if (typeof duration === "undefined") { duration = this.justReleasedRate; } + if (typeof duration === "undefined") { duration = this._game.input.justReleasedRate; } if(this.isUp === true && (this.timeUp + duration) > this._game.time.now) { return true; } else { return false; } }; - Pointer.prototype.reset = function () { + Pointer.prototype.reset = /** + * Resets the Pointer properties. Called by Input.reset when you perform a State change. + * @method reset + */ + function () { this.active = false; this.identifier = null; this.isDown = false; this.isUp = true; this.totalTouches = 0; + this._holdSent = false; + this._history.length = 0; }; Pointer.prototype.renderDebug = /** * Renders the Pointer.circle object onto the stage in green if down or red if up. @@ -11050,7 +11132,7 @@ var Phaser; this._game = game; } MSPointer.prototype.start = /** - * + * Starts the event listeners running * @method start */ function () { @@ -11107,10 +11189,15 @@ var Phaser; this._game.input.stopPointer(event); }; MSPointer.prototype.stop = /** - * + * Stop the event listeners * @method stop */ function () { + if(this._game.device.mspointer == true) { + //this._game.stage.canvas.addEventListener('MSPointerDown', (event) => this.onPointerDown(event), false); + //this._game.stage.canvas.addEventListener('MSPointerMove', (event) => this.onPointerMove(event), false); + //this._game.stage.canvas.addEventListener('MSPointerUp', (event) => this.onPointerUp(event), false); + } }; return MSPointer; })(); @@ -11174,6 +11261,10 @@ var Phaser; */ this.disabled = false; /** + * Controls the expected behaviour when using a mouse and touch together on a multi-input device + */ + this.multiInputOverride = Input.MOUSE_TOUCH_COMBINE; + /** * X coordinate of the most recent Pointer event * @type {Number} * @private @@ -11196,22 +11287,69 @@ var Phaser; */ this.scaleY = 1; /** - * - * @type {Number} - */ - this.worldX = 0; - /** - * - * @type {Number} - */ - this.worldY = 0; - /** * The maximum number of Pointers allowed to be active at any one time. * For lots of games it's useful to set this to 1 * @type {Number} */ this.maxPointers = 10; + /** + * The current number of active Pointers. + * @type {Number} + */ + this.currentPointers = 0; + /** + * The number of milliseconds that the Pointer has to be pressed down and then released to be considered a tap or click + * @property tapRate + * @type {Number} + **/ + this.tapRate = 200; + /** + * The number of milliseconds between taps of the same Pointer for it to be considered a double tap / click + * @property doubleTapRate + * @type {Number} + **/ + this.doubleTapRate = 250; + /** + * The number of milliseconds that the Pointer has to be pressed down for it to fire a onHold event + * @property holdRate + * @type {Number} + **/ + this.holdRate = 2000; + /** + * The number of milliseconds below which the Pointer is considered justPressed + * @property justPressedRate + * @type {Number} + **/ + this.justPressedRate = 200; + /** + * The number of milliseconds below which the Pointer is considered justReleased + * @property justReleasedRate + * @type {Number} + **/ + this.justReleasedRate = 200; + /** + * Sets if the Pointer objects should record a history of x/y coordinates they have passed through. + * The history is cleared each time the Pointer is pressed down. + * The history is updated at the rate specified in Input.pollRate + * @property recordPointerHistory + * @type {Boolean} + **/ + this.recordPointerHistory = true; + /** + * The rate in milliseconds at which the Pointer objects should update their tracking history + * @property recordRate + * @type {Number} + */ + this.recordRate = 100; + /** + * The total number of entries that can be recorded into the Pointer objects tracking history. + * The the Pointer is tracking one event every 100ms, then a trackLimit of 100 would store the last 10 seconds worth of history. + * @property recordLimit + * @type {Number} + */ + this.recordLimit = 100; this._game = game; + this.mousePointer = new Phaser.Pointer(this._game, 0); this.pointer1 = new Phaser.Pointer(this._game, 1); this.pointer2 = new Phaser.Pointer(this._game, 2); this.pointer3 = new Phaser.Pointer(this._game, 3); @@ -11229,7 +11367,14 @@ var Phaser; this.gestures = new Phaser.Gestures(this._game); this.onDown = new Phaser.Signal(); this.onUp = new Phaser.Signal(); + this.onTap = new Phaser.Signal(); + this.onDoubleTap = new Phaser.Signal(); + this.onHold = new Phaser.Signal(); + this.currentPointers = 0; } + Input.MOUSE_OVERRIDES_TOUCH = 0; + Input.TOUCH_OVERRIDES_MOUSE = 1; + Input.MOUSE_TOUCH_COMBINE = 2; Object.defineProperty(Input.prototype, "x", { get: /** * The screen X coordinate @@ -11268,12 +11413,19 @@ var Phaser; this.gestures.start(); }; Input.prototype.update = function () { - //this.worldX = this._game.camera.worldView.x + this.x; - //this.worldY = this._game.camera.worldView.y + this.y; - this.mouse.update(); + this.mousePointer.update(); + this.pointer1.update(); + this.pointer2.update(); + this.pointer3.update(); + this.pointer4.update(); + this.pointer5.update(); + this.pointer6.update(); + this.pointer7.update(); + this.pointer8.update(); + this.pointer9.update(); + this.pointer10.update(); }; Input.prototype.reset = function () { - this.mouse.reset(); this.keyboard.reset(); this.pointer1.reset(); this.pointer2.reset(); @@ -11287,6 +11439,10 @@ var Phaser; this.pointer10.reset(); this.onDown = new Phaser.Signal(); this.onUp = new Phaser.Signal(); + this.onTap = new Phaser.Signal(); + this.onDoubleTap = new Phaser.Signal(); + this.onHold = new Phaser.Signal(); + this.currentPointers = 0; }; Object.defineProperty(Input.prototype, "totalInactivePointers", { get: /** @@ -11295,41 +11451,41 @@ var Phaser; * @return {Number} The number of Pointers currently inactive **/ function () { - return 10 - this.totalActivePointers; + return 10 - this.currentPointers; }, enumerable: true, configurable: true }); Object.defineProperty(Input.prototype, "totalActivePointers", { get: /** - * Get the total number of active Pointers + * Recalculates the total number of active Pointers * @method totalActivePointers * @return {Number} The number of Pointers currently active **/ function () { - var result = 0; + this.currentPointers = 0; if(this.pointer1.active == true) { - result++; + this.currentPointers++; } else if(this.pointer2.active == true) { - result++; + this.currentPointers++; } else if(this.pointer3.active == true) { - result++; + this.currentPointers++; } else if(this.pointer4.active == true) { - result++; + this.currentPointers++; } else if(this.pointer5.active == true) { - result++; + this.currentPointers++; } else if(this.pointer6.active == true) { - result++; + this.currentPointers++; } else if(this.pointer7.active == true) { - result++; + this.currentPointers++; } else if(this.pointer8.active == true) { - result++; + this.currentPointers++; } else if(this.pointer9.active == true) { - result++; + this.currentPointers++; } else if(this.pointer10.active == true) { - result++; + this.currentPointers++; } - return result; + return this.currentPointers; }, enumerable: true, configurable: true @@ -11518,7 +11674,7 @@ var Phaser; this._game.stage.context.fillStyle = color; this._game.stage.context.fillText('Input', x, y); this._game.stage.context.fillText('Screen X: ' + this.x + ' Screen Y: ' + this.y, x, y + 14); - this._game.stage.context.fillText('World X: ' + this.worldX + ' World Y: ' + this.worldY, x, y + 28); + this._game.stage.context.fillText('World X: ' + this.getWorldX() + ' World Y: ' + this.getWorldY(), x, y + 28); this._game.stage.context.fillText('Scale X: ' + this.scaleX.toFixed(1) + ' Scale Y: ' + this.scaleY.toFixed(1), x, y + 42); }; return Input; @@ -11799,39 +11955,21 @@ var Phaser; (function (Phaser) { var Mouse = (function () { function Mouse(game) { - this._x = 0; - this._y = 0; /** * You can disable all Input by setting disabled = true. While set all new input related events will be ignored. * @type {Boolean} */ this.disabled = false; - /** - * @type {Boolean} - */ - this.isDown = false; - /** - * @type {Boolean} - */ - this.isUp = true; - /** - * @type {Number} - */ - this.timeDown = 0; - /** - * @type {Number} - */ - this.duration = 0; - /** - * @type {Number} - */ - this.timeUp = 0; this._game = game; } Mouse.LEFT_BUTTON = 0; Mouse.MIDDLE_BUTTON = 1; Mouse.RIGHT_BUTTON = 2; - Mouse.prototype.start = function () { + Mouse.prototype.start = /** + * Starts the event listeners running + * @method start + */ + function () { var _this = this; this._game.stage.canvas.addEventListener('mousedown', function (event) { return _this.onMouseDown(event); @@ -11843,10 +11981,6 @@ var Phaser; return _this.onMouseUp(event); }, true); }; - Mouse.prototype.reset = function () { - this.isDown = false; - this.isUp = true; - }; Mouse.prototype.onMouseDown = /** * @param {MouseEvent} event */ @@ -11854,22 +11988,8 @@ var Phaser; if(this._game.input.disabled || this.disabled) { return; } - this.button = event.button; - this._x = event.clientX - this._game.stage.x; - this._y = event.clientY - this._game.stage.y; - this._game.input.x = this._x * this._game.input.scaleX; - this._game.input.y = this._y * this._game.input.scaleY; - this.isDown = true; - this.isUp = false; - this.timeDown = this._game.time.now; - this._game.input.onDown.dispatch(this._game.input.x, this._game.input.y, this.timeDown); - }; - Mouse.prototype.update = function () { - //this._game.input.x = this._x * this._game.input.scaleX; - //this._game.input.y = this._y * this._game.input.scaleY; - if(this.isDown) { - this.duration = this._game.time.now - this.timeDown; - } + event['identifier'] = 0; + this._game.input.mousePointer.start(event); }; Mouse.prototype.onMouseMove = /** * @param {MouseEvent} event @@ -11878,11 +11998,8 @@ var Phaser; if(this._game.input.disabled || this.disabled) { return; } - this.button = event.button; - this._x = event.clientX - this._game.stage.x; - this._y = event.clientY - this._game.stage.y; - this._game.input.x = this._x * this._game.input.scaleX; - this._game.input.y = this._y * this._game.input.scaleY; + event['identifier'] = 0; + this._game.input.mousePointer.move(event); }; Mouse.prototype.onMouseUp = /** * @param {MouseEvent} event @@ -11891,17 +12008,18 @@ var Phaser; if(this._game.input.disabled || this.disabled) { return; } - this.button = event.button; - this.isDown = false; - this.isUp = true; - this.timeUp = this._game.time.now; - this.duration = this.timeUp - this.timeDown; - this._x = event.clientX - this._game.stage.x; - this._y = event.clientY - this._game.stage.y; - this._game.input.x = this._x * this._game.input.scaleX; - this._game.input.y = this._y * this._game.input.scaleY; - this._game.input.onUp.dispatch(this._game.input.x, this._game.input.y, this.timeDown); + event['identifier'] = 0; + this._game.input.mousePointer.stop(event); }; + Mouse.prototype.stop = /** + * Stop the event listeners + * @method stop + */ + function () { + //this._game.stage.canvas.addEventListener('mousedown', (event: MouseEvent) => this.onMouseDown(event), true); + //this._game.stage.canvas.addEventListener('mousemove', (event: MouseEvent) => this.onMouseMove(event), true); + //this._game.stage.canvas.addEventListener('mouseup', (event: MouseEvent) => this.onMouseUp(event), true); + }; return Mouse; })(); Phaser.Mouse = Mouse; @@ -11934,32 +12052,34 @@ var Phaser; this._game = game; } Touch.prototype.start = /** - * + * Starts the event listeners running * @method start */ function () { var _this = this; - this._game.stage.canvas.addEventListener('touchstart', function (event) { - return _this.onTouchStart(event); - }, false); - this._game.stage.canvas.addEventListener('touchmove', function (event) { - return _this.onTouchMove(event); - }, false); - this._game.stage.canvas.addEventListener('touchend', function (event) { - return _this.onTouchEnd(event); - }, false); - this._game.stage.canvas.addEventListener('touchenter', function (event) { - return _this.onTouchEnter(event); - }, false); - this._game.stage.canvas.addEventListener('touchleave', function (event) { - return _this.onTouchLeave(event); - }, false); - this._game.stage.canvas.addEventListener('touchcancel', function (event) { - return _this.onTouchCancel(event); - }, false); - document.addEventListener('touchmove', function (event) { - return _this.consumeTouchMove(event); - }, false); + if(this._game.device.touch) { + this._game.stage.canvas.addEventListener('touchstart', function (event) { + return _this.onTouchStart(event); + }, false); + this._game.stage.canvas.addEventListener('touchmove', function (event) { + return _this.onTouchMove(event); + }, false); + this._game.stage.canvas.addEventListener('touchend', function (event) { + return _this.onTouchEnd(event); + }, false); + this._game.stage.canvas.addEventListener('touchenter', function (event) { + return _this.onTouchEnter(event); + }, false); + this._game.stage.canvas.addEventListener('touchleave', function (event) { + return _this.onTouchLeave(event); + }, false); + this._game.stage.canvas.addEventListener('touchcancel', function (event) { + return _this.onTouchCancel(event); + }, false); + document.addEventListener('touchmove', function (event) { + return _this.consumeTouchMove(event); + }, false); + } }; Touch.prototype.consumeTouchMove = /** * Prevent iOS bounce-back (doesn't work?) @@ -12056,17 +12176,19 @@ var Phaser; } }; Touch.prototype.stop = /** - * + * Stop the event listeners * @method stop */ function () { - //this._domElement.addEventListener('touchstart', (event) => this.onTouchStart(event), false); - //this._domElement.addEventListener('touchmove', (event) => this.onTouchMove(event), false); - //this._domElement.addEventListener('touchend', (event) => this.onTouchEnd(event), false); - //this._domElement.addEventListener('touchenter', (event) => this.onTouchEnter(event), false); - //this._domElement.addEventListener('touchleave', (event) => this.onTouchLeave(event), false); - //this._domElement.addEventListener('touchcancel', (event) => this.onTouchCancel(event), false); - }; + if(this._game.device.touch) { + //this._domElement.addEventListener('touchstart', (event) => this.onTouchStart(event), false); + //this._domElement.addEventListener('touchmove', (event) => this.onTouchMove(event), false); + //this._domElement.addEventListener('touchend', (event) => this.onTouchEnd(event), false); + //this._domElement.addEventListener('touchenter', (event) => this.onTouchEnter(event), false); + //this._domElement.addEventListener('touchleave', (event) => this.onTouchLeave(event), false); + //this._domElement.addEventListener('touchcancel', (event) => this.onTouchCancel(event), false); + } + }; return Touch; })(); Phaser.Touch = Touch; @@ -13666,7 +13788,7 @@ var Phaser; }; Tilemap.prototype.getTileFromInputXY = function (layer) { if (typeof layer === "undefined") { layer = 0; } - return this.tiles[this.layers[layer].getTileFromWorldXY(this._game.input.worldX, this._game.input.worldY)]; + return this.tiles[this.layers[layer].getTileFromWorldXY(this._game.input.getWorldX(), this._game.input.getWorldY())]; }; Tilemap.prototype.getTileOverlaps = /** * Get tiles overlaps the given object.