import config from 'config';
import recycle from 'recycle';
const
/**
* This class defines an axis-aligned bounding box (AABB) which is used during the collision process to determine if two objects are colliding. This is used in a few places including [CollisionBasic](platypus.components.CollisionBasic.html) and [[Collision-Shape]].
*
* @memberof platypus
* @class AABB
* @param x {number} The x position of the AABB. The x is always located in the center of the object.
* @param y {number} The y position of the AABB. The y is always located in the center of the object.
* @param width {number} The width of the AABB.
* @param height {number} The height of the AABB.
* @return {platypus.AABB} Returns the new aabb object.
*/
AABB = function (x, y, width, height) {
if (x instanceof AABB) {
this.set(x);
} else {
this.empty = true;
this.setAll(x, y, width, height);
}
},
proto = AABB.prototype;
/**
* Sets all of the properties of the AABB.
*
* @method platypus.AABB#setAll
* @param x {number} The x position of the AABB. The x is always located in the center of the object.
* @param y {number} The y position of the AABB. The y is always located in the center of the object.
* @param width {number} The width of the AABB.
* @param height {number} The height of the AABB.
* @chainable
*/
proto.setAll = function (x, y, width, height) {
this.empty = false;
this.x = x;
this.y = y;
this.resize(width, height);
return this;
};
/**
* Sets bounds of the AABB.
*
* @method platypus.AABB#setBounds
* @param left {number} The left side of the AABB.
* @param top {number} The top side of the AABB.
* @param right {number} The right side of the AABB.
* @param bottom {number} The bottom side of the AABB.
* @chainable
*/
proto.setBounds = function (left, top, right, bottom) {
this.empty = false;
this.x = (right + left) / 2;
this.y = (top + bottom) / 2;
this.resize(right - left, bottom - top);
return this;
};
/**
* Sets the AABB values to those of the provided AABB.
*
* @method platypus.AABB#set
* @param aabb {platypus.AABB} The AABB to copy values.
* @chainable
*/
proto.set = function (aabb) {
/**
* Whether the AABB encloses a valid space.
*
* @property empty
* @type boolean
*/
this.empty = aabb.empty;
/**
* The x position of the AABB. The x is always located in the center of the object.
*
* @property x
* @type number
*/
this.x = aabb.x;
/**
* The y position of the AABB. The y is always located in the center of the object.
*
* @property y
* @type number
*/
this.y = aabb.y;
/**
* The width of the AABB.
*
* @property width
* @type number
*/
this.width = aabb.width;
/**
* The height of the AABB.
*
* @property height
* @type number
*/
this.height = aabb.height;
/**
* Half the width of the AABB.
*
* @property halfWidth
* @type number
*/
this.halfWidth = aabb.halfWidth;
/**
* Half the height of the AABB.
*
* @property halfHeight
* @type number
*/
this.halfHeight = aabb.halfHeight;
/**
* The x-position of the left edge of the AABB.
*
* @property left
* @type number
*/
this.left = aabb.left;
/**
* The x-position of the right edge of the AABB.
*
* @property right
* @type number
*/
this.right = aabb.right;
/**
* The y-position of the top edge of the AABB.
*
* @property top
* @type number
*/
this.top = aabb.top;
/**
* The y-position of the bottom edge of the AABB.
*
* @property bottom
* @type number
*/
this.bottom = aabb.bottom;
return this;
};
/**
* Returns a string listing AABB dimensions.
*
* @method platypus.AABB#toString
* @return String
*/
proto.toString = function () {
return '[AABB: ' + this.width + 'x' + this.height + ' (' + this.x + ', ' + this.y + ')]';
};
/**
* Resets all the values in the AABB so that the AABB can be reused.
*
* @method platypus.AABB#reset
* @chainable
*/
proto.reset = function () {
this.empty = true;
return this;
};
/**
* Resizes the AABB.
*
* @method platypus.AABB#resize
* @param width {number} The new width of the AABB
* @param height {number} The new height of the AABB
* @chainable
*/
proto.resize = function (width, height) {
var w = width || 0,
h = height || 0,
hw = w / 2,
hh = h / 2;
this.width = w;
this.height = h;
this.halfWidth = hw;
this.halfHeight = hh;
if (typeof this.x === 'number') {
this.left = -hw + this.x;
this.right = hw + this.x;
} else {
this.empty = true;
}
if (typeof this.y === 'number') {
this.top = -hh + this.y;
this.bottom = hh + this.y;
} else {
this.empty = true;
}
return this;
};
/**
* Changes the size and position of the bounding box so that it contains the current area and the area described in the incoming AABB.
*
* @method platypus.AABB#include
* @param aabb {platypus.AABB} The AABB whose area will be included in the area of the current AABB.
* @chainable
*/
proto.include = function (aabb) {
if (this.empty) {
this.set(aabb);
} else {
if (this.left > aabb.left) {
this.left = aabb.left;
}
if (this.right < aabb.right) {
this.right = aabb.right;
}
if (this.top > aabb.top) {
this.top = aabb.top;
}
if (this.bottom < aabb.bottom) {
this.bottom = aabb.bottom;
}
this.width = this.right - this.left;
this.height = this.bottom - this.top;
this.halfWidth = this.width / 2;
this.halfHeight = this.height / 2;
this.x = this.left + this.halfWidth;
this.y = this.top + this.halfHeight;
}
return this;
};
/**
* Moves the AABB to the specified location.
*
* @method platypus.AABB#move
* @param x {number} The new x position of the AABB.
* @param y {number} The new y position of the AABB.
* @chainable
*/
proto.move = function (x, y) {
this.moveX(x);
this.moveY(y);
return this;
};
/**
* Moves the AABB to the specified location.
*
* @method platypus.AABB#moveX
* @param x {number} The new x position of the AABB.
* @chainable
*/
proto.moveX = function (x) {
this.x = x;
this.left = -this.halfWidth + x;
this.right = this.halfWidth + x;
return this;
};
/**
* Moves the AABB to the specified location.
*
* @method platypus.AABB#moveY
* @param y {number} The new y position of the AABB.
* @chainable
*/
proto.moveY = function (y) {
this.y = y;
this.top = -this.halfHeight + y;
this.bottom = this.halfHeight + y;
return this;
};
/**
* Moves the AABB to the specified location.
*
* @method platypus.AABB#moveXBy
* @param deltaX {number} The change in x position of the AABB.
* @chainable
*/
proto.moveXBy = function (deltaX) {
return this.moveX(this.x + deltaX);
};
/**
* Moves the AABB to the specified location.
*
* @method platypus.AABB#moveYBy
* @param deltaY {number} The change in y position of the AABB.
* @chainable
*/
proto.moveYBy = function (deltaY) {
return this.moveY(this.y + deltaY);
};
/**
* Expresses whether this AABB matches the provided AABB.
*
* @method platypus.AABB#equals
* @param aabb {platypus.AABB} The AABB to check against.
* @return {Boolean} Returns `true` if the AABB's match.
*/
proto.equals = function (aabb) {
return !this.empty && !aabb.empty && (this.left === aabb.left) && (this.top === aabb.top) && (this.right === aabb.right) && (this.bottom === aabb.bottom);
};
/**
* Expresses whether this AABB contains the given AABB.
*
* @method platypus.AABB#contains
* @param aabb {platypus.AABB} The AABB to check against
* @return {boolean} Returns `true` if this AABB contains the other AABB.
*/
proto.contains = function (aabb) {
return (aabb.top >= this.top) && (aabb.bottom <= this.bottom) && (aabb.left >= this.left) && (aabb.right <= this.right);
};
/**
* Expresses whether this AABB contains the given point.
*
* @method platypus.AABB#containsVector
* @param vector {platypus.Vector} The vector to check.
* @return {boolean} Returns `true` if this AABB contains the vector.
*/
proto.containsVector = function (vector) {
return this.containsPoint(vector.x, vector.y);
};
/**
* Expresses whether this AABB contains the given point.
*
* @method platypus.AABB#containsPoint
* @param x {number} The x-axis value.
* @param y {number} The y-axis value.
* @return {boolean} Returns `true` if this AABB contains the point.
*/
proto.containsPoint = function (x, y) {
return (y >= this.top) && (y <= this.bottom) && (x >= this.left) && (x <= this.right);
};
/**
* Expresses whether this AABB collides with the given AABB. This is similar to `intersects` but returns true for overlapping only, not touching edges.
*
* @method platypus.AABB#collides
* @param aabb {platypus.AABB} The AABB to check against
* @return {boolean} Returns `true` if this AABB collides with the other AABB.
*/
proto.collides = function (aabb) {
return (aabb.bottom > this.top) && (aabb.top < this.bottom) && (aabb.right > this.left) && (aabb.left < this.right);
};
/**
* Expresses whether this AABB collides with the given point. This is an exclusive version of containsPoint.
*
* @method platypus.AABB#collidesPoint
* @param x {number} The x-axis value.
* @param y {number} The y-axis value.
* @return {boolean} Returns `true` if this AABB collides with the point.
*/
proto.collidesPoint = function (x, y) {
return (y > this.top) && (y < this.bottom) && (x > this.left) && (x < this.right);
};
/**
* Expresses whether this AABB intersects the given AABB. This is similar to `collides` but returns true for overlapping or touching edges.
*
* @method platypus.AABB#intersects
* @param aabb {platypus.AABB} The AABB to check against
* @return {boolean} Returns `true` if this AABB intersects the other AABB.
*/
proto.intersects = function (aabb) {
return (aabb.bottom >= this.top) && (aabb.top <= this.bottom) && (aabb.right >= this.left) && (aabb.left <= this.right);
};
/**
* Returns the area of the intersection. If the AABB's do not intersect, `0` is returned.
*
* @method platypus.AABB#getIntersectionArea
* @param aabb {AABB} The AABB this AABB intersects with.
* @return {Number} Returns the area of the intersected AABB's.
*/
proto.getIntersectionArea = function (aabb) {
var max = Math.max,
min = Math.min;
if (this.intersects(aabb)) {
return (min(this.bottom, aabb.bottom) - max(this.top, aabb.top)) * (min(this.right, aabb.right) - max(this.left, aabb.left));
} else {
return 0;
}
};
/**
* Returns an AABB from cache or creates a new one if none are available.
*
* @method platypus.AABB.setUp
* @return {platypus.AABB} The instantiated AABB.
*/
/**
* Returns a AABB back to the cache.
*
* @method platypus.AABB.recycle
* @param {platypus.AABB} aabb The AABB to be recycled.
*/
/**
* Relinquishes properties of the AABB and recycles it.
*
* @method platypus.AABB#recycle
*/
recycle.add(AABB, 'AABB', AABB, null, true, config.dev);
export default AABB;