From d44775c095e8b3270031bac51e34ff11a95f8637 Mon Sep 17 00:00:00 2001 From: photonstorm Date: Mon, 10 Feb 2014 01:37:50 +0000 Subject: [PATCH] Phaser.Ellipse added. A fully compatible port of the PIXI.Ellipse class, can be used in Sprite/Image hitArea tests. Phaser.Polygon added. A fully compatible port of the PIXI.Polygon class, can be used in Sprite/Image hitArea tests. --- README.md | 2 + build/config.php | 2 +- src/Phaser.js | 3 +- src/geom/Circle.js | 84 ++++++++++++++++++++++++++++++++--------- src/geom/Ellipse.js | 2 + src/geom/Polygon.js | 92 ++++++++++++++++++++++++++++++++++++++++++--- 6 files changed, 159 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 7fa1b195..6284fe7a 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,8 @@ New features: * Text.setShadow applies a drop shadow to the Text being rendered. Control the x, y, color and blur. * Text.lineSpacing allows you to control the spacing between each line that is rendered. * Text.inputEnabled allows you to enable all input events over Text objects: dragging, clicking, etc - anything that works on a Sprite works on Text now too. +* Phaser.Ellipse added. A fully compatible port of the PIXI.Ellipse class, can be used in Sprite/Image hitArea tests. +* Phaser.Polygon added. A fully compatible port of the PIXI.Polygon class, can be used in Sprite/Image hitArea tests. New Examples: diff --git a/build/config.php b/build/config.php index b6a75deb..bd122201 100644 --- a/build/config.php +++ b/build/config.php @@ -63,9 +63,9 @@ + - diff --git a/src/Phaser.js b/src/Phaser.js index ad2bf892..1ce9b3a1 100644 --- a/src/Phaser.js +++ b/src/Phaser.js @@ -20,7 +20,7 @@ var Phaser = Phaser || { SPRITE: 0, BUTTON: 1, - BULLET: 2, + IMAGE: 2, GRAPHICS: 3, TEXT: 4, TILESPRITE: 5, @@ -34,6 +34,7 @@ var Phaser = Phaser || { BITMAPDATA: 13, CANVAS_FILTER: 14, WEBGL_FILTER: 15, + ELLIPSE: 16, NONE: 0, LEFT: 1, diff --git a/src/geom/Circle.js b/src/geom/Circle.js index 7e21cdd6..c755f013 100644 --- a/src/geom/Circle.js +++ b/src/geom/Circle.js @@ -71,11 +71,14 @@ Phaser.Circle.prototype = { * @return {Circle} This circle object. */ setTo: function (x, y, diameter) { + this.x = x; this.y = y; this._diameter = diameter; this._radius = diameter * 0.5; + return this; + }, /** @@ -85,7 +88,9 @@ Phaser.Circle.prototype = { * @return {Circle} This Circle object. */ copyFrom: function (source) { + return this.setTo(source.x, source.y, source.diameter); + }, /** @@ -94,11 +99,14 @@ Phaser.Circle.prototype = { * @param {any} dest - The object to copy to. * @return {Object} This dest object. */ - copyTo: function(dest) { + copyTo: function (dest) { + dest.x = this.x; dest.y = this.y; dest.diameter = this._diameter; + return dest; + }, /** @@ -130,7 +138,7 @@ Phaser.Circle.prototype = { * @param {Phaser.Circle} out - Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned. * @return {Phaser.Circle} The cloned Circle object. */ - clone: function(out) { + clone: function (out) { if (typeof out === "undefined") { @@ -153,7 +161,9 @@ Phaser.Circle.prototype = { * @return {boolean} True if the coordinates are within this circle, otherwise false. */ contains: function (x, y) { + return Phaser.Circle.contains(this, x, y); + }, /** @@ -165,7 +175,9 @@ Phaser.Circle.prototype = { * @return {Phaser.Point} The Point object holding the result. */ circumferencePoint: function (angle, asDegrees, out) { + return Phaser.Circle.circumferencePoint(this, angle, asDegrees, out); + }, /** @@ -176,9 +188,12 @@ Phaser.Circle.prototype = { * @return {Circle} This Circle object. */ offset: function (dx, dy) { + this.x += dx; this.y += dy; + return this; + }, /** @@ -216,7 +231,9 @@ Object.defineProperty(Phaser.Circle.prototype, "diameter", { }, set: function (value) { - if (value > 0) { + + if (value > 0) + { this._diameter = value; this._radius = value * 0.5; } @@ -236,10 +253,13 @@ Object.defineProperty(Phaser.Circle.prototype, "radius", { }, set: function (value) { - if (value > 0) { + + if (value > 0) + { this._radius = value; this._diameter = value * 2; } + } }); @@ -256,12 +276,17 @@ Object.defineProperty(Phaser.Circle.prototype, "left", { }, set: function (value) { - if (value > this.x) { + + if (value > this.x) + { this._radius = 0; this._diameter = 0; - } else { + } + else + { this.radius = this.x - value; } + } }); @@ -278,12 +303,17 @@ Object.defineProperty(Phaser.Circle.prototype, "right", { }, set: function (value) { - if (value < this.x) { + + if (value < this.x) + { this._radius = 0; this._diameter = 0; - } else { + } + else + { this.radius = value - this.x; } + } }); @@ -300,12 +330,17 @@ Object.defineProperty(Phaser.Circle.prototype, "top", { }, set: function (value) { - if (value > this.y) { + + if (value > this.y) + { this._radius = 0; this._diameter = 0; - } else { + } + else + { this.radius = this.y - value; } + } }); @@ -323,12 +358,16 @@ Object.defineProperty(Phaser.Circle.prototype, "bottom", { set: function (value) { - if (value < this.y) { + if (value < this.y) + { this._radius = 0; this._diameter = 0; - } else { + } + else + { this.radius = value - this.y; } + } }); @@ -342,11 +381,16 @@ Object.defineProperty(Phaser.Circle.prototype, "bottom", { Object.defineProperty(Phaser.Circle.prototype, "area", { get: function () { - if (this._radius > 0) { + + if (this._radius > 0) + { return Math.PI * this._radius * this._radius; - } else { + } + else + { return 0; } + } }); @@ -436,7 +480,8 @@ Phaser.Circle.circumferencePoint = function (a, angle, asDegrees, out) { if (typeof asDegrees === "undefined") { asDegrees = false; } if (typeof out === "undefined") { out = new Phaser.Point(); } - if (asDegrees === true) { + if (asDegrees === true) + { angle = Phaser.Math.radToDeg(angle); } @@ -459,18 +504,21 @@ Phaser.Circle.intersectsRectangle = function (c, r) { var cx = Math.abs(c.x - r.x - r.halfWidth); var xDist = r.halfWidth + c.radius; - if (cx > xDist) { + if (cx > xDist) + { return false; } var cy = Math.abs(c.y - r.y - r.halfHeight); var yDist = r.halfHeight + c.radius; - if (cy > yDist) { + if (cy > yDist) + { return false; } - if (cx <= r.halfWidth || cy <= r.halfHeight) { + if (cx <= r.halfWidth || cy <= r.halfHeight) + { return true; } diff --git a/src/geom/Ellipse.js b/src/geom/Ellipse.js index f50b22d6..7a5cced9 100644 --- a/src/geom/Ellipse.js +++ b/src/geom/Ellipse.js @@ -18,6 +18,8 @@ */ Phaser.Ellipse = function (x, y, width, height) { + this.type = Phaser.ELLIPSE; + x = x || 0; y = y || 0; width = width || 0; diff --git a/src/geom/Polygon.js b/src/geom/Polygon.js index c81ad370..8303a17e 100644 --- a/src/geom/Polygon.js +++ b/src/geom/Polygon.js @@ -1,5 +1,6 @@ /** * @author Richard Davey +* @author Adrien Brault * @copyright 2014 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ @@ -7,8 +8,8 @@ /** * Creates a new Polygon. You have to provide a list of points. * This can be an array of Points that form the polygon, a flat array of numbers that will be interpreted as [x,y, x,y, ...], -* or the arguments passed can be all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the -* arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are numbers. +* or the arguments passed can be all the points of the polygon e.g. `new Phaser.Polygon(new Phaser.Point(), new Phaser.Point(), ...)`, or the +* arguments passed can be flat x,y values e.g. `new Phaser.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are numbers. * * @class Phaser.Polygon * @classdesc The polygon represents a list of orderded points in space @@ -17,14 +18,93 @@ */ Phaser.Polygon = function (points) { - PIXI.Polygon.call(this, points); - /** * @property {number} type - The base object type. */ this.type = Phaser.POLYGON; + //if points isn't an array, use arguments as the array + if (!(points instanceof Array)) + { + points = Array.prototype.slice.call(arguments); + } + + //if this is a flat array of numbers, convert it to points + if (typeof points[0] === 'number') + { + var p = []; + + for (var i = 0, len = points.length; i < len; i += 2) + { + p.push(new Phaser.Point(points[i], points[i + 1])); + } + + points = p; + } + + /** + * @property {array|array} points - The array of Points. + */ + this.points = points; + }; -Phaser.Polygon.prototype = Object.create(PIXI.Polygon.prototype); -Phaser.Polygon.prototype.constructor = Phaser.Polygon; \ No newline at end of file +Phaser.Polygon.prototype = { + + /** + * Creates a clone of this polygon. + * + * @method Phaser.Polygon#clone + * @return {Phaser.Polygon} A copy of the polygon. + */ + clone: function () { + + var points = []; + + for (var i=0; i < this.points.length; i++) + { + points.push(this.points[i].clone()); + } + + return new Phaser.Polygon(points); + + }, + + /** + * Checks whether the x and y coordinates are contained within this polygon. + * + * @method Phaser.Polygon#contains + * @param {number} x - The X value of the coordinate to test. + * @param {number} y - The Y value of the coordinate to test. + * @return {boolean} True if the coordinates are within this polygon, otherwise false. + */ + contains: function (x, y) { + + var inside = false; + + // use some raycasting to test hits https://github.com/substack/point-in-polygon/blob/master/index.js + for (var i = 0, j = this.points.length - 1; i < this.points.length; j = i++) + { + var xi = this.points[i].x; + var yi = this.points[i].y; + var xj = this.points[j].x; + var yj = this.points[j].y; + + var intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); + + if (intersect) + { + inside = true; + } + } + + return inside; + + } + +}; + +Phaser.Polygon.prototype.constructor = Phaser.Polygon; + +// Because PIXI uses its own Polygon, we'll replace it with ours to avoid duplicating code or confusion. +PIXI.Polygon = Phaser.Polygon;