From 87e0c483bba4e2199d212cac7a0c5bab73431c12 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Apr 2013 18:53:21 +0100 Subject: [PATCH] Version 0.9.1 release - see the release notes for more details. --- Phaser/Motion.ts | 5 +- Phaser/Phaser.csproj | 4 + Phaser/Phaser.ts | 4 +- Phaser/gameobjects/GameObject.ts | 85 ++-- Phaser/gameobjects/GeomSprite.ts | 28 +- Phaser/gameobjects/Sprite.ts | 87 +++- Phaser/geom/MicroPoint.ts | 170 +++++++ Phaser/geom/Point.ts | 6 +- Phaser/geom/Rectangle.ts | 602 ++++++++++++++-------- Phaser/phaser.js | 4 +- Phaser/system/input/Input.ts | 6 + Phaser/system/input/Mouse.ts | 4 + Phaser/system/input/Touch.ts | 2 + Tests/Tests.csproj | 4 + Tests/geometry/rect vs rect.js | 4 + Tests/geometry/rect vs rect.ts | 9 + Tests/geometry/rectangle.js | 13 +- Tests/geometry/rectangle.ts | 15 +- Tests/phaser.js | 843 ++++++++++++++++++++++--------- Tests/sprites/align.js | 27 + Tests/sprites/align.ts | 50 ++ Tests/sprites/rotation.js | 7 +- Tests/sprites/rotation.ts | 9 +- build/phaser.js | 843 ++++++++++++++++++++++--------- 24 files changed, 2050 insertions(+), 781 deletions(-) create mode 100644 Phaser/geom/MicroPoint.ts create mode 100644 Tests/sprites/align.js create mode 100644 Tests/sprites/align.ts diff --git a/Phaser/Motion.ts b/Phaser/Motion.ts index 4a76923b..a9f15826 100644 --- a/Phaser/Motion.ts +++ b/Phaser/Motion.ts @@ -20,8 +20,7 @@ module Phaser { private _game: Game; /** - * A tween-like function that takes a starting velocity - * and some other factors and returns an altered velocity. + * A tween-like function that takes a starting velocity and some other factors and returns an altered velocity. * * @param Velocity Any component of velocity (e.g. 20). * @param Acceleration Rate at which the velocity is changing. @@ -385,7 +384,7 @@ module Phaser { public angleBetweenMouse(a:GameObject, asDegrees:bool = false):number { // In order to get the angle between the object and mouse, we need the objects screen coordinates (rather than world coordinates) - var p:Point = a.getScreenXY(); + var p:MicroPoint = a.getScreenXY(); var dx:number = a._game.input.x - p.x; var dy:number = a._game.input.y - p.y; diff --git a/Phaser/Phaser.csproj b/Phaser/Phaser.csproj index 24faf08a..32e6988d 100644 --- a/Phaser/Phaser.csproj +++ b/Phaser/Phaser.csproj @@ -100,6 +100,10 @@ Line.ts + + + MicroPoint.ts + Point.ts diff --git a/Phaser/Phaser.ts b/Phaser/Phaser.ts index 6236d1c6..1a3e1c35 100644 --- a/Phaser/Phaser.ts +++ b/Phaser/Phaser.ts @@ -1,7 +1,7 @@ /** * Phaser * -* v0.9 - April 18th 2013 +* v0.9.1 - April 19th 2013 * * A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi. * @@ -16,6 +16,6 @@ module Phaser { - export var VERSION: string = 'Phaser version 0.9'; + export var VERSION: string = 'Phaser version 0.9.1'; } diff --git a/Phaser/gameobjects/GameObject.ts b/Phaser/gameobjects/GameObject.ts index 55b81ff3..0fae8efb 100644 --- a/Phaser/gameobjects/GameObject.ts +++ b/Phaser/gameobjects/GameObject.ts @@ -24,10 +24,11 @@ module Phaser { this.alive = true; this.isGroup = false; this.alpha = 1; - this.scale = new Point(1, 1); + this.scale = new MicroPoint(1, 1); - this.last = new Point(x, y); - this.origin = new Point(this.bounds.halfWidth, this.bounds.halfHeight); + this.last = new MicroPoint(x, y); + this.origin = new MicroPoint(this.bounds.halfWidth, this.bounds.halfHeight); + this.align = GameObject.ALIGN_TOP_LEFT; this.mass = 1.0; this.elasticity = 0.0; this.health = 1; @@ -38,10 +39,10 @@ module Phaser { this.wasTouching = Collision.NONE; this.allowCollisions = Collision.ANY; - this.velocity = new Point(); - this.acceleration = new Point(); - this.drag = new Point(); - this.maxVelocity = new Point(10000, 10000); + this.velocity = new MicroPoint(); + this.acceleration = new MicroPoint(); + this.drag = new MicroPoint(); + this.maxVelocity = new MicroPoint(10000, 10000); this.angle = 0; this.angularVelocity = 0; @@ -49,40 +50,58 @@ module Phaser { this.angularDrag = 0; this.maxAngular = 10000; - this.scrollFactor = new Point(1.0, 1.0); + this.scrollFactor = new MicroPoint(1.0, 1.0); } private _angle: number = 0; - public _point: Point; + + public static ALIGN_TOP_LEFT: number = 0; + public static ALIGN_TOP_CENTER: number = 1; + public static ALIGN_TOP_RIGHT: number = 2; + public static ALIGN_CENTER_LEFT: number = 3; + public static ALIGN_CENTER: number = 4; + public static ALIGN_CENTER_RIGHT: number = 5; + public static ALIGN_BOTTOM_LEFT: number = 6; + public static ALIGN_BOTTOM_CENTER: number = 7; + public static ALIGN_BOTTOM_RIGHT: number = 8; + + public _point: MicroPoint; public bounds: Rectangle; + public align: number; public facing: number; public alpha: number; - public scale: Point; - public origin: Point; + public scale: MicroPoint; + public origin: MicroPoint; public z: number = 0; // Physics properties public immovable: bool; - public velocity: Point; + + // Velocity is given in pixels per second. Therefore a velocity of + // 100 will move at a rate of 100 pixels every 1000 ms (1sec). It's not balls-on + // accurate due to the way timers work, but it's pretty close. Expect tolerance + // of +- 10 px. Also that speed assumes no drag + public velocity: MicroPoint; + public mass: number; public elasticity: number; - public acceleration: Point; - public drag: Point; - public maxVelocity: Point; + public acceleration: MicroPoint; + public drag: MicroPoint; + public maxVelocity: MicroPoint; public angularVelocity: number; public angularAcceleration: number; public angularDrag: number; public maxAngular: number; - public scrollFactor: Point; + public scrollFactor: MicroPoint; public health: number; public moves: bool = true; public touching: number; public wasTouching: number; public allowCollisions: number; - public last: Point; + public last: MicroPoint; // Input public inputEnabled: bool = false; @@ -123,9 +142,6 @@ module Phaser { } private updateInput() { - - - } private updateMotion() { @@ -215,7 +231,7 @@ module Phaser { /** * Checks to see if this GameObject were located at the given position, would it overlap the GameObject or Group? - * This is distinct from overlapsPoint(), which just checks that ponumber, rather than taking the object's size numbero account. + * This is distinct from overlapsPoint(), which just checks that point, rather than taking the object's size numbero account. * WARNING: Currently tilemaps do NOT support screen space overlap checks! * * @param X The X position you want to check. Pretends this object (the caller, not the parameter) is located here. @@ -283,13 +299,13 @@ module Phaser { } /** - * Checks to see if a ponumber in 2D world space overlaps this GameObject object. + * Checks to see if a point in 2D world space overlaps this GameObject. * - * @param Point The ponumber in world space you want to check. + * @param Point The point in world space you want to check. * @param InScreenSpace Whether to take scroll factors numbero account when checking for overlap. * @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera. * - * @return Whether or not the ponumber overlaps this object. + * @return Whether or not the point overlaps this object. */ public overlapsPoint(point: Point, InScreenSpace: bool = false, Camera: Camera = null): bool { @@ -315,7 +331,7 @@ module Phaser { /** * Check and see if this object is currently on screen. * - * @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera. + * @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera. * * @return Whether the object is on screen or not. */ @@ -336,15 +352,15 @@ module Phaser { * Call this to figure out the on-screen position of the object. * * @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera. - * @param Point Takes a Point object and assigns the post-scrolled X and Y values of this object to it. + * @param Point Takes a MicroPoint object and assigns the post-scrolled X and Y values of this object to it. * - * @return The Point you passed in, or a new Point if you didn't pass one, containing the screen X and Y position of this object. + * @return The MicroPoint you passed in, or a new Point if you didn't pass one, containing the screen X and Y position of this object. */ - public getScreenXY(point: Point = null, Camera: Camera = null): Point { + public getScreenXY(point: MicroPoint = null, Camera: Camera = null): MicroPoint { if (point == null) { - point = new Point(); + point = new MicroPoint(); } if (Camera == null) @@ -387,21 +403,20 @@ module Phaser { } /** - * Retrieve the midponumber of this object in world coordinates. + * Retrieve the midpoint of this object in world coordinates. * * @Point Allows you to pass in an existing Point object if you're so inclined. Otherwise a new one is created. * - * @return A Point object containing the midponumber of this object in world coordinates. + * @return A Point object containing the midpoint of this object in world coordinates. */ - public getMidpoint(point: Point = null): Point { + public getMidpoint(point: MicroPoint = null): MicroPoint { if (point == null) { - point = new Point(); + point = new MicroPoint(); } - point.x = this.x + this.width * 0.5; - point.y = this.y + this.height * 0.5; + point.copyFrom(this.bounds.center); return point; diff --git a/Phaser/gameobjects/GeomSprite.ts b/Phaser/gameobjects/GeomSprite.ts index a4c8ffbc..6ea81183 100644 --- a/Phaser/gameobjects/GeomSprite.ts +++ b/Phaser/gameobjects/GeomSprite.ts @@ -182,7 +182,7 @@ module Phaser { } else { - return camera.overlap(this.bounds); + return camera.intersects(this.bounds); } } @@ -221,7 +221,8 @@ module Phaser { this._dy -= (camera.worldView.y * this.scrollFactor.y); } - // Rotation (could be misleading as it doesn't work re: collision) + // Rotation is disabled for now as I don't want it to be misleading re: collision + /* if (this.angle !== 0) { this._game.stage.context.save(); @@ -230,6 +231,7 @@ module Phaser { this._dx = -(this._dw / 2); this._dy = -(this._dh / 2); } + */ this._dx = Math.round(this._dx); this._dy = Math.round(this._dy); @@ -286,7 +288,6 @@ module Phaser { else { this._game.stage.context.beginPath(); - this._game.stage.context.rect(this._dx, this._dy, this.rect.width, this.rect.height); this._game.stage.context.stroke(); @@ -297,6 +298,19 @@ module Phaser { this._game.stage.context.closePath(); } + + // And now the edge points + this._game.stage.context.fillStyle = 'rgb(255,255,255)'; + this.renderPoint(this._dx, this._dy, this.rect.topLeft, 2); + this.renderPoint(this._dx, this._dy, this.rect.topCenter, 2); + this.renderPoint(this._dx, this._dy, this.rect.topRight, 2); + this.renderPoint(this._dx, this._dy, this.rect.leftCenter, 2); + this.renderPoint(this._dx, this._dy, this.rect.center, 2); + this.renderPoint(this._dx, this._dy, this.rect.rightCenter, 2); + this.renderPoint(this._dx, this._dy, this.rect.bottomLeft, 2); + this.renderPoint(this._dx, this._dy, this.rect.bottomCenter, 2); + this.renderPoint(this._dx, this._dy, this.rect.bottomRight, 2); + } this._game.stage.restoreCanvasValues(); @@ -316,6 +330,14 @@ module Phaser { } + public renderPoint(offsetX, offsetY, point, size) { + + offsetX = 0; + offsetY = 0; + this._game.stage.context.fillRect(offsetX + point.x, offsetY + point.y, 1, 1); + + } + public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') { //this._game.stage.context.fillStyle = color; diff --git a/Phaser/gameobjects/Sprite.ts b/Phaser/gameobjects/Sprite.ts index 383832f0..2453fc13 100644 --- a/Phaser/gameobjects/Sprite.ts +++ b/Phaser/gameobjects/Sprite.ts @@ -34,12 +34,8 @@ module Phaser { } private _texture; - private _canvas: HTMLCanvasElement; - private _context: CanvasRenderingContext2D; private _dynamicTexture: bool = false; - public animations: AnimationManager; - // local rendering related temp vars to help avoid gc spikes private _sx: number = 0; private _sy: number = 0; @@ -50,6 +46,12 @@ module Phaser { private _dw: number = 0; private _dh: number = 0; + public animations: AnimationManager; + + public renderDebug: bool = false; + public renderDebugColor: string = 'rgba(0,255,0,0.5)'; + public renderDebugPointColor: string = 'rgba(255,255,255,1)'; + public loadGraphic(key: string): Sprite { if (this._game.cache.getImage(key) !== null) @@ -98,7 +100,7 @@ module Phaser { } public inCamera(camera: Rectangle): bool { - + if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) { this._dx = this.bounds.x - (camera.x * this.scrollFactor.x); @@ -110,7 +112,7 @@ module Phaser { } else { - return camera.overlap(this.bounds); + return camera.intersects(this.bounds, this.bounds.length); } } @@ -165,11 +167,48 @@ module Phaser { this._sy = 0; this._sw = this.bounds.width; this._sh = this.bounds.height; - this._dx = cameraOffsetX + (this.bounds.x - camera.worldView.x); - this._dy = cameraOffsetY + (this.bounds.y - camera.worldView.y); + this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x); + this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y); this._dw = this.bounds.width * this.scale.x; this._dh = this.bounds.height * this.scale.y; + if (this.align == GameObject.ALIGN_TOP_CENTER) + { + this._dx -= this.bounds.halfWidth * this.scale.x; + } + else if (this.align == GameObject.ALIGN_TOP_RIGHT) + { + this._dx -= this.bounds.width * this.scale.x; + } + else if (this.align == GameObject.ALIGN_CENTER_LEFT) + { + this._dy -= this.bounds.halfHeight * this.scale.y; + } + else if (this.align == GameObject.ALIGN_CENTER) + { + this._dx -= this.bounds.halfWidth * this.scale.x; + this._dy -= this.bounds.halfHeight * this.scale.y; + } + else if (this.align == GameObject.ALIGN_CENTER_RIGHT) + { + this._dx -= this.bounds.width * this.scale.x; + this._dy -= this.bounds.halfHeight * this.scale.y; + } + else if (this.align == GameObject.ALIGN_BOTTOM_LEFT) + { + this._dy -= this.bounds.height * this.scale.y; + } + else if (this.align == GameObject.ALIGN_BOTTOM_CENTER) + { + this._dx -= this.bounds.halfWidth * this.scale.x; + this._dy -= this.bounds.height * this.scale.y; + } + else if (this.align == GameObject.ALIGN_BOTTOM_RIGHT) + { + this._dx -= this.bounds.width * this.scale.x; + this._dy -= this.bounds.height * this.scale.y; + } + if (this._dynamicTexture == false && this.animations.currentFrame !== null) { this._sx = this.animations.currentFrame.x; @@ -209,10 +248,6 @@ module Phaser { this._dw = Math.round(this._dw); this._dh = Math.round(this._dh); - // Debug test - //this._game.stage.context.fillStyle = 'rgba(255,0,0,0.3)'; - //this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh); - if (this._texture != null) { if (this._dynamicTexture) @@ -250,6 +285,11 @@ module Phaser { this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh); } + if (this.renderDebug) + { + this.renderBounds(); + } + //if (this.flip === true || this.rotation !== 0) if (this.rotation !== 0) { @@ -266,6 +306,29 @@ module Phaser { } + private renderBounds() { + + this._game.stage.context.fillStyle = this.renderDebugColor; + this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh); + this._game.stage.context.fillStyle = this.renderDebugPointColor; + + var hw = this.bounds.halfWidth * this.scale.x; + var hh = this.bounds.halfHeight * this.scale.y; + var sw = (this.bounds.width * this.scale.x) - 1; + var sh = (this.bounds.height * this.scale.y) - 1; + + this._game.stage.context.fillRect(this._dx, this._dy, 1, 1); // top left + this._game.stage.context.fillRect(this._dx + hw, this._dy, 1, 1); // top center + this._game.stage.context.fillRect(this._dx + sw, this._dy, 1, 1); // top right + this._game.stage.context.fillRect(this._dx, this._dy + hh, 1, 1); // left center + this._game.stage.context.fillRect(this._dx + hw, this._dy + hh, 1, 1); // center + this._game.stage.context.fillRect(this._dx + sw, this._dy + hh, 1, 1); // right center + this._game.stage.context.fillRect(this._dx, this._dy + sh, 1, 1); // bottom left + this._game.stage.context.fillRect(this._dx + hw, this._dy + sh, 1, 1); // bottom center + this._game.stage.context.fillRect(this._dx + sw, this._dy + sh, 1, 1); // bottom right + + } + public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') { this._game.stage.context.fillStyle = color; diff --git a/Phaser/geom/MicroPoint.ts b/Phaser/geom/MicroPoint.ts new file mode 100644 index 00000000..10cf8231 --- /dev/null +++ b/Phaser/geom/MicroPoint.ts @@ -0,0 +1,170 @@ +/// + +/** +* Phaser - MicroPoint +* +* The MicroPoint object represents a location in a two-dimensional coordinate system, +* where x represents the horizontal axis and y represents the vertical axis. +* It is different to the Point class in that it doesn't contain any of the help methods like add/substract/distanceTo, etc. +* Use a MicroPoint when all you literally need is a solid container for x and y (such as in the Rectangle class). +*/ + +module Phaser { + + export class MicroPoint { + + /** + * Creates a new point. If you pass no parameters to this method, a point is created at (0,0). + * @class MicroPoint + * @constructor + * @param {Number} x The horizontal position of this point (default 0) + * @param {Number} y The vertical position of this point (default 0) + **/ + constructor(x: number = 0, y: number = 0, parent?:any = null) { + + this._x = x; + this._y = y; + this.parent = parent; + + } + + private _x: number; + private _y: number; + + public parent: any; + + /** + * The x coordinate of the top-left corner of the rectangle + * @property x + * @type Number + **/ + public get x(): number { + + return this._x; + + } + + /** + * The y coordinate of the top-left corner of the rectangle + * @property y + * @type Number + **/ + public get y(): number { + + return this._y; + + } + + /** + * The x coordinate of the top-left corner of the rectangle + * @property x + * @type Number + **/ + public set x(value: number) { + + this._x = value; + + if (this.parent) + { + this.parent.updateBounds(); + } + + } + + /** + * The y coordinate of the top-left corner of the rectangle + * @property y + * @type Number + **/ + public set y(value:number) { + + this._y = value; + + if (this.parent) + { + this.parent.updateBounds(); + } + + } + + /** + * Copies the x and y values from any given object to this MicroPoint. + * @method copyFrom + * @param {any} source - The object to copy from. + * @return {MicroPoint} This MicroPoint object. Useful for chaining method calls. + **/ + public copyFrom(source: any): MicroPoint { + + return this.setTo(source.x, source.y); + + } + + /** + * Copies the x and y values from this MicroPoint to any given object. + * @method copyTo + * @param {any} target - The object to copy to. + * @return {any} The target object. + **/ + public copyTo(target: any): MicroPoint { + + target.x = this._x; + target.y = this._y; + + return target; + + } + + /** + * Sets the x and y values of this MicroPoint object to the given coordinates. + * @method setTo + * @param {Number} x - The horizontal position of this point. + * @param {Number} y - The vertical position of this point. + * @return {MicroPoint} This MicroPoint object. Useful for chaining method calls. + **/ + public setTo(x: number, y: number, callParent?:bool = true): MicroPoint { + + this._x = x; + this._y = y; + + if (this.parent != null && callParent == true) + { + this.parent.updateBounds(); + } + + return this; + + } + + /** + * Determines whether this MicroPoint object and the given object are equal. They are equal if they have the same x and y values. + * @method equals + * @param {any} point - The object to compare against. Must have x and y properties. + * @return {Boolean} A value of true if the object is equal to this MicroPoin object; false if it is not equal. + **/ + public equals(toCompare): bool { + + if (this._x === toCompare.x && this._y === toCompare.y) + { + return true; + } + else + { + return false; + } + + } + + /** + * Returns a string representation of this object. + * @method toString + * @return {string} a string representation of the instance. + **/ + public toString(): string { + + return '[{MicroPoint (x=' + this._x + ' y=' + this._y + ')}]'; + + } + + } + +} \ No newline at end of file diff --git a/Phaser/geom/Point.ts b/Phaser/geom/Point.ts index fbf6aa7a..932013ab 100644 --- a/Phaser/geom/Point.ts +++ b/Phaser/geom/Point.ts @@ -14,8 +14,8 @@ module Phaser { * Creates a new point. If you pass no parameters to this method, a point is created at (0,0). * @class Point * @constructor - * @param {Number} x One-liner. Default is ?. - * @param {Number} y One-liner. Default is ?. + * @param {Number} x The horizontal position of this point (default 0) + * @param {Number} y The vertical position of this point (default 0) **/ constructor(x: number = 0, y: number = 0) { @@ -298,7 +298,7 @@ module Phaser { /** * Sets the x and y values of this Point object to the given coordinates. - * @method set + * @method setTo * @param {Number} x - The horizontal position of this point. * @param {Number} y - The vertical position of this point. * @return {Point} This Point object. Useful for chaining method calls. diff --git a/Phaser/geom/Rectangle.ts b/Phaser/geom/Rectangle.ts index cd6e779b..79a4c7be 100644 --- a/Phaser/geom/Rectangle.ts +++ b/Phaser/geom/Rectangle.ts @@ -1,4 +1,5 @@ /// +/// /** * Phaser - Rectangle @@ -22,7 +23,58 @@ module Phaser { **/ constructor(x: number = 0, y: number = 0, width: number = 0, height: number = 0) { - this.setTo(x, y, width, height); + this._width = width; + + if (width > 0) + { + this._halfWidth = Math.round(width / 2); + } + + this._height = height; + + if (height > 0) + { + this._halfHeight = Math.round(height / 2); + } + + this.length = Math.max(this._width, this._height); + + this.topLeft = new MicroPoint(x, y, this); + this.topCenter = new MicroPoint(x + this._halfWidth, y, this); + this.topRight = new MicroPoint(x + this._width - 1, y, this); + this.leftCenter = new MicroPoint(x, y + this._halfHeight, this); + this.center = new MicroPoint(x + this._halfWidth, y + this._halfHeight, this); + this.rightCenter = new MicroPoint(x + this._width - 1, y + this._halfHeight, this); + this.bottomLeft = new MicroPoint(x, y + this._height - 1, this); + this.bottomCenter = new MicroPoint(x + this._halfWidth, y + this._height - 1, this); + this.bottomRight = new MicroPoint(x + this._width - 1, y + this._height - 1, this); + + } + + private _tempX: number = null; + private _tempY: number = null; + private _tempWidth: number = null; + private _tempHeight: number = null; + + /** + * The x coordinate of the top-left corner of the rectangle + * @property x + * @type Number + **/ + public get x(): number { + + return this.topLeft.x; + + } + + /** + * The y coordinate of the top-left corner of the rectangle + * @property y + * @type Number + **/ + public get y(): number { + + return this.topLeft.y; } @@ -31,157 +83,361 @@ module Phaser { * @property x * @type Number **/ - x: number = 0; + public set x(value: number) { + + this.topLeft.x = value; + + } /** * The y coordinate of the top-left corner of the rectangle * @property y * @type Number **/ - y: number = 0; + public set y(value:number) { + + this.topLeft.y = value; + + } /** - * The width of the rectangle in pixels + * The x and y coordinate of the top-left corner of the rectangle (same as x/y) + * @property topLeft + * @type MicroPoint + **/ + public topLeft: MicroPoint; + + /** + * The x and y coordinate of the top-center of the rectangle + * @property topCenter + * @type MicroPoint + **/ + public topCenter: MicroPoint; + + /** + * The x and y coordinate of the top-right corner of the rectangle + * @property topRight + * @type MicroPoint + **/ + public topRight: MicroPoint; + + /** + * The x and y coordinate of the left-center of the rectangle + * @property leftCenter + * @type MicroPoint + **/ + public leftCenter: MicroPoint; + + /** + * The x and y coordinate of the center of the rectangle + * @property center + * @type MicroPoint + **/ + public center: MicroPoint; + + /** + * The x and y coordinate of the right-center of the rectangle + * @property rightCenter + * @type MicroPoint + **/ + public rightCenter: MicroPoint; + + /** + * The x and y coordinate of the bottom-left corner of the rectangle + * @property bottomLeft + * @type MicroPoint + **/ + public bottomLeft: MicroPoint; + + /** + * The x and y coordinate of the bottom-center of the rectangle + * @property bottomCenter + * @type MicroPoint + **/ + public bottomCenter: MicroPoint; + + /** + * The x and y coordinate of the bottom-right corner of the rectangle + * @property bottomRight + * @type MicroPoint + **/ + public bottomRight: MicroPoint; + + /** + * The width of the rectangle * @property width * @type Number **/ - width: number = 0; + private _width: number = 0; /** - * The height of the rectangle in pixels + * The height of the rectangle * @property height * @type Number **/ - height: number = 0; + private _height: number = 0; - get halfWidth(): number { - - return Math.round(this.width / 2); - - } - - get halfHeight(): number { - - return Math.round(this.height / 2); - - } - - /** - * The sum of the y and height properties. Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property. - * @method bottom - * @return {Number} + /** + * Half of the width of the rectangle + * @property halfWidth + * @type Number **/ - get bottom(): number { + private _halfWidth: number = 0; - return this.y + this.height; - - } - - /** - * The sum of the y and height properties. Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property. - * @method bottom - * @param {Number} value + /** + * Half of the height of the rectangle + * @property halfHeight + * @type Number **/ - set bottom(value: number) { + private _halfHeight: number = 0; - if (value < this.y) + /** + * The size of the longest side (width or height) + * @property length + * @type Number + **/ + public length: number = 0; + + /** + * Updates all of the MicroPoints based on the values of width and height. + * You should not normally call this directly. + **/ + public updateBounds() { + + if (this._tempWidth !== null) { - this.height = 0; + this._width = this._tempWidth; + this._halfWidth = 0; + + if (this._width > 0) + { + this._halfWidth = Math.round(this._width / 2); + } + } + + if (this._tempHeight !== null) + { + this._height = this._tempHeight; + this._halfHeight = 0; + + if (this._height > 0) + { + this._halfHeight = Math.round(this._height / 2); + } + } + + this.length = Math.max(this._width, this._height); + + if (this._tempX !== null && this._tempY !== null) + { + this.topLeft.setTo(this._tempX, this._tempY, false); + } + else if (this._tempX !== null && this._tempY == null) + { + this.topLeft.setTo(this._tempX, this.topLeft.y, false); + } + else if (this._tempX == null && this._tempY !== null) + { + this.topLeft.setTo(this.topLeft.x, this._tempY, false); } else { - this.height = this.y + value; + this.topLeft.setTo(this.x, this.y, false); } + this.topCenter.setTo(this.x + this._halfWidth, this.y, false); + this.topRight.setTo(this.x + this._width - 1, this.y, false); + + this.leftCenter.setTo(this.x, this.y + this._halfHeight, false); + this.center.setTo(this.x + this._halfWidth, this.y + this._halfHeight, false); + this.rightCenter.setTo(this.x + this._width - 1, this.y + this._halfHeight, false); + + this.bottomLeft.setTo(this.x, this.y + this._height - 1, false); + this.bottomCenter.setTo(this.x + this._halfWidth, this.y + this._height - 1, false); + this.bottomRight.setTo(this.x + this._width - 1, this.y + this._height - 1, false); + + this._tempX = null; + this._tempY = null; + this._tempWidth = null; + this._tempHeight = null; + } - /** - * Returns a Point containing the location of the Rectangle's bottom-right corner, determined by the values of the right and bottom properties. - * @method bottomRight - * @return {Point} + /** + * The width of the rectangle + * @property width + * @type Number **/ - get bottomRight(): Point { + public set width(value: number) { - return new Point(this.right, this.bottom); + this._width = value; + this._halfWidth = Math.round(value / 2); + this.updateBounds(); } - /** - * Sets the bottom-right corner of this Rectangle, determined by the values of the given Point object. - * @method bottomRight - * @param {Point} value + /** + * The height of the rectangle + * @property height + * @type Number **/ - set bottomRight(value: Point) { + public set height(value: number) { - this.right = value.x; - this.bottom = value.y; + this._height = value; + this._halfHeight = Math.round(value / 2); + this.updateBounds(); + + } + + /** + * The width of the rectangle + * @property width + * @type Number + **/ + public get width(): number { + + return this._width; + + } + + /** + * The height of the rectangle + * @property height + * @type Number + **/ + public get height(): number { + + return this._height; + + } + + /** + * Half of the width of the rectangle + * @property halfWidth + * @type Number + **/ + public get halfWidth(): number { + + return this._halfWidth; + + } + + /** + * Half of the height of the rectangle + * @property halfHeight + * @type Number + **/ + public get halfHeight(): number { + + return this._halfHeight; } /** - * The x coordinate of the top-left corner of the rectangle. Changing the left property of a Rectangle object has no effect on the y and height properties. However it does affect the width property, whereas changing the x value does not affect the width property. + * The sum of the y and height properties. + * Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property. + * @method bottom + * @return {Number} + **/ + public get bottom(): number { + + return this.bottomCenter.y; + + } + + /** + * The sum of the y and height properties. + * Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property. + * @method bottom + * @param {Number} value + **/ + public set bottom(value: number) { + + if (value < this.y) + { + this._tempHeight = 0; + } + else + { + this._tempHeight = this.y + value; + } + + this.updateBounds(); + + } + + /** + * The x coordinate of the top-left corner of the rectangle. + * Changing the left property of a Rectangle object has no effect on the y and height properties. + * However it does affect the width property, whereas changing the x value does not affect the width property. * @method left * @ return {number} **/ - get left(): number { + public get left(): number { return this.x; } /** - * The x coordinate of the top-left corner of the rectangle. Changing the left property of a Rectangle object has no effect on the y and height properties. However it does affect the width property, whereas changing the x value does not affect the width property. + * The x coordinate of the top-left corner of the rectangle. + * Changing the left property of a Rectangle object has no effect on the y and height properties. + * However it does affect the width property, whereas changing the x value does not affect the width property. * @method left * @param {Number} value **/ - set left(value: number) { + public set left(value: number) { var diff = this.x - value; - if (this.width + diff < 0) + if (this._width + diff < 0) { - this.width = 0; - - this.x = value; + this._tempWidth = 0; + this._tempX = value; } else { - this.width += diff; - - this.x = value; + this._tempWidth = this._width + diff; + this._tempX = value; } + this.updateBounds(); + } /** - * The sum of the x and width properties. Changing the right property of a Rectangle object has no effect on the x, y and height properties. However it does affect the width property. + * The sum of the x and width properties. + * Changing the right property of a Rectangle object has no effect on the x, y and height properties. + * However it does affect the width property. * @method right * @return {Number} **/ - get right(): number { + public get right(): number { - return this.x + this.width; + return this.rightCenter.x; } /** - * The sum of the x and width properties. Changing the right property of a Rectangle object has no effect on the x, y and height properties. However it does affect the width property. + * The sum of the x and width properties. + * Changing the right property of a Rectangle object has no effect on the x, y and height properties. + * However it does affect the width property. * @method right * @param {Number} value **/ - set right(value: number) { + public set right(value: number) { - if (value < this.x) + if (value < this.topLeft.x) { - this.width = 0; - - return this.x; + this._tempWidth = 0; } else { - this.width = (value - this.x); + this._tempWidth = (value - this.topLeft.x); } + this.updateBounds(); + } /** @@ -190,9 +446,9 @@ module Phaser { * @param {Point} output Optional Point object. If given the values will be set into the object, otherwise a brand new Point object will be created and returned. * @return {Point} The size of the Rectangle object **/ - size(output?: Point = new Point): Point { + public size(output?: Point = new Point): Point { - return output.setTo(this.width, this.height); + return output.setTo(this._width, this._height); } @@ -201,9 +457,9 @@ module Phaser { * @method volume * @return {Number} **/ - get volume(): number { + public get volume(): number { - return this.width * this.height; + return this._width * this._height; } @@ -212,68 +468,48 @@ module Phaser { * @method perimeter * @return {Number} **/ - get perimeter(): number { + public get perimeter(): number { - return (this.width * 2) + (this.height * 2); + return (this._width * 2) + (this._height * 2); } /** - * The y coordinate of the top-left corner of the rectangle. Changing the top property of a Rectangle object has no effect on the x and width properties. However it does affect the height property, whereas changing the y value does not affect the height property. + * The y coordinate of the top-left corner of the rectangle. + * Changing the top property of a Rectangle object has no effect on the x and width properties. + * However it does affect the height property, whereas changing the y value does not affect the height property. * @method top * @return {Number} **/ - get top(): number { + public get top(): number { - return this.y; + return this.topCenter.y; } /** - * The y coordinate of the top-left corner of the rectangle. Changing the top property of a Rectangle object has no effect on the x and width properties. However it does affect the height property, whereas changing the y value does not affect the height property. + * The y coordinate of the top-left corner of the rectangle. + * Changing the top property of a Rectangle object has no effect on the x and width properties. + * However it does affect the height property, whereas changing the y value does not affect the height property. * @method top * @param {Number} value **/ - set top(value: number) { + public set top(value: number) { - var diff = this.y - value; + var diff = this.topCenter.y - value; - if (this.height + diff < 0) + if (this._height + diff < 0) { - this.height = 0; - - this.y = value; + this._tempHeight = 0; + this._tempY = value; } else { - this.height += diff; - - this.y = value; + this._tempHeight = this._height + diff; + this._tempY = value; } - - } - - /** - * The location of the Rectangle object's top-left corner, determined by the x and y coordinates of the point. - * @method topLeft - * @return {Point} - **/ - get topLeft(): Point { - - return new Point(this.x, this.y); - - } - - /** - * The location of the Rectangle object's top-left corner, determined by the x and y coordinates of the point. - * @method topLeft - * @param {Point} value - **/ - set topLeft(value: Point) { - - this.x = value.x; - this.y = value.y; + this.updateBounds(); } @@ -283,7 +519,7 @@ module Phaser { * @param {Rectangle} output Optional Rectangle object. If given the values will be set into the object, otherwise a brand new Rectangle object will be created and returned. * @return {Rectangle} **/ - clone(output?: Rectangle = new Rectangle): Rectangle { + public clone(output?: Rectangle = new Rectangle): Rectangle { return output.setTo(this.x, this.y, this.width, this.height); @@ -296,9 +532,9 @@ module Phaser { * @param {Number} y The y coordinate of the point to test. * @return {Boolean} A value of true if the Rectangle object contains the specified point; otherwise false. **/ - contains(x: number, y: number): bool { + public contains(x: number, y: number): bool { - if (x >= this.x && x <= this.right && y >= this.y && y <= this.bottom) + if (x >= this.topLeft.x && x <= this.topRight.x && y >= this.topLeft.y && y <= this.bottomRight.y) { return true; } @@ -308,24 +544,26 @@ module Phaser { } /** - * Determines whether the specified point is contained within the rectangular region defined by this Rectangle object. This method is similar to the Rectangle.contains() method, except that it takes a Point object as a parameter. + * Determines whether the specified point is contained within the rectangular region defined by this Rectangle object. + * This method is similar to the Rectangle.contains() method, except that it takes a Point object as a parameter. * @method containsPoint * @param {Point} point The point object being checked. Can be Point or any object with .x and .y values. * @return {Boolean} A value of true if the Rectangle object contains the specified point; otherwise false. **/ - containsPoint(point: Point): bool { + public containsPoint(point: any): bool { return this.contains(point.x, point.y); } /** - * Determines whether the Rectangle object specified by the rect parameter is contained within this Rectangle object. A Rectangle object is said to contain another if the second Rectangle object falls entirely within the boundaries of the first. + * Determines whether the Rectangle object specified by the rect parameter is contained within this Rectangle object. + * A Rectangle object is said to contain another if the second Rectangle object falls entirely within the boundaries of the first. * @method containsRect * @param {Rectangle} rect The rectangle object being checked. * @return {Boolean} A value of true if the Rectangle object contains the specified point; otherwise false. **/ - containsRect(rect: Rectangle): bool { + public containsRect(rect: Rectangle): bool { // If the given rect has a larger volume than this one then it can never contain it if (rect.volume > this.volume) @@ -333,7 +571,7 @@ module Phaser { return false; } - if (rect.x >= this.x && rect.y >= this.y && rect.right <= this.right && rect.bottom <= this.bottom) + if (rect.x >= this.topLeft.x && rect.y >= this.topLeft.y && rect.rightCenter.x <= this.rightCenter.x && rect.bottomCenter.y <= this.bottomCenter.y) { return true; } @@ -348,33 +586,35 @@ module Phaser { * @param {Rectangle} rect The source rectangle object to copy from * @return {Rectangle} This rectangle object **/ - copyFrom(source: Rectangle): Rectangle { + public copyFrom(source: Rectangle): Rectangle { return this.setTo(source.x, source.y, source.width, source.height); } + /** * Copies all the rectangle data from this Rectangle object into the destination Rectangle object. * @method copyTo * @param {Rectangle} rect The destination rectangle object to copy in to * @return {Rectangle} The destination rectangle object **/ - copyTo(target: Rectangle): Rectangle { + public copyTo(target: Rectangle): Rectangle { return target.copyFrom(this); } /** - * Determines whether the object specified in the toCompare parameter is equal to this Rectangle object. This method compares the x, y, width, and height properties of an object against the same properties of this Rectangle object. + * Determines whether the object specified in the toCompare parameter is equal to this Rectangle object. + * This method compares the x, y, width, and height properties of an object against the same properties of this Rectangle object. * @method equals * @param {Rectangle} toCompare The rectangle to compare to this Rectangle object. * @return {Boolean} A value of true if the object has exactly the same values for the x, y, width, and height properties as this Rectangle object; otherwise false. **/ - equals(toCompare: Rectangle): bool { + public equals(toCompare: Rectangle): bool { - if (this.x === toCompare.x && this.y === toCompare.y && this.width === toCompare.width && this.height === toCompare.height) + if (this.topLeft.equals(toCompare.topLeft) && this.bottomRight.equals(toCompare.bottomRight)) { return true; } @@ -384,54 +624,57 @@ module Phaser { } /** - * Increases the size of the Rectangle object by the specified amounts. The center point of the Rectangle object stays the same, and its size increases to the left and right by the dx value, and to the top and the bottom by the dy value. + * Increases the size of the Rectangle object by the specified amounts. + * The center point of the Rectangle object stays the same, and its size increases to the left and right by the dx value, + * and to the top and the bottom by the dy value. * @method inflate * @param {Number} dx The amount to be added to the left side of this Rectangle. * @param {Number} dy The amount to be added to the bottom side of this Rectangle. * @return {Rectangle} This Rectangle object. **/ - inflate(dx: number, dy: number): Rectangle { + public inflate(dx: number, dy: number): Rectangle { - if (!isNaN(dx) && !isNaN(dy)) - { - this.x -= dx; - this.width += 2 * dx; + this._tempX = this.topLeft.x - dx; + this._tempWidth = this._width + (2 * dx); + this._tempY = this.topLeft.y - dy; + this._tempHeight = this._height + (2 * dy); - this.y -= dy; - this.height += 2 * dy; - } + this.updateBounds(); return this; } /** - * Increases the size of the Rectangle object. This method is similar to the Rectangle.inflate() method except it takes a Point object as a parameter. + * Increases the size of the Rectangle object. + * This method is similar to the Rectangle.inflate() method except it takes a Point object as a parameter. * @method inflatePoint * @param {Point} point The x property of this Point object is used to increase the horizontal dimension of the Rectangle object. The y property is used to increase the vertical dimension of the Rectangle object. * @return {Rectangle} This Rectangle object. **/ - inflatePoint(point: Point): Rectangle { + public inflatePoint(point: Point): Rectangle { return this.inflate(point.x, point.y); } /** - * If the Rectangle object specified in the toIntersect parameter intersects with this Rectangle object, returns the area of intersection as a Rectangle object. If the rectangles do not intersect, this method returns an empty Rectangle object with its properties set to 0. + * If the Rectangle object specified in the toIntersect parameter intersects with this Rectangle object, + * returns the area of intersection as a Rectangle object. If the rectangles do not intersect, this method + * returns an empty Rectangle object with its properties set to 0. * @method intersection * @param {Rectangle} toIntersect The Rectangle object to compare against to see if it intersects with this Rectangle object. * @param {Rectangle} output Optional Rectangle object. If given the intersection values will be set into this object, otherwise a brand new Rectangle object will be created and returned. * @return {Rectangle} A Rectangle object that equals the area of intersection. If the rectangles do not intersect, this method returns an empty Rectangle object; that is, a rectangle with its x, y, width, and height properties set to 0. **/ - intersection(toIntersect: Rectangle, output?: Rectangle = new Rectangle): Rectangle { + public intersection(toIntersect: Rectangle, output?: Rectangle = new Rectangle): Rectangle { if (this.intersects(toIntersect) === true) { - output.x = Math.max(toIntersect.x, this.x); - output.y = Math.max(toIntersect.y, this.y); - output.width = Math.min(toIntersect.right, this.right) - output.x; - output.height = Math.min(toIntersect.bottom, this.bottom) - output.y; + output.x = Math.max(toIntersect.topLeft.x, this.topLeft.x); + output.y = Math.max(toIntersect.topLeft.y, this.topLeft.y); + output.width = Math.min(toIntersect.rightCenter.x, this.rightCenter.x) - output.x; + output.height = Math.min(toIntersect.bottomCenter.y, this.bottomCenter.y) - output.y; } return output; @@ -439,45 +682,16 @@ module Phaser { } /** - * Determines whether the object specified in the toIntersect parameter intersects with this Rectangle object. This method checks the x, y, width, and height properties of the specified Rectangle object to see if it intersects with this Rectangle object. + * Determines whether the object specified intersects (overlaps) with this Rectangle object. + * This method checks the x, y, width, and height properties of the specified Rectangle object to see if it intersects with this Rectangle object. * @method intersects - * @param {Rectangle} toIntersect The Rectangle object to compare against to see if it intersects with this Rectangle object. + * @param {Rectangle} r2 The Rectangle object to compare against to see if it intersects with this Rectangle object. + * @param {Number} t A tolerance value to allow for an intersection test with padding, default to 0 * @return {Boolean} A value of true if the specified object intersects with this Rectangle object; otherwise false. **/ - intersects(toIntersect: Rectangle): bool { + public intersects(r2: Rectangle, t?: number = 0): bool { - if (toIntersect.x >= this.right) - { - return false; - } - - if (toIntersect.right <= this.x) - { - return false; - } - - if (toIntersect.bottom <= this.y) - { - return false; - } - - if (toIntersect.y >= this.bottom) - { - return false; - } - - return true; - - } - - /** - * Checks for overlaps between this Rectangle and the given Rectangle. Returns an object with boolean values for each check. - * @method overlap - * @return {Boolean} true if the rectangles overlap, otherwise false - **/ - overlap(rect: Rectangle): bool { - - return (rect.x + rect.width > this.x) && (rect.x < this.x + this.width) && (rect.y + rect.height > this.y) && (rect.y < this.y + this.height); + return !(r2.left > this.right + t || r2.right < this.left - t || r2.top > this.bottom + t || r2.bottom < this.top - t); } @@ -486,7 +700,7 @@ module Phaser { * @method isEmpty * @return {Boolean} A value of true if the Rectangle object's width or height is less than or equal to 0; otherwise false. **/ - get isEmpty(): bool { + public get isEmpty(): bool { if (this.width < 1 || this.height < 1) { @@ -504,7 +718,7 @@ module Phaser { * @param {Number} dy Moves the y value of the Rectangle object by this amount. * @return {Rectangle} This Rectangle object. **/ - offset(dx: number, dy: number): Rectangle { + public offset(dx: number, dy: number): Rectangle { if (!isNaN(dx) && !isNaN(dy)) { @@ -522,7 +736,7 @@ module Phaser { * @param {Point} point A Point object to use to offset this Rectangle object. * @return {Rectangle} This Rectangle object. **/ - offsetPoint(point: Point): Rectangle { + public offsetPoint(point: Point): Rectangle { return this.offset(point.x, point.y); @@ -533,7 +747,7 @@ module Phaser { * @method setEmpty * @return {Rectangle} This rectangle object **/ - setEmpty() { + public setEmpty() { return this.setTo(0, 0, 0, 0); @@ -548,24 +762,14 @@ module Phaser { * @param {Number} height The height of the rectangle in pixels. * @return {Rectangle} This rectangle object **/ - setTo(x: number, y: number, width: number, height: number): Rectangle { + public setTo(x: number, y: number, width: number, height: number): Rectangle { - if (!isNaN(x) && !isNaN(y) && !isNaN(width) && !isNaN(height)) - { - this.x = x; - this.y = y; + this._tempX = x; + this._tempY = y; + this._tempWidth = width; + this._tempHeight = height; - if (width > 0) - { - this.width = width; - } - - if (height > 0) - { - this.height = height; - } - - } + this.updateBounds(); return this; @@ -578,7 +782,7 @@ module Phaser { * @param {Rectangle} output Optional Rectangle object. If given the new values will be set into this object, otherwise a brand new Rectangle object will be created and returned. * @return {Rectangle} A Rectangle object that is the union of the two rectangles. **/ - union(toUnion: Rectangle, output?: Rectangle = new Rectangle): Rectangle { + public union(toUnion: Rectangle, output?: Rectangle = new Rectangle): Rectangle { return output.setTo( Math.min(toUnion.x, this.x), @@ -594,7 +798,7 @@ module Phaser { * @method toString * @return {string} a string representation of the instance. **/ - toString(): string { + public toString(): string { return "[{Rectangle (x=" + this.x + " y=" + this.y + " width=" + this.width + " height=" + this.height + " empty=" + this.isEmpty + ")}]"; diff --git a/Phaser/phaser.js b/Phaser/phaser.js index 3896e52f..c2b15df5 100644 --- a/Phaser/phaser.js +++ b/Phaser/phaser.js @@ -1,7 +1,7 @@ /** * Phaser * -* v0.9 - April 18th 2013 +* v0.9.1 - April 19th 2013 * * A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi. * @@ -15,5 +15,5 @@ */ var Phaser; (function (Phaser) { - Phaser.VERSION = 'Phaser version 0.9'; + Phaser.VERSION = 'Phaser version 0.9.1'; })(Phaser || (Phaser = {})); diff --git a/Phaser/system/input/Input.ts b/Phaser/system/input/Input.ts index 9288df1b..f27c4719 100644 --- a/Phaser/system/input/Input.ts +++ b/Phaser/system/input/Input.ts @@ -19,6 +19,9 @@ module Phaser { this.keyboard = new Keyboard(this._game); this.touch = new Touch(this._game); + this.onDown = new Phaser.Signal(); + this.onUp = new Phaser.Signal(); + } private _game: Game; @@ -36,6 +39,9 @@ module Phaser { public worldX: number = 0; public worldY: number = 0; + public onDown: Phaser.Signal; + public onUp: Phaser.Signal; + public update() { this.x = Math.round(this.x); diff --git a/Phaser/system/input/Mouse.ts b/Phaser/system/input/Mouse.ts index 4918676f..e25eff5e 100644 --- a/Phaser/system/input/Mouse.ts +++ b/Phaser/system/input/Mouse.ts @@ -63,6 +63,8 @@ module Phaser { 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() { @@ -103,6 +105,8 @@ module Phaser { 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); + } } diff --git a/Phaser/system/input/Touch.ts b/Phaser/system/input/Touch.ts index ccad9bb9..45d876c3 100644 --- a/Phaser/system/input/Touch.ts +++ b/Phaser/system/input/Touch.ts @@ -229,6 +229,7 @@ module Phaser { this._game.input.x = this.x * this._game.input.scaleX; this._game.input.y = this.y * this._game.input.scaleY; this.touchDown.dispatch(this._fingers[f].x, this._fingers[f].y, this._fingers[f].timeDown, this._fingers[f].timeUp, this._fingers[f].duration); + this._game.input.onDown.dispatch(this._game.input.x, this._game.input.y, this._fingers[f].timeDown); this.isDown = true; this.isUp = false; break; @@ -373,6 +374,7 @@ module Phaser { this._game.input.x = this.x * this._game.input.scaleX; this._game.input.y = this.y * this._game.input.scaleY; this.touchUp.dispatch(this._fingers[f].x, this._fingers[f].y, this._fingers[f].timeDown, this._fingers[f].timeUp, this._fingers[f].duration); + this._game.input.onUp.dispatch(this._game.input.x, this._game.input.y, this._fingers[f].timeUp); this.isDown = false; this.isUp = true; break; diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 9b67de0a..565a1c6b 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -100,6 +100,10 @@ screen grab.ts + + + align.ts + bounce.ts diff --git a/Tests/geometry/rect vs rect.js b/Tests/geometry/rect vs rect.js index 749d18a6..b4543889 100644 --- a/Tests/geometry/rect vs rect.js +++ b/Tests/geometry/rect vs rect.js @@ -15,4 +15,8 @@ box1.fillColor = 'rgb(0,255,0)'; } } + function checkPoints() { + if(box2.rect.containsPoint(box1.rect.topLeft)) { + } + } })(); diff --git a/Tests/geometry/rect vs rect.ts b/Tests/geometry/rect vs rect.ts index f7f19d20..6c7ba5a4 100644 --- a/Tests/geometry/rect vs rect.ts +++ b/Tests/geometry/rect vs rect.ts @@ -29,4 +29,13 @@ } + function checkPoints() { + + if (box2.rect.containsPoint(box1.rect.topLeft)) + { + + } + + } + })(); diff --git a/Tests/geometry/rectangle.js b/Tests/geometry/rectangle.js index 707800dc..604e3573 100644 --- a/Tests/geometry/rectangle.js +++ b/Tests/geometry/rectangle.js @@ -3,21 +3,22 @@ var myGame = new Phaser.Game(this, 'game', 800, 600, null, create, update); var box; function create() { - box = myGame.createGeomSprite(200, 200); + box = myGame.createGeomSprite(0, 0); box.createRectangle(64, 64); + box.renderOutline = false; } function update() { box.velocity.x = 0; box.velocity.y = 0; - box.angularVelocity = 0; - box.angularAcceleration = 0; if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { - box.angularVelocity = -200; + box.velocity.x = -200; } else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { - box.angularVelocity = 200; + box.velocity.x = 200; } if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) { - box.velocity.copyFrom(myGame.motion.velocityFromAngle(box.angle, 200)); + box.velocity.y = -200; + } else if(myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN)) { + box.velocity.y = 200; } } })(); diff --git a/Tests/geometry/rectangle.ts b/Tests/geometry/rectangle.ts index c64fde8b..f91d832f 100644 --- a/Tests/geometry/rectangle.ts +++ b/Tests/geometry/rectangle.ts @@ -8,9 +8,10 @@ function create() { - box = myGame.createGeomSprite(200, 200); + box = myGame.createGeomSprite(0, 0); box.createRectangle(64, 64); + box.renderOutline = false; } @@ -18,21 +19,23 @@ box.velocity.x = 0; box.velocity.y = 0; - box.angularVelocity = 0; - box.angularAcceleration = 0; if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { - box.angularVelocity = -200; + box.velocity.x = -200; } else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { - box.angularVelocity = 200; + box.velocity.x = 200; } if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) { - box.velocity.copyFrom(myGame.motion.velocityFromAngle(box.angle, 200)); + box.velocity.y = -200; + } + else if (myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN)) + { + box.velocity.y = 200; } } diff --git a/Tests/phaser.js b/Tests/phaser.js index d2f8b662..df4d6aa0 100644 --- a/Tests/phaser.js +++ b/Tests/phaser.js @@ -478,9 +478,10 @@ var Phaser; this.alive = true; this.isGroup = false; this.alpha = 1; - this.scale = new Phaser.Point(1, 1); - this.last = new Phaser.Point(x, y); - this.origin = new Phaser.Point(this.bounds.halfWidth, this.bounds.halfHeight); + this.scale = new Phaser.MicroPoint(1, 1); + this.last = new Phaser.MicroPoint(x, y); + this.origin = new Phaser.MicroPoint(this.bounds.halfWidth, this.bounds.halfHeight); + this.align = GameObject.ALIGN_TOP_LEFT; this.mass = 1.0; this.elasticity = 0.0; this.health = 1; @@ -489,17 +490,26 @@ var Phaser; this.touching = Phaser.Collision.NONE; this.wasTouching = Phaser.Collision.NONE; this.allowCollisions = Phaser.Collision.ANY; - this.velocity = new Phaser.Point(); - this.acceleration = new Phaser.Point(); - this.drag = new Phaser.Point(); - this.maxVelocity = new Phaser.Point(10000, 10000); + this.velocity = new Phaser.MicroPoint(); + this.acceleration = new Phaser.MicroPoint(); + this.drag = new Phaser.MicroPoint(); + this.maxVelocity = new Phaser.MicroPoint(10000, 10000); this.angle = 0; this.angularVelocity = 0; this.angularAcceleration = 0; this.angularDrag = 0; this.maxAngular = 10000; - this.scrollFactor = new Phaser.Point(1.0, 1.0); + this.scrollFactor = new Phaser.MicroPoint(1.0, 1.0); } + GameObject.ALIGN_TOP_LEFT = 0; + GameObject.ALIGN_TOP_CENTER = 1; + GameObject.ALIGN_TOP_RIGHT = 2; + GameObject.ALIGN_CENTER_LEFT = 3; + GameObject.ALIGN_CENTER = 4; + GameObject.ALIGN_CENTER_RIGHT = 5; + GameObject.ALIGN_BOTTOM_LEFT = 6; + GameObject.ALIGN_BOTTOM_CENTER = 7; + GameObject.ALIGN_BOTTOM_RIGHT = 8; GameObject.prototype.preUpdate = function () { // flicker time this.last.x = this.bounds.x; @@ -583,7 +593,7 @@ var Phaser; }; GameObject.prototype.overlapsAt = /** * Checks to see if this GameObject were located at the given position, would it overlap the GameObject or Group? - * This is distinct from overlapsPoint(), which just checks that ponumber, rather than taking the object's size numbero account. + * This is distinct from overlapsPoint(), which just checks that point, rather than taking the object's size numbero account. * WARNING: Currently tilemaps do NOT support screen space overlap checks! * * @param X The X position you want to check. Pretends this object (the caller, not the parameter) is located here. @@ -636,13 +646,13 @@ var Phaser; return (objectScreenPos.x + ObjectOrGroup.width > this._point.x) && (objectScreenPos.x < this._point.x + this.width) && (objectScreenPos.y + ObjectOrGroup.height > this._point.y) && (objectScreenPos.y < this._point.y + this.height); }; GameObject.prototype.overlapsPoint = /** - * Checks to see if a ponumber in 2D world space overlaps this GameObject object. + * Checks to see if a point in 2D world space overlaps this GameObject. * - * @param Point The ponumber in world space you want to check. + * @param Point The point in world space you want to check. * @param InScreenSpace Whether to take scroll factors numbero account when checking for overlap. * @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera. * - * @return Whether or not the ponumber overlaps this object. + * @return Whether or not the point overlaps this object. */ function (point, InScreenSpace, Camera) { if (typeof InScreenSpace === "undefined") { InScreenSpace = false; } @@ -661,7 +671,7 @@ var Phaser; GameObject.prototype.onScreen = /** * Check and see if this object is currently on screen. * - * @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera. + * @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera. * * @return Whether the object is on screen or not. */ @@ -677,15 +687,15 @@ var Phaser; * Call this to figure out the on-screen position of the object. * * @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera. - * @param Point Takes a Point object and assigns the post-scrolled X and Y values of this object to it. + * @param Point Takes a MicroPoint object and assigns the post-scrolled X and Y values of this object to it. * - * @return The Point you passed in, or a new Point if you didn't pass one, containing the screen X and Y position of this object. + * @return The MicroPoint you passed in, or a new Point if you didn't pass one, containing the screen X and Y position of this object. */ function (point, Camera) { if (typeof point === "undefined") { point = null; } if (typeof Camera === "undefined") { Camera = null; } if(point == null) { - point = new Phaser.Point(); + point = new Phaser.MicroPoint(); } if(Camera == null) { Camera = this._game.camera; @@ -719,19 +729,18 @@ var Phaser; configurable: true }); GameObject.prototype.getMidpoint = /** - * Retrieve the midponumber of this object in world coordinates. + * Retrieve the midpoint of this object in world coordinates. * * @Point Allows you to pass in an existing Point object if you're so inclined. Otherwise a new one is created. * - * @return A Point object containing the midponumber of this object in world coordinates. + * @return A Point object containing the midpoint of this object in world coordinates. */ function (point) { if (typeof point === "undefined") { point = null; } if(point == null) { - point = new Phaser.Point(); + point = new Phaser.MicroPoint(); } - point.x = this.x + this.width * 0.5; - point.y = this.y + this.height * 0.5; + point.copyFrom(this.bounds.center); return point; }; GameObject.prototype.reset = /** @@ -874,6 +883,9 @@ var Phaser; this._dy = 0; this._dw = 0; this._dh = 0; + this.renderDebug = false; + this.renderDebugColor = 'rgba(0,255,0,0.5)'; + this.renderDebugPointColor = 'rgba(255,255,255,1)'; this._texture = null; this.animations = new Phaser.AnimationManager(this._game, this); if(key !== null) { @@ -920,7 +932,7 @@ var Phaser; this._dh = this.bounds.height * this.scale.y; return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh); } else { - return camera.overlap(this.bounds); + return camera.intersects(this.bounds, this.bounds.length); } }; Sprite.prototype.postUpdate = function () { @@ -967,10 +979,31 @@ var Phaser; this._sy = 0; this._sw = this.bounds.width; this._sh = this.bounds.height; - this._dx = cameraOffsetX + (this.bounds.x - camera.worldView.x); - this._dy = cameraOffsetY + (this.bounds.y - camera.worldView.y); + this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x); + this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y); this._dw = this.bounds.width * this.scale.x; this._dh = this.bounds.height * this.scale.y; + if(this.align == Phaser.GameObject.ALIGN_TOP_CENTER) { + this._dx -= this.bounds.halfWidth * this.scale.x; + } else if(this.align == Phaser.GameObject.ALIGN_TOP_RIGHT) { + this._dx -= this.bounds.width * this.scale.x; + } else if(this.align == Phaser.GameObject.ALIGN_CENTER_LEFT) { + this._dy -= this.bounds.halfHeight * this.scale.y; + } else if(this.align == Phaser.GameObject.ALIGN_CENTER) { + this._dx -= this.bounds.halfWidth * this.scale.x; + this._dy -= this.bounds.halfHeight * this.scale.y; + } else if(this.align == Phaser.GameObject.ALIGN_CENTER_RIGHT) { + this._dx -= this.bounds.width * this.scale.x; + this._dy -= this.bounds.halfHeight * this.scale.y; + } else if(this.align == Phaser.GameObject.ALIGN_BOTTOM_LEFT) { + this._dy -= this.bounds.height * this.scale.y; + } else if(this.align == Phaser.GameObject.ALIGN_BOTTOM_CENTER) { + this._dx -= this.bounds.halfWidth * this.scale.x; + this._dy -= this.bounds.height * this.scale.y; + } else if(this.align == Phaser.GameObject.ALIGN_BOTTOM_RIGHT) { + this._dx -= this.bounds.width * this.scale.x; + this._dy -= this.bounds.height * this.scale.y; + } if(this._dynamicTexture == false && this.animations.currentFrame !== null) { this._sx = this.animations.currentFrame.x; this._sy = this.animations.currentFrame.y; @@ -1001,9 +1034,6 @@ var Phaser; this._dy = Math.round(this._dy); this._dw = Math.round(this._dw); this._dh = Math.round(this._dh); - // Debug test - //this._game.stage.context.fillStyle = 'rgba(255,0,0,0.3)'; - //this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh); if(this._texture != null) { if(this._dynamicTexture) { this._game.stage.context.drawImage(this._texture.canvas, // Source Image @@ -1032,6 +1062,9 @@ var Phaser; this._game.stage.context.fillStyle = 'rgb(255,255,255)'; this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh); } + if(this.renderDebug) { + this.renderBounds(); + } //if (this.flip === true || this.rotation !== 0) if(this.rotation !== 0) { this._game.stage.context.translate(0, 0); @@ -1042,6 +1075,33 @@ var Phaser; } return true; }; + Sprite.prototype.renderBounds = function () { + this._game.stage.context.fillStyle = this.renderDebugColor; + this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh); + this._game.stage.context.fillStyle = this.renderDebugPointColor; + var hw = this.bounds.halfWidth * this.scale.x; + var hh = this.bounds.halfHeight * this.scale.y; + var sw = (this.bounds.width * this.scale.x) - 1; + var sh = (this.bounds.height * this.scale.y) - 1; + this._game.stage.context.fillRect(this._dx, this._dy, 1, 1)// top left + ; + this._game.stage.context.fillRect(this._dx + hw, this._dy, 1, 1)// top center + ; + this._game.stage.context.fillRect(this._dx + sw, this._dy, 1, 1)// top right + ; + this._game.stage.context.fillRect(this._dx, this._dy + hh, 1, 1)// left center + ; + this._game.stage.context.fillRect(this._dx + hw, this._dy + hh, 1, 1)// center + ; + this._game.stage.context.fillRect(this._dx + sw, this._dy + hh, 1, 1)// right center + ; + this._game.stage.context.fillRect(this._dx, this._dy + sh, 1, 1)// bottom left + ; + this._game.stage.context.fillRect(this._dx + hw, this._dy + sh, 1, 1)// bottom center + ; + this._game.stage.context.fillRect(this._dx + sw, this._dy + sh, 1, 1)// bottom right + ; + }; Sprite.prototype.renderDebugInfo = function (x, y, color) { if (typeof color === "undefined") { color = 'rgb(255,255,255)'; } this._game.stage.context.fillStyle = color; @@ -2182,8 +2242,8 @@ var Phaser; * Creates a new point. If you pass no parameters to this method, a point is created at (0,0). * @class Point * @constructor - * @param {Number} x One-liner. Default is ?. - * @param {Number} y One-liner. Default is ?. + * @param {Number} x The horizontal position of this point (default 0) + * @param {Number} y The vertical position of this point (default 0) **/ function Point(x, y) { if (typeof x === "undefined") { x = 0; } @@ -2393,7 +2453,7 @@ var Phaser; }; Point.prototype.setTo = /** * Sets the x and y values of this Point object to the given coordinates. - * @method set + * @method setTo * @param {Number} x - The horizontal position of this point. * @param {Number} y - The vertical position of this point. * @return {Point} This Point object. Useful for chaining method calls. @@ -2427,6 +2487,7 @@ var Phaser; Phaser.Point = Point; })(Phaser || (Phaser = {})); /// +/// /** * Phaser - Rectangle * @@ -2450,94 +2511,241 @@ var Phaser; if (typeof y === "undefined") { y = 0; } if (typeof width === "undefined") { width = 0; } if (typeof height === "undefined") { height = 0; } + this._tempX = null; + this._tempY = null; + this._tempWidth = null; + this._tempHeight = null; /** + * The width of the rectangle + * @property width + * @type Number + **/ + this._width = 0; + /** + * The height of the rectangle + * @property height + * @type Number + **/ + this._height = 0; + /** + * Half of the width of the rectangle + * @property halfWidth + * @type Number + **/ + this._halfWidth = 0; + /** + * Half of the height of the rectangle + * @property halfHeight + * @type Number + **/ + this._halfHeight = 0; + /** + * The size of the longest side (width or height) + * @property length + * @type Number + **/ + this.length = 0; + this._width = width; + if(width > 0) { + this._halfWidth = Math.round(width / 2); + } + this._height = height; + if(height > 0) { + this._halfHeight = Math.round(height / 2); + } + this.length = Math.max(this._width, this._height); + this.topLeft = new Phaser.MicroPoint(x, y, this); + this.topCenter = new Phaser.MicroPoint(x + this._halfWidth, y, this); + this.topRight = new Phaser.MicroPoint(x + this._width - 1, y, this); + this.leftCenter = new Phaser.MicroPoint(x, y + this._halfHeight, this); + this.center = new Phaser.MicroPoint(x + this._halfWidth, y + this._halfHeight, this); + this.rightCenter = new Phaser.MicroPoint(x + this._width - 1, y + this._halfHeight, this); + this.bottomLeft = new Phaser.MicroPoint(x, y + this._height - 1, this); + this.bottomCenter = new Phaser.MicroPoint(x + this._halfWidth, y + this._height - 1, this); + this.bottomRight = new Phaser.MicroPoint(x + this._width - 1, y + this._height - 1, this); + } + Object.defineProperty(Rectangle.prototype, "x", { + get: /** * The x coordinate of the top-left corner of the rectangle * @property x * @type Number **/ - this.x = 0; - /** + function () { + return this.topLeft.x; + }, + set: /** + * The x coordinate of the top-left corner of the rectangle + * @property x + * @type Number + **/ + function (value) { + this.topLeft.x = value; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Rectangle.prototype, "y", { + get: /** * The y coordinate of the top-left corner of the rectangle * @property y * @type Number **/ - this.y = 0; - /** - * The width of the rectangle in pixels + function () { + return this.topLeft.y; + }, + set: /** + * The y coordinate of the top-left corner of the rectangle + * @property y + * @type Number + **/ + function (value) { + this.topLeft.y = value; + }, + enumerable: true, + configurable: true + }); + Rectangle.prototype.updateBounds = /** + * Updates all of the MicroPoints based on the values of width and height. + * You should not normally call this directly. + **/ + function () { + if(this._tempWidth !== null) { + this._width = this._tempWidth; + this._halfWidth = 0; + if(this._width > 0) { + this._halfWidth = Math.round(this._width / 2); + } + } + if(this._tempHeight !== null) { + this._height = this._tempHeight; + this._halfHeight = 0; + if(this._height > 0) { + this._halfHeight = Math.round(this._height / 2); + } + } + this.length = Math.max(this._width, this._height); + if(this._tempX !== null && this._tempY !== null) { + this.topLeft.setTo(this._tempX, this._tempY, false); + } else if(this._tempX !== null && this._tempY == null) { + this.topLeft.setTo(this._tempX, this.topLeft.y, false); + } else if(this._tempX == null && this._tempY !== null) { + this.topLeft.setTo(this.topLeft.x, this._tempY, false); + } else { + this.topLeft.setTo(this.x, this.y, false); + } + this.topCenter.setTo(this.x + this._halfWidth, this.y, false); + this.topRight.setTo(this.x + this._width - 1, this.y, false); + this.leftCenter.setTo(this.x, this.y + this._halfHeight, false); + this.center.setTo(this.x + this._halfWidth, this.y + this._halfHeight, false); + this.rightCenter.setTo(this.x + this._width - 1, this.y + this._halfHeight, false); + this.bottomLeft.setTo(this.x, this.y + this._height - 1, false); + this.bottomCenter.setTo(this.x + this._halfWidth, this.y + this._height - 1, false); + this.bottomRight.setTo(this.x + this._width - 1, this.y + this._height - 1, false); + this._tempX = null; + this._tempY = null; + this._tempWidth = null; + this._tempHeight = null; + }; + Object.defineProperty(Rectangle.prototype, "width", { + get: /** + * The width of the rectangle * @property width * @type Number **/ - this.width = 0; - /** - * The height of the rectangle in pixels + function () { + return this._width; + }, + set: /** + * The width of the rectangle + * @property width + * @type Number + **/ + function (value) { + this._width = value; + this._halfWidth = Math.round(value / 2); + this.updateBounds(); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Rectangle.prototype, "height", { + get: /** + * The height of the rectangle * @property height * @type Number **/ - this.height = 0; - this.setTo(x, y, width, height); - } + function () { + return this._height; + }, + set: /** + * The height of the rectangle + * @property height + * @type Number + **/ + function (value) { + this._height = value; + this._halfHeight = Math.round(value / 2); + this.updateBounds(); + }, + enumerable: true, + configurable: true + }); Object.defineProperty(Rectangle.prototype, "halfWidth", { - get: function () { - return Math.round(this.width / 2); + get: /** + * Half of the width of the rectangle + * @property halfWidth + * @type Number + **/ + function () { + return this._halfWidth; }, enumerable: true, configurable: true }); Object.defineProperty(Rectangle.prototype, "halfHeight", { - get: function () { - return Math.round(this.height / 2); + get: /** + * Half of the height of the rectangle + * @property halfHeight + * @type Number + **/ + function () { + return this._halfHeight; }, enumerable: true, configurable: true }); Object.defineProperty(Rectangle.prototype, "bottom", { get: /** - * The sum of the y and height properties. Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property. + * The sum of the y and height properties. + * Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property. * @method bottom * @return {Number} **/ function () { - return this.y + this.height; + return this.bottomCenter.y; }, set: /** - * The sum of the y and height properties. Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property. + * The sum of the y and height properties. + * Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property. * @method bottom * @param {Number} value **/ function (value) { if(value < this.y) { - this.height = 0; + this._tempHeight = 0; } else { - this.height = this.y + value; + this._tempHeight = this.y + value; } - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Rectangle.prototype, "bottomRight", { - get: /** - * Returns a Point containing the location of the Rectangle's bottom-right corner, determined by the values of the right and bottom properties. - * @method bottomRight - * @return {Point} - **/ - function () { - return new Phaser.Point(this.right, this.bottom); - }, - set: /** - * Sets the bottom-right corner of this Rectangle, determined by the values of the given Point object. - * @method bottomRight - * @param {Point} value - **/ - function (value) { - this.right = value.x; - this.bottom = value.y; + this.updateBounds(); }, enumerable: true, configurable: true }); Object.defineProperty(Rectangle.prototype, "left", { get: /** - * The x coordinate of the top-left corner of the rectangle. Changing the left property of a Rectangle object has no effect on the y and height properties. However it does affect the width property, whereas changing the x value does not affect the width property. + * The x coordinate of the top-left corner of the rectangle. + * Changing the left property of a Rectangle object has no effect on the y and height properties. + * However it does affect the width property, whereas changing the x value does not affect the width property. * @method left * @ return {number} **/ @@ -2545,44 +2753,51 @@ var Phaser; return this.x; }, set: /** - * The x coordinate of the top-left corner of the rectangle. Changing the left property of a Rectangle object has no effect on the y and height properties. However it does affect the width property, whereas changing the x value does not affect the width property. + * The x coordinate of the top-left corner of the rectangle. + * Changing the left property of a Rectangle object has no effect on the y and height properties. + * However it does affect the width property, whereas changing the x value does not affect the width property. * @method left * @param {Number} value **/ function (value) { var diff = this.x - value; - if(this.width + diff < 0) { - this.width = 0; - this.x = value; + if(this._width + diff < 0) { + this._tempWidth = 0; + this._tempX = value; } else { - this.width += diff; - this.x = value; + this._tempWidth = this._width + diff; + this._tempX = value; } + this.updateBounds(); }, enumerable: true, configurable: true }); Object.defineProperty(Rectangle.prototype, "right", { get: /** - * The sum of the x and width properties. Changing the right property of a Rectangle object has no effect on the x, y and height properties. However it does affect the width property. + * The sum of the x and width properties. + * Changing the right property of a Rectangle object has no effect on the x, y and height properties. + * However it does affect the width property. * @method right * @return {Number} **/ function () { - return this.x + this.width; + return this.rightCenter.x; }, set: /** - * The sum of the x and width properties. Changing the right property of a Rectangle object has no effect on the x, y and height properties. However it does affect the width property. + * The sum of the x and width properties. + * Changing the right property of a Rectangle object has no effect on the x, y and height properties. + * However it does affect the width property. * @method right * @param {Number} value **/ function (value) { - if(value < this.x) { - this.width = 0; - return this.x; + if(value < this.topLeft.x) { + this._tempWidth = 0; } else { - this.width = (value - this.x); + this._tempWidth = (value - this.topLeft.x); } + this.updateBounds(); }, enumerable: true, configurable: true @@ -2595,7 +2810,7 @@ var Phaser; **/ function (output) { if (typeof output === "undefined") { output = new Phaser.Point(); } - return output.setTo(this.width, this.height); + return output.setTo(this._width, this._height); }; Object.defineProperty(Rectangle.prototype, "volume", { get: /** @@ -2604,7 +2819,7 @@ var Phaser; * @return {Number} **/ function () { - return this.width * this.height; + return this._width * this._height; }, enumerable: true, configurable: true @@ -2616,55 +2831,39 @@ var Phaser; * @return {Number} **/ function () { - return (this.width * 2) + (this.height * 2); + return (this._width * 2) + (this._height * 2); }, enumerable: true, configurable: true }); Object.defineProperty(Rectangle.prototype, "top", { get: /** - * The y coordinate of the top-left corner of the rectangle. Changing the top property of a Rectangle object has no effect on the x and width properties. However it does affect the height property, whereas changing the y value does not affect the height property. + * The y coordinate of the top-left corner of the rectangle. + * Changing the top property of a Rectangle object has no effect on the x and width properties. + * However it does affect the height property, whereas changing the y value does not affect the height property. * @method top * @return {Number} **/ function () { - return this.y; + return this.topCenter.y; }, set: /** - * The y coordinate of the top-left corner of the rectangle. Changing the top property of a Rectangle object has no effect on the x and width properties. However it does affect the height property, whereas changing the y value does not affect the height property. + * The y coordinate of the top-left corner of the rectangle. + * Changing the top property of a Rectangle object has no effect on the x and width properties. + * However it does affect the height property, whereas changing the y value does not affect the height property. * @method top * @param {Number} value **/ function (value) { - var diff = this.y - value; - if(this.height + diff < 0) { - this.height = 0; - this.y = value; + var diff = this.topCenter.y - value; + if(this._height + diff < 0) { + this._tempHeight = 0; + this._tempY = value; } else { - this.height += diff; - this.y = value; + this._tempHeight = this._height + diff; + this._tempY = value; } - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Rectangle.prototype, "topLeft", { - get: /** - * The location of the Rectangle object's top-left corner, determined by the x and y coordinates of the point. - * @method topLeft - * @return {Point} - **/ - function () { - return new Phaser.Point(this.x, this.y); - }, - set: /** - * The location of the Rectangle object's top-left corner, determined by the x and y coordinates of the point. - * @method topLeft - * @param {Point} value - **/ - function (value) { - this.x = value.x; - this.y = value.y; + this.updateBounds(); }, enumerable: true, configurable: true @@ -2687,13 +2886,14 @@ var Phaser; * @return {Boolean} A value of true if the Rectangle object contains the specified point; otherwise false. **/ function (x, y) { - if(x >= this.x && x <= this.right && y >= this.y && y <= this.bottom) { + if(x >= this.topLeft.x && x <= this.topRight.x && y >= this.topLeft.y && y <= this.bottomRight.y) { return true; } return false; }; Rectangle.prototype.containsPoint = /** - * Determines whether the specified point is contained within the rectangular region defined by this Rectangle object. This method is similar to the Rectangle.contains() method, except that it takes a Point object as a parameter. + * Determines whether the specified point is contained within the rectangular region defined by this Rectangle object. + * This method is similar to the Rectangle.contains() method, except that it takes a Point object as a parameter. * @method containsPoint * @param {Point} point The point object being checked. Can be Point or any object with .x and .y values. * @return {Boolean} A value of true if the Rectangle object contains the specified point; otherwise false. @@ -2702,7 +2902,8 @@ var Phaser; return this.contains(point.x, point.y); }; Rectangle.prototype.containsRect = /** - * Determines whether the Rectangle object specified by the rect parameter is contained within this Rectangle object. A Rectangle object is said to contain another if the second Rectangle object falls entirely within the boundaries of the first. + * Determines whether the Rectangle object specified by the rect parameter is contained within this Rectangle object. + * A Rectangle object is said to contain another if the second Rectangle object falls entirely within the boundaries of the first. * @method containsRect * @param {Rectangle} rect The rectangle object being checked. * @return {Boolean} A value of true if the Rectangle object contains the specified point; otherwise false. @@ -2712,7 +2913,7 @@ var Phaser; if(rect.volume > this.volume) { return false; } - if(rect.x >= this.x && rect.y >= this.y && rect.right <= this.right && rect.bottom <= this.bottom) { + if(rect.x >= this.topLeft.x && rect.y >= this.topLeft.y && rect.rightCenter.x <= this.rightCenter.x && rect.bottomCenter.y <= this.bottomCenter.y) { return true; } return false; @@ -2736,35 +2937,38 @@ var Phaser; return target.copyFrom(this); }; Rectangle.prototype.equals = /** - * Determines whether the object specified in the toCompare parameter is equal to this Rectangle object. This method compares the x, y, width, and height properties of an object against the same properties of this Rectangle object. + * Determines whether the object specified in the toCompare parameter is equal to this Rectangle object. + * This method compares the x, y, width, and height properties of an object against the same properties of this Rectangle object. * @method equals * @param {Rectangle} toCompare The rectangle to compare to this Rectangle object. * @return {Boolean} A value of true if the object has exactly the same values for the x, y, width, and height properties as this Rectangle object; otherwise false. **/ function (toCompare) { - if(this.x === toCompare.x && this.y === toCompare.y && this.width === toCompare.width && this.height === toCompare.height) { + if(this.topLeft.equals(toCompare.topLeft) && this.bottomRight.equals(toCompare.bottomRight)) { return true; } return false; }; Rectangle.prototype.inflate = /** - * Increases the size of the Rectangle object by the specified amounts. The center point of the Rectangle object stays the same, and its size increases to the left and right by the dx value, and to the top and the bottom by the dy value. + * Increases the size of the Rectangle object by the specified amounts. + * The center point of the Rectangle object stays the same, and its size increases to the left and right by the dx value, + * and to the top and the bottom by the dy value. * @method inflate * @param {Number} dx The amount to be added to the left side of this Rectangle. * @param {Number} dy The amount to be added to the bottom side of this Rectangle. * @return {Rectangle} This Rectangle object. **/ function (dx, dy) { - if(!isNaN(dx) && !isNaN(dy)) { - this.x -= dx; - this.width += 2 * dx; - this.y -= dy; - this.height += 2 * dy; - } + this._tempX = this.topLeft.x - dx; + this._tempWidth = this._width + (2 * dx); + this._tempY = this.topLeft.y - dy; + this._tempHeight = this._height + (2 * dy); + this.updateBounds(); return this; }; Rectangle.prototype.inflatePoint = /** - * Increases the size of the Rectangle object. This method is similar to the Rectangle.inflate() method except it takes a Point object as a parameter. + * Increases the size of the Rectangle object. + * This method is similar to the Rectangle.inflate() method except it takes a Point object as a parameter. * @method inflatePoint * @param {Point} point The x property of this Point object is used to increase the horizontal dimension of the Rectangle object. The y property is used to increase the vertical dimension of the Rectangle object. * @return {Rectangle} This Rectangle object. @@ -2773,7 +2977,9 @@ var Phaser; return this.inflate(point.x, point.y); }; Rectangle.prototype.intersection = /** - * If the Rectangle object specified in the toIntersect parameter intersects with this Rectangle object, returns the area of intersection as a Rectangle object. If the rectangles do not intersect, this method returns an empty Rectangle object with its properties set to 0. + * If the Rectangle object specified in the toIntersect parameter intersects with this Rectangle object, + * returns the area of intersection as a Rectangle object. If the rectangles do not intersect, this method + * returns an empty Rectangle object with its properties set to 0. * @method intersection * @param {Rectangle} toIntersect The Rectangle object to compare against to see if it intersects with this Rectangle object. * @param {Rectangle} output Optional Rectangle object. If given the intersection values will be set into this object, otherwise a brand new Rectangle object will be created and returned. @@ -2782,41 +2988,24 @@ var Phaser; function (toIntersect, output) { if (typeof output === "undefined") { output = new Rectangle(); } if(this.intersects(toIntersect) === true) { - output.x = Math.max(toIntersect.x, this.x); - output.y = Math.max(toIntersect.y, this.y); - output.width = Math.min(toIntersect.right, this.right) - output.x; - output.height = Math.min(toIntersect.bottom, this.bottom) - output.y; + output.x = Math.max(toIntersect.topLeft.x, this.topLeft.x); + output.y = Math.max(toIntersect.topLeft.y, this.topLeft.y); + output.width = Math.min(toIntersect.rightCenter.x, this.rightCenter.x) - output.x; + output.height = Math.min(toIntersect.bottomCenter.y, this.bottomCenter.y) - output.y; } return output; }; Rectangle.prototype.intersects = /** - * Determines whether the object specified in the toIntersect parameter intersects with this Rectangle object. This method checks the x, y, width, and height properties of the specified Rectangle object to see if it intersects with this Rectangle object. + * Determines whether the object specified intersects (overlaps) with this Rectangle object. + * This method checks the x, y, width, and height properties of the specified Rectangle object to see if it intersects with this Rectangle object. * @method intersects - * @param {Rectangle} toIntersect The Rectangle object to compare against to see if it intersects with this Rectangle object. + * @param {Rectangle} r2 The Rectangle object to compare against to see if it intersects with this Rectangle object. + * @param {Number} t A tolerance value to allow for an intersection test with padding, default to 0 * @return {Boolean} A value of true if the specified object intersects with this Rectangle object; otherwise false. **/ - function (toIntersect) { - if(toIntersect.x >= this.right) { - return false; - } - if(toIntersect.right <= this.x) { - return false; - } - if(toIntersect.bottom <= this.y) { - return false; - } - if(toIntersect.y >= this.bottom) { - return false; - } - return true; - }; - Rectangle.prototype.overlap = /** - * Checks for overlaps between this Rectangle and the given Rectangle. Returns an object with boolean values for each check. - * @method overlap - * @return {Boolean} true if the rectangles overlap, otherwise false - **/ - function (rect) { - return (rect.x + rect.width > this.x) && (rect.x < this.x + this.width) && (rect.y + rect.height > this.y) && (rect.y < this.y + this.height); + function (r2, t) { + if (typeof t === "undefined") { t = 0; } + return !(r2.left > this.right + t || r2.right < this.left - t || r2.top > this.bottom + t || r2.bottom < this.top - t); }; Object.defineProperty(Rectangle.prototype, "isEmpty", { get: /** @@ -2874,16 +3063,11 @@ var Phaser; * @return {Rectangle} This rectangle object **/ function (x, y, width, height) { - if(!isNaN(x) && !isNaN(y) && !isNaN(width) && !isNaN(height)) { - this.x = x; - this.y = y; - if(width > 0) { - this.width = width; - } - if(height > 0) { - this.height = height; - } - } + this._tempX = x; + this._tempY = y; + this._tempWidth = width; + this._tempHeight = height; + this.updateBounds(); return this; }; Rectangle.prototype.union = /** @@ -6568,8 +6752,7 @@ var Phaser; this._game = game; } Motion.prototype.computeVelocity = /** - * A tween-like function that takes a starting velocity - * and some other factors and returns an altered velocity. + * A tween-like function that takes a starting velocity and some other factors and returns an altered velocity. * * @param Velocity Any component of velocity (e.g. 20). * @param Acceleration Rate at which the velocity is changing. @@ -6865,6 +7048,86 @@ var Phaser; })(); Phaser.Motion = Motion; })(Phaser || (Phaser = {})); +/// +/// +/** +* Phaser - Sound +* +* A Sound file, used by the Game.SoundManager for playback. +*/ +var Phaser; +(function (Phaser) { + var Sound = (function () { + function Sound(context, gainNode, data, volume, loop) { + if (typeof volume === "undefined") { volume = 1; } + if (typeof loop === "undefined") { loop = false; } + this.loop = false; + this.isPlaying = false; + this.isDecoding = false; + this._context = context; + this._gainNode = gainNode; + this._buffer = data; + this._volume = volume; + this.loop = loop; + // Local volume control + if(this._context !== null) { + this._localGainNode = this._context.createGainNode(); + this._localGainNode.connect(this._gainNode); + this._localGainNode.gain.value = this._volume; + } + if(this._buffer === null) { + this.isDecoding = true; + } else { + this.play(); + } + } + Sound.prototype.setDecodedBuffer = function (data) { + this._buffer = data; + this.isDecoding = false; + this.play(); + }; + Sound.prototype.play = function () { + if(this._buffer === null || this.isDecoding === true) { + return; + } + this._sound = this._context.createBufferSource(); + this._sound.buffer = this._buffer; + this._sound.connect(this._localGainNode); + if(this.loop) { + this._sound.loop = true; + } + this._sound.noteOn(0)// the zero is vitally important, crashes iOS6 without it + ; + this.duration = this._sound.buffer.duration; + this.isPlaying = true; + }; + Sound.prototype.stop = function () { + if(this.isPlaying === true) { + this.isPlaying = false; + this._sound.noteOff(0); + } + }; + Sound.prototype.mute = function () { + this._localGainNode.gain.value = 0; + }; + Sound.prototype.unmute = function () { + this._localGainNode.gain.value = this._volume; + }; + Object.defineProperty(Sound.prototype, "volume", { + get: function () { + return this._volume; + }, + set: function (value) { + this._volume = value; + this._localGainNode.gain.value = this._volume; + }, + enumerable: true, + configurable: true + }); + return Sound; + })(); + Phaser.Sound = Sound; +})(Phaser || (Phaser = {})); /// /// /** @@ -7108,6 +7371,9 @@ var Phaser; } else { document.body.appendChild(this.canvas); } + // Consume default actions on the canvas + this.canvas.style.msTouchAction = 'none'; + this.canvas.style['touch-action'] = 'none'; this.context = this.canvas.getContext('2d'); this.offset = this.getOffset(this.canvas); this.bounds = new Phaser.Rectangle(this.offset.x, this.offset.y, width, height); @@ -8947,6 +9213,8 @@ var Phaser; this.mouse = new Phaser.Mouse(this._game); this.keyboard = new Phaser.Keyboard(this._game); this.touch = new Phaser.Touch(this._game); + this.onDown = new Phaser.Signal(); + this.onUp = new Phaser.Signal(); } Input.prototype.update = function () { this.x = Math.round(this.x); @@ -9227,6 +9495,7 @@ var Phaser; 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; @@ -9252,6 +9521,7 @@ var Phaser; 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); }; return Mouse; })(); @@ -9622,6 +9892,7 @@ var Phaser; this._game.input.x = this.x * this._game.input.scaleX; this._game.input.y = this.y * this._game.input.scaleY; this.touchDown.dispatch(this._fingers[f].x, this._fingers[f].y, this._fingers[f].timeDown, this._fingers[f].timeUp, this._fingers[f].duration); + this._game.input.onDown.dispatch(this._game.input.x, this._game.input.y, this._fingers[f].timeDown); this.isDown = true; this.isUp = false; break; @@ -9728,6 +9999,7 @@ var Phaser; this._game.input.x = this.x * this._game.input.scaleX; this._game.input.y = this.y * this._game.input.scaleY; this.touchUp.dispatch(this._fingers[f].x, this._fingers[f].y, this._fingers[f].timeDown, this._fingers[f].timeUp, this._fingers[f].duration); + this._game.input.onUp.dispatch(this._game.input.x, this._game.input.y, this._fingers[f].timeUp); this.isDown = false; this.isUp = true; break; @@ -10194,7 +10466,7 @@ var Phaser; this._dh = this.bounds.height * this.scale.y; return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh); } else { - return camera.overlap(this.bounds); + return camera.intersects(this.bounds); } }; GeomSprite.prototype.render = function (camera, cameraOffsetX, cameraOffsetY) { @@ -10221,14 +10493,17 @@ var Phaser; this._dx -= (camera.worldView.x * this.scrollFactor.x); this._dy -= (camera.worldView.y * this.scrollFactor.y); } - // Rotation (could be misleading as it doesn't work re: collision) - if(this.angle !== 0) { - this._game.stage.context.save(); - this._game.stage.context.translate(this._dx + (this._dw / 2) - this.origin.x, this._dy + (this._dh / 2) - this.origin.y); - this._game.stage.context.rotate(this.angle * (Math.PI / 180)); - this._dx = -(this._dw / 2); - this._dy = -(this._dh / 2); + // Rotation is disabled for now as I don't want it to be misleading re: collision + /* + if (this.angle !== 0) + { + this._game.stage.context.save(); + this._game.stage.context.translate(this._dx + (this._dw / 2) - this.origin.x, this._dy + (this._dh / 2) - this.origin.y); + this._game.stage.context.rotate(this.angle * (Math.PI / 180)); + this._dx = -(this._dw / 2); + this._dy = -(this._dh / 2); } + */ this._dx = Math.round(this._dx); this._dy = Math.round(this._dy); this._dw = Math.round(this._dw); @@ -10272,6 +10547,17 @@ var Phaser; } this._game.stage.context.closePath(); } + // And now the edge points + this._game.stage.context.fillStyle = 'rgb(255,255,255)'; + this.renderPoint(this._dx, this._dy, this.rect.topLeft, 2); + this.renderPoint(this._dx, this._dy, this.rect.topCenter, 2); + this.renderPoint(this._dx, this._dy, this.rect.topRight, 2); + this.renderPoint(this._dx, this._dy, this.rect.leftCenter, 2); + this.renderPoint(this._dx, this._dy, this.rect.center, 2); + this.renderPoint(this._dx, this._dy, this.rect.rightCenter, 2); + this.renderPoint(this._dx, this._dy, this.rect.bottomLeft, 2); + this.renderPoint(this._dx, this._dy, this.rect.bottomCenter, 2); + this.renderPoint(this._dx, this._dy, this.rect.bottomRight, 2); } this._game.stage.restoreCanvasValues(); if(this.rotation !== 0) { @@ -10283,6 +10569,11 @@ var Phaser; } return true; }; + GeomSprite.prototype.renderPoint = function (offsetX, offsetY, point, size) { + offsetX = 0; + offsetY = 0; + this._game.stage.context.fillRect(offsetX + point.x, offsetY + point.y, 1, 1); + }; GeomSprite.prototype.renderDebugInfo = function (x, y, color) { if (typeof color === "undefined") { color = 'rgb(255,255,255)'; } //this._game.stage.context.fillStyle = color; @@ -10347,7 +10638,7 @@ var Phaser; return Phaser.Collision.lineSegmentToLineSegment(this.line, source.line).result; } // Line vs. Circle - if(this.type == GeomSprite.LINE && source.type == GeomSprite.LINE) { + if(this.type == GeomSprite.LINE && source.type == GeomSprite.CIRCLE) { return Phaser.Collision.lineToCircle(this.line, source.circle).result; } // Line vs. Rect @@ -10355,7 +10646,7 @@ var Phaser; return Phaser.Collision.lineSegmentToRectangle(this.line, source.rect).result; } // Line vs. Point - if(this.type == GeomSprite.LINE && source.type == GeomSprite.LINE) { + if(this.type == GeomSprite.LINE && source.type == GeomSprite.POINT) { return this.line.isPointOnLine(source.point.x, source.point.y); } return false; @@ -11082,84 +11373,138 @@ var Phaser; Phaser.Game = Game; })(Phaser || (Phaser = {})); /// -/// /** -* Phaser - Sound +* Phaser - MicroPoint * -* A Sound file, used by the Game.SoundManager for playback. +* The MicroPoint object represents a location in a two-dimensional coordinate system, +* where x represents the horizontal axis and y represents the vertical axis. +* It is different to the Point class in that it doesn't contain any of the help methods like add/substract/distanceTo, etc. +* Use a MicroPoint when all you literally need is a solid container for x and y (such as in the Rectangle class). */ var Phaser; (function (Phaser) { - var Sound = (function () { - function Sound(context, gainNode, data, volume, loop) { - if (typeof volume === "undefined") { volume = 1; } - if (typeof loop === "undefined") { loop = false; } - this.loop = false; - this.isPlaying = false; - this.isDecoding = false; - this._context = context; - this._gainNode = gainNode; - this._buffer = data; - this._volume = volume; - this.loop = loop; - // Local volume control - if(this._context !== null) { - this._localGainNode = this._context.createGainNode(); - this._localGainNode.connect(this._gainNode); - this._localGainNode.gain.value = this._volume; - } - if(this._buffer === null) { - this.isDecoding = true; - } else { - this.play(); - } + var MicroPoint = (function () { + /** + * Creates a new point. If you pass no parameters to this method, a point is created at (0,0). + * @class MicroPoint + * @constructor + * @param {Number} x The horizontal position of this point (default 0) + * @param {Number} y The vertical position of this point (default 0) + **/ + function MicroPoint(x, y, parent) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + if (typeof parent === "undefined") { parent = null; } + this._x = x; + this._y = y; + this.parent = parent; } - Sound.prototype.setDecodedBuffer = function (data) { - this._buffer = data; - this.isDecoding = false; - this.play(); - }; - Sound.prototype.play = function () { - if(this._buffer === null || this.isDecoding === true) { - return; - } - this._sound = this._context.createBufferSource(); - this._sound.buffer = this._buffer; - this._sound.connect(this._localGainNode); - if(this.loop) { - this._sound.loop = true; - } - this._sound.noteOn(0)// the zero is vitally important, crashes iOS6 without it - ; - this.duration = this._sound.buffer.duration; - this.isPlaying = true; - }; - Sound.prototype.stop = function () { - if(this.isPlaying === true) { - this.isPlaying = false; - this._sound.noteOff(0); - } - }; - Sound.prototype.mute = function () { - this._localGainNode.gain.value = 0; - }; - Sound.prototype.unmute = function () { - this._localGainNode.gain.value = this._volume; - }; - Object.defineProperty(Sound.prototype, "volume", { - get: function () { - return this._volume; + Object.defineProperty(MicroPoint.prototype, "x", { + get: /** + * The x coordinate of the top-left corner of the rectangle + * @property x + * @type Number + **/ + function () { + return this._x; }, - set: function (value) { - this._volume = value; - this._localGainNode.gain.value = this._volume; + set: /** + * The x coordinate of the top-left corner of the rectangle + * @property x + * @type Number + **/ + function (value) { + this._x = value; + if(this.parent) { + this.parent.updateBounds(); + } }, enumerable: true, configurable: true }); - return Sound; + Object.defineProperty(MicroPoint.prototype, "y", { + get: /** + * The y coordinate of the top-left corner of the rectangle + * @property y + * @type Number + **/ + function () { + return this._y; + }, + set: /** + * The y coordinate of the top-left corner of the rectangle + * @property y + * @type Number + **/ + function (value) { + this._y = value; + if(this.parent) { + this.parent.updateBounds(); + } + }, + enumerable: true, + configurable: true + }); + MicroPoint.prototype.copyFrom = /** + * Copies the x and y values from any given object to this MicroPoint. + * @method copyFrom + * @param {any} source - The object to copy from. + * @return {MicroPoint} This MicroPoint object. Useful for chaining method calls. + **/ + function (source) { + return this.setTo(source.x, source.y); + }; + MicroPoint.prototype.copyTo = /** + * Copies the x and y values from this MicroPoint to any given object. + * @method copyTo + * @param {any} target - The object to copy to. + * @return {any} The target object. + **/ + function (target) { + target.x = this._x; + target.y = this._y; + return target; + }; + MicroPoint.prototype.setTo = /** + * Sets the x and y values of this MicroPoint object to the given coordinates. + * @method setTo + * @param {Number} x - The horizontal position of this point. + * @param {Number} y - The vertical position of this point. + * @return {MicroPoint} This MicroPoint object. Useful for chaining method calls. + **/ + function (x, y, callParent) { + if (typeof callParent === "undefined") { callParent = true; } + this._x = x; + this._y = y; + if(this.parent != null && callParent == true) { + this.parent.updateBounds(); + } + return this; + }; + MicroPoint.prototype.equals = /** + * Determines whether this MicroPoint object and the given object are equal. They are equal if they have the same x and y values. + * @method equals + * @param {any} point - The object to compare against. Must have x and y properties. + * @return {Boolean} A value of true if the object is equal to this MicroPoin object; false if it is not equal. + **/ + function (toCompare) { + if(this._x === toCompare.x && this._y === toCompare.y) { + return true; + } else { + return false; + } + }; + MicroPoint.prototype.toString = /** + * Returns a string representation of this object. + * @method toString + * @return {string} a string representation of the instance. + **/ + function () { + return '[{MicroPoint (x=' + this._x + ' y=' + this._y + ')}]'; + }; + return MicroPoint; })(); - Phaser.Sound = Sound; + Phaser.MicroPoint = MicroPoint; })(Phaser || (Phaser = {})); /// /** diff --git a/Tests/sprites/align.js b/Tests/sprites/align.js new file mode 100644 index 00000000..d47443fb --- /dev/null +++ b/Tests/sprites/align.js @@ -0,0 +1,27 @@ +/// +(function () { + var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update); + function init() { + myGame.loader.addImageFile('teddy', 'assets/pics/profil-sad_plush.png'); + myGame.loader.load(); + } + var teddy; + function create() { + teddy = myGame.createSprite(0, 0, 'teddy'); + teddy.x = myGame.stage.centerX - teddy.width / 2; + teddy.y = myGame.stage.centerY - teddy.height / 2; + myGame.input.onDown.add(click, this); + teddy.renderDebug = true; + } + function click() { + if(teddy.align == Phaser.GameObject.ALIGN_BOTTOM_RIGHT) { + teddy.align = Phaser.GameObject.ALIGN_TOP_LEFT; + } else { + teddy.align++; + } + } + function update() { + teddy.x = myGame.input.x; + teddy.y = myGame.input.y; + } +})(); diff --git a/Tests/sprites/align.ts b/Tests/sprites/align.ts new file mode 100644 index 00000000..9fe2c738 --- /dev/null +++ b/Tests/sprites/align.ts @@ -0,0 +1,50 @@ +/// + +(function () { + + var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update); + + function init() { + + myGame.loader.addImageFile('teddy', 'assets/pics/profil-sad_plush.png'); + + myGame.loader.load(); + + } + + var teddy: Phaser.Sprite; + + function create() { + + teddy = myGame.createSprite(0, 0, 'teddy'); + + teddy.x = myGame.stage.centerX - teddy.width / 2; + teddy.y = myGame.stage.centerY - teddy.height / 2; + + myGame.input.onDown.add(click, this); + + teddy.renderDebug = true; + + } + + function click() { + + if (teddy.align == Phaser.GameObject.ALIGN_BOTTOM_RIGHT) + { + teddy.align = Phaser.GameObject.ALIGN_TOP_LEFT; + } + else + { + teddy.align++; + } + + } + + function update() { + + teddy.x = myGame.input.x; + teddy.y = myGame.input.y; + + } + +})(); diff --git a/Tests/sprites/rotation.js b/Tests/sprites/rotation.js index 26589aca..2f65b3d4 100644 --- a/Tests/sprites/rotation.js +++ b/Tests/sprites/rotation.js @@ -10,15 +10,12 @@ teddy = myGame.createSprite(0, 0, 'teddy'); teddy.x = myGame.stage.centerX - teddy.width / 2; teddy.y = myGame.stage.centerY - teddy.height / 2; - teddy.origin.setTo(-100, -100); } function update() { - teddy.angularVelocity = 0; - //car.angularAcceleration = 0; if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { - teddy.angularVelocity = -200; + teddy.angularAcceleration = -40; } else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { - teddy.angularVelocity = 200; + teddy.angularAcceleration = 40; } } })(); diff --git a/Tests/sprites/rotation.ts b/Tests/sprites/rotation.ts index e008aad6..ecde90fe 100644 --- a/Tests/sprites/rotation.ts +++ b/Tests/sprites/rotation.ts @@ -20,22 +20,17 @@ teddy.x = myGame.stage.centerX - teddy.width / 2; teddy.y = myGame.stage.centerY - teddy.height / 2; - teddy.origin.setTo(-100, -100); - } function update() { - teddy.angularVelocity = 0; - //car.angularAcceleration = 0; - if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { - teddy.angularVelocity = -200; + teddy.angularAcceleration = -40; } else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { - teddy.angularVelocity = 200; + teddy.angularAcceleration = 40; } } diff --git a/build/phaser.js b/build/phaser.js index d2f8b662..df4d6aa0 100644 --- a/build/phaser.js +++ b/build/phaser.js @@ -478,9 +478,10 @@ var Phaser; this.alive = true; this.isGroup = false; this.alpha = 1; - this.scale = new Phaser.Point(1, 1); - this.last = new Phaser.Point(x, y); - this.origin = new Phaser.Point(this.bounds.halfWidth, this.bounds.halfHeight); + this.scale = new Phaser.MicroPoint(1, 1); + this.last = new Phaser.MicroPoint(x, y); + this.origin = new Phaser.MicroPoint(this.bounds.halfWidth, this.bounds.halfHeight); + this.align = GameObject.ALIGN_TOP_LEFT; this.mass = 1.0; this.elasticity = 0.0; this.health = 1; @@ -489,17 +490,26 @@ var Phaser; this.touching = Phaser.Collision.NONE; this.wasTouching = Phaser.Collision.NONE; this.allowCollisions = Phaser.Collision.ANY; - this.velocity = new Phaser.Point(); - this.acceleration = new Phaser.Point(); - this.drag = new Phaser.Point(); - this.maxVelocity = new Phaser.Point(10000, 10000); + this.velocity = new Phaser.MicroPoint(); + this.acceleration = new Phaser.MicroPoint(); + this.drag = new Phaser.MicroPoint(); + this.maxVelocity = new Phaser.MicroPoint(10000, 10000); this.angle = 0; this.angularVelocity = 0; this.angularAcceleration = 0; this.angularDrag = 0; this.maxAngular = 10000; - this.scrollFactor = new Phaser.Point(1.0, 1.0); + this.scrollFactor = new Phaser.MicroPoint(1.0, 1.0); } + GameObject.ALIGN_TOP_LEFT = 0; + GameObject.ALIGN_TOP_CENTER = 1; + GameObject.ALIGN_TOP_RIGHT = 2; + GameObject.ALIGN_CENTER_LEFT = 3; + GameObject.ALIGN_CENTER = 4; + GameObject.ALIGN_CENTER_RIGHT = 5; + GameObject.ALIGN_BOTTOM_LEFT = 6; + GameObject.ALIGN_BOTTOM_CENTER = 7; + GameObject.ALIGN_BOTTOM_RIGHT = 8; GameObject.prototype.preUpdate = function () { // flicker time this.last.x = this.bounds.x; @@ -583,7 +593,7 @@ var Phaser; }; GameObject.prototype.overlapsAt = /** * Checks to see if this GameObject were located at the given position, would it overlap the GameObject or Group? - * This is distinct from overlapsPoint(), which just checks that ponumber, rather than taking the object's size numbero account. + * This is distinct from overlapsPoint(), which just checks that point, rather than taking the object's size numbero account. * WARNING: Currently tilemaps do NOT support screen space overlap checks! * * @param X The X position you want to check. Pretends this object (the caller, not the parameter) is located here. @@ -636,13 +646,13 @@ var Phaser; return (objectScreenPos.x + ObjectOrGroup.width > this._point.x) && (objectScreenPos.x < this._point.x + this.width) && (objectScreenPos.y + ObjectOrGroup.height > this._point.y) && (objectScreenPos.y < this._point.y + this.height); }; GameObject.prototype.overlapsPoint = /** - * Checks to see if a ponumber in 2D world space overlaps this GameObject object. + * Checks to see if a point in 2D world space overlaps this GameObject. * - * @param Point The ponumber in world space you want to check. + * @param Point The point in world space you want to check. * @param InScreenSpace Whether to take scroll factors numbero account when checking for overlap. * @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera. * - * @return Whether or not the ponumber overlaps this object. + * @return Whether or not the point overlaps this object. */ function (point, InScreenSpace, Camera) { if (typeof InScreenSpace === "undefined") { InScreenSpace = false; } @@ -661,7 +671,7 @@ var Phaser; GameObject.prototype.onScreen = /** * Check and see if this object is currently on screen. * - * @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera. + * @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera. * * @return Whether the object is on screen or not. */ @@ -677,15 +687,15 @@ var Phaser; * Call this to figure out the on-screen position of the object. * * @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera. - * @param Point Takes a Point object and assigns the post-scrolled X and Y values of this object to it. + * @param Point Takes a MicroPoint object and assigns the post-scrolled X and Y values of this object to it. * - * @return The Point you passed in, or a new Point if you didn't pass one, containing the screen X and Y position of this object. + * @return The MicroPoint you passed in, or a new Point if you didn't pass one, containing the screen X and Y position of this object. */ function (point, Camera) { if (typeof point === "undefined") { point = null; } if (typeof Camera === "undefined") { Camera = null; } if(point == null) { - point = new Phaser.Point(); + point = new Phaser.MicroPoint(); } if(Camera == null) { Camera = this._game.camera; @@ -719,19 +729,18 @@ var Phaser; configurable: true }); GameObject.prototype.getMidpoint = /** - * Retrieve the midponumber of this object in world coordinates. + * Retrieve the midpoint of this object in world coordinates. * * @Point Allows you to pass in an existing Point object if you're so inclined. Otherwise a new one is created. * - * @return A Point object containing the midponumber of this object in world coordinates. + * @return A Point object containing the midpoint of this object in world coordinates. */ function (point) { if (typeof point === "undefined") { point = null; } if(point == null) { - point = new Phaser.Point(); + point = new Phaser.MicroPoint(); } - point.x = this.x + this.width * 0.5; - point.y = this.y + this.height * 0.5; + point.copyFrom(this.bounds.center); return point; }; GameObject.prototype.reset = /** @@ -874,6 +883,9 @@ var Phaser; this._dy = 0; this._dw = 0; this._dh = 0; + this.renderDebug = false; + this.renderDebugColor = 'rgba(0,255,0,0.5)'; + this.renderDebugPointColor = 'rgba(255,255,255,1)'; this._texture = null; this.animations = new Phaser.AnimationManager(this._game, this); if(key !== null) { @@ -920,7 +932,7 @@ var Phaser; this._dh = this.bounds.height * this.scale.y; return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh); } else { - return camera.overlap(this.bounds); + return camera.intersects(this.bounds, this.bounds.length); } }; Sprite.prototype.postUpdate = function () { @@ -967,10 +979,31 @@ var Phaser; this._sy = 0; this._sw = this.bounds.width; this._sh = this.bounds.height; - this._dx = cameraOffsetX + (this.bounds.x - camera.worldView.x); - this._dy = cameraOffsetY + (this.bounds.y - camera.worldView.y); + this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x); + this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y); this._dw = this.bounds.width * this.scale.x; this._dh = this.bounds.height * this.scale.y; + if(this.align == Phaser.GameObject.ALIGN_TOP_CENTER) { + this._dx -= this.bounds.halfWidth * this.scale.x; + } else if(this.align == Phaser.GameObject.ALIGN_TOP_RIGHT) { + this._dx -= this.bounds.width * this.scale.x; + } else if(this.align == Phaser.GameObject.ALIGN_CENTER_LEFT) { + this._dy -= this.bounds.halfHeight * this.scale.y; + } else if(this.align == Phaser.GameObject.ALIGN_CENTER) { + this._dx -= this.bounds.halfWidth * this.scale.x; + this._dy -= this.bounds.halfHeight * this.scale.y; + } else if(this.align == Phaser.GameObject.ALIGN_CENTER_RIGHT) { + this._dx -= this.bounds.width * this.scale.x; + this._dy -= this.bounds.halfHeight * this.scale.y; + } else if(this.align == Phaser.GameObject.ALIGN_BOTTOM_LEFT) { + this._dy -= this.bounds.height * this.scale.y; + } else if(this.align == Phaser.GameObject.ALIGN_BOTTOM_CENTER) { + this._dx -= this.bounds.halfWidth * this.scale.x; + this._dy -= this.bounds.height * this.scale.y; + } else if(this.align == Phaser.GameObject.ALIGN_BOTTOM_RIGHT) { + this._dx -= this.bounds.width * this.scale.x; + this._dy -= this.bounds.height * this.scale.y; + } if(this._dynamicTexture == false && this.animations.currentFrame !== null) { this._sx = this.animations.currentFrame.x; this._sy = this.animations.currentFrame.y; @@ -1001,9 +1034,6 @@ var Phaser; this._dy = Math.round(this._dy); this._dw = Math.round(this._dw); this._dh = Math.round(this._dh); - // Debug test - //this._game.stage.context.fillStyle = 'rgba(255,0,0,0.3)'; - //this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh); if(this._texture != null) { if(this._dynamicTexture) { this._game.stage.context.drawImage(this._texture.canvas, // Source Image @@ -1032,6 +1062,9 @@ var Phaser; this._game.stage.context.fillStyle = 'rgb(255,255,255)'; this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh); } + if(this.renderDebug) { + this.renderBounds(); + } //if (this.flip === true || this.rotation !== 0) if(this.rotation !== 0) { this._game.stage.context.translate(0, 0); @@ -1042,6 +1075,33 @@ var Phaser; } return true; }; + Sprite.prototype.renderBounds = function () { + this._game.stage.context.fillStyle = this.renderDebugColor; + this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh); + this._game.stage.context.fillStyle = this.renderDebugPointColor; + var hw = this.bounds.halfWidth * this.scale.x; + var hh = this.bounds.halfHeight * this.scale.y; + var sw = (this.bounds.width * this.scale.x) - 1; + var sh = (this.bounds.height * this.scale.y) - 1; + this._game.stage.context.fillRect(this._dx, this._dy, 1, 1)// top left + ; + this._game.stage.context.fillRect(this._dx + hw, this._dy, 1, 1)// top center + ; + this._game.stage.context.fillRect(this._dx + sw, this._dy, 1, 1)// top right + ; + this._game.stage.context.fillRect(this._dx, this._dy + hh, 1, 1)// left center + ; + this._game.stage.context.fillRect(this._dx + hw, this._dy + hh, 1, 1)// center + ; + this._game.stage.context.fillRect(this._dx + sw, this._dy + hh, 1, 1)// right center + ; + this._game.stage.context.fillRect(this._dx, this._dy + sh, 1, 1)// bottom left + ; + this._game.stage.context.fillRect(this._dx + hw, this._dy + sh, 1, 1)// bottom center + ; + this._game.stage.context.fillRect(this._dx + sw, this._dy + sh, 1, 1)// bottom right + ; + }; Sprite.prototype.renderDebugInfo = function (x, y, color) { if (typeof color === "undefined") { color = 'rgb(255,255,255)'; } this._game.stage.context.fillStyle = color; @@ -2182,8 +2242,8 @@ var Phaser; * Creates a new point. If you pass no parameters to this method, a point is created at (0,0). * @class Point * @constructor - * @param {Number} x One-liner. Default is ?. - * @param {Number} y One-liner. Default is ?. + * @param {Number} x The horizontal position of this point (default 0) + * @param {Number} y The vertical position of this point (default 0) **/ function Point(x, y) { if (typeof x === "undefined") { x = 0; } @@ -2393,7 +2453,7 @@ var Phaser; }; Point.prototype.setTo = /** * Sets the x and y values of this Point object to the given coordinates. - * @method set + * @method setTo * @param {Number} x - The horizontal position of this point. * @param {Number} y - The vertical position of this point. * @return {Point} This Point object. Useful for chaining method calls. @@ -2427,6 +2487,7 @@ var Phaser; Phaser.Point = Point; })(Phaser || (Phaser = {})); /// +/// /** * Phaser - Rectangle * @@ -2450,94 +2511,241 @@ var Phaser; if (typeof y === "undefined") { y = 0; } if (typeof width === "undefined") { width = 0; } if (typeof height === "undefined") { height = 0; } + this._tempX = null; + this._tempY = null; + this._tempWidth = null; + this._tempHeight = null; /** + * The width of the rectangle + * @property width + * @type Number + **/ + this._width = 0; + /** + * The height of the rectangle + * @property height + * @type Number + **/ + this._height = 0; + /** + * Half of the width of the rectangle + * @property halfWidth + * @type Number + **/ + this._halfWidth = 0; + /** + * Half of the height of the rectangle + * @property halfHeight + * @type Number + **/ + this._halfHeight = 0; + /** + * The size of the longest side (width or height) + * @property length + * @type Number + **/ + this.length = 0; + this._width = width; + if(width > 0) { + this._halfWidth = Math.round(width / 2); + } + this._height = height; + if(height > 0) { + this._halfHeight = Math.round(height / 2); + } + this.length = Math.max(this._width, this._height); + this.topLeft = new Phaser.MicroPoint(x, y, this); + this.topCenter = new Phaser.MicroPoint(x + this._halfWidth, y, this); + this.topRight = new Phaser.MicroPoint(x + this._width - 1, y, this); + this.leftCenter = new Phaser.MicroPoint(x, y + this._halfHeight, this); + this.center = new Phaser.MicroPoint(x + this._halfWidth, y + this._halfHeight, this); + this.rightCenter = new Phaser.MicroPoint(x + this._width - 1, y + this._halfHeight, this); + this.bottomLeft = new Phaser.MicroPoint(x, y + this._height - 1, this); + this.bottomCenter = new Phaser.MicroPoint(x + this._halfWidth, y + this._height - 1, this); + this.bottomRight = new Phaser.MicroPoint(x + this._width - 1, y + this._height - 1, this); + } + Object.defineProperty(Rectangle.prototype, "x", { + get: /** * The x coordinate of the top-left corner of the rectangle * @property x * @type Number **/ - this.x = 0; - /** + function () { + return this.topLeft.x; + }, + set: /** + * The x coordinate of the top-left corner of the rectangle + * @property x + * @type Number + **/ + function (value) { + this.topLeft.x = value; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Rectangle.prototype, "y", { + get: /** * The y coordinate of the top-left corner of the rectangle * @property y * @type Number **/ - this.y = 0; - /** - * The width of the rectangle in pixels + function () { + return this.topLeft.y; + }, + set: /** + * The y coordinate of the top-left corner of the rectangle + * @property y + * @type Number + **/ + function (value) { + this.topLeft.y = value; + }, + enumerable: true, + configurable: true + }); + Rectangle.prototype.updateBounds = /** + * Updates all of the MicroPoints based on the values of width and height. + * You should not normally call this directly. + **/ + function () { + if(this._tempWidth !== null) { + this._width = this._tempWidth; + this._halfWidth = 0; + if(this._width > 0) { + this._halfWidth = Math.round(this._width / 2); + } + } + if(this._tempHeight !== null) { + this._height = this._tempHeight; + this._halfHeight = 0; + if(this._height > 0) { + this._halfHeight = Math.round(this._height / 2); + } + } + this.length = Math.max(this._width, this._height); + if(this._tempX !== null && this._tempY !== null) { + this.topLeft.setTo(this._tempX, this._tempY, false); + } else if(this._tempX !== null && this._tempY == null) { + this.topLeft.setTo(this._tempX, this.topLeft.y, false); + } else if(this._tempX == null && this._tempY !== null) { + this.topLeft.setTo(this.topLeft.x, this._tempY, false); + } else { + this.topLeft.setTo(this.x, this.y, false); + } + this.topCenter.setTo(this.x + this._halfWidth, this.y, false); + this.topRight.setTo(this.x + this._width - 1, this.y, false); + this.leftCenter.setTo(this.x, this.y + this._halfHeight, false); + this.center.setTo(this.x + this._halfWidth, this.y + this._halfHeight, false); + this.rightCenter.setTo(this.x + this._width - 1, this.y + this._halfHeight, false); + this.bottomLeft.setTo(this.x, this.y + this._height - 1, false); + this.bottomCenter.setTo(this.x + this._halfWidth, this.y + this._height - 1, false); + this.bottomRight.setTo(this.x + this._width - 1, this.y + this._height - 1, false); + this._tempX = null; + this._tempY = null; + this._tempWidth = null; + this._tempHeight = null; + }; + Object.defineProperty(Rectangle.prototype, "width", { + get: /** + * The width of the rectangle * @property width * @type Number **/ - this.width = 0; - /** - * The height of the rectangle in pixels + function () { + return this._width; + }, + set: /** + * The width of the rectangle + * @property width + * @type Number + **/ + function (value) { + this._width = value; + this._halfWidth = Math.round(value / 2); + this.updateBounds(); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Rectangle.prototype, "height", { + get: /** + * The height of the rectangle * @property height * @type Number **/ - this.height = 0; - this.setTo(x, y, width, height); - } + function () { + return this._height; + }, + set: /** + * The height of the rectangle + * @property height + * @type Number + **/ + function (value) { + this._height = value; + this._halfHeight = Math.round(value / 2); + this.updateBounds(); + }, + enumerable: true, + configurable: true + }); Object.defineProperty(Rectangle.prototype, "halfWidth", { - get: function () { - return Math.round(this.width / 2); + get: /** + * Half of the width of the rectangle + * @property halfWidth + * @type Number + **/ + function () { + return this._halfWidth; }, enumerable: true, configurable: true }); Object.defineProperty(Rectangle.prototype, "halfHeight", { - get: function () { - return Math.round(this.height / 2); + get: /** + * Half of the height of the rectangle + * @property halfHeight + * @type Number + **/ + function () { + return this._halfHeight; }, enumerable: true, configurable: true }); Object.defineProperty(Rectangle.prototype, "bottom", { get: /** - * The sum of the y and height properties. Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property. + * The sum of the y and height properties. + * Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property. * @method bottom * @return {Number} **/ function () { - return this.y + this.height; + return this.bottomCenter.y; }, set: /** - * The sum of the y and height properties. Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property. + * The sum of the y and height properties. + * Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property. * @method bottom * @param {Number} value **/ function (value) { if(value < this.y) { - this.height = 0; + this._tempHeight = 0; } else { - this.height = this.y + value; + this._tempHeight = this.y + value; } - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Rectangle.prototype, "bottomRight", { - get: /** - * Returns a Point containing the location of the Rectangle's bottom-right corner, determined by the values of the right and bottom properties. - * @method bottomRight - * @return {Point} - **/ - function () { - return new Phaser.Point(this.right, this.bottom); - }, - set: /** - * Sets the bottom-right corner of this Rectangle, determined by the values of the given Point object. - * @method bottomRight - * @param {Point} value - **/ - function (value) { - this.right = value.x; - this.bottom = value.y; + this.updateBounds(); }, enumerable: true, configurable: true }); Object.defineProperty(Rectangle.prototype, "left", { get: /** - * The x coordinate of the top-left corner of the rectangle. Changing the left property of a Rectangle object has no effect on the y and height properties. However it does affect the width property, whereas changing the x value does not affect the width property. + * The x coordinate of the top-left corner of the rectangle. + * Changing the left property of a Rectangle object has no effect on the y and height properties. + * However it does affect the width property, whereas changing the x value does not affect the width property. * @method left * @ return {number} **/ @@ -2545,44 +2753,51 @@ var Phaser; return this.x; }, set: /** - * The x coordinate of the top-left corner of the rectangle. Changing the left property of a Rectangle object has no effect on the y and height properties. However it does affect the width property, whereas changing the x value does not affect the width property. + * The x coordinate of the top-left corner of the rectangle. + * Changing the left property of a Rectangle object has no effect on the y and height properties. + * However it does affect the width property, whereas changing the x value does not affect the width property. * @method left * @param {Number} value **/ function (value) { var diff = this.x - value; - if(this.width + diff < 0) { - this.width = 0; - this.x = value; + if(this._width + diff < 0) { + this._tempWidth = 0; + this._tempX = value; } else { - this.width += diff; - this.x = value; + this._tempWidth = this._width + diff; + this._tempX = value; } + this.updateBounds(); }, enumerable: true, configurable: true }); Object.defineProperty(Rectangle.prototype, "right", { get: /** - * The sum of the x and width properties. Changing the right property of a Rectangle object has no effect on the x, y and height properties. However it does affect the width property. + * The sum of the x and width properties. + * Changing the right property of a Rectangle object has no effect on the x, y and height properties. + * However it does affect the width property. * @method right * @return {Number} **/ function () { - return this.x + this.width; + return this.rightCenter.x; }, set: /** - * The sum of the x and width properties. Changing the right property of a Rectangle object has no effect on the x, y and height properties. However it does affect the width property. + * The sum of the x and width properties. + * Changing the right property of a Rectangle object has no effect on the x, y and height properties. + * However it does affect the width property. * @method right * @param {Number} value **/ function (value) { - if(value < this.x) { - this.width = 0; - return this.x; + if(value < this.topLeft.x) { + this._tempWidth = 0; } else { - this.width = (value - this.x); + this._tempWidth = (value - this.topLeft.x); } + this.updateBounds(); }, enumerable: true, configurable: true @@ -2595,7 +2810,7 @@ var Phaser; **/ function (output) { if (typeof output === "undefined") { output = new Phaser.Point(); } - return output.setTo(this.width, this.height); + return output.setTo(this._width, this._height); }; Object.defineProperty(Rectangle.prototype, "volume", { get: /** @@ -2604,7 +2819,7 @@ var Phaser; * @return {Number} **/ function () { - return this.width * this.height; + return this._width * this._height; }, enumerable: true, configurable: true @@ -2616,55 +2831,39 @@ var Phaser; * @return {Number} **/ function () { - return (this.width * 2) + (this.height * 2); + return (this._width * 2) + (this._height * 2); }, enumerable: true, configurable: true }); Object.defineProperty(Rectangle.prototype, "top", { get: /** - * The y coordinate of the top-left corner of the rectangle. Changing the top property of a Rectangle object has no effect on the x and width properties. However it does affect the height property, whereas changing the y value does not affect the height property. + * The y coordinate of the top-left corner of the rectangle. + * Changing the top property of a Rectangle object has no effect on the x and width properties. + * However it does affect the height property, whereas changing the y value does not affect the height property. * @method top * @return {Number} **/ function () { - return this.y; + return this.topCenter.y; }, set: /** - * The y coordinate of the top-left corner of the rectangle. Changing the top property of a Rectangle object has no effect on the x and width properties. However it does affect the height property, whereas changing the y value does not affect the height property. + * The y coordinate of the top-left corner of the rectangle. + * Changing the top property of a Rectangle object has no effect on the x and width properties. + * However it does affect the height property, whereas changing the y value does not affect the height property. * @method top * @param {Number} value **/ function (value) { - var diff = this.y - value; - if(this.height + diff < 0) { - this.height = 0; - this.y = value; + var diff = this.topCenter.y - value; + if(this._height + diff < 0) { + this._tempHeight = 0; + this._tempY = value; } else { - this.height += diff; - this.y = value; + this._tempHeight = this._height + diff; + this._tempY = value; } - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Rectangle.prototype, "topLeft", { - get: /** - * The location of the Rectangle object's top-left corner, determined by the x and y coordinates of the point. - * @method topLeft - * @return {Point} - **/ - function () { - return new Phaser.Point(this.x, this.y); - }, - set: /** - * The location of the Rectangle object's top-left corner, determined by the x and y coordinates of the point. - * @method topLeft - * @param {Point} value - **/ - function (value) { - this.x = value.x; - this.y = value.y; + this.updateBounds(); }, enumerable: true, configurable: true @@ -2687,13 +2886,14 @@ var Phaser; * @return {Boolean} A value of true if the Rectangle object contains the specified point; otherwise false. **/ function (x, y) { - if(x >= this.x && x <= this.right && y >= this.y && y <= this.bottom) { + if(x >= this.topLeft.x && x <= this.topRight.x && y >= this.topLeft.y && y <= this.bottomRight.y) { return true; } return false; }; Rectangle.prototype.containsPoint = /** - * Determines whether the specified point is contained within the rectangular region defined by this Rectangle object. This method is similar to the Rectangle.contains() method, except that it takes a Point object as a parameter. + * Determines whether the specified point is contained within the rectangular region defined by this Rectangle object. + * This method is similar to the Rectangle.contains() method, except that it takes a Point object as a parameter. * @method containsPoint * @param {Point} point The point object being checked. Can be Point or any object with .x and .y values. * @return {Boolean} A value of true if the Rectangle object contains the specified point; otherwise false. @@ -2702,7 +2902,8 @@ var Phaser; return this.contains(point.x, point.y); }; Rectangle.prototype.containsRect = /** - * Determines whether the Rectangle object specified by the rect parameter is contained within this Rectangle object. A Rectangle object is said to contain another if the second Rectangle object falls entirely within the boundaries of the first. + * Determines whether the Rectangle object specified by the rect parameter is contained within this Rectangle object. + * A Rectangle object is said to contain another if the second Rectangle object falls entirely within the boundaries of the first. * @method containsRect * @param {Rectangle} rect The rectangle object being checked. * @return {Boolean} A value of true if the Rectangle object contains the specified point; otherwise false. @@ -2712,7 +2913,7 @@ var Phaser; if(rect.volume > this.volume) { return false; } - if(rect.x >= this.x && rect.y >= this.y && rect.right <= this.right && rect.bottom <= this.bottom) { + if(rect.x >= this.topLeft.x && rect.y >= this.topLeft.y && rect.rightCenter.x <= this.rightCenter.x && rect.bottomCenter.y <= this.bottomCenter.y) { return true; } return false; @@ -2736,35 +2937,38 @@ var Phaser; return target.copyFrom(this); }; Rectangle.prototype.equals = /** - * Determines whether the object specified in the toCompare parameter is equal to this Rectangle object. This method compares the x, y, width, and height properties of an object against the same properties of this Rectangle object. + * Determines whether the object specified in the toCompare parameter is equal to this Rectangle object. + * This method compares the x, y, width, and height properties of an object against the same properties of this Rectangle object. * @method equals * @param {Rectangle} toCompare The rectangle to compare to this Rectangle object. * @return {Boolean} A value of true if the object has exactly the same values for the x, y, width, and height properties as this Rectangle object; otherwise false. **/ function (toCompare) { - if(this.x === toCompare.x && this.y === toCompare.y && this.width === toCompare.width && this.height === toCompare.height) { + if(this.topLeft.equals(toCompare.topLeft) && this.bottomRight.equals(toCompare.bottomRight)) { return true; } return false; }; Rectangle.prototype.inflate = /** - * Increases the size of the Rectangle object by the specified amounts. The center point of the Rectangle object stays the same, and its size increases to the left and right by the dx value, and to the top and the bottom by the dy value. + * Increases the size of the Rectangle object by the specified amounts. + * The center point of the Rectangle object stays the same, and its size increases to the left and right by the dx value, + * and to the top and the bottom by the dy value. * @method inflate * @param {Number} dx The amount to be added to the left side of this Rectangle. * @param {Number} dy The amount to be added to the bottom side of this Rectangle. * @return {Rectangle} This Rectangle object. **/ function (dx, dy) { - if(!isNaN(dx) && !isNaN(dy)) { - this.x -= dx; - this.width += 2 * dx; - this.y -= dy; - this.height += 2 * dy; - } + this._tempX = this.topLeft.x - dx; + this._tempWidth = this._width + (2 * dx); + this._tempY = this.topLeft.y - dy; + this._tempHeight = this._height + (2 * dy); + this.updateBounds(); return this; }; Rectangle.prototype.inflatePoint = /** - * Increases the size of the Rectangle object. This method is similar to the Rectangle.inflate() method except it takes a Point object as a parameter. + * Increases the size of the Rectangle object. + * This method is similar to the Rectangle.inflate() method except it takes a Point object as a parameter. * @method inflatePoint * @param {Point} point The x property of this Point object is used to increase the horizontal dimension of the Rectangle object. The y property is used to increase the vertical dimension of the Rectangle object. * @return {Rectangle} This Rectangle object. @@ -2773,7 +2977,9 @@ var Phaser; return this.inflate(point.x, point.y); }; Rectangle.prototype.intersection = /** - * If the Rectangle object specified in the toIntersect parameter intersects with this Rectangle object, returns the area of intersection as a Rectangle object. If the rectangles do not intersect, this method returns an empty Rectangle object with its properties set to 0. + * If the Rectangle object specified in the toIntersect parameter intersects with this Rectangle object, + * returns the area of intersection as a Rectangle object. If the rectangles do not intersect, this method + * returns an empty Rectangle object with its properties set to 0. * @method intersection * @param {Rectangle} toIntersect The Rectangle object to compare against to see if it intersects with this Rectangle object. * @param {Rectangle} output Optional Rectangle object. If given the intersection values will be set into this object, otherwise a brand new Rectangle object will be created and returned. @@ -2782,41 +2988,24 @@ var Phaser; function (toIntersect, output) { if (typeof output === "undefined") { output = new Rectangle(); } if(this.intersects(toIntersect) === true) { - output.x = Math.max(toIntersect.x, this.x); - output.y = Math.max(toIntersect.y, this.y); - output.width = Math.min(toIntersect.right, this.right) - output.x; - output.height = Math.min(toIntersect.bottom, this.bottom) - output.y; + output.x = Math.max(toIntersect.topLeft.x, this.topLeft.x); + output.y = Math.max(toIntersect.topLeft.y, this.topLeft.y); + output.width = Math.min(toIntersect.rightCenter.x, this.rightCenter.x) - output.x; + output.height = Math.min(toIntersect.bottomCenter.y, this.bottomCenter.y) - output.y; } return output; }; Rectangle.prototype.intersects = /** - * Determines whether the object specified in the toIntersect parameter intersects with this Rectangle object. This method checks the x, y, width, and height properties of the specified Rectangle object to see if it intersects with this Rectangle object. + * Determines whether the object specified intersects (overlaps) with this Rectangle object. + * This method checks the x, y, width, and height properties of the specified Rectangle object to see if it intersects with this Rectangle object. * @method intersects - * @param {Rectangle} toIntersect The Rectangle object to compare against to see if it intersects with this Rectangle object. + * @param {Rectangle} r2 The Rectangle object to compare against to see if it intersects with this Rectangle object. + * @param {Number} t A tolerance value to allow for an intersection test with padding, default to 0 * @return {Boolean} A value of true if the specified object intersects with this Rectangle object; otherwise false. **/ - function (toIntersect) { - if(toIntersect.x >= this.right) { - return false; - } - if(toIntersect.right <= this.x) { - return false; - } - if(toIntersect.bottom <= this.y) { - return false; - } - if(toIntersect.y >= this.bottom) { - return false; - } - return true; - }; - Rectangle.prototype.overlap = /** - * Checks for overlaps between this Rectangle and the given Rectangle. Returns an object with boolean values for each check. - * @method overlap - * @return {Boolean} true if the rectangles overlap, otherwise false - **/ - function (rect) { - return (rect.x + rect.width > this.x) && (rect.x < this.x + this.width) && (rect.y + rect.height > this.y) && (rect.y < this.y + this.height); + function (r2, t) { + if (typeof t === "undefined") { t = 0; } + return !(r2.left > this.right + t || r2.right < this.left - t || r2.top > this.bottom + t || r2.bottom < this.top - t); }; Object.defineProperty(Rectangle.prototype, "isEmpty", { get: /** @@ -2874,16 +3063,11 @@ var Phaser; * @return {Rectangle} This rectangle object **/ function (x, y, width, height) { - if(!isNaN(x) && !isNaN(y) && !isNaN(width) && !isNaN(height)) { - this.x = x; - this.y = y; - if(width > 0) { - this.width = width; - } - if(height > 0) { - this.height = height; - } - } + this._tempX = x; + this._tempY = y; + this._tempWidth = width; + this._tempHeight = height; + this.updateBounds(); return this; }; Rectangle.prototype.union = /** @@ -6568,8 +6752,7 @@ var Phaser; this._game = game; } Motion.prototype.computeVelocity = /** - * A tween-like function that takes a starting velocity - * and some other factors and returns an altered velocity. + * A tween-like function that takes a starting velocity and some other factors and returns an altered velocity. * * @param Velocity Any component of velocity (e.g. 20). * @param Acceleration Rate at which the velocity is changing. @@ -6865,6 +7048,86 @@ var Phaser; })(); Phaser.Motion = Motion; })(Phaser || (Phaser = {})); +/// +/// +/** +* Phaser - Sound +* +* A Sound file, used by the Game.SoundManager for playback. +*/ +var Phaser; +(function (Phaser) { + var Sound = (function () { + function Sound(context, gainNode, data, volume, loop) { + if (typeof volume === "undefined") { volume = 1; } + if (typeof loop === "undefined") { loop = false; } + this.loop = false; + this.isPlaying = false; + this.isDecoding = false; + this._context = context; + this._gainNode = gainNode; + this._buffer = data; + this._volume = volume; + this.loop = loop; + // Local volume control + if(this._context !== null) { + this._localGainNode = this._context.createGainNode(); + this._localGainNode.connect(this._gainNode); + this._localGainNode.gain.value = this._volume; + } + if(this._buffer === null) { + this.isDecoding = true; + } else { + this.play(); + } + } + Sound.prototype.setDecodedBuffer = function (data) { + this._buffer = data; + this.isDecoding = false; + this.play(); + }; + Sound.prototype.play = function () { + if(this._buffer === null || this.isDecoding === true) { + return; + } + this._sound = this._context.createBufferSource(); + this._sound.buffer = this._buffer; + this._sound.connect(this._localGainNode); + if(this.loop) { + this._sound.loop = true; + } + this._sound.noteOn(0)// the zero is vitally important, crashes iOS6 without it + ; + this.duration = this._sound.buffer.duration; + this.isPlaying = true; + }; + Sound.prototype.stop = function () { + if(this.isPlaying === true) { + this.isPlaying = false; + this._sound.noteOff(0); + } + }; + Sound.prototype.mute = function () { + this._localGainNode.gain.value = 0; + }; + Sound.prototype.unmute = function () { + this._localGainNode.gain.value = this._volume; + }; + Object.defineProperty(Sound.prototype, "volume", { + get: function () { + return this._volume; + }, + set: function (value) { + this._volume = value; + this._localGainNode.gain.value = this._volume; + }, + enumerable: true, + configurable: true + }); + return Sound; + })(); + Phaser.Sound = Sound; +})(Phaser || (Phaser = {})); /// /// /** @@ -7108,6 +7371,9 @@ var Phaser; } else { document.body.appendChild(this.canvas); } + // Consume default actions on the canvas + this.canvas.style.msTouchAction = 'none'; + this.canvas.style['touch-action'] = 'none'; this.context = this.canvas.getContext('2d'); this.offset = this.getOffset(this.canvas); this.bounds = new Phaser.Rectangle(this.offset.x, this.offset.y, width, height); @@ -8947,6 +9213,8 @@ var Phaser; this.mouse = new Phaser.Mouse(this._game); this.keyboard = new Phaser.Keyboard(this._game); this.touch = new Phaser.Touch(this._game); + this.onDown = new Phaser.Signal(); + this.onUp = new Phaser.Signal(); } Input.prototype.update = function () { this.x = Math.round(this.x); @@ -9227,6 +9495,7 @@ var Phaser; 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; @@ -9252,6 +9521,7 @@ var Phaser; 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); }; return Mouse; })(); @@ -9622,6 +9892,7 @@ var Phaser; this._game.input.x = this.x * this._game.input.scaleX; this._game.input.y = this.y * this._game.input.scaleY; this.touchDown.dispatch(this._fingers[f].x, this._fingers[f].y, this._fingers[f].timeDown, this._fingers[f].timeUp, this._fingers[f].duration); + this._game.input.onDown.dispatch(this._game.input.x, this._game.input.y, this._fingers[f].timeDown); this.isDown = true; this.isUp = false; break; @@ -9728,6 +9999,7 @@ var Phaser; this._game.input.x = this.x * this._game.input.scaleX; this._game.input.y = this.y * this._game.input.scaleY; this.touchUp.dispatch(this._fingers[f].x, this._fingers[f].y, this._fingers[f].timeDown, this._fingers[f].timeUp, this._fingers[f].duration); + this._game.input.onUp.dispatch(this._game.input.x, this._game.input.y, this._fingers[f].timeUp); this.isDown = false; this.isUp = true; break; @@ -10194,7 +10466,7 @@ var Phaser; this._dh = this.bounds.height * this.scale.y; return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh); } else { - return camera.overlap(this.bounds); + return camera.intersects(this.bounds); } }; GeomSprite.prototype.render = function (camera, cameraOffsetX, cameraOffsetY) { @@ -10221,14 +10493,17 @@ var Phaser; this._dx -= (camera.worldView.x * this.scrollFactor.x); this._dy -= (camera.worldView.y * this.scrollFactor.y); } - // Rotation (could be misleading as it doesn't work re: collision) - if(this.angle !== 0) { - this._game.stage.context.save(); - this._game.stage.context.translate(this._dx + (this._dw / 2) - this.origin.x, this._dy + (this._dh / 2) - this.origin.y); - this._game.stage.context.rotate(this.angle * (Math.PI / 180)); - this._dx = -(this._dw / 2); - this._dy = -(this._dh / 2); + // Rotation is disabled for now as I don't want it to be misleading re: collision + /* + if (this.angle !== 0) + { + this._game.stage.context.save(); + this._game.stage.context.translate(this._dx + (this._dw / 2) - this.origin.x, this._dy + (this._dh / 2) - this.origin.y); + this._game.stage.context.rotate(this.angle * (Math.PI / 180)); + this._dx = -(this._dw / 2); + this._dy = -(this._dh / 2); } + */ this._dx = Math.round(this._dx); this._dy = Math.round(this._dy); this._dw = Math.round(this._dw); @@ -10272,6 +10547,17 @@ var Phaser; } this._game.stage.context.closePath(); } + // And now the edge points + this._game.stage.context.fillStyle = 'rgb(255,255,255)'; + this.renderPoint(this._dx, this._dy, this.rect.topLeft, 2); + this.renderPoint(this._dx, this._dy, this.rect.topCenter, 2); + this.renderPoint(this._dx, this._dy, this.rect.topRight, 2); + this.renderPoint(this._dx, this._dy, this.rect.leftCenter, 2); + this.renderPoint(this._dx, this._dy, this.rect.center, 2); + this.renderPoint(this._dx, this._dy, this.rect.rightCenter, 2); + this.renderPoint(this._dx, this._dy, this.rect.bottomLeft, 2); + this.renderPoint(this._dx, this._dy, this.rect.bottomCenter, 2); + this.renderPoint(this._dx, this._dy, this.rect.bottomRight, 2); } this._game.stage.restoreCanvasValues(); if(this.rotation !== 0) { @@ -10283,6 +10569,11 @@ var Phaser; } return true; }; + GeomSprite.prototype.renderPoint = function (offsetX, offsetY, point, size) { + offsetX = 0; + offsetY = 0; + this._game.stage.context.fillRect(offsetX + point.x, offsetY + point.y, 1, 1); + }; GeomSprite.prototype.renderDebugInfo = function (x, y, color) { if (typeof color === "undefined") { color = 'rgb(255,255,255)'; } //this._game.stage.context.fillStyle = color; @@ -10347,7 +10638,7 @@ var Phaser; return Phaser.Collision.lineSegmentToLineSegment(this.line, source.line).result; } // Line vs. Circle - if(this.type == GeomSprite.LINE && source.type == GeomSprite.LINE) { + if(this.type == GeomSprite.LINE && source.type == GeomSprite.CIRCLE) { return Phaser.Collision.lineToCircle(this.line, source.circle).result; } // Line vs. Rect @@ -10355,7 +10646,7 @@ var Phaser; return Phaser.Collision.lineSegmentToRectangle(this.line, source.rect).result; } // Line vs. Point - if(this.type == GeomSprite.LINE && source.type == GeomSprite.LINE) { + if(this.type == GeomSprite.LINE && source.type == GeomSprite.POINT) { return this.line.isPointOnLine(source.point.x, source.point.y); } return false; @@ -11082,84 +11373,138 @@ var Phaser; Phaser.Game = Game; })(Phaser || (Phaser = {})); /// -/// /** -* Phaser - Sound +* Phaser - MicroPoint * -* A Sound file, used by the Game.SoundManager for playback. +* The MicroPoint object represents a location in a two-dimensional coordinate system, +* where x represents the horizontal axis and y represents the vertical axis. +* It is different to the Point class in that it doesn't contain any of the help methods like add/substract/distanceTo, etc. +* Use a MicroPoint when all you literally need is a solid container for x and y (such as in the Rectangle class). */ var Phaser; (function (Phaser) { - var Sound = (function () { - function Sound(context, gainNode, data, volume, loop) { - if (typeof volume === "undefined") { volume = 1; } - if (typeof loop === "undefined") { loop = false; } - this.loop = false; - this.isPlaying = false; - this.isDecoding = false; - this._context = context; - this._gainNode = gainNode; - this._buffer = data; - this._volume = volume; - this.loop = loop; - // Local volume control - if(this._context !== null) { - this._localGainNode = this._context.createGainNode(); - this._localGainNode.connect(this._gainNode); - this._localGainNode.gain.value = this._volume; - } - if(this._buffer === null) { - this.isDecoding = true; - } else { - this.play(); - } + var MicroPoint = (function () { + /** + * Creates a new point. If you pass no parameters to this method, a point is created at (0,0). + * @class MicroPoint + * @constructor + * @param {Number} x The horizontal position of this point (default 0) + * @param {Number} y The vertical position of this point (default 0) + **/ + function MicroPoint(x, y, parent) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + if (typeof parent === "undefined") { parent = null; } + this._x = x; + this._y = y; + this.parent = parent; } - Sound.prototype.setDecodedBuffer = function (data) { - this._buffer = data; - this.isDecoding = false; - this.play(); - }; - Sound.prototype.play = function () { - if(this._buffer === null || this.isDecoding === true) { - return; - } - this._sound = this._context.createBufferSource(); - this._sound.buffer = this._buffer; - this._sound.connect(this._localGainNode); - if(this.loop) { - this._sound.loop = true; - } - this._sound.noteOn(0)// the zero is vitally important, crashes iOS6 without it - ; - this.duration = this._sound.buffer.duration; - this.isPlaying = true; - }; - Sound.prototype.stop = function () { - if(this.isPlaying === true) { - this.isPlaying = false; - this._sound.noteOff(0); - } - }; - Sound.prototype.mute = function () { - this._localGainNode.gain.value = 0; - }; - Sound.prototype.unmute = function () { - this._localGainNode.gain.value = this._volume; - }; - Object.defineProperty(Sound.prototype, "volume", { - get: function () { - return this._volume; + Object.defineProperty(MicroPoint.prototype, "x", { + get: /** + * The x coordinate of the top-left corner of the rectangle + * @property x + * @type Number + **/ + function () { + return this._x; }, - set: function (value) { - this._volume = value; - this._localGainNode.gain.value = this._volume; + set: /** + * The x coordinate of the top-left corner of the rectangle + * @property x + * @type Number + **/ + function (value) { + this._x = value; + if(this.parent) { + this.parent.updateBounds(); + } }, enumerable: true, configurable: true }); - return Sound; + Object.defineProperty(MicroPoint.prototype, "y", { + get: /** + * The y coordinate of the top-left corner of the rectangle + * @property y + * @type Number + **/ + function () { + return this._y; + }, + set: /** + * The y coordinate of the top-left corner of the rectangle + * @property y + * @type Number + **/ + function (value) { + this._y = value; + if(this.parent) { + this.parent.updateBounds(); + } + }, + enumerable: true, + configurable: true + }); + MicroPoint.prototype.copyFrom = /** + * Copies the x and y values from any given object to this MicroPoint. + * @method copyFrom + * @param {any} source - The object to copy from. + * @return {MicroPoint} This MicroPoint object. Useful for chaining method calls. + **/ + function (source) { + return this.setTo(source.x, source.y); + }; + MicroPoint.prototype.copyTo = /** + * Copies the x and y values from this MicroPoint to any given object. + * @method copyTo + * @param {any} target - The object to copy to. + * @return {any} The target object. + **/ + function (target) { + target.x = this._x; + target.y = this._y; + return target; + }; + MicroPoint.prototype.setTo = /** + * Sets the x and y values of this MicroPoint object to the given coordinates. + * @method setTo + * @param {Number} x - The horizontal position of this point. + * @param {Number} y - The vertical position of this point. + * @return {MicroPoint} This MicroPoint object. Useful for chaining method calls. + **/ + function (x, y, callParent) { + if (typeof callParent === "undefined") { callParent = true; } + this._x = x; + this._y = y; + if(this.parent != null && callParent == true) { + this.parent.updateBounds(); + } + return this; + }; + MicroPoint.prototype.equals = /** + * Determines whether this MicroPoint object and the given object are equal. They are equal if they have the same x and y values. + * @method equals + * @param {any} point - The object to compare against. Must have x and y properties. + * @return {Boolean} A value of true if the object is equal to this MicroPoin object; false if it is not equal. + **/ + function (toCompare) { + if(this._x === toCompare.x && this._y === toCompare.y) { + return true; + } else { + return false; + } + }; + MicroPoint.prototype.toString = /** + * Returns a string representation of this object. + * @method toString + * @return {string} a string representation of the instance. + **/ + function () { + return '[{MicroPoint (x=' + this._x + ' y=' + this._y + ')}]'; + }; + return MicroPoint; })(); - Phaser.Sound = Sound; + Phaser.MicroPoint = MicroPoint; })(Phaser || (Phaser = {})); /// /**