///
/**
* Phaser - CollisionMask
*/
module Phaser {
export class CollisionMask {
/**
* CollisionMask constructor. Creates a new CollisionMask
for the given GameObject.
*
* @param game {Phaser.Game} Current game instance.
* @param parent {Phaser.GameObject} The GameObject this CollisionMask belongs to.
* @param x {number} The initial x position of the CollisionMask.
* @param y {number} The initial y position of the CollisionMask.
* @param width {number} The width of the CollisionMask.
* @param height {number} The height of the CollisionMask.
*/
constructor(game: Game, parent: GameObject, x: number, y: number, width: number, height: number) {
this._game = game;
this._parent = parent;
// By default the CollisionMask is a quad
this.type = CollisionMask.QUAD;
this.quad = new Phaser.Quad(this._parent.x, this._parent.y, this._parent.width, this._parent.height);
this.offset = new MicroPoint(0, 0);
this.last = new MicroPoint(0, 0);
this._ref = this.quad;
return this;
}
private _game;
private _parent;
// An internal reference to the active collision shape
private _ref;
/**
* Geom type of this sprite. (available: QUAD, POINT, CIRCLE, LINE, RECTANGLE, POLYGON)
* @type {number}
*/
public type: number = 0;
/**
* Quad (a smaller version of Rectangle).
* @type {number}
*/
public static QUAD: number = 0;
/**
* Point.
* @type {number}
*/
public static POINT: number = 1;
/**
* Circle.
* @type {number}
*/
public static CIRCLE: number = 2;
/**
* Line.
* @type {number}
*/
public static LINE: number = 3;
/**
* Rectangle.
* @type {number}
*/
public static RECTANGLE: number = 4;
/**
* Polygon.
* @type {number}
*/
public static POLYGON: number = 5;
/**
* Rectangle shape container. A Rectangle instance.
* @type {Rectangle}
*/
public quad: Quad;
/**
* Point shape container. A Point instance.
* @type {Point}
*/
public point: Point;
/**
* Circle shape container. A Circle instance.
* @type {Circle}
*/
public circle: Circle;
/**
* Line shape container. A Line instance.
* @type {Line}
*/
public line: Line;
/**
* Rectangle shape container. A Rectangle instance.
* @type {Rectangle}
*/
public rect: Rectangle;
/**
* A value from the top-left of the GameObject frame that this collisionMask is offset to.
* If the CollisionMask is a Quad/Rectangle the offset relates to the top-left of that Quad.
* If the CollisionMask is a Circle the offset relates to the center of the circle.
* @type {MicroPoint}
*/
public offset: MicroPoint;
/**
* The previous x/y coordinates of the CollisionMask, used for hull calculations
* @type {MicroPoint}
*/
public last: MicroPoint;
/**
* Create a circle shape with specific diameter.
* @param diameter {number} Diameter of the circle.
* @return {CollisionMask} This
*/
createCircle(diameter: number): CollisionMask {
this.type = CollisionMask.CIRCLE;
this.circle = new Circle(this.last.x, this.last.y, diameter);
this._ref = this.circle;
return this;
}
/**
* Pre-update is called right before update() on each object in the game loop.
*/
public preUpdate() {
this.last.x = this.x;
this.last.y = this.y;
}
public update() {
this._ref.x = this._parent.x + this.offset.x;
this._ref.y = this._parent.y + this.offset.y;
}
/**
* Renders the bounding box around this Sprite and the contact points. Useful for visually debugging.
* @param camera {Camera} Camera the bound will be rendered to.
* @param cameraOffsetX {number} X offset of bound to the camera.
* @param cameraOffsetY {number} Y offset of bound to the camera.
*/
public render(camera:Camera, cameraOffsetX:number, cameraOffsetY:number) {
var _dx = cameraOffsetX + (this.x - camera.worldView.x);
var _dy = cameraOffsetY + (this.y - camera.worldView.y);
this._parent.context.fillStyle = this._parent.renderDebugColor;
if (this.type == CollisionMask.QUAD)
{
this._parent.context.fillRect(_dx, _dy, this.width, this.height);
}
else if (this.type == CollisionMask.CIRCLE)
{
this._parent.context.beginPath();
this._parent.context.arc(_dx, _dy, this.circle.radius, 0, Math.PI * 2);
this._parent.context.fill();
this._parent.context.closePath();
}
}
/**
* Destroy all objects and references belonging to this CollisionMask
*/
public destroy() {
this._game = null;
this._parent = null;
this._ref = null;
this.quad = null;
this.point = null;
this.circle = null;
this.rect = null;
this.line = null;
this.offset = null;
}
public intersectsRaw(left: number, right: number, top: number, bottom: number): bool {
//if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height))
return true;
}
public intersectsVector(vector: Phaser.Vector2): bool {
if (this.type == CollisionMask.QUAD)
{
return this.quad.contains(vector.x, vector.y);
}
}
/**
* Gives a basic boolean response to a geometric collision.
* If you need the details of the collision use the Collision functions instead and inspect the IntersectResult object.
* @param source {GeomSprite} Sprite you want to check.
* @return {boolean} Whether they overlaps or not.
*/
public intersects(source: CollisionMask): bool {
// Quad vs. Quad
if (this.type == CollisionMask.QUAD && source.type == CollisionMask.QUAD)
{
return this.quad.intersects(source.quad);
}
// Circle vs. Circle
if (this.type == CollisionMask.CIRCLE && source.type == CollisionMask.CIRCLE)
{
return Collision.circleToCircle(this.circle, source.circle).result;
}
// Circle vs. Rect
if (this.type == CollisionMask.CIRCLE && source.type == CollisionMask.RECTANGLE)
{
return Collision.circleToRectangle(this.circle, source.rect).result;
}
// Circle vs. Point
if (this.type == CollisionMask.CIRCLE && source.type == CollisionMask.POINT)
{
return Collision.circleContainsPoint(this.circle, source.point).result;
}
// Circle vs. Line
if (this.type == CollisionMask.CIRCLE && source.type == CollisionMask.LINE)
{
return Collision.lineToCircle(source.line, this.circle).result;
}
// Rect vs. Rect
if (this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.RECTANGLE)
{
return Collision.rectangleToRectangle(this.rect, source.rect).result;
}
// Rect vs. Circle
if (this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.CIRCLE)
{
return Collision.circleToRectangle(source.circle, this.rect).result;
}
// Rect vs. Point
if (this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.POINT)
{
return Collision.pointToRectangle(source.point, this.rect).result;
}
// Rect vs. Line
if (this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.LINE)
{
return Collision.lineToRectangle(source.line, this.rect).result;
}
// Point vs. Point
if (this.type == CollisionMask.POINT && source.type == CollisionMask.POINT)
{
return this.point.equals(source.point);
}
// Point vs. Circle
if (this.type == CollisionMask.POINT && source.type == CollisionMask.CIRCLE)
{
return Collision.circleContainsPoint(source.circle, this.point).result;
}
// Point vs. Rect
if (this.type == CollisionMask.POINT && source.type == CollisionMask.RECTANGLE)
{
return Collision.pointToRectangle(this.point, source.rect).result;
}
// Point vs. Line
if (this.type == CollisionMask.POINT && source.type == CollisionMask.LINE)
{
return source.line.isPointOnLine(this.point.x, this.point.y);
}
// Line vs. Line
if (this.type == CollisionMask.LINE && source.type == CollisionMask.LINE)
{
return Collision.lineSegmentToLineSegment(this.line, source.line).result;
}
// Line vs. Circle
if (this.type == CollisionMask.LINE && source.type == CollisionMask.CIRCLE)
{
return Collision.lineToCircle(this.line, source.circle).result;
}
// Line vs. Rect
if (this.type == CollisionMask.LINE && source.type == CollisionMask.RECTANGLE)
{
return Collision.lineSegmentToRectangle(this.line, source.rect).result;
}
// Line vs. Point
if (this.type == CollisionMask.LINE && source.type == CollisionMask.POINT)
{
return this.line.isPointOnLine(source.point.x, source.point.y);
}
return false;
}
public checkHullIntersection(mask: CollisionMask): bool {
if ((this.hullX + this.hullWidth > mask.hullX) && (this.hullX < mask.hullX + mask.width) && (this.hullY + this.hullHeight > mask.hullY) && (this.hullY < mask.hullY + mask.hullHeight))
{
return true;
}
else
{
return false;
}
}
public get hullWidth(): number {
if (this.deltaX > 0)
{
return this.width + this.deltaX;
}
else
{
return this.width - this.deltaX;
}
}
public get hullHeight(): number {
if (this.deltaY > 0)
{
return this.height + this.deltaY;
}
else
{
return this.height - this.deltaY;
}
}
public get hullX(): number {
if (this.x < this.last.x)
{
return this.x;
}
else
{
return this.last.x;
}
}
public get hullY(): number {
if (this.y < this.last.y)
{
return this.y;
}
else
{
return this.last.y;
}
}
public get deltaXAbs(): number {
return (this.deltaX > 0 ? this.deltaX : -this.deltaX);
}
public get deltaYAbs(): number {
return (this.deltaY > 0 ? this.deltaY : -this.deltaY);
}
public get deltaX(): number {
return this.x - this.last.x;
}
public get deltaY(): number {
return this.y - this.last.y;
}
public get x(): number {
return this._ref.x;
//return this.quad.x;
}
public set x(value: number) {
this._ref.x = value;
//this.quad.x = value;
}
public get y(): number {
return this._ref.y;
//return this.quad.y;
}
public set y(value: number) {
this._ref.y = value;
//this.quad.y = value;
}
//public get rotation(): number {
// return this._angle;
//}
//public set rotation(value: number) {
// this._angle = this._game.math.wrap(value, 360, 0);
//}
//public get angle(): number {
// return this._angle;
//}
//public set angle(value: number) {
// this._angle = this._game.math.wrap(value, 360, 0);
//}
public set width(value:number) {
//this.quad.width = value;
this._ref.width = value;
}
public set height(value:number) {
//this.quad.height = value;
this._ref.height = value;
}
public get width(): number {
//return this.quad.width;
return this._ref.width;
}
public get height(): number {
//return this.quad.height;
return this._ref.height;
}
public get left(): number {
return this.x;
}
public get right(): number {
return this.x + this.width;
}
public get top(): number {
return this.y;
}
public get bottom(): number {
return this.y + this.height;
}
public get halfWidth(): number {
return this.width / 2;
}
public get halfHeight(): number {
return this.height / 2;
}
}
}