diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 6373e86..1a633ec 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -315,43 +315,11 @@ y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; //a sprite or display object with a hit area defined - if(item.hitArea) - { - var hitArea = item.hitArea; + if(item.hitArea && item.hitArea.contains && item.hitArea.contains(x, y)) { + if(isSprite) + interactionData.target = item; - //Polygon hit area - if(item.hitArea instanceof PIXI.Polygon) { - 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 = item.hitArea.points.length - 1; i < item.hitArea.points.length; j = i++) { - var xi = item.hitArea.points[i].x, yi = item.hitArea.points[i].y, - xj = item.hitArea.points[j].x, yj = item.hitArea.points[j].y, - intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); - - if(intersect) inside = !inside; - } - - if(inside) { - if(isSprite) interactionData.target = item; - return true; - } - } - //Rectangle hit area - else { - var x1 = hitArea.x; - if(x > x1 && x < x1 + hitArea.width) - { - var y1 = hitArea.y; - - if(y > y1 && y < y1 + hitArea.height) - { - if(isSprite) interactionData.target = item; - return true; - } - } - } + return true; } // a sprite with no hitarea defined else if(isSprite) diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 6373e86..1a633ec 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -315,43 +315,11 @@ y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; //a sprite or display object with a hit area defined - if(item.hitArea) - { - var hitArea = item.hitArea; + if(item.hitArea && item.hitArea.contains && item.hitArea.contains(x, y)) { + if(isSprite) + interactionData.target = item; - //Polygon hit area - if(item.hitArea instanceof PIXI.Polygon) { - 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 = item.hitArea.points.length - 1; i < item.hitArea.points.length; j = i++) { - var xi = item.hitArea.points[i].x, yi = item.hitArea.points[i].y, - xj = item.hitArea.points[j].x, yj = item.hitArea.points[j].y, - intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); - - if(intersect) inside = !inside; - } - - if(inside) { - if(isSprite) interactionData.target = item; - return true; - } - } - //Rectangle hit area - else { - var x1 = hitArea.x; - if(x > x1 && x < x1 + hitArea.width) - { - var y1 = hitArea.y; - - if(y > y1 && y < y1 + hitArea.height) - { - if(isSprite) interactionData.target = item; - return true; - } - } - } + return true; } // a sprite with no hitarea defined else if(isSprite) diff --git a/src/pixi/core/Circle.js b/src/pixi/core/Circle.js new file mode 100644 index 0000000..7a0f8af --- /dev/null +++ b/src/pixi/core/Circle.js @@ -0,0 +1,67 @@ +/** + * @author Chad Engler + */ + +/** + * @class Circle + * @constructor + * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle + * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle + * @param radius {Number} The radius of the circle + */ +PIXI.Circle = function(x, y, radius) +{ + /** + * @property x + * @type Number + * @default 0 + */ + this.x = x || 0; + + /** + * @property y + * @type Number + * @default 0 + */ + this.y = y || 0; + + /** + * @property radius + * @type Number + * @default 0 + */ + this.radius = radius || 0; +} + +/** + * @method clone + * @return a copy of the polygon + */ +PIXI.Circle.clone = function() +{ + return new PIXI.Circle(this.x, this.y, this.radius); +} + +/** + * @method contains + * @param x {Number} The X coord of the point to test + * @param y {Number} The Y coord of the point to test + * @return if the x/y coords are within this polygon + */ +PIXI.Circle.contains = function(x, y) +{ + if(this.radius <= 0) + return false; + + var dx = (this.x - x), + dy = (this.y - y), + r2 = this.radius * this.radius; + + dx *= dx; + dy *= dy; + + return (dx + dy <= r2); +} + +PIXI.Circle.constructor = PIXI.Circle; + diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 6373e86..1a633ec 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -315,43 +315,11 @@ y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; //a sprite or display object with a hit area defined - if(item.hitArea) - { - var hitArea = item.hitArea; + if(item.hitArea && item.hitArea.contains && item.hitArea.contains(x, y)) { + if(isSprite) + interactionData.target = item; - //Polygon hit area - if(item.hitArea instanceof PIXI.Polygon) { - 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 = item.hitArea.points.length - 1; i < item.hitArea.points.length; j = i++) { - var xi = item.hitArea.points[i].x, yi = item.hitArea.points[i].y, - xj = item.hitArea.points[j].x, yj = item.hitArea.points[j].y, - intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); - - if(intersect) inside = !inside; - } - - if(inside) { - if(isSprite) interactionData.target = item; - return true; - } - } - //Rectangle hit area - else { - var x1 = hitArea.x; - if(x > x1 && x < x1 + hitArea.width) - { - var y1 = hitArea.y; - - if(y > y1 && y < y1 + hitArea.height) - { - if(isSprite) interactionData.target = item; - return true; - } - } - } + return true; } // a sprite with no hitarea defined else if(isSprite) diff --git a/src/pixi/core/Circle.js b/src/pixi/core/Circle.js new file mode 100644 index 0000000..7a0f8af --- /dev/null +++ b/src/pixi/core/Circle.js @@ -0,0 +1,67 @@ +/** + * @author Chad Engler + */ + +/** + * @class Circle + * @constructor + * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle + * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle + * @param radius {Number} The radius of the circle + */ +PIXI.Circle = function(x, y, radius) +{ + /** + * @property x + * @type Number + * @default 0 + */ + this.x = x || 0; + + /** + * @property y + * @type Number + * @default 0 + */ + this.y = y || 0; + + /** + * @property radius + * @type Number + * @default 0 + */ + this.radius = radius || 0; +} + +/** + * @method clone + * @return a copy of the polygon + */ +PIXI.Circle.clone = function() +{ + return new PIXI.Circle(this.x, this.y, this.radius); +} + +/** + * @method contains + * @param x {Number} The X coord of the point to test + * @param y {Number} The Y coord of the point to test + * @return if the x/y coords are within this polygon + */ +PIXI.Circle.contains = function(x, y) +{ + if(this.radius <= 0) + return false; + + var dx = (this.x - x), + dy = (this.y - y), + r2 = this.radius * this.radius; + + dx *= dx; + dy *= dy; + + return (dx + dy <= r2); +} + +PIXI.Circle.constructor = PIXI.Circle; + diff --git a/src/pixi/core/Ellipse.js b/src/pixi/core/Ellipse.js new file mode 100644 index 0000000..0330766 --- /dev/null +++ b/src/pixi/core/Ellipse.js @@ -0,0 +1,81 @@ +/** + * @author Chad Engler + */ + +/** + * @class Ellipse + * @constructor + * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle + * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle + * @param width {Number} The overall height of this ellipse + * @param height {Number} The overall width of this ellipse + */ +PIXI.Ellipse = function(x, y, width, height) +{ + /** + * @property x + * @type Number + * @default 0 + */ + this.x = x || 0; + + /** + * @property y + * @type Number + * @default 0 + */ + this.y = y || 0; + + /** + * @property width + * @type Number + * @default 0 + */ + this.width = width || 0; + + /** + * @property height + * @type Number + * @default 0 + */ + this.height = height || 0; +} + +/** + * @method clone + * @return a copy of the polygon + */ +PIXI.Ellipse.clone = function() +{ + return new PIXI.Ellipse(this.x, this.y, this.width, this.height); +} + +/** + * @method contains + * @param x {Number} The X coord of the point to test + * @param y {Number} The Y coord of the point to test + * @return if the x/y coords are within this polygon + */ +PIXI.Ellipse.contains = function(x, y) +{ + if(this.width <= 0 || this.height <= 0) + return false; + + //normalize the coords to an ellipse with center 0,0 + //and a radius of 0.5 + var normx = ((x - this.x) / this.width) - 0.5, + normy = ((y - this.y) / this.height) - 0.5; + + normx *= normx; + normy *= normy; + + return (normx + normy < 0.25); +} + +PIXI.Ellipse.getBounds = function() +{ + return new PIXI.Rectangle(this.x, this.y, this.width, this.height); +} + +PIXI.Ellipse.constructor = PIXI.Ellipse; + diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 6373e86..1a633ec 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -315,43 +315,11 @@ y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; //a sprite or display object with a hit area defined - if(item.hitArea) - { - var hitArea = item.hitArea; + if(item.hitArea && item.hitArea.contains && item.hitArea.contains(x, y)) { + if(isSprite) + interactionData.target = item; - //Polygon hit area - if(item.hitArea instanceof PIXI.Polygon) { - 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 = item.hitArea.points.length - 1; i < item.hitArea.points.length; j = i++) { - var xi = item.hitArea.points[i].x, yi = item.hitArea.points[i].y, - xj = item.hitArea.points[j].x, yj = item.hitArea.points[j].y, - intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); - - if(intersect) inside = !inside; - } - - if(inside) { - if(isSprite) interactionData.target = item; - return true; - } - } - //Rectangle hit area - else { - var x1 = hitArea.x; - if(x > x1 && x < x1 + hitArea.width) - { - var y1 = hitArea.y; - - if(y > y1 && y < y1 + hitArea.height) - { - if(isSprite) interactionData.target = item; - return true; - } - } - } + return true; } // a sprite with no hitarea defined else if(isSprite) diff --git a/src/pixi/core/Circle.js b/src/pixi/core/Circle.js new file mode 100644 index 0000000..7a0f8af --- /dev/null +++ b/src/pixi/core/Circle.js @@ -0,0 +1,67 @@ +/** + * @author Chad Engler + */ + +/** + * @class Circle + * @constructor + * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle + * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle + * @param radius {Number} The radius of the circle + */ +PIXI.Circle = function(x, y, radius) +{ + /** + * @property x + * @type Number + * @default 0 + */ + this.x = x || 0; + + /** + * @property y + * @type Number + * @default 0 + */ + this.y = y || 0; + + /** + * @property radius + * @type Number + * @default 0 + */ + this.radius = radius || 0; +} + +/** + * @method clone + * @return a copy of the polygon + */ +PIXI.Circle.clone = function() +{ + return new PIXI.Circle(this.x, this.y, this.radius); +} + +/** + * @method contains + * @param x {Number} The X coord of the point to test + * @param y {Number} The Y coord of the point to test + * @return if the x/y coords are within this polygon + */ +PIXI.Circle.contains = function(x, y) +{ + if(this.radius <= 0) + return false; + + var dx = (this.x - x), + dy = (this.y - y), + r2 = this.radius * this.radius; + + dx *= dx; + dy *= dy; + + return (dx + dy <= r2); +} + +PIXI.Circle.constructor = PIXI.Circle; + diff --git a/src/pixi/core/Ellipse.js b/src/pixi/core/Ellipse.js new file mode 100644 index 0000000..0330766 --- /dev/null +++ b/src/pixi/core/Ellipse.js @@ -0,0 +1,81 @@ +/** + * @author Chad Engler + */ + +/** + * @class Ellipse + * @constructor + * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle + * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle + * @param width {Number} The overall height of this ellipse + * @param height {Number} The overall width of this ellipse + */ +PIXI.Ellipse = function(x, y, width, height) +{ + /** + * @property x + * @type Number + * @default 0 + */ + this.x = x || 0; + + /** + * @property y + * @type Number + * @default 0 + */ + this.y = y || 0; + + /** + * @property width + * @type Number + * @default 0 + */ + this.width = width || 0; + + /** + * @property height + * @type Number + * @default 0 + */ + this.height = height || 0; +} + +/** + * @method clone + * @return a copy of the polygon + */ +PIXI.Ellipse.clone = function() +{ + return new PIXI.Ellipse(this.x, this.y, this.width, this.height); +} + +/** + * @method contains + * @param x {Number} The X coord of the point to test + * @param y {Number} The Y coord of the point to test + * @return if the x/y coords are within this polygon + */ +PIXI.Ellipse.contains = function(x, y) +{ + if(this.width <= 0 || this.height <= 0) + return false; + + //normalize the coords to an ellipse with center 0,0 + //and a radius of 0.5 + var normx = ((x - this.x) / this.width) - 0.5, + normy = ((y - this.y) / this.height) - 0.5; + + normx *= normx; + normy *= normy; + + return (normx + normy < 0.25); +} + +PIXI.Ellipse.getBounds = function() +{ + return new PIXI.Rectangle(this.x, this.y, this.width, this.height); +} + +PIXI.Ellipse.constructor = PIXI.Ellipse; + diff --git a/src/pixi/core/Polygon.js b/src/pixi/core/Polygon.js index d9f6ef0..a433bb4 100644 --- a/src/pixi/core/Polygon.js +++ b/src/pixi/core/Polygon.js @@ -5,10 +5,23 @@ /** * @class Polygon * @constructor - * @param points {Array} + * @param points {Array|Array} This cna be an array of Points or a flat array of numbers + * that will be interpreted as [x,y, x,y, ...] */ PIXI.Polygon = function(points) { + //if this is a flat array of numbers, convert it to points + if(typeof points[0] === 'number') { + var p = []; + for(var i = 0, il = points.length; i < il; i+=2) { + p.push( + new PIXI.Point(points[i], points[i + 1]) + ); + } + + points = p; + } + this.points = points; } @@ -26,5 +39,28 @@ return new PIXI.Polygon(points); } +/** + * @method contains + * @param x {Number} The X coord of the point to test + * @param y {Number} The Y coord of the point to test + * @return if the x/y coords are within this polygon + */ +PIXI.Polygon.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, yi = this.points[i].y, + xj = this.points[j].x, yj = this.points[j].y, + intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); + + if(intersect) inside = !inside; + } + + return inside; +} + PIXI.Polygon.constructor = PIXI.Polygon; diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 6373e86..1a633ec 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -315,43 +315,11 @@ y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; //a sprite or display object with a hit area defined - if(item.hitArea) - { - var hitArea = item.hitArea; + if(item.hitArea && item.hitArea.contains && item.hitArea.contains(x, y)) { + if(isSprite) + interactionData.target = item; - //Polygon hit area - if(item.hitArea instanceof PIXI.Polygon) { - 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 = item.hitArea.points.length - 1; i < item.hitArea.points.length; j = i++) { - var xi = item.hitArea.points[i].x, yi = item.hitArea.points[i].y, - xj = item.hitArea.points[j].x, yj = item.hitArea.points[j].y, - intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); - - if(intersect) inside = !inside; - } - - if(inside) { - if(isSprite) interactionData.target = item; - return true; - } - } - //Rectangle hit area - else { - var x1 = hitArea.x; - if(x > x1 && x < x1 + hitArea.width) - { - var y1 = hitArea.y; - - if(y > y1 && y < y1 + hitArea.height) - { - if(isSprite) interactionData.target = item; - return true; - } - } - } + return true; } // a sprite with no hitarea defined else if(isSprite) diff --git a/src/pixi/core/Circle.js b/src/pixi/core/Circle.js new file mode 100644 index 0000000..7a0f8af --- /dev/null +++ b/src/pixi/core/Circle.js @@ -0,0 +1,67 @@ +/** + * @author Chad Engler + */ + +/** + * @class Circle + * @constructor + * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle + * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle + * @param radius {Number} The radius of the circle + */ +PIXI.Circle = function(x, y, radius) +{ + /** + * @property x + * @type Number + * @default 0 + */ + this.x = x || 0; + + /** + * @property y + * @type Number + * @default 0 + */ + this.y = y || 0; + + /** + * @property radius + * @type Number + * @default 0 + */ + this.radius = radius || 0; +} + +/** + * @method clone + * @return a copy of the polygon + */ +PIXI.Circle.clone = function() +{ + return new PIXI.Circle(this.x, this.y, this.radius); +} + +/** + * @method contains + * @param x {Number} The X coord of the point to test + * @param y {Number} The Y coord of the point to test + * @return if the x/y coords are within this polygon + */ +PIXI.Circle.contains = function(x, y) +{ + if(this.radius <= 0) + return false; + + var dx = (this.x - x), + dy = (this.y - y), + r2 = this.radius * this.radius; + + dx *= dx; + dy *= dy; + + return (dx + dy <= r2); +} + +PIXI.Circle.constructor = PIXI.Circle; + diff --git a/src/pixi/core/Ellipse.js b/src/pixi/core/Ellipse.js new file mode 100644 index 0000000..0330766 --- /dev/null +++ b/src/pixi/core/Ellipse.js @@ -0,0 +1,81 @@ +/** + * @author Chad Engler + */ + +/** + * @class Ellipse + * @constructor + * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle + * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle + * @param width {Number} The overall height of this ellipse + * @param height {Number} The overall width of this ellipse + */ +PIXI.Ellipse = function(x, y, width, height) +{ + /** + * @property x + * @type Number + * @default 0 + */ + this.x = x || 0; + + /** + * @property y + * @type Number + * @default 0 + */ + this.y = y || 0; + + /** + * @property width + * @type Number + * @default 0 + */ + this.width = width || 0; + + /** + * @property height + * @type Number + * @default 0 + */ + this.height = height || 0; +} + +/** + * @method clone + * @return a copy of the polygon + */ +PIXI.Ellipse.clone = function() +{ + return new PIXI.Ellipse(this.x, this.y, this.width, this.height); +} + +/** + * @method contains + * @param x {Number} The X coord of the point to test + * @param y {Number} The Y coord of the point to test + * @return if the x/y coords are within this polygon + */ +PIXI.Ellipse.contains = function(x, y) +{ + if(this.width <= 0 || this.height <= 0) + return false; + + //normalize the coords to an ellipse with center 0,0 + //and a radius of 0.5 + var normx = ((x - this.x) / this.width) - 0.5, + normy = ((y - this.y) / this.height) - 0.5; + + normx *= normx; + normy *= normy; + + return (normx + normy < 0.25); +} + +PIXI.Ellipse.getBounds = function() +{ + return new PIXI.Rectangle(this.x, this.y, this.width, this.height); +} + +PIXI.Ellipse.constructor = PIXI.Ellipse; + diff --git a/src/pixi/core/Polygon.js b/src/pixi/core/Polygon.js index d9f6ef0..a433bb4 100644 --- a/src/pixi/core/Polygon.js +++ b/src/pixi/core/Polygon.js @@ -5,10 +5,23 @@ /** * @class Polygon * @constructor - * @param points {Array} + * @param points {Array|Array} This cna be an array of Points or a flat array of numbers + * that will be interpreted as [x,y, x,y, ...] */ PIXI.Polygon = function(points) { + //if this is a flat array of numbers, convert it to points + if(typeof points[0] === 'number') { + var p = []; + for(var i = 0, il = points.length; i < il; i+=2) { + p.push( + new PIXI.Point(points[i], points[i + 1]) + ); + } + + points = p; + } + this.points = points; } @@ -26,5 +39,28 @@ return new PIXI.Polygon(points); } +/** + * @method contains + * @param x {Number} The X coord of the point to test + * @param y {Number} The Y coord of the point to test + * @return if the x/y coords are within this polygon + */ +PIXI.Polygon.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, yi = this.points[i].y, + xj = this.points[j].x, yj = this.points[j].y, + intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); + + if(intersect) inside = !inside; + } + + return inside; +} + PIXI.Polygon.constructor = PIXI.Polygon; diff --git a/src/pixi/core/Rectangle.js b/src/pixi/core/Rectangle.js index f3513eb..6ac1884 100644 --- a/src/pixi/core/Rectangle.js +++ b/src/pixi/core/Rectangle.js @@ -51,6 +51,31 @@ return new PIXI.Rectangle(this.x, this.y, this.width, this.height); } +/** + * @method contains + * @param x {Number} The X coord of the point to test + * @param y {Number} The Y coord of the point to test + * @return if the x/y coords are within this polygon + */ +PIXI.Rectangle.contains = function(x, y) +{ + if(this.width <= 0 || this.height <= 0) + return false; + + var x1 = this.x; + if(x > x1 && x < x1 + this.width) + { + var y1 = this.y; + + if(y > y1 && y < y1 + this.height) + { + return true; + } + } + + return false; +} + // constructor PIXI.Rectangle.constructor = PIXI.Rectangle;