diff --git a/Phaser/AnimationManager.ts b/Phaser/AnimationManager.ts
index c8aac8ee..8c530f37 100644
--- a/Phaser/AnimationManager.ts
+++ b/Phaser/AnimationManager.ts
@@ -211,7 +211,15 @@ module Phaser {
}
public get frameTotal(): number {
- return this._frameData.total;
+
+ if (this._frameData)
+ {
+ return this._frameData.total;
+ }
+ else
+ {
+ return -1;
+ }
}
public get frame(): number {
@@ -248,6 +256,19 @@ module Phaser {
}
+ /**
+ * Removes all related references
+ */
+ public destroy() {
+
+ this._anims = {};
+ this._frameData = null;
+ this._frameIndex = 0;
+ this.currentAnim = null;
+ this.currentFrame = null;
+
+ }
+
}
}
\ No newline at end of file
diff --git a/Phaser/CameraManager.ts b/Phaser/CameraManager.ts
index fa8a7af2..272a5f7e 100644
--- a/Phaser/CameraManager.ts
+++ b/Phaser/CameraManager.ts
@@ -6,9 +6,6 @@
*
* Your game only has one CameraManager instance and it's responsible for looking after, creating and destroying
* all of the cameras in the world.
-*
-* TODO: If the Camera is larger than the Stage size then the rotation offset isn't correct
-* TODO: Texture Repeat doesn't scroll, because it's part of the camera not the world, need to think about this more
*/
module Phaser {
diff --git a/Phaser/Collision.ts b/Phaser/Collision.ts
index 36e46a0e..2ba41621 100644
--- a/Phaser/Collision.ts
+++ b/Phaser/Collision.ts
@@ -5,6 +5,8 @@
///
///
///
+///
+///
///
/**
@@ -25,6 +27,20 @@ module Phaser {
this._game = game;
+ Collision.T_VECTORS = [];
+
+ for (var i = 0; i < 10; i++)
+ {
+ Collision.T_VECTORS.push(new Vector2);
+ }
+
+ Collision.T_ARRAYS = [];
+
+ for (var i = 0; i < 5; i++)
+ {
+ Collision.T_ARRAYS.push([]);
+ }
+
}
/**
@@ -553,20 +569,6 @@ module Phaser {
}
- /*
- public static circleToQuad(circle: Circle, quad: Quad): bool {
-
- // Check if the center of the circle is within the Quad
- if (quad.contains(circle.x, circle.y))
- {
- return true;
- }
-
- // Failing that let's check each line of the quad against the circle
- return false;
- }
- */
-
/**
* Checks if the Circle object intersects with the Rectangle and returns the result in an IntersectResult object.
* @param circle The Circle object to check
@@ -647,8 +649,6 @@ module Phaser {
*/
public static separate(object1, object2): bool {
- console.log('sep o');
-
object1.collisionMask.update();
object2.collisionMask.update();
@@ -667,6 +667,8 @@ module Phaser {
*/
public static separateTile(object:GameObject, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, collideUp: bool, collideDown: bool, separateX: bool, separateY: bool): bool {
+ object.collisionMask.update();
+
var separatedX: bool = Collision.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separateX);
var separatedY: bool = Collision.separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separateY);
@@ -691,11 +693,13 @@ module Phaser {
// First, get the object delta
var overlap: number = 0;
var objDelta: number = object.x - object.last.x;
+ //var objDelta: number = object.collisionMask.deltaX;
if (objDelta != 0)
{
// Check if the X hulls actually overlap
var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta;
+ //var objDeltaAbs: number = object.collisionMask.deltaXAbs;
var objBounds: Quad = new Quad(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height);
if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height))
@@ -739,6 +743,7 @@ module Phaser {
{
if (separate == true)
{
+ //console.log('
object.x = object.x - overlap;
object.velocity.x = -(object.velocity.x * object.elasticity);
}
@@ -831,6 +836,170 @@ module Phaser {
}
}
+
+ /**
+ * Separates the two objects on their x axis
+ * @param object The GameObject to separate
+ * @param tile The Tile to separate
+ * @returns {boolean} Whether the objects in fact touched and were separated along the X axis.
+ */
+ public static NEWseparateTileX(object:GameObject, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool {
+
+ // Can't separate two immovable objects (tiles are always immovable)
+ if (object.immovable)
+ {
+ return false;
+ }
+
+ // First, get the object delta
+ var overlap: number = 0;
+
+ if (object.collisionMask.deltaX != 0)
+ {
+ // Check if the X hulls actually overlap
+ //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta;
+ //var objBounds: Quad = new Quad(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height);
+
+ //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height))
+ if (object.collisionMask.intersectsRaw(x, x + width, y, y + height))
+ {
+ var maxOverlap: number = object.collisionMask.deltaXAbs + Collision.OVERLAP_BIAS;
+
+ // If they did overlap (and can), figure out by how much and flip the corresponding flags
+ if (object.collisionMask.deltaX > 0)
+ {
+ //overlap = object.x + object.width - x;
+ overlap = object.collisionMask.right - x;
+
+ if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false)
+ {
+ overlap = 0;
+ }
+ else
+ {
+ object.touching |= Collision.RIGHT;
+ }
+ }
+ else if (object.collisionMask.deltaX < 0)
+ {
+ //overlap = object.x - width - x;
+ overlap = object.collisionMask.x - width - x;
+
+ if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false)
+ {
+ overlap = 0;
+ }
+ else
+ {
+ object.touching |= Collision.LEFT;
+ }
+
+ }
+
+ }
+ }
+
+ // Then adjust their positions and velocities accordingly (if there was any overlap)
+ if (overlap != 0)
+ {
+ if (separate == true)
+ {
+ object.x = object.x - overlap;
+ object.velocity.x = -(object.velocity.x * object.elasticity);
+ }
+
+ Collision.TILE_OVERLAP = true;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+
+ }
+
+ /**
+ * Separates the two objects on their y axis
+ * @param object The first GameObject to separate
+ * @param tile The second GameObject to separate
+ * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis.
+ */
+ public static NEWseparateTileY(object: GameObject, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool {
+
+ // Can't separate two immovable objects (tiles are always immovable)
+ if (object.immovable)
+ {
+ return false;
+ }
+
+ // First, get the two object deltas
+ var overlap: number = 0;
+ //var objDelta: number = object.y - object.last.y;
+
+ if (object.collisionMask.deltaY != 0)
+ {
+ // Check if the Y hulls actually overlap
+ //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta;
+ //var objBounds: Quad = new Quad(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs);
+
+ //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height))
+ if (object.collisionMask.intersectsRaw(x, x + width, y, y + height))
+ {
+ //var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS;
+ var maxOverlap: number = object.collisionMask.deltaYAbs + Collision.OVERLAP_BIAS;
+
+ // If they did overlap (and can), figure out by how much and flip the corresponding flags
+ if (object.collisionMask.deltaY > 0)
+ {
+ //overlap = object.y + object.height - y;
+ overlap = object.collisionMask.bottom - y;
+
+ if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false)
+ {
+ overlap = 0;
+ }
+ else
+ {
+ object.touching |= Collision.DOWN;
+ }
+ }
+ else if (object.collisionMask.deltaY < 0)
+ {
+ //overlap = object.y - height - y;
+ overlap = object.collisionMask.y - height - y;
+
+ if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false)
+ {
+ overlap = 0;
+ }
+ else
+ {
+ object.touching |= Collision.UP;
+ }
+ }
+ }
+ }
+
+ // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here
+
+ // Then adjust their positions and velocities accordingly (if there was any overlap)
+ if (overlap != 0)
+ {
+ if (separate == true)
+ {
+ object.y = object.y - overlap;
+ object.velocity.y = -(object.velocity.y * object.elasticity);
+ }
+
+ Collision.TILE_OVERLAP = true;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
/**
* Separates the two objects on their x axis
* @param object1 The first GameObject to separate
@@ -1032,229 +1201,6 @@ module Phaser {
}
}
- /**
- * Separates the two objects on their x axis
- * @param object1 The first GameObject to separate
- * @param object2 The second GameObject to separate
- * @returns {boolean} Whether the objects in fact touched and were separated along the X axis.
- */
- public static OLDseparateX(object1, object2): bool {
-
- // Can't separate two immovable objects
- if (object1.immovable && object2.immovable)
- {
- return false;
- }
-
- // First, get the two object deltas
- var overlap: number = 0;
- var obj1Delta: number = object1.x - object1.last.x;
- var obj2Delta: number = object2.x - object2.last.x;
-
- if (obj1Delta != obj2Delta)
- {
- // Check if the X hulls actually overlap
- var obj1DeltaAbs: number = (obj1Delta > 0) ? obj1Delta : -obj1Delta;
- var obj2DeltaAbs: number = (obj2Delta > 0) ? obj2Delta : -obj2Delta;
- var obj1Bounds: Quad = new Quad(object1.x - ((obj1Delta > 0) ? obj1Delta : 0), object1.last.y, object1.width + ((obj1Delta > 0) ? obj1Delta : -obj1Delta), object1.height);
- var obj2Bounds: Quad = new Quad(object2.x - ((obj2Delta > 0) ? obj2Delta : 0), object2.last.y, object2.width + ((obj2Delta > 0) ? obj2Delta : -obj2Delta), object2.height);
-
- if ((obj1Bounds.x + obj1Bounds.width > obj2Bounds.x) && (obj1Bounds.x < obj2Bounds.x + obj2Bounds.width) && (obj1Bounds.y + obj1Bounds.height > obj2Bounds.y) && (obj1Bounds.y < obj2Bounds.y + obj2Bounds.height))
- {
- var maxOverlap: number = obj1DeltaAbs + obj2DeltaAbs + Collision.OVERLAP_BIAS;
-
- // If they did overlap (and can), figure out by how much and flip the corresponding flags
- if (obj1Delta > obj2Delta)
- {
- overlap = object1.x + object1.width - object2.x;
-
- if ((overlap > maxOverlap) || !(object1.allowCollisions & Collision.RIGHT) || !(object2.allowCollisions & Collision.LEFT))
- {
- overlap = 0;
- }
- else
- {
- object1.touching |= Collision.RIGHT;
- object2.touching |= Collision.LEFT;
- }
- }
- else if (obj1Delta < obj2Delta)
- {
- overlap = object1.x - object2.width - object2.x;
-
- if ((-overlap > maxOverlap) || !(object1.allowCollisions & Collision.LEFT) || !(object2.allowCollisions & Collision.RIGHT))
- {
- overlap = 0;
- }
- else
- {
- object1.touching |= Collision.LEFT;
- object2.touching |= Collision.RIGHT;
- }
-
- }
-
- }
- }
-
- // Then adjust their positions and velocities accordingly (if there was any overlap)
- if (overlap != 0)
- {
- var obj1Velocity: number = object1.velocity.x;
- var obj2Velocity: number = object2.velocity.x;
-
- if (!object1.immovable && !object2.immovable)
- {
- overlap *= 0.5;
- object1.x = object1.x - overlap;
- object2.x += overlap;
-
- var obj1NewVelocity: number = Math.sqrt((obj2Velocity * obj2Velocity * object2.mass) / object1.mass) * ((obj2Velocity > 0) ? 1 : -1);
- var obj2NewVelocity: number = Math.sqrt((obj1Velocity * obj1Velocity * object1.mass) / object2.mass) * ((obj1Velocity > 0) ? 1 : -1);
- var average: number = (obj1NewVelocity + obj2NewVelocity) * 0.5;
- obj1NewVelocity -= average;
- obj2NewVelocity -= average;
- object1.velocity.x = average + obj1NewVelocity * object1.elasticity;
- object2.velocity.x = average + obj2NewVelocity * object2.elasticity;
- }
- else if (!object1.immovable)
- {
- object1.x = object1.x - overlap;
- object1.velocity.x = obj2Velocity - obj1Velocity * object1.elasticity;
- }
- else if (!object2.immovable)
- {
- object2.x += overlap;
- object2.velocity.x = obj1Velocity - obj2Velocity * object2.elasticity;
- }
-
- return true;
- }
- else
- {
- return false;
- }
-
- }
-
- /**
- * Separates the two objects on their y axis
- * @param object1 The first GameObject to separate
- * @param object2 The second GameObject to separate
- * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis.
- */
- public static OLDseparateY(object1, object2): bool {
-
- // Can't separate two immovable objects
- if (object1.immovable && object2.immovable) {
- return false;
- }
-
- // First, get the two object deltas
- var overlap: number = 0;
- var obj1Delta: number = object1.y - object1.last.y;
- var obj2Delta: number = object2.y - object2.last.y;
-
- if (obj1Delta != obj2Delta)
- {
- // Check if the Y hulls actually overlap
- var obj1DeltaAbs: number = (obj1Delta > 0) ? obj1Delta : -obj1Delta;
- var obj2DeltaAbs: number = (obj2Delta > 0) ? obj2Delta : -obj2Delta;
- var obj1Bounds: Quad = new Quad(object1.x, object1.y - ((obj1Delta > 0) ? obj1Delta : 0), object1.width, object1.height + obj1DeltaAbs);
- var obj2Bounds: Quad = new Quad(object2.x, object2.y - ((obj2Delta > 0) ? obj2Delta : 0), object2.width, object2.height + obj2DeltaAbs);
-
- console.log(obj1Bounds.toString(), obj2Bounds.toString());
-
- if ((obj1Bounds.x + obj1Bounds.width > obj2Bounds.x) && (obj1Bounds.x < obj2Bounds.x + obj2Bounds.width) && (obj1Bounds.y + obj1Bounds.height > obj2Bounds.y) && (obj1Bounds.y < obj2Bounds.y + obj2Bounds.height))
- {
- var maxOverlap: number = obj1DeltaAbs + obj2DeltaAbs + Collision.OVERLAP_BIAS;
- console.log('max33', maxOverlap, obj1Delta, obj2Delta, obj1DeltaAbs, obj2DeltaAbs);
-
- // If they did overlap (and can), figure out by how much and flip the corresponding flags
- if (obj1Delta > obj2Delta)
- {
- overlap = object1.y + object1.height - object2.y;
-
- if ((overlap > maxOverlap) || !(object1.allowCollisions & Collision.DOWN) || !(object2.allowCollisions & Collision.UP))
- {
- overlap = 0;
- }
- else
- {
- object1.touching |= Collision.DOWN;
- object2.touching |= Collision.UP;
- }
- }
- else if (obj1Delta < obj2Delta)
- {
- overlap = object1.y - object2.height - object2.y;
-
- if ((-overlap > maxOverlap) || !(object1.allowCollisions & Collision.UP) || !(object2.allowCollisions & Collision.DOWN))
- {
- overlap = 0;
- }
- else
- {
- object1.touching |= Collision.UP;
- object2.touching |= Collision.DOWN;
- }
- }
- }
- }
-
- // Then adjust their positions and velocities accordingly (if there was any overlap)
- if (overlap != 0)
- {
- console.log('y overlap', overlap);
-
- var obj1Velocity: number = object1.velocity.y;
- var obj2Velocity: number = object2.velocity.y;
-
- if (!object1.immovable && !object2.immovable)
- {
- overlap *= 0.5;
- object1.y = object1.y - overlap;
- object2.y += overlap;
-
- var obj1NewVelocity: number = Math.sqrt((obj2Velocity * obj2Velocity * object2.mass) / object1.mass) * ((obj2Velocity > 0) ? 1 : -1);
- var obj2NewVelocity: number = Math.sqrt((obj1Velocity * obj1Velocity * object1.mass) / object2.mass) * ((obj1Velocity > 0) ? 1 : -1);
- var average: number = (obj1NewVelocity + obj2NewVelocity) * 0.5;
- obj1NewVelocity -= average;
- obj2NewVelocity -= average;
- object1.velocity.y = average + obj1NewVelocity * object1.elasticity;
- object2.velocity.y = average + obj2NewVelocity * object2.elasticity;
- }
- else if (!object1.immovable)
- {
- object1.y = object1.y - overlap;
- object1.velocity.y = obj2Velocity - obj1Velocity * object1.elasticity;
- // This is special case code that handles things like horizontal moving platforms you can ride
- if (object2.active && object2.moves && (obj1Delta > obj2Delta))
- {
- object1.x += object2.x - object2.last.x;
- }
- console.log('y2', object1.y, object1.velocity.y);
- }
- else if (!object2.immovable)
- {
- object2.y += overlap;
- object2.velocity.y = obj1Velocity - obj2Velocity * object2.elasticity;
- // This is special case code that handles things like horizontal moving platforms you can ride
- if (object1.active && object1.moves && (obj1Delta < obj2Delta))
- {
- object2.x += object1.x - object1.last.x;
- }
- console.log('y3', object2.y, object2.velocity.y);
- }
-
- return true;
- }
- else
- {
- return false;
- }
- }
-
/**
* Returns the distance between the two given coordinates.
* @param x1 The X value of the first coordinate
@@ -1279,6 +1225,478 @@ module Phaser {
return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
}
+
+
+ // SAT
+
+ /**
+ * Flattens the specified array of points onto a unit vector axis,
+ * resulting in a one dimensional range of the minimum and
+ * maximum value on that axis.
+ *
+ * @param {Array.} points The points to flatten.
+ * @param {Vector} normal The unit vector axis to flatten on.
+ * @param {Array.} result An array. After calling this function,
+ * result[0] will be the minimum value,
+ * result[1] will be the maximum value.
+ */
+ public static flattenPointsOn(points, normal, result) {
+
+ var min = Number.MAX_VALUE;
+ var max = -Number.MAX_VALUE;
+ var len = points.length;
+
+ for (var i = 0; i < len; i++)
+ {
+ // Get the magnitude of the projection of the point onto the normal
+ var dot = points[i].dot(normal);
+ if (dot < min) { min = dot; }
+ if (dot > max) { max = dot; }
+ }
+
+ result[0] = min; result[1] = max;
+
+ }
+
+ /**
+ * Pool of Vectors used in calculations.
+ *
+ * @type {Array.}
+ */
+ public static T_VECTORS: Vector2[];
+
+ /**
+ * Pool of Arrays used in calculations.
+ *
+ * @type {Array.>}
+ */
+ public static T_ARRAYS;
+
+ /**
+ * Check whether two convex clockwise polygons are separated by the specified
+ * axis (must be a unit vector).
+ *
+ * @param {Vector} aPos The position of the first polygon.
+ * @param {Vector} bPos The position of the second polygon.
+ * @param {Array.} aPoints The points in the first polygon.
+ * @param {Array.} bPoints The points in the second polygon.
+ * @param {Vector} axis The axis (unit sized) to test against. The points of both polygons
+ * will be projected onto this axis.
+ * @param {Response=} response A Response object (optional) which will be populated
+ * if the axis is not a separating axis.
+ * @return {boolean} true if it is a separating axis, false otherwise. If false,
+ * and a response is passed in, information about how much overlap and
+ * the direction of the overlap will be populated.
+ */
+ public static isSeparatingAxis(aPos, bPos, aPoints, bPoints, axis, response?:Response = null): bool {
+
+ var rangeA = Collision.T_ARRAYS.pop();
+ var rangeB = Collision.T_ARRAYS.pop();
+
+ // Get the magnitude of the offset between the two polygons
+ var offsetV = Collision.T_VECTORS.pop().copyFrom(bPos).sub(aPos);
+ var projectedOffset = offsetV.dot(axis);
+
+ // Project the polygons onto the axis.
+ Collision.flattenPointsOn(aPoints, axis, rangeA);
+ Collision.flattenPointsOn(bPoints, axis, rangeB);
+
+ // Move B's range to its position relative to A.
+ rangeB[0] += projectedOffset;
+ rangeB[1] += projectedOffset;
+
+ // Check if there is a gap. If there is, this is a separating axis and we can stop
+ if (rangeA[0] > rangeB[1] || rangeB[0] > rangeA[1])
+ {
+ Collision.T_VECTORS.push(offsetV);
+ Collision.T_ARRAYS.push(rangeA);
+ Collision.T_ARRAYS.push(rangeB);
+ return true;
+ }
+
+ // If we're calculating a response, calculate the overlap.
+ if (response)
+ {
+ var overlap = 0;
+
+ // A starts further left than B
+ if (rangeA[0] < rangeB[0])
+ {
+ response.aInB = false;
+
+ // A ends before B does. We have to pull A out of B
+ if (rangeA[1] < rangeB[1])
+ {
+ overlap = rangeA[1] - rangeB[0];
+ response.bInA = false;
+ // B is fully inside A. Pick the shortest way out.
+ }
+ else
+ {
+ var option1 = rangeA[1] - rangeB[0];
+ var option2 = rangeB[1] - rangeA[0];
+ overlap = option1 < option2 ? option1 : -option2;
+ }
+ // B starts further left than A
+ }
+ else
+ {
+ response.bInA = false;
+
+ // B ends before A ends. We have to push A out of B
+ if (rangeA[1] > rangeB[1])
+ {
+ overlap = rangeA[0] - rangeB[1];
+ response.aInB = false;
+ // A is fully inside B. Pick the shortest way out.
+ }
+ else
+ {
+ var option1 = rangeA[1] - rangeB[0];
+ var option2 = rangeB[1] - rangeA[0];
+ overlap = option1 < option2 ? option1 : -option2;
+ }
+ }
+
+ // If this is the smallest amount of overlap we've seen so far, set it as the minimum overlap.
+ var absOverlap = Math.abs(overlap);
+
+ if (absOverlap < response.overlap)
+ {
+ response.overlap = absOverlap;
+ response.overlapN.copyFrom(axis);
+
+ if (overlap < 0)
+ {
+ response.overlapN.reverse();
+ }
+ }
+ }
+
+ Collision.T_VECTORS.push(offsetV);
+ Collision.T_ARRAYS.push(rangeA);
+ Collision.T_ARRAYS.push(rangeB);
+
+ return false;
+
+ }
+
+ public static LEFT_VORNOI_REGION:number = -1;
+ public static MIDDLE_VORNOI_REGION:number = 0;
+ public static RIGHT_VORNOI_REGION:number = 1;
+
+ /**
+ * Calculates which Vornoi region a point is on a line segment.
+ * It is assumed that both the line and the point are relative to (0, 0)
+ *
+ * | (0) |
+ * (-1) [0]--------------[1] (1)
+ * | (0) |
+ *
+ * @param {Vector} line The line segment.
+ * @param {Vector} point The point.
+ * @return {number} LEFT_VORNOI_REGION (-1) if it is the left region,
+ * MIDDLE_VORNOI_REGION (0) if it is the middle region,
+ * RIGHT_VORNOI_REGION (1) if it is the right region.
+ */
+ public static vornoiRegion(line: Vector2, point: Vector2): number {
+
+ var len2 = line.length2();
+ var dp = point.dot(line);
+
+ if (dp < 0) { return Collision.LEFT_VORNOI_REGION; }
+ else if (dp > len2) { return Collision.RIGHT_VORNOI_REGION; }
+ else { return Collision.MIDDLE_VORNOI_REGION; }
+
+ }
+
+ /**
+ * Check if two circles intersect.
+ *
+ * @param {Circle} a The first circle.
+ * @param {Circle} b The second circle.
+ * @param {Response=} response Response object (optional) that will be populated if
+ * the circles intersect.
+ * @return {boolean} true if the circles intersect, false if they don't.
+ */
+ public static testCircleCircle(a: Circle, b: Circle, response?: Response = null): bool {
+
+ var differenceV = Collision.T_VECTORS.pop().copyFrom(b.pos).sub(a.pos);
+ var totalRadius = a.radius + b.radius;
+ var totalRadiusSq = totalRadius * totalRadius;
+ var distanceSq = differenceV.length2();
+
+ if (distanceSq > totalRadiusSq)
+ {
+ // They do not intersect
+ Collision.T_VECTORS.push(differenceV);
+ return false;
+ }
+
+ // They intersect. If we're calculating a response, calculate the overlap.
+ if (response)
+ {
+ var dist = Math.sqrt(distanceSq);
+ response.a = a;
+ response.b = b;
+ response.overlap = totalRadius - dist;
+ response.overlapN.copyFrom(differenceV.normalize());
+ response.overlapV.copyFrom(differenceV).scale(response.overlap);
+ response.aInB = a.radius <= b.radius && dist <= b.radius - a.radius;
+ response.bInA = b.radius <= a.radius && dist <= a.radius - b.radius;
+ }
+
+ Collision.T_VECTORS.push(differenceV);
+ return true;
+
+ }
+
+ /**
+ * Check if a polygon and a circle intersect.
+ *
+ * @param {Polygon} polygon The polygon.
+ * @param {Circle} circle The circle.
+ * @param {Response=} response Response object (optional) that will be populated if
+ * they interset.
+ * @return {boolean} true if they intersect, false if they don't.
+ */
+ public static testPolygonCircle(polygon: Polygon, circle: Circle, response?: Response = null): bool {
+
+ var circlePos = Collision.T_VECTORS.pop().copyFrom(circle.pos).sub(polygon.pos);
+ var radius = circle.radius;
+ var radius2 = radius * radius;
+ var points = polygon.points;
+ var len = points.length;
+ var edge = T_VECTORS.pop();
+ var point = T_VECTORS.pop();
+
+ // For each edge in the polygon
+ for (var i = 0; i < len; i++)
+ {
+ var next = i === len - 1 ? 0 : i + 1;
+ var prev = i === 0 ? len - 1 : i - 1;
+ var overlap = 0;
+ var overlapN = null;
+
+ // Get the edge
+ edge.copyFrom(polygon.edges[i]);
+ // Calculate the center of the cirble relative to the starting point of the edge
+ point.copyFrom(circlePos).sub(points[i]);
+
+ // If the distance between the center of the circle and the point
+ // is bigger than the radius, the polygon is definitely not fully in
+ // the circle.
+ if (response && point.length2() > radius2)
+ {
+ response.aInB = false;
+ }
+
+ // Calculate which Vornoi region the center of the circle is in.
+ var region = vornoiRegion(edge, point);
+
+ if (region === Collision.LEFT_VORNOI_REGION)
+ {
+ // Need to make sure we're in the RIGHT_VORNOI_REGION of the previous edge.
+ edge.copyFrom(polygon.edges[prev]);
+
+ // Calculate the center of the circle relative the starting point of the previous edge
+ var point2 = Collision.T_VECTORS.pop().copyFrom(circlePos).sub(points[prev]);
+ region = vornoiRegion(edge, point2);
+
+ if (region === Collision.RIGHT_VORNOI_REGION)
+ {
+ // It's in the region we want. Check if the circle intersects the point.
+ var dist = point.length2();
+
+ if (dist > radius)
+ {
+ // No intersection
+ Collision.T_VECTORS.push(circlePos);
+ Collision.T_VECTORS.push(edge);
+ Collision.T_VECTORS.push(point);
+ Collision.T_VECTORS.push(point2);
+ return false;
+ }
+ else if (response)
+ {
+ // It intersects, calculate the overlap
+ response.bInA = false;
+ overlapN = point.normalize();
+ overlap = radius - dist;
+ }
+ }
+
+ Collision.T_VECTORS.push(point2);
+
+ }
+ else if (region === Collision.RIGHT_VORNOI_REGION)
+ {
+ // Need to make sure we're in the left region on the next edge
+ edge.copyFrom(polygon.edges[next]);
+
+ // Calculate the center of the circle relative to the starting point of the next edge
+ point.copyFrom(circlePos).sub(points[next]);
+ region = vornoiRegion(edge, point);
+
+ if (region === Collision.LEFT_VORNOI_REGION)
+ {
+ // It's in the region we want. Check if the circle intersects the point.
+ var dist = point.length2();
+
+ if (dist > radius)
+ {
+ // No intersection
+ Collision.T_VECTORS.push(circlePos);
+ Collision.T_VECTORS.push(edge);
+ Collision.T_VECTORS.push(point);
+ return false;
+ }
+ else if (response)
+ {
+ // It intersects, calculate the overlap
+ response.bInA = false;
+ overlapN = point.normalize();
+ overlap = radius - dist;
+ }
+ }
+ // MIDDLE_VORNOI_REGION
+ }
+ else
+ {
+ // Need to check if the circle is intersecting the edge,
+ // Change the edge into its "edge normal".
+ var normal = edge.perp().normalize();
+
+ // Find the perpendicular distance between the center of the
+ // circle and the edge.
+ var dist = point.dot(normal);
+ var distAbs = Math.abs(dist);
+
+ // If the circle is on the outside of the edge, there is no intersection
+ if (dist > 0 && distAbs > radius)
+ {
+ Collision.T_VECTORS.push(circlePos);
+ Collision.T_VECTORS.push(normal);
+ Collision.T_VECTORS.push(point);
+ return false;
+ }
+ else if (response)
+ {
+ // It intersects, calculate the overlap.
+ overlapN = normal;
+ overlap = radius - dist;
+ // If the center of the circle is on the outside of the edge, or part of the
+ // circle is on the outside, the circle is not fully inside the polygon.
+ if (dist >= 0 || overlap < 2 * radius)
+ {
+ response.bInA = false;
+ }
+ }
+ }
+
+ // If this is the smallest overlap we've seen, keep it.
+ // (overlapN may be null if the circle was in the wrong Vornoi region)
+ if (overlapN && response && Math.abs(overlap) < Math.abs(response.overlap))
+ {
+ response.overlap = overlap;
+ response.overlapN.copyFrom(overlapN);
+ }
+ }
+
+ // Calculate the final overlap vector - based on the smallest overlap.
+ if (response)
+ {
+ response.a = polygon;
+ response.b = circle;
+ response.overlapV.copyFrom(response.overlapN).scale(response.overlap);
+ }
+
+ Collision.T_VECTORS.push(circlePos);
+ Collision.T_VECTORS.push(edge);
+ Collision.T_VECTORS.push(point);
+
+ return true;
+ }
+
+ /**
+ * Check if a circle and a polygon intersect.
+ *
+ * NOTE: This runs slightly slower than polygonCircle as it just
+ * runs polygonCircle and reverses everything at the end.
+ *
+ * @param {Circle} circle The circle.
+ * @param {Polygon} polygon The polygon.
+ * @param {Response=} response Response object (optional) that will be populated if
+ * they interset.
+ * @return {boolean} true if they intersect, false if they don't.
+ */
+ public static testCirclePolygon(circle: Circle, polygon: Polygon, response?: Response = null): bool {
+
+ var result = Collision.testPolygonCircle(polygon, circle, response);
+
+ if (result && response)
+ {
+ // Swap A and B in the response.
+ var a = response.a;
+ var aInB = response.aInB;
+ response.overlapN.reverse();
+ response.overlapV.reverse();
+ response.a = response.b;
+ response.b = a;
+ response.aInB = response.bInA;
+ response.bInA = aInB;
+ }
+
+ return result;
+ }
+
+ /**
+ * Checks whether two convex, clockwise polygons intersect.
+ *
+ * @param {Polygon} a The first polygon.
+ * @param {Polygon} b The second polygon.
+ * @param {Response=} response Response object (optional) that will be populated if
+ * they interset.
+ * @return {boolean} true if they intersect, false if they don't.
+ */
+ public static testPolygonPolygon(a: Polygon, b: Polygon, response?: Response = null): bool {
+
+ var aPoints = a.points;
+ var aLen = aPoints.length;
+ var bPoints = b.points;
+ var bLen = bPoints.length;
+
+ // If any of the edge normals of A is a separating axis, no intersection.
+ for (var i = 0; i < aLen; i++)
+ {
+ if (Collision.isSeparatingAxis(a.pos, b.pos, aPoints, bPoints, a.normals[i], response))
+ {
+ return false;
+ }
+ }
+
+ // If any of the edge normals of B is a separating axis, no intersection.
+ for (var i = 0; i < bLen; i++)
+ {
+ if (Collision.isSeparatingAxis(a.pos, b.pos, aPoints, bPoints, b.normals[i], response))
+ {
+ return false;
+ }
+ }
+
+ // Since none of the edge normals of A or B are a separating axis, there is an intersection
+ // and we've already calculated the smallest overlap (in isSeparatingAxis). Calculate the
+ // final overlap vector.
+ if (response)
+ {
+ response.a = a;
+ response.b = b;
+ response.overlapV.copyFrom(response.overlapN).scale(response.overlap);
+ }
+
+ return true;
+ }
+
}
}
\ No newline at end of file
diff --git a/Phaser/Game.ts b/Phaser/Game.ts
index 76c1ec1d..a8befff3 100644
--- a/Phaser/Game.ts
+++ b/Phaser/Game.ts
@@ -6,6 +6,7 @@
///
///
///
+///
///
///
///
@@ -172,6 +173,12 @@ module Phaser {
*/
public onDestroyCallback = null;
+ /**
+ * Reference to the GameObject Factory.
+ * @type {GameObjectFactory}
+ */
+ public add: GameObjectFactory;
+
/**
* Reference to the assets cache.
* @type {Cache}
@@ -251,7 +258,7 @@ module Phaser {
public rnd: RandomDataGenerator;
/**
- * Device detector.
+ * Contains device information and capabilities.
* @type {Device}
*/
public device: Device;
@@ -292,6 +299,7 @@ module Phaser {
this.math = new GameMath(this);
this.stage = new Stage(this, parent, width, height);
this.world = new World(this, width, height);
+ this.add = new GameObjectFactory(this);
this.sound = new SoundManager(this);
this.cache = new Cache(this);
this.collision = new Collision(this);
@@ -619,125 +627,6 @@ module Phaser {
}
- // Handy Proxy methods
-
- /**
- * Create a new camera with specific position and size.
- *
- * @param x {number} X position of the new camera.
- * @param y {number} Y position of the new camera.
- * @param width {number} Width of the new camera.
- * @param height {number} Height of the new camera.
- * @returns {Camera} The newly created camera object.
- */
- public createCamera(x: number, y: number, width: number, height: number): Camera {
- return this.world.createCamera(x, y, width, height);
- }
-
- /**
- * Create a new GeomSprite with specific position.
- *
- * @param x {number} X position of the new geom sprite.
- * @param y {number} Y position of the new geom sprite.
- * @returns {GeomSprite} The newly created geom sprite object.
- */
- public createGeomSprite(x: number, y: number): GeomSprite {
- return this.world.createGeomSprite(x, y);
- }
-
- /**
- * Create a new Sprite with specific position and sprite sheet key.
- *
- * @param x {number} X position of the new sprite.
- * @param y {number} Y position of the new sprite.
- * @param key {string} Optional, key for the sprite sheet you want it to use.
- * @returns {Sprite} The newly created sprite object.
- */
- public createSprite(x: number, y: number, key?: string = ''): Sprite {
- return this.world.createSprite(x, y, key);
- }
-
- /**
- * Create a new DynamicTexture with specific size.
- *
- * @param width {number} Width of the texture.
- * @param height {number} Height of the texture.
- * @returns {DynamicTexture} The newly created dynamic texture object.
- */
- public createDynamicTexture(width: number, height: number): DynamicTexture {
- return this.world.createDynamicTexture(width, height);
- }
-
- /**
- * Create a new object container.
- *
- * @param maxSize {number} Optional, capacity of this group.
- * @returns {Group} The newly created group.
- */
- public createGroup(maxSize?: number = 0): Group {
- return this.world.createGroup(maxSize);
- }
-
- /**
- * Create a new Particle.
- *
- * @return {Particle} The newly created particle object.
- */
- public createParticle(): Particle {
- return this.world.createParticle();
- }
-
- /**
- * Create a new Emitter.
- *
- * @param x {number} Optional, x position of the emitter.
- * @param y {number} Optional, y position of the emitter.
- * @param size {number} Optional, size of this emitter.
- * @return {Emitter} The newly created emitter object.
- */
- public createEmitter(x?: number = 0, y?: number = 0, size?: number = 0): Emitter {
- return this.world.createEmitter(x, y, size);
- }
-
- /**
- * Create a new ScrollZone object with image key, position and size.
- *
- * @param key {string} Key to a image you wish this object to use.
- * @param x {number} X position of this object.
- * @param y {number} Y position of this object.
- * @param width number} Width of this object.
- * @param height {number} Height of this object.
- * @returns {ScrollZone} The newly created scroll zone object.
- */
- public createScrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone {
- return this.world.createScrollZone(key, x, y, width, height);
- }
-
- /**
- * Create a new Tilemap.
- *
- * @param key {string} Key for tileset image.
- * @param mapData {string} Data of this tilemap.
- * @param format {number} Format of map data. (Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON)
- * @param [resizeWorld] {boolean} resize the world to make same as tilemap?
- * @param [tileWidth] {number} width of each tile.
- * @param [tileHeight] {number} height of each tile.
- * @return {Tilemap} The newly created tilemap object.
- */
- public createTilemap(key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0): Tilemap {
- return this.world.createTilemap(key, mapData, format, resizeWorld, tileWidth, tileHeight);
- }
-
- /**
- * Create a tween object for a specific object.
- *
- * @param obj Object you wish the tween will affect.
- * @return {Phaser.Tween} The newly created tween object.
- */
- public createTween(obj): Tween {
- return this.tweens.create(obj);
- }
-
/**
* Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group.
* Note: Does not take the objects scrollFactor into account. All overlaps are check in world space.
diff --git a/Phaser/GameMath.ts b/Phaser/GameMath.ts
index 8138252b..1264e46f 100644
--- a/Phaser/GameMath.ts
+++ b/Phaser/GameMath.ts
@@ -1039,25 +1039,32 @@ module Phaser {
}
/**
- * Rotates a point around the x/y coordinates given to the desired angle
+ * Rotates the point around the x/y coordinates given to the desired angle and distance
+ * @param point {Object} Any object with exposed x and y properties
* @param x {number} The x coordinate of the anchor point
* @param y {number} The y coordinate of the anchor point
- * @param angle {number} The angle of the rotation in radians
- * @param point {Point} The point object to perform the rotation on
+ * @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from.
+ * @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)?
+ * @param {Number} distance An optional distance constraint between the point and the anchor
* @return The modified point object
*/
- public rotatePoint(x: number, y: number, angle: number, point) {
+ public rotatePoint(point, x1: number, y1: number, angle: number, asDegrees: bool = false, distance?:number = null) {
- var s: number = Math.sin(angle);
- var c: number = Math.cos(angle);
+ if (asDegrees)
+ {
+ angle = angle * GameMath.DEG_TO_RAD;
+ }
- point.x -= x;
- point.y -= y;
+ // Get distance from origin to the point
+ if (distance === null)
+ {
+ distance = Math.sqrt(((x1 - point.x) * (x1 - point.x)) + ((y1 - point.y) * (y1 - point.y)));
+ }
- var newX: number = point.x * c - point.y * s;
- var newY: number = point.x * s - point.y * c;
+ point.x = x1 + distance * Math.cos(angle);
+ point.y = y1 + distance * Math.sin(angle);
- return point.setTo(newX + x, newY + y);
+ return point;
}
diff --git a/Phaser/GameObjectFactory.ts b/Phaser/GameObjectFactory.ts
new file mode 100644
index 00000000..8be5beed
--- /dev/null
+++ b/Phaser/GameObjectFactory.ts
@@ -0,0 +1,219 @@
+///
+
+/**
+* Phaser - GameObjectFactory
+*
+* A quick way to create new world objects and add existing objects to the current world.
+*/
+
+module Phaser {
+
+ export class GameObjectFactory {
+
+ /**
+ * GameObjectFactory constructor
+ * @param game {Game} A reference to the current Game.
+ */
+ constructor(game: Phaser.Game) {
+
+ this._game = game;
+ this._world = this._game.world;
+
+ }
+
+ /**
+ * Local private reference to Game
+ */
+ private _game: Phaser.Game;
+
+ /**
+ * Local private reference to World
+ */
+ private _world: Phaser.World;
+
+ /**
+ * Create a new camera with specific position and size.
+ *
+ * @param x {number} X position of the new camera.
+ * @param y {number} Y position of the new camera.
+ * @param width {number} Width of the new camera.
+ * @param height {number} Height of the new camera.
+ * @returns {Camera} The newly created camera object.
+ */
+ public camera(x: number, y: number, width: number, height: number): Camera {
+ return this._world.createCamera(x, y, width, height);
+ }
+
+ /**
+ * Create a new GeomSprite with specific position.
+ *
+ * @param x {number} X position of the new geom sprite.
+ * @param y {number} Y position of the new geom sprite.
+ * @returns {GeomSprite} The newly created geom sprite object.
+ */
+ public geomSprite(x: number, y: number): GeomSprite {
+ return this._world.createGeomSprite(x, y);
+ }
+
+ /**
+ * Create a new Sprite with specific position and sprite sheet key.
+ *
+ * @param x {number} X position of the new sprite.
+ * @param y {number} Y position of the new sprite.
+ * @param key {string} Optional, key for the sprite sheet you want it to use.
+ * @returns {Sprite} The newly created sprite object.
+ */
+ public sprite(x: number, y: number, key?: string = ''): Sprite {
+ return this._world.createSprite(x, y, key);
+ }
+
+ /**
+ * Create a new DynamicTexture with specific size.
+ *
+ * @param width {number} Width of the texture.
+ * @param height {number} Height of the texture.
+ * @returns {DynamicTexture} The newly created dynamic texture object.
+ */
+ public dynamicTexture(width: number, height: number): DynamicTexture {
+ return this._world.createDynamicTexture(width, height);
+ }
+
+ /**
+ * Create a new object container.
+ *
+ * @param maxSize {number} Optional, capacity of this group.
+ * @returns {Group} The newly created group.
+ */
+ public group(maxSize?: number = 0): Group {
+ return this._world.createGroup(maxSize);
+ }
+
+ /**
+ * Create a new Particle.
+ *
+ * @return {Particle} The newly created particle object.
+ */
+ public particle(): Particle {
+ return this._world.createParticle();
+ }
+
+ /**
+ * Create a new Emitter.
+ *
+ * @param x {number} Optional, x position of the emitter.
+ * @param y {number} Optional, y position of the emitter.
+ * @param size {number} Optional, size of this emitter.
+ * @return {Emitter} The newly created emitter object.
+ */
+ public emitter(x?: number = 0, y?: number = 0, size?: number = 0): Emitter {
+ return this._world.createEmitter(x, y, size);
+ }
+
+ /**
+ * Create a new ScrollZone object with image key, position and size.
+ *
+ * @param key {string} Key to a image you wish this object to use.
+ * @param x {number} X position of this object.
+ * @param y {number} Y position of this object.
+ * @param width number} Width of this object.
+ * @param height {number} Height of this object.
+ * @returns {ScrollZone} The newly created scroll zone object.
+ */
+ public scrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone {
+ return this._world.createScrollZone(key, x, y, width, height);
+ }
+
+ /**
+ * Create a new Tilemap.
+ *
+ * @param key {string} Key for tileset image.
+ * @param mapData {string} Data of this tilemap.
+ * @param format {number} Format of map data. (Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON)
+ * @param [resizeWorld] {boolean} resize the world to make same as tilemap?
+ * @param [tileWidth] {number} width of each tile.
+ * @param [tileHeight] {number} height of each tile.
+ * @return {Tilemap} The newly created tilemap object.
+ */
+ public tilemap(key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0): Tilemap {
+ return this._world.createTilemap(key, mapData, format, resizeWorld, tileWidth, tileHeight);
+ }
+
+ /**
+ * Create a tween object for a specific object.
+ *
+ * @param obj Object you wish the tween will affect.
+ * @return {Phaser.Tween} The newly created tween object.
+ */
+ public tween(obj): Tween {
+ return this._game.tweens.create(obj);
+ }
+
+ /**
+ * Add an existing Sprite to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param sprite The Sprite to add to the Game World
+ * @return {Phaser.Sprite} The Sprite object
+ */
+ public existingSprite(sprite: Sprite): Sprite {
+ return this._world.group.add(sprite);
+ }
+
+ /**
+ * Add an existing GeomSprite to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param sprite The GeomSprite to add to the Game World
+ * @return {Phaser.GeomSprite} The GeomSprite object
+ */
+ public existingGeomSprite(sprite: GeomSprite): GeomSprite {
+ return this._world.group.add(sprite);
+ }
+
+ /**
+ * Add an existing Emitter to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param emitter The Emitter to add to the Game World
+ * @return {Phaser.Emitter} The Emitter object
+ */
+ public existingEmitter(emitter: Emitter): Emitter {
+ return this._world.group.add(emitter);
+ }
+
+ /**
+ * Add an existing ScrollZone to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param scrollZone The ScrollZone to add to the Game World
+ * @return {Phaser.ScrollZone} The ScrollZone object
+ */
+ public existingScrollZone(scrollZone: ScrollZone): ScrollZone {
+ return this._world.group.add(scrollZone);
+ }
+
+ /**
+ * Add an existing Tilemap to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param tilemap The Tilemap to add to the Game World
+ * @return {Phaser.Tilemap} The Tilemap object
+ */
+ public existingTilemap(tilemap: Tilemap): Tilemap {
+ return this._world.group.add(tilemap);
+ }
+
+ /**
+ * Add an existing Tween to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param tween The Tween to add to the Game World
+ * @return {Phaser.Tween} The Tween object
+ */
+ public existingTween(tween: Tween): Tween {
+ return this._game.tweens.add(tween);
+ }
+
+ }
+
+}
diff --git a/Phaser/Loader.ts b/Phaser/Loader.ts
index 0c25fd19..6b604c19 100644
--- a/Phaser/Loader.ts
+++ b/Phaser/Loader.ts
@@ -76,6 +76,12 @@ module Phaser {
*/
public progress: number;
+ /**
+ * The crossOrigin value applied to loaded images
+ * @type {string}
+ */
+ public crossOrigin: string = '';
+
/**
* Reset loader, this will remove all loaded assets.
*/
@@ -280,6 +286,7 @@ module Phaser {
file.data.name = file.key;
file.data.onload = () => this.fileComplete(file.key);
file.data.onerror = () => this.fileError(file.key);
+ file.data.crossOrigin = this.crossOrigin;
file.data.src = file.url;
break;
diff --git a/Phaser/Phaser.csproj b/Phaser/Phaser.csproj
index 4bce4c50..9e1c2a0e 100644
--- a/Phaser/Phaser.csproj
+++ b/Phaser/Phaser.csproj
@@ -79,6 +79,10 @@
GameMath.ts
+
+
+ GameObjectFactory.ts
+
Emitter.ts
@@ -107,6 +111,14 @@
+
+
+ Polygon.ts
+
+
+
+ Response.ts
+
VerletManager.ts
diff --git a/Phaser/Phaser.ts b/Phaser/Phaser.ts
index 623bae7d..a2f663b4 100644
--- a/Phaser/Phaser.ts
+++ b/Phaser/Phaser.ts
@@ -1,7 +1,7 @@
/**
* Phaser
*
-* v0.9.5 - April 28th 2013
+* v0.9.6 - May 21st 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.5';
+ export var VERSION: string = 'Phaser version 0.9.6';
}
diff --git a/Phaser/Stage.ts b/Phaser/Stage.ts
index 24bb9b3e..38ee1305 100644
--- a/Phaser/Stage.ts
+++ b/Phaser/Stage.ts
@@ -195,23 +195,35 @@ module Phaser {
{
if (this._game.paused == false)
{
- this._pauseScreen.onPaused();
- this.saveCanvasValues();
- this._game.paused = true;
+ this.pauseGame();
}
}
else
{
if (this._game.paused == true)
{
- this._pauseScreen.onResume();
- this._game.paused = false;
- this.restoreCanvasValues();
+ this.resumeGame();
}
}
}
+ public pauseGame() {
+
+ this._pauseScreen.onPaused();
+ this.saveCanvasValues();
+ this._game.paused = true;
+
+ }
+
+ public resumeGame() {
+
+ this._pauseScreen.onResume();
+ this.restoreCanvasValues();
+ this._game.paused = false;
+
+ }
+
/**
* Get the DOM offset values of the given element
*/
diff --git a/Phaser/State.ts b/Phaser/State.ts
index 329e18da..99800280 100644
--- a/Phaser/State.ts
+++ b/Phaser/State.ts
@@ -18,6 +18,7 @@ module Phaser {
this.game = game;
+ this.add = game.add;
this.camera = game.camera;
this.cache = game.cache;
this.collision = game.collision;
@@ -56,6 +57,12 @@ module Phaser {
*/
public collision: Collision;
+ /**
+ * Reference to the GameObject Factory.
+ * @type {GameObjectFactory}
+ */
+ public add: GameObjectFactory;
+
/**
* Reference to the input manager
* @type {Input}
@@ -144,125 +151,6 @@ module Phaser {
*/
public destroy() { }
- // Handy Proxy methods
-
- /**
- * Create a new camera with specific position and size.
- *
- * @param x {number} X position of the new camera.
- * @param y {number} Y position of the new camera.
- * @param width {number} Width of the new camera.
- * @param height {number} Height of the new camera.
- * @returns {Camera} The newly created camera object.
- */
- public createCamera(x: number, y: number, width: number, height: number): Camera {
- return this.game.world.createCamera(x, y, width, height);
- }
-
- /**
- * Create a new GeomSprite with specific position.
- *
- * @param x {number} X position of the new geom sprite.
- * @param y {number} Y position of the new geom sprite.
- * @returns {GeomSprite} The newly created geom sprite object.
- */
- public createGeomSprite(x: number, y: number): GeomSprite {
- return this.world.createGeomSprite(x, y);
- }
-
- /**
- * Create a new Sprite with specific position and sprite sheet key.
- *
- * @param x {number} X position of the new sprite.
- * @param y {number} Y position of the new sprite.
- * @param key {string} [optional] key for the sprite sheet you want it to use.
- * @returns {Sprite} The newly created sprite object.
- */
- public createSprite(x: number, y: number, key?: string = ''): Sprite {
- return this.game.world.createSprite(x, y, key);
- }
-
- /**
- * Create a new DynamicTexture with specific size.
- *
- * @param width {number} Width of the texture.
- * @param height {number} Height of the texture.
- * @returns {DynamicTexture} The newly created dynamic texture object.
- */
- public createDynamicTexture(width: number, height: number): DynamicTexture {
- return this.game.world.createDynamicTexture(width, height);
- }
-
- /**
- * Create a new object container.
- *
- * @param maxSize {number} [optional] capacity of this group.
- * @returns {Group} The newly created group.
- */
- public createGroup(maxSize?: number = 0): Group {
- return this.game.world.createGroup(maxSize);
- }
-
- /**
- * Create a new Particle.
- *
- * @return {Particle} The newly created particle object.
- */
- public createParticle(): Particle {
- return this.game.world.createParticle();
- }
-
- /**
- * Create a new Emitter.
- *
- * @param x {number} [optional] x position of the emitter.
- * @param y {number} [optional] y position of the emitter.
- * @param size {number} [optional] size of this emitter.
- * @return {Emitter} The newly created emitter object.
- */
- public createEmitter(x?: number = 0, y?: number = 0, size?: number = 0): Emitter {
- return this.game.world.createEmitter(x, y, size);
- }
-
- /**
- * Create a new ScrollZone object with image key, position and size.
- *
- * @param key {string} Key to a image you wish this object to use.
- * @param x {number} X position of this object.
- * @param y {number} Y position of this object.
- * @param width {number} Width of this object.
- * @param height {number} Height of this object.
- * @returns {ScrollZone} The newly created scroll zone object.
- */
- public createScrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone {
- return this.game.world.createScrollZone(key, x, y, width, height);
- }
-
- /**
- * Create a new Tilemap.
- *
- * @param key {string} Key for tileset image.
- * @param mapData {string} Data of this tilemap.
- * @param format {number} Format of map data. (Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON)
- * @param resizeWorld {boolean} [optional] resize the world to make same as tilemap?
- * @param tileWidth {number} [optional] width of each tile.
- * @param tileHeight number} [optional] height of each tile.
- * @return {Tilemap} The newly created tilemap object.
- */
- public createTilemap(key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0): Tilemap {
- return this.game.world.createTilemap(key, mapData, format, resizeWorld, tileWidth, tileHeight);
- }
-
- /**
- * Create a tween object for a specific object.
- *
- * @param obj Object you wish the tween will affect.
- * @return {Phaser.Tween} The newly created tween object.
- */
- public createTween(obj): Tween {
- return this.game.tweens.create(obj);
- }
-
/**
* Call this method to see if one object collids another.
* @return {boolean} Whether the given objects or groups collids.
diff --git a/Phaser/TweenManager.ts b/Phaser/TweenManager.ts
index f5cdb5c4..f6d1a897 100644
--- a/Phaser/TweenManager.ts
+++ b/Phaser/TweenManager.ts
@@ -30,6 +30,7 @@ module Phaser {
* Local private reference to Game
*/
private _game: Phaser.Game;
+
/**
* Local private array which is the container of all tween objects.
*/
diff --git a/Phaser/VerletManager.ts b/Phaser/VerletManager.ts
index c9a60b69..8f4d1f52 100644
--- a/Phaser/VerletManager.ts
+++ b/Phaser/VerletManager.ts
@@ -42,12 +42,13 @@ module Phaser.Verlet {
}
private _game: Game;
+ private _v = new Phaser.Vector2;
public composites = [];
public width: number;
public height: number;
- public step: number = 32;
+ public step: number = 16;
public gravity: Vector2;
public friction: number;
public groundFriction: number;
@@ -55,15 +56,14 @@ module Phaser.Verlet {
public draggedEntity = null;
public highlightColor = '#4f545c';
-
/**
- * This class is actually a wrapper of canvas.
+ * A reference to the canvas this renders to
* @type {HTMLCanvasElement}
*/
public canvas: HTMLCanvasElement;
/**
- * Canvas context of this object.
+ * A reference to the context this renders to
* @type {CanvasRenderingContext2D}
*/
public context: CanvasRenderingContext2D;
@@ -71,10 +71,10 @@ module Phaser.Verlet {
/**
* Computes time of intersection of a particle with a wall
*
- * @param {Vec2} line wall's root position
- * @param {Vec2} p particle's position
- * @param {Vec2} dir walls's direction
- * @param {Vec2} v particle's velocity
+ * @param {Vec2} line walls root position
+ * @param {Vec2} p particle position
+ * @param {Vec2} dir walls direction
+ * @param {Vec2} v particles velocity
*/
public intersectionTime(wall, p, dir, v) {
@@ -100,81 +100,56 @@ module Phaser.Verlet {
return new Phaser.Vector2(p.x + v.x * t, p.y + v.y * t);
}
- private v = new Phaser.Vector2();
-
public bounds(particle: Phaser.Verlet.Particle) {
- this.v.mutableSet(particle.pos);
- this.v.mutableSub(particle.lastPos);
+ this._v.mutableSet(particle.pos);
+ this._v.mutableSub(particle.lastPos);
if (particle.pos.y > this.height - 1)
{
- particle.pos.mutableSet(
- this.intersectionPoint(new Phaser.Vector2(0, this.height - 1), particle.lastPos, new Phaser.Vector2(1, 0), this.v));
+ particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, this.height - 1), particle.lastPos, new Phaser.Vector2(1, 0), this._v));
}
if (particle.pos.x < 0)
{
- particle.pos.mutableSet(
- this.intersectionPoint(new Phaser.Vector2(0, 0), particle.pos, new Phaser.Vector2(0, 1), this.v));
+ particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, 0), particle.pos, new Phaser.Vector2(0, 1), this._v));
}
if (particle.pos.x > this.width - 1)
{
- particle.pos.mutableSet(
- this.intersectionPoint(new Phaser.Vector2(this.width - 1, 0), particle.pos, new Phaser.Vector2(0, 1), this.v));
+ particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(this.width - 1, 0), particle.pos, new Phaser.Vector2(0, 1), this._v));
}
}
- public OLDbounds(particle: Phaser.Verlet.Particle) {
-
- if (particle.pos.y > this.height - 1)
- particle.pos.y = this.height - 1;
-
- if (particle.pos.x < 0)
- {
- var vx = particle.pos.x - particle.lastPos.x;
- var vy = particle.pos.y - particle.lastPos.y;
-
- if (vx == 0)
- {
- particle.pos.x = 0;
- }
- else
- {
- var t = -particle.lastPos.x / vx;
- particle.pos.x = particle.lastPos.x + t * vx;
- particle.pos.y = particle.lastPos.y + t * vy;
- }
- }
-
- if (particle.pos.x > this.width - 1)
- particle.pos.x = this.width - 1;
-
- }
-
public createPoint(pos: Vector2) {
var composite = new Phaser.Verlet.Composite(this._game);
+
composite.particles.push(new Phaser.Verlet.Particle(pos));
+
this.composites.push(composite);
+
return composite;
}
public createLineSegments(vertices, stiffness) {
- var i;
var composite = new Phaser.Verlet.Composite(this._game);
+ var i;
for (i in vertices)
{
composite.particles.push(new Phaser.Verlet.Particle(vertices[i]));
+
if (i > 0)
+ {
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[i], composite.particles[i - 1], stiffness));
+ }
}
this.composites.push(composite);
+
return composite;
}
@@ -186,30 +161,40 @@ module Phaser.Verlet {
var xStride = width / segments;
var yStride = height / segments;
- var x, y;
+ var x;
+ var y;
+
for (y = 0; y < segments; ++y)
{
for (x = 0; x < segments; ++x)
{
var px = origin.x + x * xStride - width / 2 + xStride / 2;
var py = origin.y + y * yStride - height / 2 + yStride / 2;
+
composite.particles.push(new Phaser.Verlet.Particle(new Vector2(px, py)));
if (x > 0)
+ {
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[y * segments + x], composite.particles[y * segments + x - 1], stiffness));
+ }
if (y > 0)
+ {
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[y * segments + x], composite.particles[(y - 1) * segments + x], stiffness));
+ }
}
}
for (x = 0; x < segments; ++x)
{
if (x % pinMod == 0)
+ {
composite.pin(x);
+ }
}
this.composites.push(composite);
+
return composite;
}
@@ -284,7 +269,9 @@ module Phaser.Verlet {
// handle dragging of entities
if (this.draggedEntity)
- this.draggedEntity.pos.mutableSet(new Vector2(this._game.input.x, this._game.input.y));
+ {
+ this.draggedEntity.pos.mutableSet(this._game.input.position);
+ }
// relax
var stepCoef = 1 / this.step;
@@ -292,17 +279,25 @@ module Phaser.Verlet {
for (c in this.composites)
{
var constraints = this.composites[c].constraints;
+
for (i = 0; i < this.step; ++i)
+ {
for (j in constraints)
+ {
constraints[j].relax(stepCoef);
+ }
+ }
}
// bounds checking
for (c in this.composites)
{
var particles = this.composites[c].particles;
+
for (i in particles)
+ {
this.bounds(particles[i]);
+ }
}
}
@@ -335,7 +330,7 @@ module Phaser.Verlet {
for (i in particles)
{
- var d2 = particles[i].pos.dist2(new Vector2(this._game.input.x, this._game.input.y));
+ var d2 = particles[i].pos.distance2(this._game.input.position);
if (d2 <= this.selectionRadius * this.selectionRadius && (entity == null || d2 < d2Nearest))
{
@@ -348,13 +343,19 @@ module Phaser.Verlet {
// search for pinned constraints for this entity
for (i in constraintsNearest)
+ {
if (constraintsNearest[i] instanceof PinConstraint && constraintsNearest[i].a == entity)
+ {
entity = constraintsNearest[i];
+ }
+ }
return entity;
}
+ public hideNearestEntityCircle: bool = false;
+
public render() {
var i, c;
@@ -365,34 +366,43 @@ module Phaser.Verlet {
if (this.composites[c].drawConstraints)
{
this.composites[c].drawConstraints(this.context, this.composites[c]);
- } else
+ }
+ else
{
var constraints = this.composites[c].constraints;
+
for (i in constraints)
+ {
constraints[i].render(this.context);
+ }
}
// draw particles
if (this.composites[c].drawParticles)
{
this.composites[c].drawParticles(this.context, this.composites[c]);
- } else
+ }
+ else
{
var particles = this.composites[c].particles;
+
for (i in particles)
+ {
particles[i].render(this.context);
+ }
}
}
// highlight nearest / dragged entity
var nearest = this.draggedEntity || this.nearestEntity();
- if (nearest)
+ if (nearest && this.hideNearestEntityCircle == false)
{
this.context.beginPath();
this.context.arc(nearest.pos.x, nearest.pos.y, 8, 0, 2 * Math.PI);
this.context.strokeStyle = this.highlightColor;
this.context.stroke();
+ this.context.closePath();
}
}
diff --git a/Phaser/World.ts b/Phaser/World.ts
index 1f8abfc0..d490d497 100644
--- a/Phaser/World.ts
+++ b/Phaser/World.ts
@@ -101,13 +101,14 @@ module Phaser {
/**
* Update size of this world with specific width and height.
- * You can choose update camera bounds automatically or not.
+ * You can choose update camera bounds and verlet manager automatically or not.
*
* @param width {number} New width of the world.
* @param height {number} New height of the world.
* @param [updateCameraBounds] {boolean} update camera bounds automatically or not. Default to true.
+ * @param [updateVerletBounds] {boolean} update verlet bounds automatically or not. Default to true.
*/
- public setSize(width: number, height: number, updateCameraBounds: bool = true) {
+ public setSize(width: number, height: number, updateCameraBounds: bool = true, updateVerletBounds: bool = true) {
this.bounds.width = width;
this.bounds.height = height;
@@ -117,6 +118,12 @@ module Phaser {
this._game.camera.setBounds(0, 0, width, height);
}
+ if (updateVerletBounds == true)
+ {
+ this._game.verlet.width = width;
+ this._game.verlet.height = height;
+ }
+
}
public get width(): number {
diff --git a/Phaser/gameobjects/GameObject.ts b/Phaser/gameobjects/GameObject.ts
index 9ddf6559..b4a945bd 100644
--- a/Phaser/gameobjects/GameObject.ts
+++ b/Phaser/gameobjects/GameObject.ts
@@ -835,6 +835,12 @@ module Phaser {
* Clean up memory.
*/
public destroy() {
+ }
+
+ public setPosition(x: number, y: number) {
+
+ this.x = x;
+ this.y = y;
}
diff --git a/Phaser/gameobjects/GeomSprite.ts b/Phaser/gameobjects/GeomSprite.ts
index 4c68c2ba..053c3dd6 100644
--- a/Phaser/gameobjects/GeomSprite.ts
+++ b/Phaser/gameobjects/GeomSprite.ts
@@ -1,4 +1,5 @@
///
+///
/**
* Phaser - GeomSprite
@@ -71,6 +72,12 @@ module Phaser {
*/
public static RECTANGLE: number = 4;
+ /**
+ * Polygon.
+ * @type {number}
+ */
+ public static POLYGON: number = 5;
+
/**
* Circle shape container. A Circle instance.
* @type {Circle}
@@ -95,6 +102,12 @@ module Phaser {
*/
public rect: Rectangle;
+ /**
+ * Polygon shape container. A Polygon instance.
+ * @type {Polygon}
+ */
+ public polygon: Polygon;
+
/**
* Render outline of this sprite or not. (default is true)
* @type {boolean}
@@ -243,6 +256,22 @@ module Phaser {
}
+ /**
+ * Create a polygon object
+ * @param width {Number} Width of the rectangle
+ * @param height {Number} Height of the rectangle
+ * @return {GeomSprite} GeomSprite instance.
+ */
+ createPolygon(points?: Vector2[] = []): GeomSprite {
+
+ this.refresh();
+ this.polygon = new Polygon(new Vector2(this.x, this.y), points);
+ this.type = GeomSprite.POLYGON;
+ //this.frameBounds.copyFrom(this.rect);
+ return this;
+
+ }
+
/**
* Destroy all geom shapes of this sprite.
*/
diff --git a/Phaser/gameobjects/Sprite.ts b/Phaser/gameobjects/Sprite.ts
index 8563fd95..c4a4eff7 100644
--- a/Phaser/gameobjects/Sprite.ts
+++ b/Phaser/gameobjects/Sprite.ts
@@ -109,9 +109,15 @@ module Phaser {
/**
* Load graphic for this sprite. (graphic can be SpriteSheet or Texture)
* @param key {string} Key of the graphic you want to load for this sprite.
+ * @param clearAnimations {boolean} If this Sprite has a set of animation data already loaded you can choose to keep or clear it with this boolean
* @return {Sprite} Sprite instance itself.
*/
- public loadGraphic(key: string): Sprite {
+ public loadGraphic(key: string, clearAnimations: bool = true): Sprite {
+
+ if (clearAnimations && this.animations.frameData !== null)
+ {
+ this.animations.destroy();
+ }
if (this._game.cache.getImage(key) !== null)
{
@@ -127,8 +133,8 @@ module Phaser {
{
this._texture = this._game.cache.getImage(key);
this.animations.loadFrameData(this._game.cache.getFrameData(key));
- //this.collisionMask.width = this._texture.width;
- //this.collisionMask.height = this._texture.height;
+ this.collisionMask.width = this.animations.currentFrame.width;
+ this.collisionMask.height = this.animations.currentFrame.height;
}
this._dynamicTexture = false;
@@ -181,19 +187,27 @@ module Phaser {
*/
public inCamera(camera: Rectangle): bool {
- if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
+ // Object fixed in place regardless of the camera scrolling? Then it's always visible
+ if (this.scrollFactor.x == 0 && this.scrollFactor.y == 0)
{
- this._dx = this.frameBounds.x - (camera.x * this.scrollFactor.x);
- this._dy = this.frameBounds.y - (camera.y * this.scrollFactor.x);
+ return true;
+ }
+
+ // Otherwise, if it's scrolling perfectly in sync with the camera (1 to 1) then it's a simple bounds check on world coordinates
+ if (this.scrollFactor.x == 1 && this.scrollFactor.y == 1)
+ {
+ return camera.intersects(this.frameBounds, this.frameBounds.length);
+ }
+ else
+ {
+ // Else apply the offsets
+ this._dx = (this.frameBounds.x - camera.x) * this.scrollFactor.x;
+ this._dy = (this.frameBounds.y - camera.y) * this.scrollFactor.y;
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.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.intersects(this.frameBounds, this.frameBounds.length);
- }
}
@@ -250,8 +264,9 @@ module Phaser {
this._sy = 0;
this._sw = this.frameBounds.width;
this._sh = this.frameBounds.height;
- this._dx = cameraOffsetX + (this.frameBounds.topLeft.x - camera.worldView.x);
- this._dy = cameraOffsetY + (this.frameBounds.topLeft.y - camera.worldView.y);
+
+ this._dx = (cameraOffsetX * this.scrollFactor.x) + this.frameBounds.topLeft.x - (camera.worldView.x * this.scrollFactor.x);
+ this._dy = (cameraOffsetY * this.scrollFactor.y) + this.frameBounds.topLeft.y - (camera.worldView.y * this.scrollFactor.y);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
@@ -305,10 +320,10 @@ module Phaser {
}
// Apply camera difference
- if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
+ if (this.scrollFactor.x !== 1 || this.scrollFactor.y !== 1)
{
- this._dx -= (camera.worldView.x * this.scrollFactor.x);
- this._dy -= (camera.worldView.y * this.scrollFactor.y);
+ //this._dx -= (camera.worldView.x * this.scrollFactor.x);
+ //this._dy -= (camera.worldView.y * this.scrollFactor.y);
}
// Rotation - needs to work from origin point really, but for now from center
diff --git a/Phaser/geom/Circle.ts b/Phaser/geom/Circle.ts
index f162c179..348096bb 100644
--- a/Phaser/geom/Circle.ts
+++ b/Phaser/geom/Circle.ts
@@ -21,12 +21,14 @@ module Phaser {
**/
constructor(x: number = 0, y: number = 0, diameter: number = 0) {
+ this._pos = new Vector2;
this.setTo(x, y, diameter);
}
private _diameter: number = 0;
private _radius: number = 0;
+ private _pos: Vector2;
/**
* The x coordinate of the center of the circle
@@ -42,15 +44,22 @@ module Phaser {
**/
public y: number = 0;
+ /**
+ * The position of this Circle object represented by a Vector2
+ * @property pos
+ * @type Vector2
+ **/
+ public get pos(): Vector2 {
+ return this._pos.setTo(this.x, this.y);
+ }
+
/**
* The diameter of the circle. The largest distance between any two points on the circle. The same as the radius * 2.
* @method diameter
* @return {Number}
**/
get diameter(): number {
-
return this._diameter;
-
}
/**
diff --git a/Phaser/geom/Polygon.ts b/Phaser/geom/Polygon.ts
new file mode 100644
index 00000000..cef1b05c
--- /dev/null
+++ b/Phaser/geom/Polygon.ts
@@ -0,0 +1,60 @@
+///
+
+/**
+* Phaser - Polygon
+*
+*/
+
+module Phaser {
+
+ export class Polygon {
+
+ /**
+ * A *convex* clockwise polygon
+ * @class Polygon
+ * @constructor
+ * @param {Vector2} pos A vector representing the origin of the polygon (all other points are relative to this one)
+ * @param {Array.} points An Array of vectors representing the points in the polygon, in clockwise order.
+ **/
+ constructor(pos?: Vector2 = new Vector2, points?: Vector2[] = [], parent?:any = null) {
+
+ this.pos = pos;
+ this.points = points;
+ this.parent = parent;
+ this.recalc();
+
+ }
+
+ public parent: any;
+ public pos: Vector2;
+ public points: Vector2[];
+ public edges: Vector2[];
+ public normals: Vector2[];
+
+ /**
+ * Recalculate the edges and normals of the polygon. This
+ * MUST be called if the points array is modified at all and
+ * the edges or normals are to be accessed.
+ */
+ public recalc() {
+
+ var points = this.points;
+ var len = points.length;
+
+ this.edges = [];
+ this.normals = [];
+
+ for (var i = 0; i < len; i++)
+ {
+ var p1 = points[i];
+ var p2 = i < len - 1 ? points[i + 1] : points[0];
+ var e = new Vector2().copyFrom(p2).sub(p1);
+ var n = new Vector2().copyFrom(e).perp().normalize();
+ this.edges.push(e);
+ this.normals.push(n);
+ }
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/Phaser/geom/Quad.ts b/Phaser/geom/Quad.ts
index d6cb7aa0..4008c7a5 100644
--- a/Phaser/geom/Quad.ts
+++ b/Phaser/geom/Quad.ts
@@ -1,4 +1,5 @@
///
+///
/**
* Phaser - Quad
@@ -90,6 +91,22 @@ module Phaser {
}
+ /**
+ * Determines whether the object specified intersects (overlaps) with the given values.
+ * @method intersectsProps
+ * @param {Number} left
+ * @param {Number} right
+ * @param {Number} top
+ * @param {Number} bottomt
+ * @param {Number} tolerance 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 Quad; otherwise false.
+ **/
+ public intersectsRaw(left: number, right: number, top: number, bottom: number, tolerance?: number = 0): bool {
+
+ return !(left > this.right + tolerance || right < this.left - tolerance || top > this.bottom + tolerance || bottom < this.top - tolerance);
+
+ }
+
/**
* Determines whether the specified coordinates are contained within the region defined by this Quad object.
* @method contains
@@ -133,6 +150,20 @@ module Phaser {
}
+ /**
+ * Creates and returns a Polygon that is the same as this Quad.
+ * @method toPolygon
+ * @return {Polygon} A new Polygon that represents this quad.
+ **/
+ public toPolygon(): Polygon {
+
+ return new Polygon(new Vector2(this.x, this.y), [
+ new Vector2(), new Vector2(this.width, 0),
+ new Vector2(this.width, this.height), new Vector2(0, this.height)
+ ]);
+
+ }
+
/**
* Returns a string representation of this object.
* @method toString
diff --git a/Phaser/geom/Response.ts b/Phaser/geom/Response.ts
new file mode 100644
index 00000000..563f25cb
--- /dev/null
+++ b/Phaser/geom/Response.ts
@@ -0,0 +1,87 @@
+///
+///
+
+/**
+* Phaser - Response
+*
+*/
+
+module Phaser {
+
+ export class Response {
+
+ /**
+ * An object representing the result of an intersection. Contain information about:
+ * - The two objects participating in the intersection
+ * - The vector representing the minimum change necessary to extract the first object
+ * from the second one.
+ * - Whether the first object is entirely inside the second, or vice versa.
+ *
+ * @constructor
+ */
+ constructor() {
+
+ this.a = null;
+ this.b = null;
+ this.overlapN = new Vector2;
+ this.overlapV = new Vector2;
+
+ this.clear();
+
+ }
+
+ /**
+ * The first object in the collision
+ */
+ public a;
+
+ /**
+ * The second object in the collision
+ */
+ public b;
+
+ /**
+ * The shortest colliding axis (unit-vector)
+ */
+ public overlapN: Vector2;
+
+ /**
+ * The overlap vector (i.e. overlapN.scale(overlap, overlap)).
+ * If this vector is subtracted from the position of `a`, `a` and `b` will no longer be colliding.
+ */
+ public overlapV: Vector2;
+
+ /**
+ * Whether the first object is completely inside the second.
+ */
+ public aInB: bool;
+
+ /**
+ * Whether the second object is completely inside the first.
+ */
+ public bInA: bool;
+
+ /**
+ * Magnitude of the overlap on the shortest colliding axis
+ */
+ public overlap: number;
+
+ /**
+ * Set some values of the response back to their defaults. Call this between tests if
+ * you are going to reuse a single Response object for multiple intersection tests (recommented)
+ *
+ * @return {Response} This for chaining
+ */
+ public clear() {
+
+ this.aInB = true;
+ this.bInA = true;
+ this.overlap = Number.MAX_VALUE;
+
+ return this;
+
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/Phaser/geom/Vector2.ts b/Phaser/geom/Vector2.ts
index 7ea3d62e..91da7f43 100644
--- a/Phaser/geom/Vector2.ts
+++ b/Phaser/geom/Vector2.ts
@@ -3,7 +3,8 @@
/**
* Phaser - Vector2
*
-* A simple 2-dimensional vector class. Based on the one included with verlet-js by Sub Protocol released under MIT
+* A two dimensional vector.
+* Contains methods and ideas from verlet-js by Sub Protocol, SAT.js by Jim Riecken and N by Metanet Software.
*/
module Phaser {
@@ -14,8 +15,8 @@ module Phaser {
* Creates a new Vector2 object.
* @class Vector2
* @constructor
- * @param {Number} x The x coordinate of vector2
- * @param {Number} y The y coordinate of vector2
+ * @param {Number} x The x position of the vector
+ * @param {Number} y The y position of the vector
* @return {Vector2} This object
**/
constructor(x: number = 0, y: number = 0) {
@@ -34,62 +35,163 @@ module Phaser {
return this;
}
+ /**
+ * Add this vector to the given one and return the result.
+ *
+ * @param {Vector2} v The other Vector.
+ * @param {Vector2} The output Vector.
+ * @return {Vector2} The new Vector
+ */
public add(v: Vector2, output?:Vector2 = new Vector2): Vector2 {
return output.setTo(this.x + v.x, this.y + v.y);
}
+ /**
+ * Subtract this vector to the given one and return the result.
+ *
+ * @param {Vector2} v The other Vector.
+ * @param {Vector2} The output Vector.
+ * @return {Vector2} The new Vector
+ */
public sub(v: Vector2, output?:Vector2 = new Vector2): Vector2 {
return output.setTo(this.x - v.x, this.y - v.y);
}
+ /**
+ * Multiply this vector with the given one and return the result.
+ *
+ * @param {Vector2} v The other Vector.
+ * @param {Vector2} The output Vector.
+ * @return {Vector2} The new Vector
+ */
public mul(v: Vector2, output?:Vector2 = new Vector2): Vector2 {
return output.setTo(this.x * v.x, this.y * v.y);
}
+ /**
+ * Divide this vector by the given one and return the result.
+ *
+ * @param {Vector2} v The other Vector.
+ * @param {Vector2} The output Vector.
+ * @return {Vector2} The new Vector
+ */
public div(v: Vector2, output?:Vector2 = new Vector2): Vector2 {
return output.setTo(this.x / v.x, this.y / v.y);
}
- public scale(coef: number, output?:Vector2 = new Vector2): Vector2 {
- return output.setTo(this.x * coef, this.y * coef);
+ /**
+ * Scale this vector by the given values and return the result.
+ *
+ * @param {number} x The scaling factor in the x direction.
+ * @param {?number=} y The scaling factor in the y direction. If this
+ * is not specified, the x scaling factor will be used.
+ * @return {Vector} The new Vector
+ */
+ public scale(x: number, y?:number = null, output?:Vector2 = new Vector2): Vector2 {
+
+ if (y === null)
+ {
+ y = x;
+ }
+
+ return output.setTo(this.x * x, this.y * y);
+
}
+ /**
+ * Rotate this vector by 90 degrees
+ *
+ * @return {Vector} This for chaining.
+ */
+ public perp(output?: Vector2 = this): Vector2 {
+ var x = this.x;
+ return output.setTo(this.y, -x);
+ }
+
+ // Same as copyFrom, used by VerletManager
public mutableSet(v: Vector2): Vector2 {
this.x = v.x;
this.y = v.y;
return this;
}
+ /**
+ * Add another vector to this one.
+ *
+ * @param {Vector} other The other Vector.
+ * @return {Vector} This for chaining.
+ */
public mutableAdd(v: Vector2): Vector2 {
this.x += v.x;
this.y += v.y;
return this;
}
+ /**
+ * Subtract another vector from this one.
+ *
+ * @param {Vector} other The other Vector.
+ * @return {Vector} This for chaining.
+ */
public mutableSub(v: Vector2): Vector2 {
this.x -= v.x;
this.y -= v.y;
return this;
}
+ /**
+ * Multiply another vector with this one.
+ *
+ * @param {Vector} other The other Vector.
+ * @return {Vector} This for chaining.
+ */
public mutableMul(v: Vector2): Vector2 {
this.x *= v.x;
this.y *= v.y;
return this;
}
+ /**
+ * Divide this vector by another one.
+ *
+ * @param {Vector} other The other Vector.
+ * @return {Vector} This for chaining.
+ */
public mutableDiv(v: Vector2): Vector2 {
this.x /= v.x;
this.y /= v.y;
return this;
}
- public mutableScale(coef: number): Vector2 {
- this.x *= coef;
- this.y *= coef;
+ /**
+ * Scale this vector.
+ *
+ * @param {number} x The scaling factor in the x direction.
+ * @param {?number=} y The scaling factor in the y direction. If this
+ * is not specified, the x scaling factor will be used.
+ * @return {Vector} This for chaining.
+ */
+ public mutableScale(x: number, y?:number): Vector2 {
+ this.x *= x;
+ this.y *= y || x;
return this;
}
+ /**
+ * Reverse this vector.
+ *
+ * @return {Vector} This for chaining.
+ */
+ public reverse(): Vector2 {
+ this.x = -this.x;
+ this.y = -this.y;
+ return this;
+ }
+
+ public edge(v: Vector2, output?: Vector2 = new Vector2): Vector2 {
+ return this.sub(v, output);
+ }
+
public equals(v: Vector2): bool {
return this.x == v.x && this.y == v.y;
}
@@ -98,31 +200,190 @@ module Phaser {
return Math.abs(this.x - v.x) <= epsilon && Math.abs(this.y - v.y) <= epsilon;
}
+ /**
+ * Get the length of this vector.
+ *
+ * @return {number} The length of this vector.
+ */
public length(): number {
- return Math.sqrt(this.x * this.x + this.y * this.y);
+ return Math.sqrt((this.x * this.x) + (this.y * this.y));
}
+ /**
+ * Get the length^2 of this vector.
+ *
+ * @return {number} The length^2 of this vector.
+ */
public length2(): number {
- return this.x * this.x + this.y * this.y;
+ return (this.x * this.x) + (this.y * this.y);
}
- public dist(v: Vector2): number {
- return Math.sqrt(this.dist2(v));
+ /**
+ * Get the distance between this vector and the given vector.
+ *
+ * @return {Vector2} v The vector to check
+ */
+ public distance(v: Vector2): number {
+ return Math.sqrt(this.distance2(v));
}
- public dist2(v: Vector2): number {
+ /**
+ * Get the distance^2 between this vector and the given vector.
+ *
+ * @return {Vector2} v The vector to check
+ */
+ public distance2(v: Vector2): number {
return ((v.x - this.x) * (v.x - this.x)) + ((v.y - this.y) * (v.y - this.y));
}
- public normal(output?: Vector2 = new Vector2) {
- var m = Math.sqrt(this.x * this.x + this.y * this.y);
- return output.setTo(this.x / m, this.y / m);
+ /**
+ * Project this vector on to another vector.
+ *
+ * @param {Vector} other The vector to project onto.
+ * @return {Vector} This for chaining.
+ */
+ public project(other: Vector2): Vector2 {
+
+ var amt = this.dot(other) / other.length2();
+
+ if (amt != 0)
+ {
+ this.x = amt * other.x;
+ this.y = amt * other.y;
+ }
+
+ return this;
+
}
+ /**
+ * Project this vector onto a vector of unit length.
+ *
+ * @param {Vector} other The unit vector to project onto.
+ * @return {Vector} This for chaining.
+ */
+ public projectN(other: Vector2): Vector2 {
+
+ var amt = this.dot(other);
+
+ if (amt != 0)
+ {
+ this.x = amt * other.x;
+ this.y = amt * other.y;
+ }
+
+ return this;
+
+ }
+
+ /**
+ * Reflect this vector on an arbitrary axis.
+ *
+ * @param {Vector} axis The vector representing the axis.
+ * @return {Vector} This for chaining.
+ */
+ public reflect(axis): Vector2 {
+
+ var x = this.x;
+ var y = this.y;
+ this.project(axis).scale(2);
+ this.x -= x;
+ this.y -= y;
+
+ return this;
+
+ }
+
+ /**
+ * Reflect this vector on an arbitrary axis (represented by a unit vector)
+ *
+ * @param {Vector} axis The unit vector representing the axis.
+ * @return {Vector} This for chaining.
+ */
+ public reflectN(axis): Vector2 {
+
+ var x = this.x;
+ var y = this.y;
+ this.projectN(axis).scale(2);
+ this.x -= x;
+ this.y -= y;
+
+ return this;
+
+ }
+
+ public getProjectionMagnitude(v: Vector2): number {
+
+ var den = v.dot(v);
+
+ if (den == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return Math.abs(this.dot(v) / den);
+ }
+
+ }
+
+ public direction(output?: Vector2 = new Vector2): Vector2 {
+
+ output.copyFrom(this);
+ return this.normalize(output);
+
+ }
+
+ public normalRightHand(output?: Vector2 = this): Vector2 {
+ return output.setTo(this.y * -1, this.x);
+ }
+
+ /**
+ * Normalize (make unit length) this vector.
+ *
+ * @return {Vector} This for chaining.
+ */
+ public normalize(output?: Vector2 = this): Vector2 {
+
+ var m = this.length();
+
+ if (m != 0)
+ {
+ output.setTo(this.x / m, this.y / m);
+ }
+
+ return output;
+ }
+
+ public getMagnitude(): number {
+ return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
+ }
+
+ /**
+ * Get the dot product of this vector against another.
+ *
+ * @param {Vector} other The vector to dot this one against.
+ * @return {number} The dot product.
+ */
public dot(v: Vector2): number {
- return this.x * v.x + this.y * v.y;
+ return ((this.x * v.x) + (this.y * v.y));
}
+ /**
+ * Get the cross product of this vector against another.
+ *
+ * @param {Vector} other The vector to cross this one against.
+ * @return {number} The cross product.
+ */
+ public cross(v: Vector2): number {
+ return ((this.x * v.y) - (this.y * v.x));
+ }
+
+ /**
+ * Get the angle between this vector and the given vector.
+ *
+ * @return {Vector2} v The vector to check
+ */
public angle(v: Vector2): number {
return Math.atan2(this.x * v.y - this.y * v.x, this.x * v.x + this.y * v.y);
}
@@ -131,12 +392,31 @@ module Phaser {
return vLeft.sub(this).angle(vRight.sub(this));
}
+ /**
+ * Rotate this vector around the origin to the given angle (theta) and return the result in a new Vector
+ *
+ * @return {Vector2} v The vector to check
+ */
public rotate(origin, theta, output?: Vector2 = new Vector2): Vector2 {
var x = this.x - origin.x;
var y = this.y - origin.y;
return output.setTo(x * Math.cos(theta) - y * Math.sin(theta) + origin.x, x * Math.sin(theta) + y * Math.cos(theta) + origin.y);
}
+ public clone(output?: Vector2 = new Vector2): Vector2 {
+ return output.setTo(this.x, this.y);
+ }
+
+ public copyFrom(v: Vector2): Vector2 {
+ this.x = v.x;
+ this.y = v.y;
+ return this;
+ }
+
+ public copyTo(v: Vector2): Vector2 {
+ return v.setTo(this.x, this.y);
+ }
+
/**
* Returns a string representation of this object.
* @method toString
diff --git a/Phaser/phaser.js b/Phaser/phaser.js
index d2fe1029..9d6e7b54 100644
--- a/Phaser/phaser.js
+++ b/Phaser/phaser.js
@@ -1,7 +1,7 @@
/**
* Phaser
*
-* v0.9.5 - April 28th 2013
+* v0.9.6 - May 21st 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.5';
+ Phaser.VERSION = 'Phaser version 0.9.6';
})(Phaser || (Phaser = {}));
diff --git a/Phaser/system/Camera.ts b/Phaser/system/Camera.ts
index 029bf999..e7a585c6 100644
--- a/Phaser/system/Camera.ts
+++ b/Phaser/system/Camera.ts
@@ -318,7 +318,7 @@ module Phaser {
{
if (this.deadzone == null)
{
- this.focusOnXY(this._target.x + this._target.origin.x, this._target.y + this._target.origin.y);
+ this.focusOnXY(this._target.x, this._target.y);
}
else
{
diff --git a/Phaser/system/CollisionMask.ts b/Phaser/system/CollisionMask.ts
index 61ae360d..f0186ae0 100644
--- a/Phaser/system/CollisionMask.ts
+++ b/Phaser/system/CollisionMask.ts
@@ -155,8 +155,6 @@ module Phaser {
public update() {
- //this.quad.x = this._parent.x + this.offset.x;
- //this.quad.y = this._parent.y + this.offset.y;
this._ref.x = this._parent.x + this.offset.x;
this._ref.y = this._parent.y + this.offset.y;
@@ -173,8 +171,7 @@ module Phaser {
var _dx = cameraOffsetX + (this.x - camera.worldView.x);
var _dy = cameraOffsetY + (this.y - camera.worldView.y);
- //this._parent.context.fillStyle = this._parent.renderDebugColor;
- this._parent.context.fillStyle = 'rgba(255,0,0,0.4)';
+ this._parent.context.fillStyle = this._parent.renderDebugColor;
if (this.type == CollisionMask.QUAD)
{
@@ -207,6 +204,23 @@ module Phaser {
}
+ 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.
@@ -224,7 +238,6 @@ module Phaser {
// Circle vs. Circle
if (this.type == CollisionMask.CIRCLE && source.type == CollisionMask.CIRCLE)
{
- console.log('c vs c');
return Collision.circleToCircle(this.circle, source.circle).result;
}
diff --git a/Phaser/system/input/Input.ts b/Phaser/system/input/Input.ts
index a71725ab..3449a437 100644
--- a/Phaser/system/input/Input.ts
+++ b/Phaser/system/input/Input.ts
@@ -25,11 +25,6 @@ module Phaser {
this.pointer3 = new Pointer(this._game, 3);
this.pointer4 = new Pointer(this._game, 4);
this.pointer5 = new Pointer(this._game, 5);
- this.pointer6 = new Pointer(this._game, 6);
- this.pointer7 = new Pointer(this._game, 7);
- this.pointer8 = new Pointer(this._game, 8);
- this.pointer9 = new Pointer(this._game, 9);
- this.pointer10 = new Pointer(this._game, 10);
this.mouse = new Mouse(this._game);
this.keyboard = new Keyboard(this._game);
@@ -42,7 +37,7 @@ module Phaser {
this.onTap = new Phaser.Signal();
this.onHold = new Phaser.Signal();
- this.point = new Point();
+ this.position = new Vector2;
this.circle = new Circle(0, 0, 44);
this.currentPointers = 0;
@@ -115,11 +110,11 @@ module Phaser {
public gestures: Gestures;
/**
- * A Point object representing the x/y screen coordinates of the Pointer.
- * @property point
- * @type {Point}
+ * A vector object representing the current position of the Pointer.
+ * @property vector
+ * @type {Vector2}
**/
- public point: Point = null;
+ public position: Vector2 = null;
/**
* A Circle object centered on the x/y screen coordinates of the Input.
@@ -299,35 +294,35 @@ module Phaser {
* @property pointer6
* @type {Pointer}
**/
- public pointer6: Pointer;
+ public pointer6: Pointer = null;
/**
* A Pointer object
* @property pointer7
* @type {Pointer}
**/
- public pointer7: Pointer;
+ public pointer7: Pointer = null;
/**
* A Pointer object
* @property pointer8
* @type {Pointer}
**/
- public pointer8: Pointer;
+ public pointer8: Pointer = null;
/**
* A Pointer object
* @property pointer9
* @type {Pointer}
**/
- public pointer9: Pointer;
+ public pointer9: Pointer = null;
/**
* A Pointer object
* @property pointer10
* @type {Pointer}
**/
- public pointer10: Pointer;
+ public pointer10: Pointer = null;
/**
* The screen X coordinate
@@ -363,6 +358,58 @@ module Phaser {
}
+ /**
+ * Add a new Pointer object to the Input Manager. By default Input creates 5 pointer objects for you. If you need more
+ * use this to create a new one, up to a maximum of 10.
+ * @method addPointer
+ * @return {Pointer} A reference to the new Pointer object
+ **/
+ public addPointer(): Pointer {
+
+ var next: number = 0;
+
+ if (this.pointer10 === null)
+ {
+ next = 10;
+ }
+
+ if (this.pointer9 === null)
+ {
+ next = 9;
+ }
+
+ if (this.pointer8 === null)
+ {
+ next = 8;
+ }
+
+ if (this.pointer7 === null)
+ {
+ next = 7;
+ }
+
+ if (this.pointer6 === null)
+ {
+ next = 6;
+ }
+
+ if (next == 0)
+ {
+ throw new Error("You can only have 10 Pointer objects");
+ return null;
+ }
+ else
+ {
+ this['pointer' + next] = new Pointer(this._game, next);
+ return this['pointer' + next];
+ }
+
+ }
+
+ /**
+ * Starts the Input Manager running
+ * @method start
+ **/
public start() {
this.mouse.start();
@@ -373,6 +420,10 @@ module Phaser {
}
+ /**
+ * Updates the Input Manager. Called by the core Game loop.
+ * @method update
+ **/
public update() {
this.mousePointer.update();
@@ -381,11 +432,12 @@ module Phaser {
this.pointer3.update();
this.pointer4.update();
this.pointer5.update();
- this.pointer6.update();
- this.pointer7.update();
- this.pointer8.update();
- this.pointer9.update();
- this.pointer10.update();
+
+ if (this.pointer6) { this.pointer6.update(); }
+ if (this.pointer7) { this.pointer7.update(); }
+ if (this.pointer8) { this.pointer8.update(); }
+ if (this.pointer9) { this.pointer9.update(); }
+ if (this.pointer10) { this.pointer10.update(); }
}
@@ -403,11 +455,12 @@ module Phaser {
this.pointer3.reset();
this.pointer4.reset();
this.pointer5.reset();
- this.pointer6.reset();
- this.pointer7.reset();
- this.pointer8.reset();
- this.pointer9.reset();
- this.pointer10.reset();
+
+ if (this.pointer6) { this.pointer6.reset(); }
+ if (this.pointer7) { this.pointer7.reset(); }
+ if (this.pointer8) { this.pointer8.reset(); }
+ if (this.pointer9) { this.pointer9.reset(); }
+ if (this.pointer10) { this.pointer10.reset(); }
this.currentPointers = 0;
@@ -417,7 +470,6 @@ module Phaser {
this.onUp = new Phaser.Signal();
this.onTap = new Phaser.Signal();
this.onHold = new Phaser.Signal();
-
}
}
@@ -462,23 +514,23 @@ module Phaser {
{
this.currentPointers++;
}
- else if (this.pointer6.active == true)
+ else if (this.pointer6 && this.pointer6.active == true)
{
this.currentPointers++;
}
- else if (this.pointer7.active == true)
+ else if (this.pointer7 && this.pointer7.active == true)
{
this.currentPointers++;
}
- else if (this.pointer8.active == true)
+ else if (this.pointer8 && this.pointer8.active == true)
{
this.currentPointers++;
}
- else if (this.pointer9.active == true)
+ else if (this.pointer9 && this.pointer9.active == true)
{
this.currentPointers++;
}
- else if (this.pointer10.active == true)
+ else if (this.pointer10 && this.pointer10.active == true)
{
this.currentPointers++;
}
@@ -521,23 +573,23 @@ module Phaser {
{
return this.pointer5.start(event);
}
- else if (this.pointer6.active == false)
+ else if (this.pointer6 && this.pointer6.active == false)
{
return this.pointer6.start(event);
}
- else if (this.pointer7.active == false)
+ else if (this.pointer7 && this.pointer7.active == false)
{
return this.pointer7.start(event);
}
- else if (this.pointer8.active == false)
+ else if (this.pointer8 && this.pointer8.active == false)
{
return this.pointer8.start(event);
}
- else if (this.pointer9.active == false)
+ else if (this.pointer9 && this.pointer9.active == false)
{
return this.pointer9.start(event);
}
- else if (this.pointer10.active == false)
+ else if (this.pointer10 && this.pointer10.active == false)
{
return this.pointer10.start(event);
}
@@ -575,23 +627,23 @@ module Phaser {
{
return this.pointer5.move(event);
}
- else if (this.pointer6.active == true && this.pointer6.identifier == event.identifier)
+ else if (this.pointer6 && this.pointer6.active == true && this.pointer6.identifier == event.identifier)
{
return this.pointer6.move(event);
}
- else if (this.pointer7.active == true && this.pointer7.identifier == event.identifier)
+ else if (this.pointer7 && this.pointer7.active == true && this.pointer7.identifier == event.identifier)
{
return this.pointer7.move(event);
}
- else if (this.pointer8.active == true && this.pointer8.identifier == event.identifier)
+ else if (this.pointer8 && this.pointer8.active == true && this.pointer8.identifier == event.identifier)
{
return this.pointer8.move(event);
}
- else if (this.pointer9.active == true && this.pointer9.identifier == event.identifier)
+ else if (this.pointer9 && this.pointer9.active == true && this.pointer9.identifier == event.identifier)
{
return this.pointer9.move(event);
}
- else if (this.pointer10.active == true && this.pointer10.identifier == event.identifier)
+ else if (this.pointer10 && this.pointer10.active == true && this.pointer10.identifier == event.identifier)
{
return this.pointer10.move(event);
}
@@ -629,23 +681,23 @@ module Phaser {
{
return this.pointer5.stop(event);
}
- else if (this.pointer6.active == true && this.pointer6.identifier == event.identifier)
+ else if (this.pointer6 && this.pointer6.active == true && this.pointer6.identifier == event.identifier)
{
return this.pointer6.stop(event);
}
- else if (this.pointer7.active == true && this.pointer7.identifier == event.identifier)
+ else if (this.pointer7 && this.pointer7.active == true && this.pointer7.identifier == event.identifier)
{
return this.pointer7.stop(event);
}
- else if (this.pointer8.active == true && this.pointer8.identifier == event.identifier)
+ else if (this.pointer8 && this.pointer8.active == true && this.pointer8.identifier == event.identifier)
{
return this.pointer8.stop(event);
}
- else if (this.pointer9.active == true && this.pointer9.identifier == event.identifier)
+ else if (this.pointer9 && this.pointer9.active == true && this.pointer9.identifier == event.identifier)
{
return this.pointer9.stop(event);
}
- else if (this.pointer10.active == true && this.pointer10.identifier == event.identifier)
+ else if (this.pointer10 && this.pointer10.active == true && this.pointer10.identifier == event.identifier)
{
return this.pointer10.stop(event);
}
@@ -683,23 +735,23 @@ module Phaser {
{
return this.pointer5;
}
- else if (this.pointer6.active == state)
+ else if (this.pointer6 && this.pointer6.active == state)
{
return this.pointer6;
}
- else if (this.pointer7.active == state)
+ else if (this.pointer7 && this.pointer7.active == state)
{
return this.pointer7;
}
- else if (this.pointer8.active == state)
+ else if (this.pointer8 && this.pointer8.active == state)
{
return this.pointer8;
}
- else if (this.pointer9.active == state)
+ else if (this.pointer9 && this.pointer9.active == state)
{
return this.pointer9;
}
- else if (this.pointer10.active == state)
+ else if (this.pointer10 && this.pointer10.active == state)
{
return this.pointer10;
}
@@ -737,23 +789,23 @@ module Phaser {
{
return this.pointer5;
}
- else if (this.pointer6.identifier == identifier)
+ else if (this.pointer6 && this.pointer6.identifier == identifier)
{
return this.pointer6;
}
- else if (this.pointer7.identifier == identifier)
+ else if (this.pointer7 && this.pointer7.identifier == identifier)
{
return this.pointer7;
}
- else if (this.pointer8.identifier == identifier)
+ else if (this.pointer8 && this.pointer8.identifier == identifier)
{
return this.pointer8;
}
- else if (this.pointer9.identifier == identifier)
+ else if (this.pointer9 && this.pointer9.identifier == identifier)
{
return this.pointer9;
}
- else if (this.pointer10.identifier == identifier)
+ else if (this.pointer10 && this.pointer10.identifier == identifier)
{
return this.pointer10;
}
@@ -797,32 +849,24 @@ module Phaser {
}
/**
- *
- * @method calculateDistance
- * @param {Finger} finger1
- * @param {Finger} finger2
+ * Get the distance between two Pointer objects
+ * @method getDistance
+ * @param {Pointer} pointer1
+ * @param {Pointer} pointer2
**/
- //public calculateDistance(finger1: Finger, finger2: Finger) {
- //}
+ public getDistance(pointer1: Pointer, pointer2: Pointer): number {
+ return pointer1.position.distance(pointer2.position);
+ }
/**
- *
- * @method calculateAngle
- * @param {Finger} finger1
- * @param {Finger} finger2
+ * Get the angle between two Pointer objects
+ * @method getAngle
+ * @param {Pointer} pointer1
+ * @param {Pointer} pointer2
**/
- //public calculateAngle(finger1: Finger, finger2: Finger) {
- //}
-
- /**
- *
- * @method checkOverlap
- * @param {Finger} finger1
- * @param {Finger} finger2
- **/
- //public checkOverlap(finger1: Finger, finger2: Finger) {
- //}
-
+ public getAngle(pointer1: Pointer, pointer2: Pointer): number {
+ return pointer1.position.angle(pointer2.position);
+ }
}
diff --git a/Phaser/system/input/Pointer.ts b/Phaser/system/input/Pointer.ts
index a461f265..f12bc62e 100644
--- a/Phaser/system/input/Pointer.ts
+++ b/Phaser/system/input/Pointer.ts
@@ -1,4 +1,5 @@
///
+///
/**
* Phaser - Pointer
@@ -21,8 +22,8 @@ module Phaser {
this.id = id;
this.active = false;
- this.pointA = new Point();
- this.pointB = new Point();
+ this.position = new Vector2;
+ this.positionDown = new Vector2;
this.circle = new Circle(0, 0, 44);
if (id == 0)
@@ -88,18 +89,18 @@ module Phaser {
public active: bool;
/**
- * A Point object representing the x/y screen coordinates of the Pointer.
- * @property pointA
- * @type {Point}
+ * A Vector object containing the initial position when the Pointer was engaged with the screen.
+ * @property positionDown
+ * @type {Vector2}
**/
- public pointA: Point = null;
+ public positionDown: Vector2 = null;
/**
- * A Point object representing the x/y screen coordinates of the Pointer.
- * @property pointB
- * @type {Point}
+ * A Vector object containing the current position of the Pointer on the screen.
+ * @property position
+ * @type {Vector2}
**/
- public pointB: Point = null;
+ public position: Vector2 = null;
/**
* A Circle object centered on the x/y screen coordinates of the Pointer.
@@ -286,11 +287,18 @@ module Phaser {
this.button = event.button;
}
+ // Fix to stop rogue browser plugins from blocking the visibility state event
+ if (this._game.paused == true)
+ {
+ this._game.stage.resumeGame();
+ return this;
+ }
+
this._history.length = 0;
this.move(event);
- this.pointA.setTo(this.x, this.y);
+ this.positionDown.setTo(this.x, this.y);
this.active = true;
this.withinGame = true;
@@ -335,7 +343,7 @@ module Phaser {
if (this._game.input.recordPointerHistory && this._game.time.now >= this._nextDrop)
{
this._nextDrop = this._game.time.now + this._game.input.recordRate;
- this._history.push({ x: this.pointB.x, y: this.pointB.y });
+ this._history.push({ x: this.position.x, y: this.position.y });
if (this._history.length > this._game.input.recordLimit)
{
@@ -369,7 +377,7 @@ module Phaser {
this.x = this.pageX - this._game.stage.offset.x;
this.y = this.pageY - this._game.stage.offset.y;
- this.pointB.setTo(this.x, this.y);
+ this.position.setTo(this.x, this.y);
this.circle.x = this.x;
this.circle.y = this.y;
@@ -377,7 +385,7 @@ 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.point.setTo(this._game.input.x, this._game.input.y);
+ this._game.input.position.setTo(this._game.input.x, this._game.input.y);
this._game.input.circle.x = this._game.input.x;
this._game.input.circle.y = this._game.input.y;
}
@@ -529,8 +537,8 @@ module Phaser {
// Render the points
this._game.stage.context.beginPath();
- this._game.stage.context.moveTo(this.pointA.x, this.pointA.y);
- this._game.stage.context.lineTo(this.pointB.x, this.pointB.y);
+ this._game.stage.context.moveTo(this.positionDown.x, this.positionDown.y);
+ this._game.stage.context.lineTo(this.position.x, this.position.y);
this._game.stage.context.lineWidth = 2;
this._game.stage.context.stroke();
this._game.stage.context.closePath();
diff --git a/Phaser/system/screens/BootScreen.ts b/Phaser/system/screens/BootScreen.ts
index 22c80284..b84d6c76 100644
--- a/Phaser/system/screens/BootScreen.ts
+++ b/Phaser/system/screens/BootScreen.ts
@@ -112,7 +112,7 @@ module Phaser {
*/
private colorCycle() {
- this._fade = this._game.createTween(this._color2);
+ this._fade = this._game.add.tween(this._color2);
this._fade.to({ r: Math.random() * 250, g: Math.random() * 250, b: Math.random() * 250 }, 3000, Phaser.Easing.Linear.None);
this._fade.onComplete.add(this.colorCycle, this);
diff --git a/Phaser/system/screens/PauseScreen.ts b/Phaser/system/screens/PauseScreen.ts
index 5ef4482c..875c59a9 100644
--- a/Phaser/system/screens/PauseScreen.ts
+++ b/Phaser/system/screens/PauseScreen.ts
@@ -31,11 +31,13 @@ module Phaser {
* Local private reference to game.
*/
private _game: Game;
+
/**
* Canvas element used by engine.
* @type {HTMLCanvasElement}
*/
private _canvas: HTMLCanvasElement;
+
/**
* Render context of stage's canvas.
* @type {CanvasRenderingContext2D}
@@ -46,6 +48,7 @@ module Phaser {
* Background color.
*/
private _color;
+
/**
* Fade effect tween.
* @type {Phaser.Tween}
@@ -114,7 +117,7 @@ module Phaser {
*/
private fadeOut() {
- this._fade = this._game.createTween(this._color);
+ this._fade = this._game.add.tween(this._color);
this._fade.to({ r: 50, g: 50, b: 50 }, 1000, Phaser.Easing.Linear.None);
this._fade.onComplete.add(this.fadeIn, this);
@@ -127,7 +130,7 @@ module Phaser {
*/
private fadeIn() {
- this._fade = this._game.createTween(this._color);
+ this._fade = this._game.add.tween(this._color);
this._fade.to({ r: 255, g: 255, b: 255 }, 1000, Phaser.Easing.Linear.None);
this._fade.onComplete.add(this.fadeOut, this);
diff --git a/Phaser/verlet/Composite.ts b/Phaser/verlet/Composite.ts
index 19055cfa..4d9dcaed 100644
--- a/Phaser/verlet/Composite.ts
+++ b/Phaser/verlet/Composite.ts
@@ -25,19 +25,47 @@ module Phaser.Verlet {
this._game = game;
+ this.sprites = [];
this.particles = [];
this.constraints = [];
+ this.frameBounds = new Phaser.Quad();
+
}
private _game: Game;
+ /**
+ * Texture of the particles to be rendered.
+ */
+ private _texture = null;
+
+ /**
+ * Rendering bounds for the texture
+ * @type {Quad}
+ */
+ private frameBounds: Quad;
+
+ // local rendering related temp vars to help avoid gc spikes
+ private _sx: number = 0;
+ private _sy: number = 0;
+ private _sw: number = 0;
+ private _sh: number = 0;
+ private _dx: number = 0;
+ private _dy: number = 0;
+ private _dw: number = 0;
+ private _dh: number = 0;
+ private _hw: number = 0;
+ private _hh: number = 0;
+
+ public sprites: Phaser.Sprite[];
public particles: Phaser.Verlet.Particle[];
public constraints;
+
public drawParticles = null;
public drawConstraints = null;
- // Map sprites to particles
+ // Create Constraints
public createDistanceConstraint(a: Phaser.Verlet.Particle, b: Phaser.Verlet.Particle, stiffness: number, distance?: number = null): Phaser.Verlet.DistanceConstraint {
@@ -60,6 +88,103 @@ module Phaser.Verlet {
}
+ /**
+ * Load a graphic for this Composite. The graphic cannot be a SpriteSheet yet.
+ * @param key {string} Key of the graphic you want to load for this sprite.
+ * @return {Composite} This object
+ */
+ public loadGraphic(key: string): Composite {
+
+ if (this._game.cache.getImage(key) !== null)
+ {
+ if (this._game.cache.isSpriteSheet(key) == false)
+ {
+ this._texture = this._game.cache.getImage(key);
+ this.frameBounds.width = this._texture.width;
+ this.frameBounds.height = this._texture.height;
+ this._hw = Math.floor(this.frameBounds.width / 2);
+ this._hh = Math.floor(this.frameBounds.width / 2);
+ this.drawParticles = this.render;
+ this.drawConstraints = this.renderConstraints;
+ }
+ }
+
+ return this;
+
+ }
+
+ public hideConstraints: bool = true;
+ public constraintLineColor: string = 'rgba(200,200,200,1)';
+
+ private renderConstraints(context) {
+
+ if (this.hideConstraints == true || this.constraints.length == 0)
+ {
+ return;
+ }
+
+ var i;
+
+ context.beginPath();
+
+ for (i in this.constraints)
+ {
+ if (this.constraints[i].b)
+ {
+ context.moveTo(this.constraints[i].a.pos.x, this.constraints[i].a.pos.y);
+ context.lineTo(this.constraints[i].b.pos.x, this.constraints[i].b.pos.y);
+ }
+ }
+
+ context.strokeStyle = this.constraintLineColor;
+ context.stroke();
+ context.closePath();
+
+ }
+
+ private render(context) {
+
+ this._sx = 0;
+ this._sy = 0;
+ this._sw = this.frameBounds.width;
+ this._sh = this.frameBounds.height;
+ this._dw = this.frameBounds.width;
+ this._dh = this.frameBounds.height;
+
+ this._sx = Math.round(this._sx);
+ this._sy = Math.round(this._sy);
+ this._sw = Math.round(this._sw);
+ this._sh = Math.round(this._sh);
+ this._dw = Math.round(this._dw);
+ this._dh = Math.round(this._dh);
+
+ var i;
+
+ for (i in this.particles)
+ {
+ //this._dx = cameraOffsetX + (this.frameBounds.topLeft.x - camera.worldView.x);
+ //this._dy = cameraOffsetY + (this.frameBounds.topLeft.y - camera.worldView.y);
+ this._dx = this.particles[i].pos.x - this._hw;
+ this._dy = this.particles[i].pos.y - this._hh;
+ this._dx = Math.round(this._dx);
+ this._dy = Math.round(this._dy);
+
+ context.drawImage(
+ this._texture, // Source Image
+ this._sx, // Source X (location within the source image)
+ this._sy, // Source Y
+ this._sw, // Source Width
+ this._sh, // Source Height
+ this._dx, // Destination X (where on the canvas it'll be drawn)
+ this._dy, // Destination Y
+ this._dw, // Destination Width (always same as Source Width unless scaled)
+ this._dh // Destination Height (always same as Source Height unless scaled)
+ );
+
+ }
+
+ }
+
public pin(index, pos?=null) {
if (pos == null)
diff --git a/Phaser/verlet/DistanceConstraint.ts b/Phaser/verlet/DistanceConstraint.ts
index f2aa0eec..881c2503 100644
--- a/Phaser/verlet/DistanceConstraint.ts
+++ b/Phaser/verlet/DistanceConstraint.ts
@@ -62,6 +62,7 @@ module Phaser.Verlet {
ctx.lineTo(this.b.pos.x, this.b.pos.y);
ctx.strokeStyle = "#d8dde2";
ctx.stroke();
+ ctx.closePath();
}
}
diff --git a/README.md b/README.md
index ba4131d6..142085d2 100644
--- a/README.md
+++ b/README.md
@@ -53,8 +53,12 @@ V0.9.6
* Added Input.startPointer, Input.updatePointer and Input.stopPointer.
* Phaser Input now confirmed working on Windows Phone 8 (Nokia Lumia 920).
* Added Input.maxPointers to allow you to limit the number of fingers your game will listen for on multi-touch systems.
+* Added Input.addPointer. By default Input will create 5 pointers (+1 for the mouse). Use addPointer() to add up to a maximum of 10.
+* Added Input.position - a Vector2 object containing the most recent position of the most recently active Pointer.
+* Added Input.getDistance. Find the distance between the two given Pointer objects.
+* Added Input.getAngle. Find the angle between the two given Pointer objects.
* Pointer.totalTouches value keeps a running total of the number of times the Pointer has been pressed.
-* Added Pointer.pointA and pointB - pointA is placed on touch, pointB is moved on update, useful for tracking distance/direction/gestures.
+* Added Pointer.position and positionDown. positionDown is placed on touch and position is update on move, useful for tracking distance/direction/gestures.
* Added Game.state - now contains a reference to the current state object (if any was given).
* Moved the Input start events from the constructors to a single Input.start method.
* Added Input.disabled boolean to globally turn off all input event processing.
@@ -71,7 +75,7 @@ V0.9.6
* Added Basic.ignoreGlobalUpdate - stops the object being updated as part of the main game loop, you'll need to call update on it yourself
* Added Basic.ignoreGlobalRender - stops the object being rendered as part of the main game loop, you'll need to call render on it yourself
* Added forceUpdate and forceRender parameters to Group.update and Group.render respectively. Combined with ignoreGlobal you can create custom rendering set-ups
-* Fixed Loader.progress calculation so it now accurate passes a value between 0 and 100% to your loader callback
+* Fixed Loader.progress calculation so it now accurately passes a value between 0 and 100 to your loader callback
* Added a 'hard reset' parameter to Input.reset. A hard reset clears Input signals (such as on a state swap), a soft (such as on game pause) doesn't
* Added Device.isConsoleOpen() to check if the browser console is open. Tested on Firefox with Firebug and Chrome with DevTools
* Added delay parameter to Tween.to()
@@ -91,19 +95,29 @@ V0.9.6
* Added Group.alpha to apply a globalAlpha before the groups children are rendered. Useful to save on alpha calls.
* Added Group.globalCompositeOperation to apply a composite operation before all of the groups children are rendered.
* Added Camera black list support to Group along with Group.showToCamera, Group.hideFromCamera and Group.clearCameraList
-
-
+* Added GameMath.rotatePoint to allow for point rotation at any angle around a given anchor and distance
+* Updated World.setSize() to optionally update the VerletManager dimensions as well
+* Added GameObject.setPosition(x, y)
+* Added Quad.intersectsRaw(left, right, top, bottom, tolerance)
+* Updated Sprite.inCamera to correctly apply the scrollFactor to the camera bounds check
+* Added Loader.crossOrigin property which is applied to loaded Images
+* Added AnimationManager.destroy() to clear out all local references and objects
+* Added the clearAnimations parameter to Sprite.loadGraphic(). Allows you to change animation textures but retain the frame data.
+* Added the GameObjectFactory to Game. You now make Sprites like this: game.add.sprite(). Much better separation of game object creation methods now. But you'll have to update ALL code, sorry!
+* Added GameObjectFactory methods to add existing objects to the game world, such as existingSprite(), existingTween(), etc.
+* Added the GameObjectFactory to Phaser.State
* TODO: Check that tween pausing works with the new performance.now
* TODO: Game.Time should monitor pause duration
* TODO: Investigate bug re: tilemap collision and animation frames
* TODO: Update tests that use arrow keys and include touch/mouse support
* TODO: GameObject.clipRect
-* TODO: Use CollisionMask in Input instead of Circle?
* TODO: Polygon geom primitive
* TODO: Move GameObject transforms to a single matrix
-
-
+* TODO: this.target.view.style.cursor = "pointer"; ("default")
+* TODO: Fix bug in scrollFactor inCamera check where the scrollFactor > 0 and < 1
+* TODO: If the Camera is larger than the Stage size then the rotation offset isn't correct
+* TODO: Texture Repeat doesn't scroll, because it's part of the camera not the world, need to think about this more
Requirements
------------
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index c6dd907f..71198992 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -118,6 +118,10 @@
+
+
+ mask animation 1.ts
+
mask test 1.ts
@@ -131,6 +135,10 @@
+
+
+ rope bridge.ts
+
rotate point 1.ts
@@ -190,6 +198,14 @@
mousetrail.ts
+
+
+ temp1.ts
+
+
+
+ temp2.ts
+
ballscroller.ts
diff --git a/Tests/collision/mask animation 1.js b/Tests/collision/mask animation 1.js
new file mode 100644
index 00000000..19d7f97e
--- /dev/null
+++ b/Tests/collision/mask animation 1.js
@@ -0,0 +1,31 @@
+///
+(function () {
+ var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
+ function init() {
+ myGame.loader.addImageFile('card', 'assets/sprites/mana_card.png');
+ myGame.loader.addTextureAtlas('bot', 'assets/sprites/running_bot.png', 'assets/sprites/running_bot.json');
+ myGame.loader.load();
+ }
+ var card;
+ var bot;
+ function create() {
+ card = myGame.createSprite(200, 220, 'card');
+ bot = myGame.createSprite(myGame.stage.width - 100, 300, 'bot');
+ // The collision mask is much thinner than the animated sprite
+ bot.collisionMask.offset.x = 16;
+ bot.collisionMask.width = 32;
+ bot.renderDebug = true;
+ bot.animations.add('run');
+ bot.animations.play('run', 10, true);
+ bot.velocity.x = -150;
+ }
+ function update() {
+ if(bot.x < -bot.width) {
+ bot.x = myGame.stage.width;
+ bot.velocity.x = -150;
+ card.x = 200;
+ card.velocity.x = 0;
+ }
+ myGame.collide(card, bot);
+ }
+})();
diff --git a/Tests/collision/mask animation 1.ts b/Tests/collision/mask animation 1.ts
new file mode 100644
index 00000000..c07da0b5
--- /dev/null
+++ b/Tests/collision/mask animation 1.ts
@@ -0,0 +1,50 @@
+///
+
+(function () {
+
+ var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
+
+ function init() {
+
+ myGame.loader.addImageFile('card', 'assets/sprites/mana_card.png');
+ myGame.loader.addTextureAtlas('bot', 'assets/sprites/running_bot.png', 'assets/sprites/running_bot.json');
+ myGame.loader.load();
+
+ }
+
+ var card: Phaser.Sprite;
+ var bot: Phaser.Sprite;
+
+ function create() {
+
+ card = myGame.createSprite(200, 220, 'card');
+
+ bot = myGame.createSprite(myGame.stage.width - 100, 300, 'bot');
+
+ // The collision mask is much thinner than the animated sprite
+ bot.collisionMask.offset.x = 16;
+ bot.collisionMask.width = 32;
+ bot.renderDebug = true;
+
+ bot.animations.add('run');
+ bot.animations.play('run', 10, true);
+
+ bot.velocity.x = -150;
+
+ }
+
+ function update() {
+
+ if (bot.x < -bot.width)
+ {
+ bot.x = myGame.stage.width;
+ bot.velocity.x = -150;
+ card.x = 200;
+ card.velocity.x = 0;
+ }
+
+ myGame.collide(card, bot);
+
+ }
+
+})();
diff --git a/Tests/collision/mask test 1.js b/Tests/collision/mask test 1.js
index e0bdb749..9eb41dfb 100644
--- a/Tests/collision/mask test 1.js
+++ b/Tests/collision/mask test 1.js
@@ -34,6 +34,5 @@
console.log('Collision!!!!!');
}
function render() {
- //atari1.ren
- }
+ }
})();
diff --git a/Tests/collision/mask test 1.ts b/Tests/collision/mask test 1.ts
index 78d35dba..fe608d2e 100644
--- a/Tests/collision/mask test 1.ts
+++ b/Tests/collision/mask test 1.ts
@@ -59,9 +59,6 @@
}
function render() {
-
- //atari1.ren
-
}
})();
diff --git a/Tests/geometry/rope bridge.js b/Tests/geometry/rope bridge.js
new file mode 100644
index 00000000..60a056d1
--- /dev/null
+++ b/Tests/geometry/rope bridge.js
@@ -0,0 +1,34 @@
+///
+(function () {
+ var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update, render);
+ function init() {
+ myGame.loader.addImageFile('ball5', 'assets/sprites/purple_ball.png');
+ myGame.loader.load();
+ }
+ var segment;
+ function create() {
+ myGame.verlet.friction = 1;
+ myGame.verlet.hideNearestEntityCircle = true;
+ var points = [];
+ var startX = 100;
+ var startY = 200;
+ var spacing = 20;
+ for(var i = 0; i < 30; i++) {
+ points.push(new Phaser.Vector2(startX + (i * spacing), startY));
+ }
+ segment = myGame.verlet.createLineSegments(points, 0.5);
+ segment.loadGraphic('ball5');
+ segment.hideConstraints = false;
+ segment.pin(0);
+ segment.pin(points.length - 1);
+ }
+ function update() {
+ }
+ function render() {
+ myGame.verlet.render();
+ //myGame.stage.context.fillStyle = 'rgb(255,255,0)';
+ //myGame.stage.context.fillRect(p1.x, p1.y, 4, 4);
+ //myGame.stage.context.fillStyle = 'rgb(255,0,0)';
+ //myGame.stage.context.fillRect(p2.x, p2.y, 4, 4);
+ }
+})();
diff --git a/Tests/geometry/rope bridge.ts b/Tests/geometry/rope bridge.ts
new file mode 100644
index 00000000..1d1a437f
--- /dev/null
+++ b/Tests/geometry/rope bridge.ts
@@ -0,0 +1,55 @@
+///
+
+(function () {
+
+ var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update, render);
+
+ function init() {
+
+ myGame.loader.addImageFile('ball5', 'assets/sprites/purple_ball.png');
+ myGame.loader.load();
+
+ }
+
+ var segment: Phaser.Verlet.Composite;
+
+ function create() {
+
+ myGame.verlet.friction = 1;
+ myGame.verlet.hideNearestEntityCircle = true;
+
+ var points: Phaser.Vector2[] = [];
+ var startX: number = 100;
+ var startY: number = 200;
+ var spacing: number = 20;
+
+ for (var i = 0; i < 30; i++)
+ {
+ points.push(new Phaser.Vector2(startX + (i * spacing), startY));
+ }
+
+ segment = myGame.verlet.createLineSegments(points, 0.5);
+ segment.loadGraphic('ball5');
+ segment.hideConstraints = false;
+
+ segment.pin(0);
+ segment.pin(points.length - 1);
+
+ }
+
+ function update() {
+ }
+
+ function render() {
+
+ myGame.verlet.render();
+
+ //myGame.stage.context.fillStyle = 'rgb(255,255,0)';
+ //myGame.stage.context.fillRect(p1.x, p1.y, 4, 4);
+
+ //myGame.stage.context.fillStyle = 'rgb(255,0,0)';
+ //myGame.stage.context.fillRect(p2.x, p2.y, 4, 4);
+
+ }
+
+})();
diff --git a/Tests/geometry/verlet 1.js b/Tests/geometry/verlet 1.js
index c951b1b7..ac4a3816 100644
--- a/Tests/geometry/verlet 1.js
+++ b/Tests/geometry/verlet 1.js
@@ -22,9 +22,5 @@
}
function render() {
myGame.verlet.render();
- //myGame.stage.context.fillStyle = 'rgb(255,255,0)';
- //myGame.stage.context.fillRect(p1.x, p1.y, 4, 4);
- //myGame.stage.context.fillStyle = 'rgb(255,0,0)';
- //myGame.stage.context.fillRect(p2.x, p2.y, 4, 4);
- }
+ }
})();
diff --git a/Tests/geometry/verlet 1.ts b/Tests/geometry/verlet 1.ts
index 455ad974..d6265c00 100644
--- a/Tests/geometry/verlet 1.ts
+++ b/Tests/geometry/verlet 1.ts
@@ -28,12 +28,6 @@
myGame.verlet.render();
- //myGame.stage.context.fillStyle = 'rgb(255,255,0)';
- //myGame.stage.context.fillRect(p1.x, p1.y, 4, 4);
-
- //myGame.stage.context.fillStyle = 'rgb(255,0,0)';
- //myGame.stage.context.fillRect(p2.x, p2.y, 4, 4);
-
}
})();
diff --git a/Tests/geometry/verlet sprites.js b/Tests/geometry/verlet sprites.js
index 93dbc2c1..52f41605 100644
--- a/Tests/geometry/verlet sprites.js
+++ b/Tests/geometry/verlet sprites.js
@@ -1,11 +1,6 @@
///
(function () {
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update, render);
- var cube;
- var b1;
- var b2;
- var b3;
- var b4;
function init() {
myGame.loader.addImageFile('ball0', 'assets/sprites/yellow_ball.png');
myGame.loader.addImageFile('ball1', 'assets/sprites/aqua_ball.png');
@@ -15,33 +10,23 @@
myGame.loader.addImageFile('ball5', 'assets/sprites/purple_ball.png');
myGame.loader.load();
}
+ var wheel;
+ var diamond;
+ var triangle;
+ var cube;
function create() {
myGame.verlet.friction = 1;
myGame.verlet.step = 32;
- //var wheel = myGame.verlet.createTire(new Phaser.Vector2(200,50), 100, 30, 0.3, 0.9);
- //var tire2 = myGame.verlet.createTire(new Phaser.Vector2(400,50), 70, 7, 0.1, 0.2);
- cube = myGame.verlet.createTire(new Phaser.Vector2(300, 50), 100, 4, 1, 1);
- //var tri = myGame.verlet.createTire(new Phaser.Vector2(700,50), 100, 3, 1, 1);
- var dc = new Phaser.Verlet.DistanceConstraint(cube.particles[0], cube.particles[1], 1);
- cube.constraints.push(dc);
- var dc2 = new Phaser.Verlet.DistanceConstraint(cube.particles[1], cube.particles[2], 1);
- cube.constraints.push(dc2);
- var dc3 = new Phaser.Verlet.DistanceConstraint(cube.particles[2], cube.particles[3], 1);
- cube.constraints.push(dc3);
- b1 = myGame.createSprite(cube.particles[0].pos.x, cube.particles[0].pos.y, 'ball0');
- b2 = myGame.createSprite(cube.particles[1].pos.x, cube.particles[1].pos.y, 'ball1');
- b3 = myGame.createSprite(cube.particles[2].pos.x, cube.particles[2].pos.y, 'ball2');
- b4 = myGame.createSprite(cube.particles[3].pos.x, cube.particles[3].pos.y, 'ball3');
+ wheel = myGame.verlet.createTire(new Phaser.Vector2(200, 50), 100, 30, 0.3, 0.9);
+ wheel.loadGraphic('ball0');
+ diamond = myGame.verlet.createTire(new Phaser.Vector2(400, 50), 70, 7, 0.1, 0.2);
+ diamond.loadGraphic('ball1');
+ triangle = myGame.verlet.createTire(new Phaser.Vector2(600, 50), 100, 3, 1, 1);
+ triangle.loadGraphic('ball2');
+ cube = myGame.verlet.createTire(new Phaser.Vector2(300, 50), 100, 4, 0.3, 0.9);
+ cube.loadGraphic('ball3');
}
function update() {
- b1.x = cube.particles[0].pos.x - 8;
- b1.y = cube.particles[0].pos.y - 8;
- b2.x = cube.particles[1].pos.x - 8;
- b2.y = cube.particles[1].pos.y - 8;
- b3.x = cube.particles[2].pos.x - 8;
- b3.y = cube.particles[2].pos.y - 8;
- b4.x = cube.particles[3].pos.x - 8;
- b4.y = cube.particles[3].pos.y - 8;
}
function render() {
myGame.verlet.render();
diff --git a/Tests/geometry/verlet sprites.ts b/Tests/geometry/verlet sprites.ts
index 30c5dc85..3432b36b 100644
--- a/Tests/geometry/verlet sprites.ts
+++ b/Tests/geometry/verlet sprites.ts
@@ -4,13 +4,6 @@
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update, render);
- var cube: Phaser.Verlet.Composite;
-
- var b1: Phaser.Sprite;
- var b2: Phaser.Sprite;
- var b3: Phaser.Sprite;
- var b4: Phaser.Sprite;
-
function init() {
myGame.loader.addImageFile('ball0', 'assets/sprites/yellow_ball.png');
@@ -24,46 +17,31 @@
}
+ var wheel: Phaser.Verlet.Composite;
+ var diamond: Phaser.Verlet.Composite;
+ var triangle: Phaser.Verlet.Composite;
+ var cube: Phaser.Verlet.Composite;
+
function create() {
myGame.verlet.friction = 1;
myGame.verlet.step = 32;
- //var wheel = myGame.verlet.createTire(new Phaser.Vector2(200,50), 100, 30, 0.3, 0.9);
- //var tire2 = myGame.verlet.createTire(new Phaser.Vector2(400,50), 70, 7, 0.1, 0.2);
- cube = myGame.verlet.createTire(new Phaser.Vector2(300, 50), 100, 4, 1, 1);
- //var tri = myGame.verlet.createTire(new Phaser.Vector2(700,50), 100, 3, 1, 1);
-
- var dc: Phaser.Verlet.DistanceConstraint = new Phaser.Verlet.DistanceConstraint(cube.particles[0], cube.particles[1], 1);
- cube.constraints.push(dc);
-
- var dc2: Phaser.Verlet.DistanceConstraint = new Phaser.Verlet.DistanceConstraint(cube.particles[1], cube.particles[2], 1);
- cube.constraints.push(dc2);
-
- var dc3: Phaser.Verlet.DistanceConstraint = new Phaser.Verlet.DistanceConstraint(cube.particles[2], cube.particles[3], 1);
- cube.constraints.push(dc3);
-
- b1 = myGame.createSprite(cube.particles[0].pos.x, cube.particles[0].pos.y, 'ball0');
- b2 = myGame.createSprite(cube.particles[1].pos.x, cube.particles[1].pos.y, 'ball1');
- b3 = myGame.createSprite(cube.particles[2].pos.x, cube.particles[2].pos.y, 'ball2');
- b4 = myGame.createSprite(cube.particles[3].pos.x, cube.particles[3].pos.y, 'ball3');
+ wheel = myGame.verlet.createTire(new Phaser.Vector2(200,50), 100, 30, 0.3, 0.9);
+ wheel.loadGraphic('ball0');
+
+ diamond = myGame.verlet.createTire(new Phaser.Vector2(400,50), 70, 7, 0.1, 0.2);
+ diamond.loadGraphic('ball1');
+
+ triangle = myGame.verlet.createTire(new Phaser.Vector2(600,50), 100, 3, 1, 1);
+ triangle.loadGraphic('ball2');
+
+ cube = myGame.verlet.createTire(new Phaser.Vector2(300, 50), 100, 4, 0.3, 0.9);
+ cube.loadGraphic('ball3');
}
function update() {
-
- b1.x = cube.particles[0].pos.x - 8;
- b1.y = cube.particles[0].pos.y - 8;
-
- b2.x = cube.particles[1].pos.x - 8;
- b2.y = cube.particles[1].pos.y - 8;
-
- b3.x = cube.particles[2].pos.x - 8;
- b3.y = cube.particles[2].pos.y - 8;
-
- b4.x = cube.particles[3].pos.x - 8;
- b4.y = cube.particles[3].pos.y - 8;
-
}
function render() {
diff --git a/Tests/phaser.js b/Tests/phaser.js
index 1d5e6f54..e4136383 100644
--- a/Tests/phaser.js
+++ b/Tests/phaser.js
@@ -504,8 +504,6 @@ var Phaser;
this.last.y = this.y;
};
CollisionMask.prototype.update = function () {
- //this.quad.x = this._parent.x + this.offset.x;
- //this.quad.y = this._parent.y + this.offset.y;
this._ref.x = this._parent.x + this.offset.x;
this._ref.y = this._parent.y + this.offset.y;
};
@@ -518,8 +516,7 @@ var Phaser;
function (camera, cameraOffsetX, cameraOffsetY) {
var _dx = cameraOffsetX + (this.x - camera.worldView.x);
var _dy = cameraOffsetY + (this.y - camera.worldView.y);
- //this._parent.context.fillStyle = this._parent.renderDebugColor;
- this._parent.context.fillStyle = 'rgba(255,0,0,0.4)';
+ 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) {
@@ -543,6 +540,15 @@ var Phaser;
this.line = null;
this.offset = null;
};
+ CollisionMask.prototype.intersectsRaw = function (left, right, top, bottom) {
+ //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height))
+ return true;
+ };
+ CollisionMask.prototype.intersectsVector = function (vector) {
+ if(this.type == CollisionMask.QUAD) {
+ return this.quad.contains(vector.x, vector.y);
+ }
+ };
CollisionMask.prototype.intersects = /**
* 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.
@@ -556,7 +562,6 @@ var Phaser;
}
// Circle vs. Circle
if(this.type == CollisionMask.CIRCLE && source.type == CollisionMask.CIRCLE) {
- console.log('c vs c');
return Phaser.Collision.circleToCircle(this.circle, source.circle).result;
}
// Circle vs. Rect
@@ -889,7 +894,6 @@ var Phaser;
this.alpha = 1;
this.scale = new Phaser.MicroPoint(1, 1);
this.last = new Phaser.MicroPoint(x, y);
- //this.origin = new MicroPoint(this.frameBounds.halfWidth, this.frameBounds.halfHeight);
this.align = GameObject.ALIGN_TOP_LEFT;
this.mass = 1;
this.elasticity = 0;
@@ -1273,6 +1277,10 @@ var Phaser;
*/
function () {
};
+ GameObject.prototype.setPosition = function (x, y) {
+ this.x = x;
+ this.y = y;
+ };
Object.defineProperty(GameObject.prototype, "x", {
get: function () {
return this.frameBounds.x;
@@ -1554,7 +1562,7 @@ var Phaser;
this.fx.preUpdate();
if(this._target !== null) {
if(this.deadzone == null) {
- this.focusOnXY(this._target.x + this._target.origin.x, this._target.y + this._target.origin.y);
+ this.focusOnXY(this._target.x, this._target.y);
} else {
var edge;
var targetX = this._target.x + ((this._target.x > 0) ? 0.0000001 : -0.0000001);
@@ -1893,9 +1901,14 @@ var Phaser;
Sprite.prototype.loadGraphic = /**
* Load graphic for this sprite. (graphic can be SpriteSheet or Texture)
* @param key {string} Key of the graphic you want to load for this sprite.
+ * @param clearAnimations {boolean} If this Sprite has a set of animation data already loaded you can choose to keep or clear it with this boolean
* @return {Sprite} Sprite instance itself.
*/
- function (key) {
+ function (key, clearAnimations) {
+ if (typeof clearAnimations === "undefined") { clearAnimations = true; }
+ if(clearAnimations && this.animations.frameData !== null) {
+ this.animations.destroy();
+ }
if(this._game.cache.getImage(key) !== null) {
if(this._game.cache.isSpriteSheet(key) == false) {
this._texture = this._game.cache.getImage(key);
@@ -1906,9 +1919,9 @@ var Phaser;
} else {
this._texture = this._game.cache.getImage(key);
this.animations.loadFrameData(this._game.cache.getFrameData(key));
- //this.collisionMask.width = this._texture.width;
- //this.collisionMask.height = this._texture.height;
- }
+ this.collisionMask.width = this.animations.currentFrame.width;
+ this.collisionMask.height = this.animations.currentFrame.height;
+ }
this._dynamicTexture = false;
}
return this;
@@ -1947,14 +1960,20 @@ var Phaser;
* @return {boolean} Return true if bounds of this sprite intersects the given rectangle, otherwise return false.
*/
function (camera) {
- if(this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) {
- this._dx = this.frameBounds.x - (camera.x * this.scrollFactor.x);
- this._dy = this.frameBounds.y - (camera.y * this.scrollFactor.x);
+ // Object fixed in place regardless of the camera scrolling? Then it's always visible
+ if(this.scrollFactor.x == 0 && this.scrollFactor.y == 0) {
+ return true;
+ }
+ // Otherwise, if it's scrolling perfectly in sync with the camera (1 to 1) then it's a simple bounds check on world coordinates
+ if(this.scrollFactor.x == 1 && this.scrollFactor.y == 1) {
+ return camera.intersects(this.frameBounds, this.frameBounds.length);
+ } else {
+ // Else apply the offsets
+ this._dx = (this.frameBounds.x - camera.x) * this.scrollFactor.x;
+ this._dy = (this.frameBounds.y - camera.y) * this.scrollFactor.y;
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.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.intersects(this.frameBounds, this.frameBounds.length);
}
};
Sprite.prototype.postUpdate = /**
@@ -2005,8 +2024,8 @@ var Phaser;
this._sy = 0;
this._sw = this.frameBounds.width;
this._sh = this.frameBounds.height;
- this._dx = cameraOffsetX + (this.frameBounds.topLeft.x - camera.worldView.x);
- this._dy = cameraOffsetY + (this.frameBounds.topLeft.y - camera.worldView.y);
+ this._dx = (cameraOffsetX * this.scrollFactor.x) + this.frameBounds.topLeft.x - (camera.worldView.x * this.scrollFactor.x);
+ this._dy = (cameraOffsetY * this.scrollFactor.y) + this.frameBounds.topLeft.y - (camera.worldView.y * this.scrollFactor.y);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
if(this.align == Phaser.GameObject.ALIGN_TOP_CENTER) {
@@ -2039,10 +2058,10 @@ var Phaser;
}
}
// Apply camera difference
- if(this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) {
- this._dx -= (camera.worldView.x * this.scrollFactor.x);
- this._dy -= (camera.worldView.y * this.scrollFactor.y);
- }
+ if(this.scrollFactor.x !== 1 || this.scrollFactor.y !== 1) {
+ //this._dx -= (camera.worldView.x * this.scrollFactor.x);
+ //this._dy -= (camera.worldView.y * this.scrollFactor.y);
+ }
// Rotation - needs to work from origin point really, but for now from center
if(this.angle !== 0 || this.rotationOffset !== 0 || this.flipped == true) {
this.context.save();
@@ -2711,7 +2730,11 @@ var Phaser;
});
Object.defineProperty(AnimationManager.prototype, "frameTotal", {
get: function () {
- return this._frameData.total;
+ if(this._frameData) {
+ return this._frameData.total;
+ } else {
+ return -1;
+ }
},
enumerable: true,
configurable: true
@@ -2746,6 +2769,17 @@ var Phaser;
enumerable: true,
configurable: true
});
+ AnimationManager.prototype.destroy = /**
+ * Removes all related references
+ */
+ function () {
+ this._anims = {
+ };
+ this._frameData = null;
+ this._frameIndex = 0;
+ this.currentAnim = null;
+ this.currentFrame = null;
+ };
return AnimationManager;
})();
Phaser.AnimationManager = AnimationManager;
@@ -2971,9 +3005,6 @@ var Phaser;
*
* Your game only has one CameraManager instance and it's responsible for looking after, creating and destroying
* all of the cameras in the world.
-*
-* TODO: If the Camera is larger than the Stage size then the rotation offset isn't correct
-* TODO: Texture Repeat doesn't scroll, because it's part of the camera not the world, need to think about this more
*/
var Phaser;
(function (Phaser) {
@@ -4086,6 +4117,54 @@ var Phaser;
})(Phaser || (Phaser = {}));
///
/**
+* Phaser - Polygon
+*
+*/
+var Phaser;
+(function (Phaser) {
+ var Polygon = (function () {
+ /**
+ * A *convex* clockwise polygon
+ * @class Polygon
+ * @constructor
+ * @param {Vector2} pos A vector representing the origin of the polygon (all other points are relative to this one)
+ * @param {Array.} points An Array of vectors representing the points in the polygon, in clockwise order.
+ **/
+ function Polygon(pos, points, parent) {
+ if (typeof pos === "undefined") { pos = new Phaser.Vector2(); }
+ if (typeof points === "undefined") { points = []; }
+ if (typeof parent === "undefined") { parent = null; }
+ this.pos = pos;
+ this.points = points;
+ this.parent = parent;
+ this.recalc();
+ }
+ Polygon.prototype.recalc = /**
+ * Recalculate the edges and normals of the polygon. This
+ * MUST be called if the points array is modified at all and
+ * the edges or normals are to be accessed.
+ */
+ function () {
+ var points = this.points;
+ var len = points.length;
+ this.edges = [];
+ this.normals = [];
+ for(var i = 0; i < len; i++) {
+ var p1 = points[i];
+ var p2 = i < len - 1 ? points[i + 1] : points[0];
+ var e = new Phaser.Vector2().copyFrom(p2).sub(p1);
+ var n = new Phaser.Vector2().copyFrom(e).perp().normalize();
+ this.edges.push(e);
+ this.normals.push(n);
+ }
+ };
+ return Polygon;
+ })();
+ Phaser.Polygon = Polygon;
+})(Phaser || (Phaser = {}));
+///
+///
+/**
* Phaser - Quad
*
* A Quad object is an area defined by its position, as indicated by its top-left corner (x,y) and width and height.
@@ -4181,6 +4260,20 @@ var Phaser;
if (typeof tolerance === "undefined") { tolerance = 0; }
return !(quad.left > this.right + tolerance || quad.right < this.left - tolerance || quad.top > this.bottom + tolerance || quad.bottom < this.top - tolerance);
};
+ Quad.prototype.intersectsRaw = /**
+ * Determines whether the object specified intersects (overlaps) with the given values.
+ * @method intersectsProps
+ * @param {Number} left
+ * @param {Number} right
+ * @param {Number} top
+ * @param {Number} bottomt
+ * @param {Number} tolerance 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 Quad; otherwise false.
+ **/
+ function (left, right, top, bottom, tolerance) {
+ if (typeof tolerance === "undefined") { tolerance = 0; }
+ return !(left > this.right + tolerance || right < this.left - tolerance || top > this.bottom + tolerance || bottom < this.top - tolerance);
+ };
Quad.prototype.contains = /**
* Determines whether the specified coordinates are contained within the region defined by this Quad object.
* @method contains
@@ -4212,6 +4305,19 @@ var Phaser;
function (target) {
return target.copyFrom(this);
};
+ Quad.prototype.toPolygon = /**
+ * Creates and returns a Polygon that is the same as this Quad.
+ * @method toPolygon
+ * @return {Polygon} A new Polygon that represents this quad.
+ **/
+ function () {
+ return new Phaser.Polygon(new Phaser.Vector2(this.x, this.y), [
+ new Phaser.Vector2(),
+ new Phaser.Vector2(this.width, 0),
+ new Phaser.Vector2(this.width, this.height),
+ new Phaser.Vector2(0, this.height)
+ ]);
+ };
Quad.prototype.toString = /**
* Returns a string representation of this object.
* @method toString
@@ -4260,8 +4366,21 @@ var Phaser;
* @type Number
**/
this.y = 0;
+ this._pos = new Phaser.Vector2();
this.setTo(x, y, diameter);
}
+ Object.defineProperty(Circle.prototype, "pos", {
+ get: /**
+ * The position of this Circle object represented by a Vector2
+ * @property pos
+ * @type Vector2
+ **/
+ function () {
+ return this._pos.setTo(this.x, this.y);
+ },
+ enumerable: true,
+ configurable: true
+ });
Object.defineProperty(Circle.prototype, "diameter", {
get: /**
* The diameter of the circle. The largest distance between any two points on the circle. The same as the radius * 2.
@@ -4952,6 +5071,414 @@ var Phaser;
Phaser.IntersectResult = IntersectResult;
})(Phaser || (Phaser = {}));
///
+///
+/**
+* Phaser - Response
+*
+*/
+var Phaser;
+(function (Phaser) {
+ var Response = (function () {
+ /**
+ * An object representing the result of an intersection. Contain information about:
+ * - The two objects participating in the intersection
+ * - The vector representing the minimum change necessary to extract the first object
+ * from the second one.
+ * - Whether the first object is entirely inside the second, or vice versa.
+ *
+ * @constructor
+ */
+ function Response() {
+ this.a = null;
+ this.b = null;
+ this.overlapN = new Phaser.Vector2();
+ this.overlapV = new Phaser.Vector2();
+ this.clear();
+ }
+ Response.prototype.clear = /**
+ * Set some values of the response back to their defaults. Call this between tests if
+ * you are going to reuse a single Response object for multiple intersection tests (recommented)
+ *
+ * @return {Response} This for chaining
+ */
+ function () {
+ this.aInB = true;
+ this.bInA = true;
+ this.overlap = Number.MAX_VALUE;
+ return this;
+ };
+ return Response;
+ })();
+ Phaser.Response = Response;
+})(Phaser || (Phaser = {}));
+///
+/**
+* Phaser - Vector2
+*
+* A two dimensional vector.
+* Contains methods and ideas from verlet-js by Sub Protocol, SAT.js by Jim Riecken and N by Metanet Software.
+*/
+var Phaser;
+(function (Phaser) {
+ var Vector2 = (function () {
+ /**
+ * Creates a new Vector2 object.
+ * @class Vector2
+ * @constructor
+ * @param {Number} x The x position of the vector
+ * @param {Number} y The y position of the vector
+ * @return {Vector2} This object
+ **/
+ function Vector2(x, y) {
+ if (typeof x === "undefined") { x = 0; }
+ if (typeof y === "undefined") { y = 0; }
+ this.x = x;
+ this.y = y;
+ }
+ Vector2.prototype.setTo = function (x, y) {
+ this.x = x;
+ this.y = y;
+ return this;
+ };
+ Vector2.prototype.add = /**
+ * Add this vector to the given one and return the result.
+ *
+ * @param {Vector2} v The other Vector.
+ * @param {Vector2} The output Vector.
+ * @return {Vector2} The new Vector
+ */
+ function (v, output) {
+ if (typeof output === "undefined") { output = new Vector2(); }
+ return output.setTo(this.x + v.x, this.y + v.y);
+ };
+ Vector2.prototype.sub = /**
+ * Subtract this vector to the given one and return the result.
+ *
+ * @param {Vector2} v The other Vector.
+ * @param {Vector2} The output Vector.
+ * @return {Vector2} The new Vector
+ */
+ function (v, output) {
+ if (typeof output === "undefined") { output = new Vector2(); }
+ return output.setTo(this.x - v.x, this.y - v.y);
+ };
+ Vector2.prototype.mul = /**
+ * Multiply this vector with the given one and return the result.
+ *
+ * @param {Vector2} v The other Vector.
+ * @param {Vector2} The output Vector.
+ * @return {Vector2} The new Vector
+ */
+ function (v, output) {
+ if (typeof output === "undefined") { output = new Vector2(); }
+ return output.setTo(this.x * v.x, this.y * v.y);
+ };
+ Vector2.prototype.div = /**
+ * Divide this vector by the given one and return the result.
+ *
+ * @param {Vector2} v The other Vector.
+ * @param {Vector2} The output Vector.
+ * @return {Vector2} The new Vector
+ */
+ function (v, output) {
+ if (typeof output === "undefined") { output = new Vector2(); }
+ return output.setTo(this.x / v.x, this.y / v.y);
+ };
+ Vector2.prototype.scale = /**
+ * Scale this vector by the given values and return the result.
+ *
+ * @param {number} x The scaling factor in the x direction.
+ * @param {?number=} y The scaling factor in the y direction. If this
+ * is not specified, the x scaling factor will be used.
+ * @return {Vector} The new Vector
+ */
+ function (x, y, output) {
+ if (typeof y === "undefined") { y = null; }
+ if (typeof output === "undefined") { output = new Vector2(); }
+ if(y === null) {
+ y = x;
+ }
+ return output.setTo(this.x * x, this.y * y);
+ };
+ Vector2.prototype.perp = /**
+ * Rotate this vector by 90 degrees
+ *
+ * @return {Vector} This for chaining.
+ */
+ function (output) {
+ if (typeof output === "undefined") { output = this; }
+ var x = this.x;
+ return output.setTo(this.y, -x);
+ };
+ Vector2.prototype.mutableSet = // Same as copyFrom, used by VerletManager
+ function (v) {
+ this.x = v.x;
+ this.y = v.y;
+ return this;
+ };
+ Vector2.prototype.mutableAdd = /**
+ * Add another vector to this one.
+ *
+ * @param {Vector} other The other Vector.
+ * @return {Vector} This for chaining.
+ */
+ function (v) {
+ this.x += v.x;
+ this.y += v.y;
+ return this;
+ };
+ Vector2.prototype.mutableSub = /**
+ * Subtract another vector from this one.
+ *
+ * @param {Vector} other The other Vector.
+ * @return {Vector} This for chaining.
+ */
+ function (v) {
+ this.x -= v.x;
+ this.y -= v.y;
+ return this;
+ };
+ Vector2.prototype.mutableMul = /**
+ * Multiply another vector with this one.
+ *
+ * @param {Vector} other The other Vector.
+ * @return {Vector} This for chaining.
+ */
+ function (v) {
+ this.x *= v.x;
+ this.y *= v.y;
+ return this;
+ };
+ Vector2.prototype.mutableDiv = /**
+ * Divide this vector by another one.
+ *
+ * @param {Vector} other The other Vector.
+ * @return {Vector} This for chaining.
+ */
+ function (v) {
+ this.x /= v.x;
+ this.y /= v.y;
+ return this;
+ };
+ Vector2.prototype.mutableScale = /**
+ * Scale this vector.
+ *
+ * @param {number} x The scaling factor in the x direction.
+ * @param {?number=} y The scaling factor in the y direction. If this
+ * is not specified, the x scaling factor will be used.
+ * @return {Vector} This for chaining.
+ */
+ function (x, y) {
+ this.x *= x;
+ this.y *= y || x;
+ return this;
+ };
+ Vector2.prototype.reverse = /**
+ * Reverse this vector.
+ *
+ * @return {Vector} This for chaining.
+ */
+ function () {
+ this.x = -this.x;
+ this.y = -this.y;
+ return this;
+ };
+ Vector2.prototype.edge = function (v, output) {
+ if (typeof output === "undefined") { output = new Vector2(); }
+ return this.sub(v, output);
+ };
+ Vector2.prototype.equals = function (v) {
+ return this.x == v.x && this.y == v.y;
+ };
+ Vector2.prototype.epsilonEquals = function (v, epsilon) {
+ return Math.abs(this.x - v.x) <= epsilon && Math.abs(this.y - v.y) <= epsilon;
+ };
+ Vector2.prototype.length = /**
+ * Get the length of this vector.
+ *
+ * @return {number} The length of this vector.
+ */
+ function () {
+ return Math.sqrt((this.x * this.x) + (this.y * this.y));
+ };
+ Vector2.prototype.length2 = /**
+ * Get the length^2 of this vector.
+ *
+ * @return {number} The length^2 of this vector.
+ */
+ function () {
+ return (this.x * this.x) + (this.y * this.y);
+ };
+ Vector2.prototype.distance = /**
+ * Get the distance between this vector and the given vector.
+ *
+ * @return {Vector2} v The vector to check
+ */
+ function (v) {
+ return Math.sqrt(this.distance2(v));
+ };
+ Vector2.prototype.distance2 = /**
+ * Get the distance^2 between this vector and the given vector.
+ *
+ * @return {Vector2} v The vector to check
+ */
+ function (v) {
+ return ((v.x - this.x) * (v.x - this.x)) + ((v.y - this.y) * (v.y - this.y));
+ };
+ Vector2.prototype.project = /**
+ * Project this vector on to another vector.
+ *
+ * @param {Vector} other The vector to project onto.
+ * @return {Vector} This for chaining.
+ */
+ function (other) {
+ var amt = this.dot(other) / other.length2();
+ if(amt != 0) {
+ this.x = amt * other.x;
+ this.y = amt * other.y;
+ }
+ return this;
+ };
+ Vector2.prototype.projectN = /**
+ * Project this vector onto a vector of unit length.
+ *
+ * @param {Vector} other The unit vector to project onto.
+ * @return {Vector} This for chaining.
+ */
+ function (other) {
+ var amt = this.dot(other);
+ if(amt != 0) {
+ this.x = amt * other.x;
+ this.y = amt * other.y;
+ }
+ return this;
+ };
+ Vector2.prototype.reflect = /**
+ * Reflect this vector on an arbitrary axis.
+ *
+ * @param {Vector} axis The vector representing the axis.
+ * @return {Vector} This for chaining.
+ */
+ function (axis) {
+ var x = this.x;
+ var y = this.y;
+ this.project(axis).scale(2);
+ this.x -= x;
+ this.y -= y;
+ return this;
+ };
+ Vector2.prototype.reflectN = /**
+ * Reflect this vector on an arbitrary axis (represented by a unit vector)
+ *
+ * @param {Vector} axis The unit vector representing the axis.
+ * @return {Vector} This for chaining.
+ */
+ function (axis) {
+ var x = this.x;
+ var y = this.y;
+ this.projectN(axis).scale(2);
+ this.x -= x;
+ this.y -= y;
+ return this;
+ };
+ Vector2.prototype.getProjectionMagnitude = function (v) {
+ var den = v.dot(v);
+ if(den == 0) {
+ return 0;
+ } else {
+ return Math.abs(this.dot(v) / den);
+ }
+ };
+ Vector2.prototype.direction = function (output) {
+ if (typeof output === "undefined") { output = new Vector2(); }
+ output.copyFrom(this);
+ return this.normalize(output);
+ };
+ Vector2.prototype.normalRightHand = function (output) {
+ if (typeof output === "undefined") { output = this; }
+ return output.setTo(this.y * -1, this.x);
+ };
+ Vector2.prototype.normalize = /**
+ * Normalize (make unit length) this vector.
+ *
+ * @return {Vector} This for chaining.
+ */
+ function (output) {
+ if (typeof output === "undefined") { output = this; }
+ var m = this.length();
+ if(m != 0) {
+ output.setTo(this.x / m, this.y / m);
+ }
+ return output;
+ };
+ Vector2.prototype.getMagnitude = function () {
+ return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
+ };
+ Vector2.prototype.dot = /**
+ * Get the dot product of this vector against another.
+ *
+ * @param {Vector} other The vector to dot this one against.
+ * @return {number} The dot product.
+ */
+ function (v) {
+ return ((this.x * v.x) + (this.y * v.y));
+ };
+ Vector2.prototype.cross = /**
+ * Get the cross product of this vector against another.
+ *
+ * @param {Vector} other The vector to cross this one against.
+ * @return {number} The cross product.
+ */
+ function (v) {
+ return ((this.x * v.y) - (this.y * v.x));
+ };
+ Vector2.prototype.angle = /**
+ * Get the angle between this vector and the given vector.
+ *
+ * @return {Vector2} v The vector to check
+ */
+ function (v) {
+ return Math.atan2(this.x * v.y - this.y * v.x, this.x * v.x + this.y * v.y);
+ };
+ Vector2.prototype.angle2 = function (vLeft, vRight) {
+ return vLeft.sub(this).angle(vRight.sub(this));
+ };
+ Vector2.prototype.rotate = /**
+ * Rotate this vector around the origin to the given angle (theta) and return the result in a new Vector
+ *
+ * @return {Vector2} v The vector to check
+ */
+ function (origin, theta, output) {
+ if (typeof output === "undefined") { output = new Vector2(); }
+ var x = this.x - origin.x;
+ var y = this.y - origin.y;
+ return output.setTo(x * Math.cos(theta) - y * Math.sin(theta) + origin.x, x * Math.sin(theta) + y * Math.cos(theta) + origin.y);
+ };
+ Vector2.prototype.clone = function (output) {
+ if (typeof output === "undefined") { output = new Vector2(); }
+ return output.setTo(this.x, this.y);
+ };
+ Vector2.prototype.copyFrom = function (v) {
+ this.x = v.x;
+ this.y = v.y;
+ return this;
+ };
+ Vector2.prototype.copyTo = function (v) {
+ return v.setTo(this.x, this.y);
+ };
+ Vector2.prototype.toString = /**
+ * Returns a string representation of this object.
+ * @method toString
+ * @return {string} a string representation of the object.
+ **/
+ function () {
+ return "[{Vector2 (x=" + this.x + " y=" + this.y + ")}]";
+ };
+ return Vector2;
+ })();
+ Phaser.Vector2 = Vector2;
+})(Phaser || (Phaser = {}));
+///
/**
* Phaser - LinkedList
*
@@ -5338,6 +5865,8 @@ var Phaser;
///
///
///
+///
+///
///
/**
* Phaser - Collision
@@ -5353,6 +5882,14 @@ var Phaser;
*/
function Collision(game) {
this._game = game;
+ Collision.T_VECTORS = [];
+ for(var i = 0; i < 10; i++) {
+ Collision.T_VECTORS.push(new Phaser.Vector2());
+ }
+ Collision.T_ARRAYS = [];
+ for(var i = 0; i < 5; i++) {
+ Collision.T_ARRAYS.push([]);
+ }
}
Collision.LEFT = 0x0001;
Collision.RIGHT = 0x0010;
@@ -5703,20 +6240,7 @@ var Phaser;
output.result = ((circle1.radius + circle2.radius) * (circle1.radius + circle2.radius)) >= Collision.distanceSquared(circle1.x, circle1.y, circle2.x, circle2.y);
return output;
};
- Collision.circleToRectangle = /*
- public static circleToQuad(circle: Circle, quad: Quad): bool {
-
- // Check if the center of the circle is within the Quad
- if (quad.contains(circle.x, circle.y))
- {
- return true;
- }
-
- // Failing that let's check each line of the quad against the circle
- return false;
- }
- */
- /**
+ Collision.circleToRectangle = /**
* Checks if the Circle object intersects with the Rectangle and returns the result in an IntersectResult object.
* @param circle The Circle object to check
* @param rect The Rectangle object to check
@@ -5779,7 +6303,6 @@ var Phaser;
* @returns {boolean} Returns true if the objects were separated, otherwise false.
*/
function separate(object1, object2) {
- console.log('sep o');
object1.collisionMask.update();
object2.collisionMask.update();
var separatedX = Collision.separateX(object1, object2);
@@ -5793,6 +6316,7 @@ var Phaser;
* @returns {boolean} Whether the objects in fact touched and were separated
*/
function separateTile(object, x, y, width, height, mass, collideLeft, collideRight, collideUp, collideDown, separateX, separateY) {
+ object.collisionMask.update();
var separatedX = Collision.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separateX);
var separatedY = Collision.separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separateY);
return separatedX || separatedY;
@@ -5811,9 +6335,11 @@ var Phaser;
// First, get the object delta
var overlap = 0;
var objDelta = object.x - object.last.x;
+ //var objDelta: number = object.collisionMask.deltaX;
if(objDelta != 0) {
// Check if the X hulls actually overlap
var objDeltaAbs = (objDelta > 0) ? objDelta : -objDelta;
+ //var objDeltaAbs: number = object.collisionMask.deltaXAbs;
var objBounds = new Phaser.Quad(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height);
if((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) {
var maxOverlap = objDeltaAbs + Collision.OVERLAP_BIAS;
@@ -5838,6 +6364,7 @@ var Phaser;
// Then adjust their positions and velocities accordingly (if there was any overlap)
if(overlap != 0) {
if(separate == true) {
+ //console.log('
object.x = object.x - overlap;
object.velocity.x = -(object.velocity.x * object.elasticity);
}
@@ -5898,6 +6425,113 @@ var Phaser;
return false;
}
};
+ Collision.NEWseparateTileX = /**
+ * Separates the two objects on their x axis
+ * @param object The GameObject to separate
+ * @param tile The Tile to separate
+ * @returns {boolean} Whether the objects in fact touched and were separated along the X axis.
+ */
+ function NEWseparateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separate) {
+ // Can't separate two immovable objects (tiles are always immovable)
+ if(object.immovable) {
+ return false;
+ }
+ // First, get the object delta
+ var overlap = 0;
+ if(object.collisionMask.deltaX != 0) {
+ // Check if the X hulls actually overlap
+ //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta;
+ //var objBounds: Quad = new Quad(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height);
+ //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height))
+ if(object.collisionMask.intersectsRaw(x, x + width, y, y + height)) {
+ var maxOverlap = object.collisionMask.deltaXAbs + Collision.OVERLAP_BIAS;
+ // If they did overlap (and can), figure out by how much and flip the corresponding flags
+ if(object.collisionMask.deltaX > 0) {
+ //overlap = object.x + object.width - x;
+ overlap = object.collisionMask.right - x;
+ if((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) {
+ overlap = 0;
+ } else {
+ object.touching |= Collision.RIGHT;
+ }
+ } else if(object.collisionMask.deltaX < 0) {
+ //overlap = object.x - width - x;
+ overlap = object.collisionMask.x - width - x;
+ if((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) {
+ overlap = 0;
+ } else {
+ object.touching |= Collision.LEFT;
+ }
+ }
+ }
+ }
+ // Then adjust their positions and velocities accordingly (if there was any overlap)
+ if(overlap != 0) {
+ if(separate == true) {
+ object.x = object.x - overlap;
+ object.velocity.x = -(object.velocity.x * object.elasticity);
+ }
+ Collision.TILE_OVERLAP = true;
+ return true;
+ } else {
+ return false;
+ }
+ };
+ Collision.NEWseparateTileY = /**
+ * Separates the two objects on their y axis
+ * @param object The first GameObject to separate
+ * @param tile The second GameObject to separate
+ * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis.
+ */
+ function NEWseparateTileY(object, x, y, width, height, mass, collideUp, collideDown, separate) {
+ // Can't separate two immovable objects (tiles are always immovable)
+ if(object.immovable) {
+ return false;
+ }
+ // First, get the two object deltas
+ var overlap = 0;
+ //var objDelta: number = object.y - object.last.y;
+ if(object.collisionMask.deltaY != 0) {
+ // Check if the Y hulls actually overlap
+ //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta;
+ //var objBounds: Quad = new Quad(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs);
+ //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height))
+ if(object.collisionMask.intersectsRaw(x, x + width, y, y + height)) {
+ //var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS;
+ var maxOverlap = object.collisionMask.deltaYAbs + Collision.OVERLAP_BIAS;
+ // If they did overlap (and can), figure out by how much and flip the corresponding flags
+ if(object.collisionMask.deltaY > 0) {
+ //overlap = object.y + object.height - y;
+ overlap = object.collisionMask.bottom - y;
+ if((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) {
+ overlap = 0;
+ } else {
+ object.touching |= Collision.DOWN;
+ }
+ } else if(object.collisionMask.deltaY < 0) {
+ //overlap = object.y - height - y;
+ overlap = object.collisionMask.y - height - y;
+ if((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) {
+ overlap = 0;
+ } else {
+ object.touching |= Collision.UP;
+ }
+ }
+ }
+ }
+ // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here
+ // Then adjust their positions and velocities accordingly (if there was any overlap)
+ if(overlap != 0) {
+ if(separate == true) {
+ object.y = object.y - overlap;
+ object.velocity.y = -(object.velocity.y * object.elasticity);
+ }
+ Collision.TILE_OVERLAP = true;
+ return true;
+ } else {
+ return false;
+ }
+ };
Collision.separateX = /**
* Separates the two objects on their x axis
* @param object1 The first GameObject to separate
@@ -6033,159 +6667,6 @@ var Phaser;
return false;
}
};
- Collision.OLDseparateX = /**
- * Separates the two objects on their x axis
- * @param object1 The first GameObject to separate
- * @param object2 The second GameObject to separate
- * @returns {boolean} Whether the objects in fact touched and were separated along the X axis.
- */
- function OLDseparateX(object1, object2) {
- // Can't separate two immovable objects
- if(object1.immovable && object2.immovable) {
- return false;
- }
- // First, get the two object deltas
- var overlap = 0;
- var obj1Delta = object1.x - object1.last.x;
- var obj2Delta = object2.x - object2.last.x;
- if(obj1Delta != obj2Delta) {
- // Check if the X hulls actually overlap
- var obj1DeltaAbs = (obj1Delta > 0) ? obj1Delta : -obj1Delta;
- var obj2DeltaAbs = (obj2Delta > 0) ? obj2Delta : -obj2Delta;
- var obj1Bounds = new Phaser.Quad(object1.x - ((obj1Delta > 0) ? obj1Delta : 0), object1.last.y, object1.width + ((obj1Delta > 0) ? obj1Delta : -obj1Delta), object1.height);
- var obj2Bounds = new Phaser.Quad(object2.x - ((obj2Delta > 0) ? obj2Delta : 0), object2.last.y, object2.width + ((obj2Delta > 0) ? obj2Delta : -obj2Delta), object2.height);
- if((obj1Bounds.x + obj1Bounds.width > obj2Bounds.x) && (obj1Bounds.x < obj2Bounds.x + obj2Bounds.width) && (obj1Bounds.y + obj1Bounds.height > obj2Bounds.y) && (obj1Bounds.y < obj2Bounds.y + obj2Bounds.height)) {
- var maxOverlap = obj1DeltaAbs + obj2DeltaAbs + Collision.OVERLAP_BIAS;
- // If they did overlap (and can), figure out by how much and flip the corresponding flags
- if(obj1Delta > obj2Delta) {
- overlap = object1.x + object1.width - object2.x;
- if((overlap > maxOverlap) || !(object1.allowCollisions & Collision.RIGHT) || !(object2.allowCollisions & Collision.LEFT)) {
- overlap = 0;
- } else {
- object1.touching |= Collision.RIGHT;
- object2.touching |= Collision.LEFT;
- }
- } else if(obj1Delta < obj2Delta) {
- overlap = object1.x - object2.width - object2.x;
- if((-overlap > maxOverlap) || !(object1.allowCollisions & Collision.LEFT) || !(object2.allowCollisions & Collision.RIGHT)) {
- overlap = 0;
- } else {
- object1.touching |= Collision.LEFT;
- object2.touching |= Collision.RIGHT;
- }
- }
- }
- }
- // Then adjust their positions and velocities accordingly (if there was any overlap)
- if(overlap != 0) {
- var obj1Velocity = object1.velocity.x;
- var obj2Velocity = object2.velocity.x;
- if(!object1.immovable && !object2.immovable) {
- overlap *= 0.5;
- object1.x = object1.x - overlap;
- object2.x += overlap;
- var obj1NewVelocity = Math.sqrt((obj2Velocity * obj2Velocity * object2.mass) / object1.mass) * ((obj2Velocity > 0) ? 1 : -1);
- var obj2NewVelocity = Math.sqrt((obj1Velocity * obj1Velocity * object1.mass) / object2.mass) * ((obj1Velocity > 0) ? 1 : -1);
- var average = (obj1NewVelocity + obj2NewVelocity) * 0.5;
- obj1NewVelocity -= average;
- obj2NewVelocity -= average;
- object1.velocity.x = average + obj1NewVelocity * object1.elasticity;
- object2.velocity.x = average + obj2NewVelocity * object2.elasticity;
- } else if(!object1.immovable) {
- object1.x = object1.x - overlap;
- object1.velocity.x = obj2Velocity - obj1Velocity * object1.elasticity;
- } else if(!object2.immovable) {
- object2.x += overlap;
- object2.velocity.x = obj1Velocity - obj2Velocity * object2.elasticity;
- }
- return true;
- } else {
- return false;
- }
- };
- Collision.OLDseparateY = /**
- * Separates the two objects on their y axis
- * @param object1 The first GameObject to separate
- * @param object2 The second GameObject to separate
- * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis.
- */
- function OLDseparateY(object1, object2) {
- // Can't separate two immovable objects
- if(object1.immovable && object2.immovable) {
- return false;
- }
- // First, get the two object deltas
- var overlap = 0;
- var obj1Delta = object1.y - object1.last.y;
- var obj2Delta = object2.y - object2.last.y;
- if(obj1Delta != obj2Delta) {
- // Check if the Y hulls actually overlap
- var obj1DeltaAbs = (obj1Delta > 0) ? obj1Delta : -obj1Delta;
- var obj2DeltaAbs = (obj2Delta > 0) ? obj2Delta : -obj2Delta;
- var obj1Bounds = new Phaser.Quad(object1.x, object1.y - ((obj1Delta > 0) ? obj1Delta : 0), object1.width, object1.height + obj1DeltaAbs);
- var obj2Bounds = new Phaser.Quad(object2.x, object2.y - ((obj2Delta > 0) ? obj2Delta : 0), object2.width, object2.height + obj2DeltaAbs);
- console.log(obj1Bounds.toString(), obj2Bounds.toString());
- if((obj1Bounds.x + obj1Bounds.width > obj2Bounds.x) && (obj1Bounds.x < obj2Bounds.x + obj2Bounds.width) && (obj1Bounds.y + obj1Bounds.height > obj2Bounds.y) && (obj1Bounds.y < obj2Bounds.y + obj2Bounds.height)) {
- var maxOverlap = obj1DeltaAbs + obj2DeltaAbs + Collision.OVERLAP_BIAS;
- console.log('max33', maxOverlap, obj1Delta, obj2Delta, obj1DeltaAbs, obj2DeltaAbs);
- // If they did overlap (and can), figure out by how much and flip the corresponding flags
- if(obj1Delta > obj2Delta) {
- overlap = object1.y + object1.height - object2.y;
- if((overlap > maxOverlap) || !(object1.allowCollisions & Collision.DOWN) || !(object2.allowCollisions & Collision.UP)) {
- overlap = 0;
- } else {
- object1.touching |= Collision.DOWN;
- object2.touching |= Collision.UP;
- }
- } else if(obj1Delta < obj2Delta) {
- overlap = object1.y - object2.height - object2.y;
- if((-overlap > maxOverlap) || !(object1.allowCollisions & Collision.UP) || !(object2.allowCollisions & Collision.DOWN)) {
- overlap = 0;
- } else {
- object1.touching |= Collision.UP;
- object2.touching |= Collision.DOWN;
- }
- }
- }
- }
- // Then adjust their positions and velocities accordingly (if there was any overlap)
- if(overlap != 0) {
- console.log('y overlap', overlap);
- var obj1Velocity = object1.velocity.y;
- var obj2Velocity = object2.velocity.y;
- if(!object1.immovable && !object2.immovable) {
- overlap *= 0.5;
- object1.y = object1.y - overlap;
- object2.y += overlap;
- var obj1NewVelocity = Math.sqrt((obj2Velocity * obj2Velocity * object2.mass) / object1.mass) * ((obj2Velocity > 0) ? 1 : -1);
- var obj2NewVelocity = Math.sqrt((obj1Velocity * obj1Velocity * object1.mass) / object2.mass) * ((obj1Velocity > 0) ? 1 : -1);
- var average = (obj1NewVelocity + obj2NewVelocity) * 0.5;
- obj1NewVelocity -= average;
- obj2NewVelocity -= average;
- object1.velocity.y = average + obj1NewVelocity * object1.elasticity;
- object2.velocity.y = average + obj2NewVelocity * object2.elasticity;
- } else if(!object1.immovable) {
- object1.y = object1.y - overlap;
- object1.velocity.y = obj2Velocity - obj1Velocity * object1.elasticity;
- // This is special case code that handles things like horizontal moving platforms you can ride
- if(object2.active && object2.moves && (obj1Delta > obj2Delta)) {
- object1.x += object2.x - object2.last.x;
- }
- console.log('y2', object1.y, object1.velocity.y);
- } else if(!object2.immovable) {
- object2.y += overlap;
- object2.velocity.y = obj1Velocity - obj2Velocity * object2.elasticity;
- // This is special case code that handles things like horizontal moving platforms you can ride
- if(object1.active && object1.moves && (obj1Delta < obj2Delta)) {
- object2.x += object1.x - object1.last.x;
- }
- console.log('y3', object2.y, object2.velocity.y);
- }
- return true;
- } else {
- return false;
- }
- };
Collision.distance = /**
* Returns the distance between the two given coordinates.
* @param x1 The X value of the first coordinate
@@ -6208,6 +6689,369 @@ var Phaser;
function distanceSquared(x1, y1, x2, y2) {
return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
};
+ Collision.flattenPointsOn = // SAT
+ /**
+ * Flattens the specified array of points onto a unit vector axis,
+ * resulting in a one dimensional range of the minimum and
+ * maximum value on that axis.
+ *
+ * @param {Array.} points The points to flatten.
+ * @param {Vector} normal The unit vector axis to flatten on.
+ * @param {Array.} result An array. After calling this function,
+ * result[0] will be the minimum value,
+ * result[1] will be the maximum value.
+ */
+ function flattenPointsOn(points, normal, result) {
+ var min = Number.MAX_VALUE;
+ var max = -Number.MAX_VALUE;
+ var len = points.length;
+ for(var i = 0; i < len; i++) {
+ // Get the magnitude of the projection of the point onto the normal
+ var dot = points[i].dot(normal);
+ if(dot < min) {
+ min = dot;
+ }
+ if(dot > max) {
+ max = dot;
+ }
+ }
+ result[0] = min;
+ result[1] = max;
+ };
+ Collision.isSeparatingAxis = /**
+ * Check whether two convex clockwise polygons are separated by the specified
+ * axis (must be a unit vector).
+ *
+ * @param {Vector} aPos The position of the first polygon.
+ * @param {Vector} bPos The position of the second polygon.
+ * @param {Array.} aPoints The points in the first polygon.
+ * @param {Array.} bPoints The points in the second polygon.
+ * @param {Vector} axis The axis (unit sized) to test against. The points of both polygons
+ * will be projected onto this axis.
+ * @param {Response=} response A Response object (optional) which will be populated
+ * if the axis is not a separating axis.
+ * @return {boolean} true if it is a separating axis, false otherwise. If false,
+ * and a response is passed in, information about how much overlap and
+ * the direction of the overlap will be populated.
+ */
+ function isSeparatingAxis(aPos, bPos, aPoints, bPoints, axis, response) {
+ if (typeof response === "undefined") { response = null; }
+ var rangeA = Collision.T_ARRAYS.pop();
+ var rangeB = Collision.T_ARRAYS.pop();
+ // Get the magnitude of the offset between the two polygons
+ var offsetV = Collision.T_VECTORS.pop().copyFrom(bPos).sub(aPos);
+ var projectedOffset = offsetV.dot(axis);
+ // Project the polygons onto the axis.
+ Collision.flattenPointsOn(aPoints, axis, rangeA);
+ Collision.flattenPointsOn(bPoints, axis, rangeB);
+ // Move B's range to its position relative to A.
+ rangeB[0] += projectedOffset;
+ rangeB[1] += projectedOffset;
+ // Check if there is a gap. If there is, this is a separating axis and we can stop
+ if(rangeA[0] > rangeB[1] || rangeB[0] > rangeA[1]) {
+ Collision.T_VECTORS.push(offsetV);
+ Collision.T_ARRAYS.push(rangeA);
+ Collision.T_ARRAYS.push(rangeB);
+ return true;
+ }
+ // If we're calculating a response, calculate the overlap.
+ if(response) {
+ var overlap = 0;
+ // A starts further left than B
+ if(rangeA[0] < rangeB[0]) {
+ response.aInB = false;
+ // A ends before B does. We have to pull A out of B
+ if(rangeA[1] < rangeB[1]) {
+ overlap = rangeA[1] - rangeB[0];
+ response.bInA = false;
+ // B is fully inside A. Pick the shortest way out.
+ } else {
+ var option1 = rangeA[1] - rangeB[0];
+ var option2 = rangeB[1] - rangeA[0];
+ overlap = option1 < option2 ? option1 : -option2;
+ }
+ // B starts further left than A
+ } else {
+ response.bInA = false;
+ // B ends before A ends. We have to push A out of B
+ if(rangeA[1] > rangeB[1]) {
+ overlap = rangeA[0] - rangeB[1];
+ response.aInB = false;
+ // A is fully inside B. Pick the shortest way out.
+ } else {
+ var option1 = rangeA[1] - rangeB[0];
+ var option2 = rangeB[1] - rangeA[0];
+ overlap = option1 < option2 ? option1 : -option2;
+ }
+ }
+ // If this is the smallest amount of overlap we've seen so far, set it as the minimum overlap.
+ var absOverlap = Math.abs(overlap);
+ if(absOverlap < response.overlap) {
+ response.overlap = absOverlap;
+ response.overlapN.copyFrom(axis);
+ if(overlap < 0) {
+ response.overlapN.reverse();
+ }
+ }
+ }
+ Collision.T_VECTORS.push(offsetV);
+ Collision.T_ARRAYS.push(rangeA);
+ Collision.T_ARRAYS.push(rangeB);
+ return false;
+ };
+ Collision.LEFT_VORNOI_REGION = -1;
+ Collision.MIDDLE_VORNOI_REGION = 0;
+ Collision.RIGHT_VORNOI_REGION = 1;
+ Collision.vornoiRegion = /**
+ * Calculates which Vornoi region a point is on a line segment.
+ * It is assumed that both the line and the point are relative to (0, 0)
+ *
+ * | (0) |
+ * (-1) [0]--------------[1] (1)
+ * | (0) |
+ *
+ * @param {Vector} line The line segment.
+ * @param {Vector} point The point.
+ * @return {number} LEFT_VORNOI_REGION (-1) if it is the left region,
+ * MIDDLE_VORNOI_REGION (0) if it is the middle region,
+ * RIGHT_VORNOI_REGION (1) if it is the right region.
+ */
+ function vornoiRegion(line, point) {
+ var len2 = line.length2();
+ var dp = point.dot(line);
+ if(dp < 0) {
+ return Collision.LEFT_VORNOI_REGION;
+ } else if(dp > len2) {
+ return Collision.RIGHT_VORNOI_REGION;
+ } else {
+ return Collision.MIDDLE_VORNOI_REGION;
+ }
+ };
+ Collision.testCircleCircle = /**
+ * Check if two circles intersect.
+ *
+ * @param {Circle} a The first circle.
+ * @param {Circle} b The second circle.
+ * @param {Response=} response Response object (optional) that will be populated if
+ * the circles intersect.
+ * @return {boolean} true if the circles intersect, false if they don't.
+ */
+ function testCircleCircle(a, b, response) {
+ if (typeof response === "undefined") { response = null; }
+ var differenceV = Collision.T_VECTORS.pop().copyFrom(b.pos).sub(a.pos);
+ var totalRadius = a.radius + b.radius;
+ var totalRadiusSq = totalRadius * totalRadius;
+ var distanceSq = differenceV.length2();
+ if(distanceSq > totalRadiusSq) {
+ // They do not intersect
+ Collision.T_VECTORS.push(differenceV);
+ return false;
+ }
+ // They intersect. If we're calculating a response, calculate the overlap.
+ if(response) {
+ var dist = Math.sqrt(distanceSq);
+ response.a = a;
+ response.b = b;
+ response.overlap = totalRadius - dist;
+ response.overlapN.copyFrom(differenceV.normalize());
+ response.overlapV.copyFrom(differenceV).scale(response.overlap);
+ response.aInB = a.radius <= b.radius && dist <= b.radius - a.radius;
+ response.bInA = b.radius <= a.radius && dist <= a.radius - b.radius;
+ }
+ Collision.T_VECTORS.push(differenceV);
+ return true;
+ };
+ Collision.testPolygonCircle = /**
+ * Check if a polygon and a circle intersect.
+ *
+ * @param {Polygon} polygon The polygon.
+ * @param {Circle} circle The circle.
+ * @param {Response=} response Response object (optional) that will be populated if
+ * they interset.
+ * @return {boolean} true if they intersect, false if they don't.
+ */
+ function testPolygonCircle(polygon, circle, response) {
+ if (typeof response === "undefined") { response = null; }
+ var circlePos = Collision.T_VECTORS.pop().copyFrom(circle.pos).sub(polygon.pos);
+ var radius = circle.radius;
+ var radius2 = radius * radius;
+ var points = polygon.points;
+ var len = points.length;
+ var edge = Collision.T_VECTORS.pop();
+ var point = Collision.T_VECTORS.pop();
+ // For each edge in the polygon
+ for(var i = 0; i < len; i++) {
+ var next = i === len - 1 ? 0 : i + 1;
+ var prev = i === 0 ? len - 1 : i - 1;
+ var overlap = 0;
+ var overlapN = null;
+ // Get the edge
+ edge.copyFrom(polygon.edges[i]);
+ // Calculate the center of the cirble relative to the starting point of the edge
+ point.copyFrom(circlePos).sub(points[i]);
+ // If the distance between the center of the circle and the point
+ // is bigger than the radius, the polygon is definitely not fully in
+ // the circle.
+ if(response && point.length2() > radius2) {
+ response.aInB = false;
+ }
+ // Calculate which Vornoi region the center of the circle is in.
+ var region = Collision.vornoiRegion(edge, point);
+ if(region === Collision.LEFT_VORNOI_REGION) {
+ // Need to make sure we're in the RIGHT_VORNOI_REGION of the previous edge.
+ edge.copyFrom(polygon.edges[prev]);
+ // Calculate the center of the circle relative the starting point of the previous edge
+ var point2 = Collision.T_VECTORS.pop().copyFrom(circlePos).sub(points[prev]);
+ region = Collision.vornoiRegion(edge, point2);
+ if(region === Collision.RIGHT_VORNOI_REGION) {
+ // It's in the region we want. Check if the circle intersects the point.
+ var dist = point.length2();
+ if(dist > radius) {
+ // No intersection
+ Collision.T_VECTORS.push(circlePos);
+ Collision.T_VECTORS.push(edge);
+ Collision.T_VECTORS.push(point);
+ Collision.T_VECTORS.push(point2);
+ return false;
+ } else if(response) {
+ // It intersects, calculate the overlap
+ response.bInA = false;
+ overlapN = point.normalize();
+ overlap = radius - dist;
+ }
+ }
+ Collision.T_VECTORS.push(point2);
+ } else if(region === Collision.RIGHT_VORNOI_REGION) {
+ // Need to make sure we're in the left region on the next edge
+ edge.copyFrom(polygon.edges[next]);
+ // Calculate the center of the circle relative to the starting point of the next edge
+ point.copyFrom(circlePos).sub(points[next]);
+ region = Collision.vornoiRegion(edge, point);
+ if(region === Collision.LEFT_VORNOI_REGION) {
+ // It's in the region we want. Check if the circle intersects the point.
+ var dist = point.length2();
+ if(dist > radius) {
+ // No intersection
+ Collision.T_VECTORS.push(circlePos);
+ Collision.T_VECTORS.push(edge);
+ Collision.T_VECTORS.push(point);
+ return false;
+ } else if(response) {
+ // It intersects, calculate the overlap
+ response.bInA = false;
+ overlapN = point.normalize();
+ overlap = radius - dist;
+ }
+ }
+ // MIDDLE_VORNOI_REGION
+ } else {
+ // Need to check if the circle is intersecting the edge,
+ // Change the edge into its "edge normal".
+ var normal = edge.perp().normalize();
+ // Find the perpendicular distance between the center of the
+ // circle and the edge.
+ var dist = point.dot(normal);
+ var distAbs = Math.abs(dist);
+ // If the circle is on the outside of the edge, there is no intersection
+ if(dist > 0 && distAbs > radius) {
+ Collision.T_VECTORS.push(circlePos);
+ Collision.T_VECTORS.push(normal);
+ Collision.T_VECTORS.push(point);
+ return false;
+ } else if(response) {
+ // It intersects, calculate the overlap.
+ overlapN = normal;
+ overlap = radius - dist;
+ // If the center of the circle is on the outside of the edge, or part of the
+ // circle is on the outside, the circle is not fully inside the polygon.
+ if(dist >= 0 || overlap < 2 * radius) {
+ response.bInA = false;
+ }
+ }
+ }
+ // If this is the smallest overlap we've seen, keep it.
+ // (overlapN may be null if the circle was in the wrong Vornoi region)
+ if(overlapN && response && Math.abs(overlap) < Math.abs(response.overlap)) {
+ response.overlap = overlap;
+ response.overlapN.copyFrom(overlapN);
+ }
+ }
+ // Calculate the final overlap vector - based on the smallest overlap.
+ if(response) {
+ response.a = polygon;
+ response.b = circle;
+ response.overlapV.copyFrom(response.overlapN).scale(response.overlap);
+ }
+ Collision.T_VECTORS.push(circlePos);
+ Collision.T_VECTORS.push(edge);
+ Collision.T_VECTORS.push(point);
+ return true;
+ };
+ Collision.testCirclePolygon = /**
+ * Check if a circle and a polygon intersect.
+ *
+ * NOTE: This runs slightly slower than polygonCircle as it just
+ * runs polygonCircle and reverses everything at the end.
+ *
+ * @param {Circle} circle The circle.
+ * @param {Polygon} polygon The polygon.
+ * @param {Response=} response Response object (optional) that will be populated if
+ * they interset.
+ * @return {boolean} true if they intersect, false if they don't.
+ */
+ function testCirclePolygon(circle, polygon, response) {
+ if (typeof response === "undefined") { response = null; }
+ var result = Collision.testPolygonCircle(polygon, circle, response);
+ if(result && response) {
+ // Swap A and B in the response.
+ var a = response.a;
+ var aInB = response.aInB;
+ response.overlapN.reverse();
+ response.overlapV.reverse();
+ response.a = response.b;
+ response.b = a;
+ response.aInB = response.bInA;
+ response.bInA = aInB;
+ }
+ return result;
+ };
+ Collision.testPolygonPolygon = /**
+ * Checks whether two convex, clockwise polygons intersect.
+ *
+ * @param {Polygon} a The first polygon.
+ * @param {Polygon} b The second polygon.
+ * @param {Response=} response Response object (optional) that will be populated if
+ * they interset.
+ * @return {boolean} true if they intersect, false if they don't.
+ */
+ function testPolygonPolygon(a, b, response) {
+ if (typeof response === "undefined") { response = null; }
+ var aPoints = a.points;
+ var aLen = aPoints.length;
+ var bPoints = b.points;
+ var bLen = bPoints.length;
+ // If any of the edge normals of A is a separating axis, no intersection.
+ for(var i = 0; i < aLen; i++) {
+ if(Collision.isSeparatingAxis(a.pos, b.pos, aPoints, bPoints, a.normals[i], response)) {
+ return false;
+ }
+ }
+ // If any of the edge normals of B is a separating axis, no intersection.
+ for(var i = 0; i < bLen; i++) {
+ if(Collision.isSeparatingAxis(a.pos, b.pos, aPoints, bPoints, b.normals[i], response)) {
+ return false;
+ }
+ }
+ // Since none of the edge normals of A or B are a separating axis, there is an intersection
+ // and we've already calculated the smallest overlap (in isSeparatingAxis). Calculate the
+ // final overlap vector.
+ if(response) {
+ response.a = a;
+ response.b = b;
+ response.overlapV.copyFrom(response.overlapN).scale(response.overlap);
+ }
+ return true;
+ };
return Collision;
})();
Phaser.Collision = Collision;
@@ -7345,26 +8189,233 @@ var Phaser;
return Math.sqrt(dx * dx + dy * dy);
};
GameMath.prototype.rotatePoint = /**
- * Rotates a point around the x/y coordinates given to the desired angle
+ * Rotates the point around the x/y coordinates given to the desired angle and distance
+ * @param point {Object} Any object with exposed x and y properties
* @param x {number} The x coordinate of the anchor point
* @param y {number} The y coordinate of the anchor point
- * @param angle {number} The angle of the rotation in radians
- * @param point {Point} The point object to perform the rotation on
+ * @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from.
+ * @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)?
+ * @param {Number} distance An optional distance constraint between the point and the anchor
* @return The modified point object
*/
- function (x, y, angle, point) {
- var s = Math.sin(angle);
- var c = Math.cos(angle);
- point.x -= x;
- point.y -= y;
- var newX = point.x * c - point.y * s;
- var newY = point.x * s - point.y * c;
- return point.setTo(newX + x, newY + y);
+ function (point, x1, y1, angle, asDegrees, distance) {
+ if (typeof asDegrees === "undefined") { asDegrees = false; }
+ if (typeof distance === "undefined") { distance = null; }
+ if(asDegrees) {
+ angle = angle * GameMath.DEG_TO_RAD;
+ }
+ // Get distance from origin to the point
+ if(distance === null) {
+ distance = Math.sqrt(((x1 - point.x) * (x1 - point.x)) + ((y1 - point.y) * (y1 - point.y)));
+ }
+ point.x = x1 + distance * Math.cos(angle);
+ point.y = y1 + distance * Math.sin(angle);
+ return point;
};
return GameMath;
})();
Phaser.GameMath = GameMath;
})(Phaser || (Phaser = {}));
+///
+/**
+* Phaser - GameObjectFactory
+*
+* A quick way to create new world objects and add existing objects to the current world.
+*/
+var Phaser;
+(function (Phaser) {
+ var GameObjectFactory = (function () {
+ /**
+ * GameObjectFactory constructor
+ * @param game {Game} A reference to the current Game.
+ */
+ function GameObjectFactory(game) {
+ this._game = game;
+ this._world = this._game.world;
+ }
+ GameObjectFactory.prototype.camera = /**
+ * Create a new camera with specific position and size.
+ *
+ * @param x {number} X position of the new camera.
+ * @param y {number} Y position of the new camera.
+ * @param width {number} Width of the new camera.
+ * @param height {number} Height of the new camera.
+ * @returns {Camera} The newly created camera object.
+ */
+ function (x, y, width, height) {
+ return this._world.createCamera(x, y, width, height);
+ };
+ GameObjectFactory.prototype.geomSprite = /**
+ * Create a new GeomSprite with specific position.
+ *
+ * @param x {number} X position of the new geom sprite.
+ * @param y {number} Y position of the new geom sprite.
+ * @returns {GeomSprite} The newly created geom sprite object.
+ */
+ function (x, y) {
+ return this._world.createGeomSprite(x, y);
+ };
+ GameObjectFactory.prototype.sprite = /**
+ * Create a new Sprite with specific position and sprite sheet key.
+ *
+ * @param x {number} X position of the new sprite.
+ * @param y {number} Y position of the new sprite.
+ * @param key {string} Optional, key for the sprite sheet you want it to use.
+ * @returns {Sprite} The newly created sprite object.
+ */
+ function (x, y, key) {
+ if (typeof key === "undefined") { key = ''; }
+ return this._world.createSprite(x, y, key);
+ };
+ GameObjectFactory.prototype.dynamicTexture = /**
+ * Create a new DynamicTexture with specific size.
+ *
+ * @param width {number} Width of the texture.
+ * @param height {number} Height of the texture.
+ * @returns {DynamicTexture} The newly created dynamic texture object.
+ */
+ function (width, height) {
+ return this._world.createDynamicTexture(width, height);
+ };
+ GameObjectFactory.prototype.group = /**
+ * Create a new object container.
+ *
+ * @param maxSize {number} Optional, capacity of this group.
+ * @returns {Group} The newly created group.
+ */
+ function (maxSize) {
+ if (typeof maxSize === "undefined") { maxSize = 0; }
+ return this._world.createGroup(maxSize);
+ };
+ GameObjectFactory.prototype.particle = /**
+ * Create a new Particle.
+ *
+ * @return {Particle} The newly created particle object.
+ */
+ function () {
+ return this._world.createParticle();
+ };
+ GameObjectFactory.prototype.emitter = /**
+ * Create a new Emitter.
+ *
+ * @param x {number} Optional, x position of the emitter.
+ * @param y {number} Optional, y position of the emitter.
+ * @param size {number} Optional, size of this emitter.
+ * @return {Emitter} The newly created emitter object.
+ */
+ function (x, y, size) {
+ if (typeof x === "undefined") { x = 0; }
+ if (typeof y === "undefined") { y = 0; }
+ if (typeof size === "undefined") { size = 0; }
+ return this._world.createEmitter(x, y, size);
+ };
+ GameObjectFactory.prototype.scrollZone = /**
+ * Create a new ScrollZone object with image key, position and size.
+ *
+ * @param key {string} Key to a image you wish this object to use.
+ * @param x {number} X position of this object.
+ * @param y {number} Y position of this object.
+ * @param width number} Width of this object.
+ * @param height {number} Height of this object.
+ * @returns {ScrollZone} The newly created scroll zone object.
+ */
+ function (key, x, y, width, height) {
+ if (typeof x === "undefined") { x = 0; }
+ if (typeof y === "undefined") { y = 0; }
+ if (typeof width === "undefined") { width = 0; }
+ if (typeof height === "undefined") { height = 0; }
+ return this._world.createScrollZone(key, x, y, width, height);
+ };
+ GameObjectFactory.prototype.tilemap = /**
+ * Create a new Tilemap.
+ *
+ * @param key {string} Key for tileset image.
+ * @param mapData {string} Data of this tilemap.
+ * @param format {number} Format of map data. (Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON)
+ * @param [resizeWorld] {boolean} resize the world to make same as tilemap?
+ * @param [tileWidth] {number} width of each tile.
+ * @param [tileHeight] {number} height of each tile.
+ * @return {Tilemap} The newly created tilemap object.
+ */
+ function (key, mapData, format, resizeWorld, tileWidth, tileHeight) {
+ if (typeof resizeWorld === "undefined") { resizeWorld = true; }
+ if (typeof tileWidth === "undefined") { tileWidth = 0; }
+ if (typeof tileHeight === "undefined") { tileHeight = 0; }
+ return this._world.createTilemap(key, mapData, format, resizeWorld, tileWidth, tileHeight);
+ };
+ GameObjectFactory.prototype.tween = /**
+ * Create a tween object for a specific object.
+ *
+ * @param obj Object you wish the tween will affect.
+ * @return {Phaser.Tween} The newly created tween object.
+ */
+ function (obj) {
+ return this._game.tweens.create(obj);
+ };
+ GameObjectFactory.prototype.existingSprite = /**
+ * Add an existing Sprite to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param sprite The Sprite to add to the Game World
+ * @return {Phaser.Sprite} The Sprite object
+ */
+ function (sprite) {
+ return this._world.group.add(sprite);
+ };
+ GameObjectFactory.prototype.existingGeomSprite = /**
+ * Add an existing GeomSprite to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param sprite The GeomSprite to add to the Game World
+ * @return {Phaser.GeomSprite} The GeomSprite object
+ */
+ function (sprite) {
+ return this._world.group.add(sprite);
+ };
+ GameObjectFactory.prototype.existingEmitter = /**
+ * Add an existing Emitter to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param emitter The Emitter to add to the Game World
+ * @return {Phaser.Emitter} The Emitter object
+ */
+ function (emitter) {
+ return this._world.group.add(emitter);
+ };
+ GameObjectFactory.prototype.existingScrollZone = /**
+ * Add an existing ScrollZone to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param scrollZone The ScrollZone to add to the Game World
+ * @return {Phaser.ScrollZone} The ScrollZone object
+ */
+ function (scrollZone) {
+ return this._world.group.add(scrollZone);
+ };
+ GameObjectFactory.prototype.existingTilemap = /**
+ * Add an existing Tilemap to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param tilemap The Tilemap to add to the Game World
+ * @return {Phaser.Tilemap} The Tilemap object
+ */
+ function (tilemap) {
+ return this._world.group.add(tilemap);
+ };
+ GameObjectFactory.prototype.existingTween = /**
+ * Add an existing Tween to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param tween The Tween to add to the Game World
+ * @return {Phaser.Tween} The Tween object
+ */
+ function (tween) {
+ return this._game.tweens.add(tween);
+ };
+ return GameObjectFactory;
+ })();
+ Phaser.GameObjectFactory = GameObjectFactory;
+})(Phaser || (Phaser = {}));
///
///
/**
@@ -7398,9 +8449,36 @@ var Phaser;
this._maxSize = MaxSize;
this._marker = 0;
this._sortIndex = null;
+ this.cameraBlacklist = [];
}
Group.ASCENDING = -1;
Group.DESCENDING = 1;
+ Group.prototype.hideFromCamera = /**
+ * If you do not wish this object to be visible to a specific camera, pass the camera here.
+ *
+ * @param camera {Camera} The specific camera.
+ */
+ function (camera) {
+ if(this.cameraBlacklist.indexOf(camera.ID) == -1) {
+ this.cameraBlacklist.push(camera.ID);
+ }
+ };
+ Group.prototype.showToCamera = /**
+ * Make this object only visible to a specific camera.
+ *
+ * @param camera {Camera} The camera you wish it to be visible.
+ */
+ function (camera) {
+ if(this.cameraBlacklist.indexOf(camera.ID) !== -1) {
+ this.cameraBlacklist.slice(this.cameraBlacklist.indexOf(camera.ID), 1);
+ }
+ };
+ Group.prototype.clearCameraList = /**
+ * This clears the camera black list, making the GameObject visible to all cameras.
+ */
+ function () {
+ this.cameraBlacklist.length = 0;
+ };
Group.prototype.destroy = /**
* Override this function to handle any deleting or "shutdown" type operations you might need,
* such as removing traditional Flash children like Basic objects.
@@ -7443,6 +8521,9 @@ var Phaser;
*/
function (camera, cameraOffsetX, cameraOffsetY, forceRender) {
if (typeof forceRender === "undefined") { forceRender = false; }
+ if(this.cameraBlacklist.indexOf(camera.ID) !== -1) {
+ return;
+ }
if(this.ignoreGlobalRender && forceRender == false) {
return;
}
@@ -7945,6 +9026,11 @@ var Phaser;
* @param callback {function} This will be called when assets completely loaded.
*/
function Loader(game, callback) {
+ /**
+ * The crossOrigin value applied to loaded images
+ * @type {string}
+ */
+ this.crossOrigin = '';
this._game = game;
this._gameCreateComplete = callback;
this._keys = [];
@@ -8174,6 +9260,7 @@ var Phaser;
file.data.onerror = function () {
return _this.fileError(file.key);
};
+ file.data.crossOrigin = this.crossOrigin;
file.data.src = file.url;
break;
case 'audio':
@@ -8844,7 +9931,7 @@ var Phaser;
/**
* Phaser
*
-* v0.9.5 - April 28th 2013
+* v0.9.6 - May 21st 2013
*
* A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi.
*
@@ -8858,7 +9945,7 @@ var Phaser;
*/
var Phaser;
(function (Phaser) {
- Phaser.VERSION = 'Phaser version 0.9.5';
+ Phaser.VERSION = 'Phaser version 0.9.6';
})(Phaser || (Phaser = {}));
///
/**
@@ -9185,7 +10272,7 @@ var Phaser;
* Start color fading cycle.
*/
function () {
- this._fade = this._game.createTween(this._color2);
+ this._fade = this._game.add.tween(this._color2);
this._fade.to({
r: Math.random() * 250,
g: Math.random() * 250,
@@ -9274,7 +10361,7 @@ var Phaser;
* Start fadeOut effect.
*/
function () {
- this._fade = this._game.createTween(this._color);
+ this._fade = this._game.add.tween(this._color);
this._fade.to({
r: 50,
g: 50,
@@ -9287,7 +10374,7 @@ var Phaser;
* Start fadeIn effect.
*/
function () {
- this._fade = this._game.createTween(this._color);
+ this._fade = this._game.add.tween(this._color);
this._fade.to({
r: 255,
g: 255,
@@ -9414,18 +10501,24 @@ var Phaser;
}
if(event.type == 'blur' || document['hidden'] == true || document['webkitHidden'] == true) {
if(this._game.paused == false) {
- this._pauseScreen.onPaused();
- this.saveCanvasValues();
- this._game.paused = true;
+ this.pauseGame();
}
} else {
if(this._game.paused == true) {
- this._pauseScreen.onResume();
- this._game.paused = false;
- this.restoreCanvasValues();
+ this.resumeGame();
}
}
};
+ Stage.prototype.pauseGame = function () {
+ this._pauseScreen.onPaused();
+ this.saveCanvasValues();
+ this._game.paused = true;
+ };
+ Stage.prototype.resumeGame = function () {
+ this._pauseScreen.onResume();
+ this.restoreCanvasValues();
+ this._game.paused = false;
+ };
Stage.prototype.getOffset = /**
* Get the DOM offset values of the given element
*/
@@ -10357,134 +11450,6 @@ var Phaser;
})();
Phaser.TweenManager = TweenManager;
})(Phaser || (Phaser = {}));
-///
-/**
-* Phaser - Vector2
-*
-* A simple 2-dimensional vector class. Based on the one included with verlet-js by Sub Protocol released under MIT
-*/
-var Phaser;
-(function (Phaser) {
- var Vector2 = (function () {
- /**
- * Creates a new Vector2 object.
- * @class Vector2
- * @constructor
- * @param {Number} x The x coordinate of vector2
- * @param {Number} y The y coordinate of vector2
- * @return {Vector2} This object
- **/
- function Vector2(x, y) {
- if (typeof x === "undefined") { x = 0; }
- if (typeof y === "undefined") { y = 0; }
- this.x = x;
- this.y = y;
- }
- Vector2.prototype.setTo = function (x, y) {
- this.x = x;
- this.y = y;
- return this;
- };
- Vector2.prototype.add = function (v, output) {
- if (typeof output === "undefined") { output = new Vector2(); }
- return output.setTo(this.x + v.x, this.y + v.y);
- };
- Vector2.prototype.sub = function (v, output) {
- if (typeof output === "undefined") { output = new Vector2(); }
- return output.setTo(this.x - v.x, this.y - v.y);
- };
- Vector2.prototype.mul = function (v, output) {
- if (typeof output === "undefined") { output = new Vector2(); }
- return output.setTo(this.x * v.x, this.y * v.y);
- };
- Vector2.prototype.div = function (v, output) {
- if (typeof output === "undefined") { output = new Vector2(); }
- return output.setTo(this.x / v.x, this.y / v.y);
- };
- Vector2.prototype.scale = function (coef, output) {
- if (typeof output === "undefined") { output = new Vector2(); }
- return output.setTo(this.x * coef, this.y * coef);
- };
- Vector2.prototype.mutableSet = function (v) {
- this.x = v.x;
- this.y = v.y;
- return this;
- };
- Vector2.prototype.mutableAdd = function (v) {
- this.x += v.x;
- this.y += v.y;
- return this;
- };
- Vector2.prototype.mutableSub = function (v) {
- this.x -= v.x;
- this.y -= v.y;
- return this;
- };
- Vector2.prototype.mutableMul = function (v) {
- this.x *= v.x;
- this.y *= v.y;
- return this;
- };
- Vector2.prototype.mutableDiv = function (v) {
- this.x /= v.x;
- this.y /= v.y;
- return this;
- };
- Vector2.prototype.mutableScale = function (coef) {
- this.x *= coef;
- this.y *= coef;
- return this;
- };
- Vector2.prototype.equals = function (v) {
- return this.x == v.x && this.y == v.y;
- };
- Vector2.prototype.epsilonEquals = function (v, epsilon) {
- return Math.abs(this.x - v.x) <= epsilon && Math.abs(this.y - v.y) <= epsilon;
- };
- Vector2.prototype.length = function () {
- return Math.sqrt(this.x * this.x + this.y * this.y);
- };
- Vector2.prototype.length2 = function () {
- return this.x * this.x + this.y * this.y;
- };
- Vector2.prototype.dist = function (v) {
- return Math.sqrt(this.dist2(v));
- };
- Vector2.prototype.dist2 = function (v) {
- return ((v.x - this.x) * (v.x - this.x)) + ((v.y - this.y) * (v.y - this.y));
- };
- Vector2.prototype.normal = function (output) {
- if (typeof output === "undefined") { output = new Vector2(); }
- var m = Math.sqrt(this.x * this.x + this.y * this.y);
- return output.setTo(this.x / m, this.y / m);
- };
- Vector2.prototype.dot = function (v) {
- return this.x * v.x + this.y * v.y;
- };
- Vector2.prototype.angle = function (v) {
- return Math.atan2(this.x * v.y - this.y * v.x, this.x * v.x + this.y * v.y);
- };
- Vector2.prototype.angle2 = function (vLeft, vRight) {
- return vLeft.sub(this).angle(vRight.sub(this));
- };
- Vector2.prototype.rotate = function (origin, theta, output) {
- if (typeof output === "undefined") { output = new Vector2(); }
- var x = this.x - origin.x;
- var y = this.y - origin.y;
- return output.setTo(x * Math.cos(theta) - y * Math.sin(theta) + origin.x, x * Math.sin(theta) + y * Math.cos(theta) + origin.y);
- };
- Vector2.prototype.toString = /**
- * Returns a string representation of this object.
- * @method toString
- * @return {string} a string representation of the object.
- **/
- function () {
- return "[{Vector2 (x=" + this.x + " y=" + this.y + ")}]";
- };
- return Vector2;
- })();
- Phaser.Vector2 = Vector2;
-})(Phaser || (Phaser = {}));
var Phaser;
(function (Phaser) {
///
@@ -10581,13 +11546,32 @@ var Phaser;
* @return {Composite} This object
**/
function Composite(game) {
+ /**
+ * Texture of the particles to be rendered.
+ */
+ this._texture = null;
+ // local rendering related temp vars to help avoid gc spikes
+ this._sx = 0;
+ this._sy = 0;
+ this._sw = 0;
+ this._sh = 0;
+ this._dx = 0;
+ this._dy = 0;
+ this._dw = 0;
+ this._dh = 0;
+ this._hw = 0;
+ this._hh = 0;
this.drawParticles = null;
this.drawConstraints = null;
+ this.hideConstraints = true;
+ this.constraintLineColor = 'rgba(200,200,200,1)';
this._game = game;
+ this.sprites = [];
this.particles = [];
this.constraints = [];
+ this.frameBounds = new Phaser.Quad();
}
- Composite.prototype.createDistanceConstraint = // Map sprites to particles
+ Composite.prototype.createDistanceConstraint = // Create Constraints
function (a, b, stiffness, distance) {
if (typeof distance === "undefined") { distance = null; }
this.constraints.push(new Phaser.Verlet.DistanceConstraint(a, b, stiffness, distance));
@@ -10601,6 +11585,74 @@ var Phaser;
this.constraints.push(new Phaser.Verlet.PinConstraint(a, pos));
return this.constraints[this.constraints.length - 1];
};
+ Composite.prototype.loadGraphic = /**
+ * Load a graphic for this Composite. The graphic cannot be a SpriteSheet yet.
+ * @param key {string} Key of the graphic you want to load for this sprite.
+ * @return {Composite} This object
+ */
+ function (key) {
+ if(this._game.cache.getImage(key) !== null) {
+ if(this._game.cache.isSpriteSheet(key) == false) {
+ this._texture = this._game.cache.getImage(key);
+ this.frameBounds.width = this._texture.width;
+ this.frameBounds.height = this._texture.height;
+ this._hw = Math.floor(this.frameBounds.width / 2);
+ this._hh = Math.floor(this.frameBounds.width / 2);
+ this.drawParticles = this.render;
+ this.drawConstraints = this.renderConstraints;
+ }
+ }
+ return this;
+ };
+ Composite.prototype.renderConstraints = function (context) {
+ if(this.hideConstraints == true || this.constraints.length == 0) {
+ return;
+ }
+ var i;
+ context.beginPath();
+ for(i in this.constraints) {
+ if(this.constraints[i].b) {
+ context.moveTo(this.constraints[i].a.pos.x, this.constraints[i].a.pos.y);
+ context.lineTo(this.constraints[i].b.pos.x, this.constraints[i].b.pos.y);
+ }
+ }
+ context.strokeStyle = this.constraintLineColor;
+ context.stroke();
+ context.closePath();
+ };
+ Composite.prototype.render = function (context) {
+ this._sx = 0;
+ this._sy = 0;
+ this._sw = this.frameBounds.width;
+ this._sh = this.frameBounds.height;
+ this._dw = this.frameBounds.width;
+ this._dh = this.frameBounds.height;
+ this._sx = Math.round(this._sx);
+ this._sy = Math.round(this._sy);
+ this._sw = Math.round(this._sw);
+ this._sh = Math.round(this._sh);
+ this._dw = Math.round(this._dw);
+ this._dh = Math.round(this._dh);
+ var i;
+ for(i in this.particles) {
+ //this._dx = cameraOffsetX + (this.frameBounds.topLeft.x - camera.worldView.x);
+ //this._dy = cameraOffsetY + (this.frameBounds.topLeft.y - camera.worldView.y);
+ this._dx = this.particles[i].pos.x - this._hw;
+ this._dy = this.particles[i].pos.y - this._hh;
+ this._dx = Math.round(this._dx);
+ this._dy = Math.round(this._dy);
+ context.drawImage(this._texture, // Source Image
+ this._sx, // Source X (location within the source image)
+ this._sy, // Source Y
+ this._sw, // Source Width
+ this._sh, // Source Height
+ this._dx, // Destination X (where on the canvas it'll be drawn)
+ this._dy, // Destination Y
+ this._dw, // Destination Width (always same as Source Width unless scaled)
+ this._dh);
+ // Destination Height (always same as Source Height unless scaled)
+ }
+ };
Composite.prototype.pin = function (index, pos) {
if (typeof pos === "undefined") { pos = null; }
if(pos == null) {
@@ -10660,6 +11712,7 @@ var Phaser;
ctx.lineTo(this.b.pos.x, this.b.pos.y);
ctx.strokeStyle = "#d8dde2";
ctx.stroke();
+ ctx.closePath();
};
return DistanceConstraint;
})();
@@ -10750,12 +11803,13 @@ var Phaser;
* @return {Vector2} This object
**/
function VerletManager(game, width, height) {
+ this._v = new Phaser.Vector2();
this.composites = [];
- this.step = 32;
+ this.step = 16;
this.selectionRadius = 20;
this.draggedEntity = null;
this.highlightColor = '#4f545c';
- this.v = new Phaser.Vector2();
+ this.hideNearestEntityCircle = false;
this._game = game;
this.width = width;
this.height = height;
@@ -10770,10 +11824,10 @@ var Phaser;
VerletManager.prototype.intersectionTime = /**
* Computes time of intersection of a particle with a wall
*
- * @param {Vec2} line wall's root position
- * @param {Vec2} p particle's position
- * @param {Vec2} dir walls's direction
- * @param {Vec2} v particle's velocity
+ * @param {Vec2} line walls root position
+ * @param {Vec2} p particle position
+ * @param {Vec2} dir walls direction
+ * @param {Vec2} v particles velocity
*/
function (wall, p, dir, v) {
if(dir.x != 0) {
@@ -10799,35 +11853,16 @@ var Phaser;
return new Phaser.Vector2(p.x + v.x * t, p.y + v.y * t);
};
VerletManager.prototype.bounds = function (particle) {
- this.v.mutableSet(particle.pos);
- this.v.mutableSub(particle.lastPos);
+ this._v.mutableSet(particle.pos);
+ this._v.mutableSub(particle.lastPos);
if(particle.pos.y > this.height - 1) {
- particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, this.height - 1), particle.lastPos, new Phaser.Vector2(1, 0), this.v));
+ particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, this.height - 1), particle.lastPos, new Phaser.Vector2(1, 0), this._v));
}
if(particle.pos.x < 0) {
- particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, 0), particle.pos, new Phaser.Vector2(0, 1), this.v));
+ particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, 0), particle.pos, new Phaser.Vector2(0, 1), this._v));
}
if(particle.pos.x > this.width - 1) {
- particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(this.width - 1, 0), particle.pos, new Phaser.Vector2(0, 1), this.v));
- }
- };
- VerletManager.prototype.OLDbounds = function (particle) {
- if(particle.pos.y > this.height - 1) {
- particle.pos.y = this.height - 1;
- }
- if(particle.pos.x < 0) {
- var vx = particle.pos.x - particle.lastPos.x;
- var vy = particle.pos.y - particle.lastPos.y;
- if(vx == 0) {
- particle.pos.x = 0;
- } else {
- var t = -particle.lastPos.x / vx;
- particle.pos.x = particle.lastPos.x + t * vx;
- particle.pos.y = particle.lastPos.y + t * vy;
- }
- }
- if(particle.pos.x > this.width - 1) {
- particle.pos.x = this.width - 1;
+ particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(this.width - 1, 0), particle.pos, new Phaser.Vector2(0, 1), this._v));
}
};
VerletManager.prototype.createPoint = function (pos) {
@@ -10837,8 +11872,8 @@ var Phaser;
return composite;
};
VerletManager.prototype.createLineSegments = function (vertices, stiffness) {
- var i;
var composite = new Phaser.Verlet.Composite(this._game);
+ var i;
for(i in vertices) {
composite.particles.push(new Phaser.Verlet.Particle(vertices[i]));
if(i > 0) {
@@ -10852,7 +11887,8 @@ var Phaser;
var composite = new Phaser.Verlet.Composite(this._game);
var xStride = width / segments;
var yStride = height / segments;
- var x, y;
+ var x;
+ var y;
for(y = 0; y < segments; ++y) {
for(x = 0; x < segments; ++x) {
var px = origin.x + x * xStride - width / 2 + xStride / 2;
@@ -10921,7 +11957,7 @@ var Phaser;
}
// handle dragging of entities
if(this.draggedEntity) {
- this.draggedEntity.pos.mutableSet(new Phaser.Vector2(this._game.input.x, this._game.input.y));
+ this.draggedEntity.pos.mutableSet(this._game.input.position);
}
// relax
var stepCoef = 1 / this.step;
@@ -10959,7 +11995,7 @@ var Phaser;
for(c in this.composites) {
var particles = this.composites[c].particles;
for(i in particles) {
- var d2 = particles[i].pos.dist2(new Phaser.Vector2(this._game.input.x, this._game.input.y));
+ var d2 = particles[i].pos.distance2(this._game.input.position);
if(d2 <= this.selectionRadius * this.selectionRadius && (entity == null || d2 < d2Nearest)) {
entity = particles[i];
constraintsNearest = this.composites[c].constraints;
@@ -10999,11 +12035,12 @@ var Phaser;
}
// highlight nearest / dragged entity
var nearest = this.draggedEntity || this.nearestEntity();
- if(nearest) {
+ if(nearest && this.hideNearestEntityCircle == false) {
this.context.beginPath();
this.context.arc(nearest.pos.x, nearest.pos.y, 8, 0, 2 * Math.PI);
this.context.strokeStyle = this.highlightColor;
this.context.stroke();
+ this.context.closePath();
}
};
return VerletManager;
@@ -11065,19 +12102,25 @@ var Phaser;
World.prototype.setSize = // World methods
/**
* Update size of this world with specific width and height.
- * You can choose update camera bounds automatically or not.
+ * You can choose update camera bounds and verlet manager automatically or not.
*
* @param width {number} New width of the world.
* @param height {number} New height of the world.
* @param [updateCameraBounds] {boolean} update camera bounds automatically or not. Default to true.
+ * @param [updateVerletBounds] {boolean} update verlet bounds automatically or not. Default to true.
*/
- function (width, height, updateCameraBounds) {
+ function (width, height, updateCameraBounds, updateVerletBounds) {
if (typeof updateCameraBounds === "undefined") { updateCameraBounds = true; }
+ if (typeof updateVerletBounds === "undefined") { updateVerletBounds = true; }
this.bounds.width = width;
this.bounds.height = height;
if(updateCameraBounds == true) {
this._game.camera.setBounds(0, 0, width, height);
}
+ if(updateVerletBounds == true) {
+ this._game.verlet.width = width;
+ this._game.verlet.height = height;
+ }
};
Object.defineProperty(World.prototype, "width", {
get: function () {
@@ -12030,6 +13073,7 @@ var Phaser;
Phaser.RequestAnimationFrame = RequestAnimationFrame;
})(Phaser || (Phaser = {}));
///
+///
/**
* Phaser - Pointer
*
@@ -12066,17 +13110,17 @@ var Phaser;
*/
this._nextDrop = 0;
/**
- * A Point object representing the x/y screen coordinates of the Pointer.
- * @property pointA
- * @type {Point}
+ * A Vector object containing the initial position when the Pointer was engaged with the screen.
+ * @property positionDown
+ * @type {Vector2}
**/
- this.pointA = null;
+ this.positionDown = null;
/**
- * A Point object representing the x/y screen coordinates of the Pointer.
- * @property pointB
- * @type {Point}
+ * A Vector object containing the current position of the Pointer on the screen.
+ * @property position
+ * @type {Vector2}
**/
- this.pointB = null;
+ this.position = null;
/**
* A Circle object centered on the x/y screen coordinates of the Pointer.
* Default size of 44px (Apple's recommended "finger tip" size)
@@ -12183,8 +13227,8 @@ var Phaser;
this._game = game;
this.id = id;
this.active = false;
- this.pointA = new Phaser.Point();
- this.pointB = new Phaser.Point();
+ this.position = new Phaser.Vector2();
+ this.positionDown = new Phaser.Vector2();
this.circle = new Phaser.Circle(0, 0, 44);
if(id == 0) {
this.isMouse = true;
@@ -12232,9 +13276,14 @@ var Phaser;
if(event.button) {
this.button = event.button;
}
+ // Fix to stop rogue browser plugins from blocking the visibility state event
+ if(this._game.paused == true) {
+ this._game.stage.resumeGame();
+ return this;
+ }
this._history.length = 0;
this.move(event);
- this.pointA.setTo(this.x, this.y);
+ this.positionDown.setTo(this.x, this.y);
this.active = true;
this.withinGame = true;
this.isDown = true;
@@ -12264,8 +13313,8 @@ var Phaser;
if(this._game.input.recordPointerHistory && this._game.time.now >= this._nextDrop) {
this._nextDrop = this._game.time.now + this._game.input.recordRate;
this._history.push({
- x: this.pointB.x,
- y: this.pointB.y
+ x: this.position.x,
+ y: this.position.y
});
if(this._history.length > this._game.input.recordLimit) {
this._history.shift();
@@ -12290,13 +13339,13 @@ var Phaser;
this.screenY = event.screenY;
this.x = this.pageX - this._game.stage.offset.x;
this.y = this.pageY - this._game.stage.offset.y;
- this.pointB.setTo(this.x, this.y);
+ this.position.setTo(this.x, this.y);
this.circle.x = this.x;
this.circle.y = this.y;
if(this._game.input.multiInputOverride == Phaser.Input.MOUSE_OVERRIDES_TOUCH || this._game.input.multiInputOverride == Phaser.Input.MOUSE_TOUCH_COMBINE || (this._game.input.multiInputOverride == Phaser.Input.TOUCH_OVERRIDES_MOUSE && this._game.input.currentPointers == 0)) {
this._game.input.x = this.x * this._game.input.scaleX;
this._game.input.y = this.y * this._game.input.scaleY;
- this._game.input.point.setTo(this._game.input.x, this._game.input.y);
+ this._game.input.position.setTo(this._game.input.x, this._game.input.y);
this._game.input.circle.x = this._game.input.x;
this._game.input.circle.y = this._game.input.y;
}
@@ -12405,8 +13454,8 @@ var Phaser;
this._game.stage.context.closePath();
// Render the points
this._game.stage.context.beginPath();
- this._game.stage.context.moveTo(this.pointA.x, this.pointA.y);
- this._game.stage.context.lineTo(this.pointB.x, this.pointB.y);
+ this._game.stage.context.moveTo(this.positionDown.x, this.positionDown.y);
+ this._game.stage.context.lineTo(this.position.x, this.position.y);
this._game.stage.context.lineWidth = 2;
this._game.stage.context.stroke();
this._game.stage.context.closePath();
@@ -12588,11 +13637,11 @@ var Phaser;
*/
this.multiInputOverride = Input.MOUSE_TOUCH_COMBINE;
/**
- * A Point object representing the x/y screen coordinates of the Pointer.
- * @property point
- * @type {Point}
+ * A vector object representing the current position of the Pointer.
+ * @property vector
+ * @type {Vector2}
**/
- this.point = null;
+ this.position = null;
/**
* A Circle object centered on the x/y screen coordinates of the Input.
* Default size of 44px (Apples recommended "finger tip" size) but can be changed to anything
@@ -12684,6 +13733,36 @@ var Phaser;
* @type {Number}
*/
this.recordLimit = 100;
+ /**
+ * A Pointer object
+ * @property pointer6
+ * @type {Pointer}
+ **/
+ this.pointer6 = null;
+ /**
+ * A Pointer object
+ * @property pointer7
+ * @type {Pointer}
+ **/
+ this.pointer7 = null;
+ /**
+ * A Pointer object
+ * @property pointer8
+ * @type {Pointer}
+ **/
+ this.pointer8 = null;
+ /**
+ * A Pointer object
+ * @property pointer9
+ * @type {Pointer}
+ **/
+ this.pointer9 = null;
+ /**
+ * A Pointer object
+ * @property pointer10
+ * @type {Pointer}
+ **/
+ this.pointer10 = null;
this._game = game;
this.mousePointer = new Phaser.Pointer(this._game, 0);
this.pointer1 = new Phaser.Pointer(this._game, 1);
@@ -12691,11 +13770,6 @@ var Phaser;
this.pointer3 = new Phaser.Pointer(this._game, 3);
this.pointer4 = new Phaser.Pointer(this._game, 4);
this.pointer5 = new Phaser.Pointer(this._game, 5);
- this.pointer6 = new Phaser.Pointer(this._game, 6);
- this.pointer7 = new Phaser.Pointer(this._game, 7);
- this.pointer8 = new Phaser.Pointer(this._game, 8);
- this.pointer9 = new Phaser.Pointer(this._game, 9);
- this.pointer10 = new Phaser.Pointer(this._game, 10);
this.mouse = new Phaser.Mouse(this._game);
this.keyboard = new Phaser.Keyboard(this._game);
this.touch = new Phaser.Touch(this._game);
@@ -12705,7 +13779,7 @@ var Phaser;
this.onUp = new Phaser.Signal();
this.onTap = new Phaser.Signal();
this.onHold = new Phaser.Signal();
- this.point = new Phaser.Point();
+ this.position = new Phaser.Vector2();
this.circle = new Phaser.Circle(0, 0, 44);
this.currentPointers = 0;
}
@@ -12742,25 +13816,74 @@ var Phaser;
enumerable: true,
configurable: true
});
- Input.prototype.start = function () {
+ Input.prototype.addPointer = /**
+ * Add a new Pointer object to the Input Manager. By default Input creates 5 pointer objects for you. If you need more
+ * use this to create a new one, up to a maximum of 10.
+ * @method addPointer
+ * @return {Pointer} A reference to the new Pointer object
+ **/
+ function () {
+ var next = 0;
+ if(this.pointer10 === null) {
+ next = 10;
+ }
+ if(this.pointer9 === null) {
+ next = 9;
+ }
+ if(this.pointer8 === null) {
+ next = 8;
+ }
+ if(this.pointer7 === null) {
+ next = 7;
+ }
+ if(this.pointer6 === null) {
+ next = 6;
+ }
+ if(next == 0) {
+ throw new Error("You can only have 10 Pointer objects");
+ return null;
+ } else {
+ this['pointer' + next] = new Phaser.Pointer(this._game, next);
+ return this['pointer' + next];
+ }
+ };
+ Input.prototype.start = /**
+ * Starts the Input Manager running
+ * @method start
+ **/
+ function () {
this.mouse.start();
this.keyboard.start();
this.touch.start();
this.mspointer.start();
this.gestures.start();
};
- Input.prototype.update = function () {
+ Input.prototype.update = /**
+ * Updates the Input Manager. Called by the core Game loop.
+ * @method update
+ **/
+ function () {
this.mousePointer.update();
this.pointer1.update();
this.pointer2.update();
this.pointer3.update();
this.pointer4.update();
this.pointer5.update();
- this.pointer6.update();
- this.pointer7.update();
- this.pointer8.update();
- this.pointer9.update();
- this.pointer10.update();
+ if(this.pointer6) {
+ this.pointer6.update();
+ }
+ if(this.pointer7) {
+ this.pointer7.update();
+ }
+ if(this.pointer8) {
+ this.pointer8.update();
+ }
+ if(this.pointer9) {
+ this.pointer9.update();
+ }
+ if(this.pointer10) {
+ this.pointer10.update();
+ }
};
Input.prototype.reset = /**
* Reset all of the Pointers and Input states
@@ -12775,11 +13898,21 @@ var Phaser;
this.pointer3.reset();
this.pointer4.reset();
this.pointer5.reset();
- this.pointer6.reset();
- this.pointer7.reset();
- this.pointer8.reset();
- this.pointer9.reset();
- this.pointer10.reset();
+ if(this.pointer6) {
+ this.pointer6.reset();
+ }
+ if(this.pointer7) {
+ this.pointer7.reset();
+ }
+ if(this.pointer8) {
+ this.pointer8.reset();
+ }
+ if(this.pointer9) {
+ this.pointer9.reset();
+ }
+ if(this.pointer10) {
+ this.pointer10.reset();
+ }
this.currentPointers = 0;
if(hard == true) {
this.onDown = new Phaser.Signal();
@@ -12818,15 +13951,15 @@ var Phaser;
this.currentPointers++;
} else if(this.pointer5.active == true) {
this.currentPointers++;
- } else if(this.pointer6.active == true) {
+ } else if(this.pointer6 && this.pointer6.active == true) {
this.currentPointers++;
- } else if(this.pointer7.active == true) {
+ } else if(this.pointer7 && this.pointer7.active == true) {
this.currentPointers++;
- } else if(this.pointer8.active == true) {
+ } else if(this.pointer8 && this.pointer8.active == true) {
this.currentPointers++;
- } else if(this.pointer9.active == true) {
+ } else if(this.pointer9 && this.pointer9.active == true) {
this.currentPointers++;
- } else if(this.pointer10.active == true) {
+ } else if(this.pointer10 && this.pointer10.active == true) {
this.currentPointers++;
}
return this.currentPointers;
@@ -12855,15 +13988,15 @@ var Phaser;
return this.pointer4.start(event);
} else if(this.pointer5.active == false) {
return this.pointer5.start(event);
- } else if(this.pointer6.active == false) {
+ } else if(this.pointer6 && this.pointer6.active == false) {
return this.pointer6.start(event);
- } else if(this.pointer7.active == false) {
+ } else if(this.pointer7 && this.pointer7.active == false) {
return this.pointer7.start(event);
- } else if(this.pointer8.active == false) {
+ } else if(this.pointer8 && this.pointer8.active == false) {
return this.pointer8.start(event);
- } else if(this.pointer9.active == false) {
+ } else if(this.pointer9 && this.pointer9.active == false) {
return this.pointer9.start(event);
- } else if(this.pointer10.active == false) {
+ } else if(this.pointer10 && this.pointer10.active == false) {
return this.pointer10.start(event);
}
return null;
@@ -12886,15 +14019,15 @@ var Phaser;
return this.pointer4.move(event);
} else if(this.pointer5.active == true && this.pointer5.identifier == event.identifier) {
return this.pointer5.move(event);
- } else if(this.pointer6.active == true && this.pointer6.identifier == event.identifier) {
+ } else if(this.pointer6 && this.pointer6.active == true && this.pointer6.identifier == event.identifier) {
return this.pointer6.move(event);
- } else if(this.pointer7.active == true && this.pointer7.identifier == event.identifier) {
+ } else if(this.pointer7 && this.pointer7.active == true && this.pointer7.identifier == event.identifier) {
return this.pointer7.move(event);
- } else if(this.pointer8.active == true && this.pointer8.identifier == event.identifier) {
+ } else if(this.pointer8 && this.pointer8.active == true && this.pointer8.identifier == event.identifier) {
return this.pointer8.move(event);
- } else if(this.pointer9.active == true && this.pointer9.identifier == event.identifier) {
+ } else if(this.pointer9 && this.pointer9.active == true && this.pointer9.identifier == event.identifier) {
return this.pointer9.move(event);
- } else if(this.pointer10.active == true && this.pointer10.identifier == event.identifier) {
+ } else if(this.pointer10 && this.pointer10.active == true && this.pointer10.identifier == event.identifier) {
return this.pointer10.move(event);
}
return null;
@@ -12917,15 +14050,15 @@ var Phaser;
return this.pointer4.stop(event);
} else if(this.pointer5.active == true && this.pointer5.identifier == event.identifier) {
return this.pointer5.stop(event);
- } else if(this.pointer6.active == true && this.pointer6.identifier == event.identifier) {
+ } else if(this.pointer6 && this.pointer6.active == true && this.pointer6.identifier == event.identifier) {
return this.pointer6.stop(event);
- } else if(this.pointer7.active == true && this.pointer7.identifier == event.identifier) {
+ } else if(this.pointer7 && this.pointer7.active == true && this.pointer7.identifier == event.identifier) {
return this.pointer7.stop(event);
- } else if(this.pointer8.active == true && this.pointer8.identifier == event.identifier) {
+ } else if(this.pointer8 && this.pointer8.active == true && this.pointer8.identifier == event.identifier) {
return this.pointer8.stop(event);
- } else if(this.pointer9.active == true && this.pointer9.identifier == event.identifier) {
+ } else if(this.pointer9 && this.pointer9.active == true && this.pointer9.identifier == event.identifier) {
return this.pointer9.stop(event);
- } else if(this.pointer10.active == true && this.pointer10.identifier == event.identifier) {
+ } else if(this.pointer10 && this.pointer10.active == true && this.pointer10.identifier == event.identifier) {
return this.pointer10.stop(event);
}
return null;
@@ -12949,15 +14082,15 @@ var Phaser;
return this.pointer4;
} else if(this.pointer5.active == state) {
return this.pointer5;
- } else if(this.pointer6.active == state) {
+ } else if(this.pointer6 && this.pointer6.active == state) {
return this.pointer6;
- } else if(this.pointer7.active == state) {
+ } else if(this.pointer7 && this.pointer7.active == state) {
return this.pointer7;
- } else if(this.pointer8.active == state) {
+ } else if(this.pointer8 && this.pointer8.active == state) {
return this.pointer8;
- } else if(this.pointer9.active == state) {
+ } else if(this.pointer9 && this.pointer9.active == state) {
return this.pointer9;
- } else if(this.pointer10.active == state) {
+ } else if(this.pointer10 && this.pointer10.active == state) {
return this.pointer10;
}
return null;
@@ -12980,15 +14113,15 @@ var Phaser;
return this.pointer4;
} else if(this.pointer5.identifier == identifier) {
return this.pointer5;
- } else if(this.pointer6.identifier == identifier) {
+ } else if(this.pointer6 && this.pointer6.identifier == identifier) {
return this.pointer6;
- } else if(this.pointer7.identifier == identifier) {
+ } else if(this.pointer7 && this.pointer7.identifier == identifier) {
return this.pointer7;
- } else if(this.pointer8.identifier == identifier) {
+ } else if(this.pointer8 && this.pointer8.identifier == identifier) {
return this.pointer8;
- } else if(this.pointer9.identifier == identifier) {
+ } else if(this.pointer9 && this.pointer9.identifier == identifier) {
return this.pointer9;
- } else if(this.pointer10.identifier == identifier) {
+ } else if(this.pointer10 && this.pointer10.identifier == identifier) {
return this.pointer10;
}
return null;
@@ -13021,34 +14154,28 @@ var Phaser;
this._game.stage.context.fillText('World X: ' + this.getWorldX() + ' World Y: ' + this.getWorldY(), x, y + 28);
this._game.stage.context.fillText('Scale X: ' + this.scaleX.toFixed(1) + ' Scale Y: ' + this.scaleY.toFixed(1), x, y + 42);
};
+ Input.prototype.getDistance = /**
+ * Get the distance between two Pointer objects
+ * @method getDistance
+ * @param {Pointer} pointer1
+ * @param {Pointer} pointer2
+ **/
+ function (pointer1, pointer2) {
+ return pointer1.position.distance(pointer2.position);
+ };
+ Input.prototype.getAngle = /**
+ * Get the angle between two Pointer objects
+ * @method getAngle
+ * @param {Pointer} pointer1
+ * @param {Pointer} pointer2
+ **/
+ function (pointer1, pointer2) {
+ return pointer1.position.angle(pointer2.position);
+ };
return Input;
})();
Phaser.Input = Input;
- /**
- *
- * @method calculateDistance
- * @param {Finger} finger1
- * @param {Finger} finger2
- **/
- //public calculateDistance(finger1: Finger, finger2: Finger) {
- //}
- /**
- *
- * @method calculateAngle
- * @param {Finger} finger1
- * @param {Finger} finger2
- **/
- //public calculateAngle(finger1: Finger, finger2: Finger) {
- //}
- /**
- *
- * @method checkOverlap
- * @param {Finger} finger1
- * @param {Finger} finger2
- **/
- //public checkOverlap(finger1: Finger, finger2: Finger) {
- //}
- })(Phaser || (Phaser = {}));
+})(Phaser || (Phaser = {}));
///
/**
* Phaser - Keyboard
@@ -13822,6 +14949,7 @@ var Phaser;
Phaser.Emitter = Emitter;
})(Phaser || (Phaser = {}));
///
+///
/**
* Phaser - GeomSprite
*
@@ -13888,6 +15016,7 @@ var Phaser;
GeomSprite.LINE = 2;
GeomSprite.POINT = 3;
GeomSprite.RECTANGLE = 4;
+ GeomSprite.POLYGON = 5;
GeomSprite.prototype.loadCircle = /**
* Just like Sprite.loadGraphic(), this will load a circle and set its shape to Circle.
* @param circle {Circle} Circle geometry define.
@@ -13982,6 +15111,20 @@ var Phaser;
this.frameBounds.copyFrom(this.rect);
return this;
};
+ GeomSprite.prototype.createPolygon = /**
+ * Create a polygon object
+ * @param width {Number} Width of the rectangle
+ * @param height {Number} Height of the rectangle
+ * @return {GeomSprite} GeomSprite instance.
+ */
+ function (points) {
+ if (typeof points === "undefined") { points = []; }
+ this.refresh();
+ this.polygon = new Phaser.Polygon(new Phaser.Vector2(this.x, this.y), points);
+ this.type = GeomSprite.POLYGON;
+ //this.frameBounds.copyFrom(this.rect);
+ return this;
+ };
GeomSprite.prototype.refresh = /**
* Destroy all geom shapes of this sprite.
*/
@@ -15572,6 +16715,7 @@ var Phaser;
///
///
///
+///
///
///
///
@@ -15751,6 +16895,7 @@ var Phaser;
this.math = new Phaser.GameMath(this);
this.stage = new Phaser.Stage(this, parent, width, height);
this.world = new Phaser.World(this, width, height);
+ this.add = new Phaser.GameObjectFactory(this);
this.sound = new Phaser.SoundManager(this);
this.cache = new Phaser.Cache(this);
this.collision = new Phaser.Collision(this);
@@ -15989,126 +17134,6 @@ var Phaser;
enumerable: true,
configurable: true
});
- Game.prototype.createCamera = // Handy Proxy methods
- /**
- * Create a new camera with specific position and size.
- *
- * @param x {number} X position of the new camera.
- * @param y {number} Y position of the new camera.
- * @param width {number} Width of the new camera.
- * @param height {number} Height of the new camera.
- * @returns {Camera} The newly created camera object.
- */
- function (x, y, width, height) {
- return this.world.createCamera(x, y, width, height);
- };
- Game.prototype.createGeomSprite = /**
- * Create a new GeomSprite with specific position.
- *
- * @param x {number} X position of the new geom sprite.
- * @param y {number} Y position of the new geom sprite.
- * @returns {GeomSprite} The newly created geom sprite object.
- */
- function (x, y) {
- return this.world.createGeomSprite(x, y);
- };
- Game.prototype.createSprite = /**
- * Create a new Sprite with specific position and sprite sheet key.
- *
- * @param x {number} X position of the new sprite.
- * @param y {number} Y position of the new sprite.
- * @param key {string} Optional, key for the sprite sheet you want it to use.
- * @returns {Sprite} The newly created sprite object.
- */
- function (x, y, key) {
- if (typeof key === "undefined") { key = ''; }
- return this.world.createSprite(x, y, key);
- };
- Game.prototype.createDynamicTexture = /**
- * Create a new DynamicTexture with specific size.
- *
- * @param width {number} Width of the texture.
- * @param height {number} Height of the texture.
- * @returns {DynamicTexture} The newly created dynamic texture object.
- */
- function (width, height) {
- return this.world.createDynamicTexture(width, height);
- };
- Game.prototype.createGroup = /**
- * Create a new object container.
- *
- * @param maxSize {number} Optional, capacity of this group.
- * @returns {Group} The newly created group.
- */
- function (maxSize) {
- if (typeof maxSize === "undefined") { maxSize = 0; }
- return this.world.createGroup(maxSize);
- };
- Game.prototype.createParticle = /**
- * Create a new Particle.
- *
- * @return {Particle} The newly created particle object.
- */
- function () {
- return this.world.createParticle();
- };
- Game.prototype.createEmitter = /**
- * Create a new Emitter.
- *
- * @param x {number} Optional, x position of the emitter.
- * @param y {number} Optional, y position of the emitter.
- * @param size {number} Optional, size of this emitter.
- * @return {Emitter} The newly created emitter object.
- */
- function (x, y, size) {
- if (typeof x === "undefined") { x = 0; }
- if (typeof y === "undefined") { y = 0; }
- if (typeof size === "undefined") { size = 0; }
- return this.world.createEmitter(x, y, size);
- };
- Game.prototype.createScrollZone = /**
- * Create a new ScrollZone object with image key, position and size.
- *
- * @param key {string} Key to a image you wish this object to use.
- * @param x {number} X position of this object.
- * @param y {number} Y position of this object.
- * @param width number} Width of this object.
- * @param height {number} Height of this object.
- * @returns {ScrollZone} The newly created scroll zone object.
- */
- function (key, x, y, width, height) {
- if (typeof x === "undefined") { x = 0; }
- if (typeof y === "undefined") { y = 0; }
- if (typeof width === "undefined") { width = 0; }
- if (typeof height === "undefined") { height = 0; }
- return this.world.createScrollZone(key, x, y, width, height);
- };
- Game.prototype.createTilemap = /**
- * Create a new Tilemap.
- *
- * @param key {string} Key for tileset image.
- * @param mapData {string} Data of this tilemap.
- * @param format {number} Format of map data. (Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON)
- * @param [resizeWorld] {boolean} resize the world to make same as tilemap?
- * @param [tileWidth] {number} width of each tile.
- * @param [tileHeight] {number} height of each tile.
- * @return {Tilemap} The newly created tilemap object.
- */
- function (key, mapData, format, resizeWorld, tileWidth, tileHeight) {
- if (typeof resizeWorld === "undefined") { resizeWorld = true; }
- if (typeof tileWidth === "undefined") { tileWidth = 0; }
- if (typeof tileHeight === "undefined") { tileHeight = 0; }
- return this.world.createTilemap(key, mapData, format, resizeWorld, tileWidth, tileHeight);
- };
- Game.prototype.createTween = /**
- * Create a tween object for a specific object.
- *
- * @param obj Object you wish the tween will affect.
- * @return {Phaser.Tween} The newly created tween object.
- */
- function (obj) {
- return this.tweens.create(obj);
- };
Game.prototype.collide = /**
* Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group.
* Note: Does not take the objects scrollFactor into account. All overlaps are check in world space.
@@ -16302,6 +17327,7 @@ var Phaser;
*/
function State(game) {
this.game = game;
+ this.add = game.add;
this.camera = game.camera;
this.cache = game.cache;
this.collision = game.collision;
@@ -16348,126 +17374,6 @@ var Phaser;
*/
function () {
};
- State.prototype.createCamera = // Handy Proxy methods
- /**
- * Create a new camera with specific position and size.
- *
- * @param x {number} X position of the new camera.
- * @param y {number} Y position of the new camera.
- * @param width {number} Width of the new camera.
- * @param height {number} Height of the new camera.
- * @returns {Camera} The newly created camera object.
- */
- function (x, y, width, height) {
- return this.game.world.createCamera(x, y, width, height);
- };
- State.prototype.createGeomSprite = /**
- * Create a new GeomSprite with specific position.
- *
- * @param x {number} X position of the new geom sprite.
- * @param y {number} Y position of the new geom sprite.
- * @returns {GeomSprite} The newly created geom sprite object.
- */
- function (x, y) {
- return this.world.createGeomSprite(x, y);
- };
- State.prototype.createSprite = /**
- * Create a new Sprite with specific position and sprite sheet key.
- *
- * @param x {number} X position of the new sprite.
- * @param y {number} Y position of the new sprite.
- * @param key {string} [optional] key for the sprite sheet you want it to use.
- * @returns {Sprite} The newly created sprite object.
- */
- function (x, y, key) {
- if (typeof key === "undefined") { key = ''; }
- return this.game.world.createSprite(x, y, key);
- };
- State.prototype.createDynamicTexture = /**
- * Create a new DynamicTexture with specific size.
- *
- * @param width {number} Width of the texture.
- * @param height {number} Height of the texture.
- * @returns {DynamicTexture} The newly created dynamic texture object.
- */
- function (width, height) {
- return this.game.world.createDynamicTexture(width, height);
- };
- State.prototype.createGroup = /**
- * Create a new object container.
- *
- * @param maxSize {number} [optional] capacity of this group.
- * @returns {Group} The newly created group.
- */
- function (maxSize) {
- if (typeof maxSize === "undefined") { maxSize = 0; }
- return this.game.world.createGroup(maxSize);
- };
- State.prototype.createParticle = /**
- * Create a new Particle.
- *
- * @return {Particle} The newly created particle object.
- */
- function () {
- return this.game.world.createParticle();
- };
- State.prototype.createEmitter = /**
- * Create a new Emitter.
- *
- * @param x {number} [optional] x position of the emitter.
- * @param y {number} [optional] y position of the emitter.
- * @param size {number} [optional] size of this emitter.
- * @return {Emitter} The newly created emitter object.
- */
- function (x, y, size) {
- if (typeof x === "undefined") { x = 0; }
- if (typeof y === "undefined") { y = 0; }
- if (typeof size === "undefined") { size = 0; }
- return this.game.world.createEmitter(x, y, size);
- };
- State.prototype.createScrollZone = /**
- * Create a new ScrollZone object with image key, position and size.
- *
- * @param key {string} Key to a image you wish this object to use.
- * @param x {number} X position of this object.
- * @param y {number} Y position of this object.
- * @param width {number} Width of this object.
- * @param height {number} Height of this object.
- * @returns {ScrollZone} The newly created scroll zone object.
- */
- function (key, x, y, width, height) {
- if (typeof x === "undefined") { x = 0; }
- if (typeof y === "undefined") { y = 0; }
- if (typeof width === "undefined") { width = 0; }
- if (typeof height === "undefined") { height = 0; }
- return this.game.world.createScrollZone(key, x, y, width, height);
- };
- State.prototype.createTilemap = /**
- * Create a new Tilemap.
- *
- * @param key {string} Key for tileset image.
- * @param mapData {string} Data of this tilemap.
- * @param format {number} Format of map data. (Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON)
- * @param resizeWorld {boolean} [optional] resize the world to make same as tilemap?
- * @param tileWidth {number} [optional] width of each tile.
- * @param tileHeight number} [optional] height of each tile.
- * @return {Tilemap} The newly created tilemap object.
- */
- function (key, mapData, format, resizeWorld, tileWidth, tileHeight) {
- if (typeof resizeWorld === "undefined") { resizeWorld = true; }
- if (typeof tileWidth === "undefined") { tileWidth = 0; }
- if (typeof tileHeight === "undefined") { tileHeight = 0; }
- return this.game.world.createTilemap(key, mapData, format, resizeWorld, tileWidth, tileHeight);
- };
- State.prototype.createTween = /**
- * Create a tween object for a specific object.
- *
- * @param obj Object you wish the tween will affect.
- * @return {Phaser.Tween} The newly created tween object.
- */
- function (obj) {
- return this.game.tweens.create(obj);
- };
State.prototype.collide = /**
* Call this method to see if one object collids another.
* @return {boolean} Whether the given objects or groups collids.
diff --git a/Tests/physics/temp1.js b/Tests/physics/temp1.js
new file mode 100644
index 00000000..9b6e962b
--- /dev/null
+++ b/Tests/physics/temp1.js
@@ -0,0 +1,113 @@
+///
+var Physics = (function () {
+ function Physics() {
+ this.max_bodies = 512;
+ this.max_vertices = 1024;
+ this.max_edges = 1024;
+ this.max_body_vertices = 64;
+ this.max_body_edges = 64;
+ this.vertices = [];
+ this.edges = [];
+ this.bodies = [];
+ }
+ Physics.prototype.updateForces = // Sets the force on each vertex to the gravity force. You could of course apply other forces like magnetism etc.
+ function () {
+ for(var i = 0; i < this.vertexCount; i++) {
+ this.vertices[i].acceleration = this.gravity;
+ }
+ };
+ Physics.prototype.updateVerlet = // Updates the vertex position
+ function () {
+ for(var i = 0; i < this.vertexCount; i++) {
+ var v = this.vertices[i];
+ var temp = v.position;
+ //v.position.mutableAdd(
+ //v.position += v.position - v.oldPosition + v.acceleration * this.timestep * this.timestep;
+ }
+ };
+ Physics.prototype.updateEdges = function () {
+ };
+ Physics.prototype.iterateCollisions = function () {
+ };
+ Physics.prototype.detectCollision = function (body1, body2) {
+ };
+ Physics.prototype.processCollision = function () {
+ };
+ Physics.prototype.intervalDistance = function (minA, maxA, minB, maxB) {
+ };
+ Physics.prototype.bodiesOverlap = function (body1, body2) {
+ };
+ Physics.prototype.update = // CollisionInfo
+ // depth, normal, edge, vertex
+ function () {
+ };
+ Physics.prototype.render = function () {
+ };
+ Physics.prototype.addBody = function (body) {
+ this.bodies.push(body);
+ this.bodyCount = this.bodies.length;
+ };
+ Physics.prototype.addEdge = function (edge) {
+ this.edges.push(edge);
+ this.edgeCount = this.edges.length;
+ };
+ Physics.prototype.addVertex = function (vertex) {
+ this.vertices.push(vertex);
+ this.vertexCount = this.vertices.length;
+ };
+ Physics.prototype.findVertex = function (x, y) {
+ };
+ return Physics;
+})();
+var PhysicsBody = (function () {
+ function PhysicsBody() {
+ this.vertices = [];
+ this.edges = [];
+ }
+ PhysicsBody.prototype.addEdge = function (edge) {
+ };
+ PhysicsBody.prototype.addVertex = function (vertex) {
+ };
+ PhysicsBody.prototype.projectToAxis = function (axis, min, max) {
+ };
+ PhysicsBody.prototype.calculateCenter = function () {
+ };
+ PhysicsBody.prototype.createBox = function (x, y, width, height) {
+ };
+ return PhysicsBody;
+})();
+var Vertex = (function () {
+ function Vertex(body, posX, posY) {
+ }
+ return Vertex;
+})();
+var Edge = (function () {
+ function Edge(body, pV1, pV2, pBoundary) {
+ }
+ return Edge;
+})();
+(function () {
+ var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update, render);
+ function init() {
+ myGame.loader.addImageFile('atari1', 'assets/sprites/atari130xe.png');
+ myGame.loader.load();
+ }
+ function create() {
+ var p = new Physics();
+ //p.max_bodies
+ }
+ function update() {
+ }
+ function render() {
+ //myGame.stage.context.strokeStyle = 'rgb(0,255,0)';
+ //myGame.stage.context.beginPath();
+ //myGame.stage.context.moveTo(poly1.points[0].x + poly1.pos.x, poly1.points[0].y + poly1.pos.y);
+ //for (var i = 1; i < poly1.points.length; i++)
+ //{
+ // myGame.stage.context.lineTo(poly1.points[i].x + poly1.pos.x, poly1.points[i].y + poly1.pos.y);
+ //}
+ //myGame.stage.context.lineTo(poly1.points[0].x + poly1.pos.x, poly1.points[0].y + poly1.pos.y);
+ //myGame.stage.context.stroke();
+ //myGame.stage.context.closePath();
+ }
+})();
diff --git a/Tests/physics/temp1.ts b/Tests/physics/temp1.ts
new file mode 100644
index 00000000..bd379200
--- /dev/null
+++ b/Tests/physics/temp1.ts
@@ -0,0 +1,200 @@
+///
+
+class Physics {
+
+ constructor() {
+
+ this.vertices = [];
+ this.edges = [];
+ this.bodies = [];
+
+ }
+
+ public gravity: Phaser.Vector2;
+
+ public max_bodies: number = 512;
+ public max_vertices: number = 1024;
+ public max_edges: number = 1024;
+ public max_body_vertices: number = 64;
+ public max_body_edges: number = 64;
+
+ public bodyCount: number;
+ public vertexCount: number;
+ public edgeCount: number;
+ public timestep: number;
+ public iterations;
+
+ public vertices: Vertex[];
+ public edges: Edge[];
+ public bodies: PhysicsBody[];
+
+ // Sets the force on each vertex to the gravity force. You could of course apply other forces like magnetism etc.
+ public updateForces() {
+
+ for (var i:number = 0; i < this.vertexCount; i++)
+ {
+ this.vertices[i].acceleration = this.gravity;
+ }
+ }
+
+ // Updates the vertex position
+ public updateVerlet() {
+
+ for (var i:number = 0; i < this.vertexCount; i++)
+ {
+ var v:Vertex = this.vertices[i];
+ var temp: Phaser.Vector2 = v.position;
+ //v.position.mutableAdd(
+ //v.position += v.position - v.oldPosition + v.acceleration * this.timestep * this.timestep;
+ }
+
+ }
+
+ public updateEdges() {
+ }
+
+ public iterateCollisions() {
+ }
+
+ public detectCollision(body1, body2) {
+ }
+
+ public processCollision() {
+ }
+
+ public intervalDistance(minA, maxA, minB, maxB) {
+ }
+
+ public bodiesOverlap(body1, body2) {
+ }
+
+ // CollisionInfo
+ // depth, normal, edge, vertex
+
+ public update() {
+ }
+
+ public render() {
+ }
+
+ public addBody(body:PhysicsBody) {
+ this.bodies.push(body);
+ this.bodyCount = this.bodies.length;
+ }
+
+ public addEdge(edge:Edge) {
+ this.edges.push(edge);
+ this.edgeCount = this.edges.length;
+ }
+
+ public addVertex(vertex:Vertex) {
+ this.vertices.push(vertex);
+ this.vertexCount = this.vertices.length;
+ }
+
+ public findVertex(x, y) {
+ }
+
+}
+
+class PhysicsBody {
+
+ constructor() {
+ }
+
+ center: Phaser.Vector2;
+ minX;
+ minY;
+ maxX;
+ maxY;
+ vertextCount;
+ edgeCount;
+
+ vertices = [];
+ edges = [];
+
+ public addEdge(edge) {
+ }
+
+ public addVertex(vertex) {
+
+ }
+
+ public projectToAxis(axis, min, max) {
+ }
+
+ public calculateCenter() {
+ }
+
+ public createBox(x, y, width, height) {
+ }
+
+}
+
+class Vertex {
+
+ constructor(body, posX, posY) {
+ }
+
+ position: Phaser.Vector2;
+ oldPosition: Phaser.Vector2;
+ acceleration: Phaser.Vector2;
+ parent: PhysicsBody;
+}
+
+class Edge {
+
+ constructor(body, pV1, pV2, pBoundary) {
+ }
+
+ v1: Vertex;
+ v2: Vertex;
+ length;
+ boundary;
+ parent: PhysicsBody;
+
+}
+
+(function () {
+
+
+ var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update, render);
+
+ function init() {
+
+ myGame.loader.addImageFile('atari1', 'assets/sprites/atari130xe.png');
+ myGame.loader.load();
+
+ }
+
+ function create() {
+
+ var p = new Physics();
+ //p.max_bodies
+
+ }
+
+ function update() {
+
+
+ }
+
+ function render() {
+
+ //myGame.stage.context.strokeStyle = 'rgb(0,255,0)';
+ //myGame.stage.context.beginPath();
+ //myGame.stage.context.moveTo(poly1.points[0].x + poly1.pos.x, poly1.points[0].y + poly1.pos.y);
+
+ //for (var i = 1; i < poly1.points.length; i++)
+ //{
+ // myGame.stage.context.lineTo(poly1.points[i].x + poly1.pos.x, poly1.points[i].y + poly1.pos.y);
+ //}
+
+ //myGame.stage.context.lineTo(poly1.points[0].x + poly1.pos.x, poly1.points[0].y + poly1.pos.y);
+
+ //myGame.stage.context.stroke();
+ //myGame.stage.context.closePath();
+
+ }
+
+})();
diff --git a/Tests/physics/temp2.js b/Tests/physics/temp2.js
new file mode 100644
index 00000000..6eaf2b5e
--- /dev/null
+++ b/Tests/physics/temp2.js
@@ -0,0 +1,1218 @@
+///
+var NPhysics = (function () {
+ function NPhysics() {
+ this.grav = 0.2;
+ this.drag = 1;
+ this.bounce = 0.3;
+ this.friction = 0.05;
+ this.min_f = 0;
+ this.max_f = 1;
+ this.min_b = 0;
+ this.max_b = 1;
+ this.min_g = 0;
+ this.max_g = 1;
+ this.xmin = 0;
+ this.xmax = 800;
+ this.ymin = 0;
+ this.ymax = 600;
+ this.objrad = 24;
+ this.tilerad = 24 * 2;
+ this.objspeed = 0.2;
+ this.maxspeed = 20;
+ }
+ NPhysics.prototype.update = function () {
+ // demoObj.Verlet();
+ // demoObj.CollideVsWorldBounds();
+ };
+ return NPhysics;
+})();
+var AABB = (function () {
+ function AABB(pos, xw, yw) {
+ this.type = 0;
+ this.pos = pos.clone();
+ this.oldpos = pos.clone();
+ this.xw = Math.abs(xw);
+ this.yw = Math.abs(yw);
+ }
+ return AABB;
+})();
+var TileMapCell = (function () {
+ function TileMapCell(x, y, xw, yw) {
+ this.ID = TileMapCell.TID_EMPTY//all tiles start empty
+ ;
+ this.CTYPE = TileMapCell.CTYPE_EMPTY;
+ this.pos = new Phaser.Vector2(x, y)//setup collision properties
+ ;
+ this.xw = xw;
+ this.yw = yw;
+ this.minx = this.pos.x - this.xw;
+ this.maxx = this.pos.x + this.xw;
+ this.miny = this.pos.y - this.yw;
+ this.maxy = this.pos.y + this.yw;
+ //this stores tile-specific collision information
+ this.signx = 0;
+ this.signy = 0;
+ this.sx = 0;
+ this.sy = 0;
+ }
+ TileMapCell.TID_EMPTY = 0;
+ TileMapCell.TID_FULL = 1;
+ TileMapCell.TID_45DEGpn = 2;
+ TileMapCell.TID_45DEGnn = 3;
+ TileMapCell.TID_45DEGnp = 4;
+ TileMapCell.TID_45DEGpp = 5;
+ TileMapCell.TID_CONCAVEpn = 6;
+ TileMapCell.TID_CONCAVEnn = 7;
+ TileMapCell.TID_CONCAVEnp = 8;
+ TileMapCell.TID_CONCAVEpp = 9;
+ TileMapCell.TID_CONVEXpn = 10;
+ TileMapCell.TID_CONVEXnn = 11;
+ TileMapCell.TID_CONVEXnp = 12;
+ TileMapCell.TID_CONVEXpp = 13;
+ TileMapCell.TID_22DEGpnS = 14;
+ TileMapCell.TID_22DEGnnS = 15;
+ TileMapCell.TID_22DEGnpS = 16;
+ TileMapCell.TID_22DEGppS = 17;
+ TileMapCell.TID_22DEGpnB = 18;
+ TileMapCell.TID_22DEGnnB = 19;
+ TileMapCell.TID_22DEGnpB = 20;
+ TileMapCell.TID_22DEGppB = 21;
+ TileMapCell.TID_67DEGpnS = 22;
+ TileMapCell.TID_67DEGnnS = 23;
+ TileMapCell.TID_67DEGnpS = 24;
+ TileMapCell.TID_67DEGppS = 25;
+ TileMapCell.TID_67DEGpnB = 26;
+ TileMapCell.TID_67DEGnnB = 27;
+ TileMapCell.TID_67DEGnpB = 28;
+ TileMapCell.TID_67DEGppB = 29;
+ TileMapCell.TID_HALFd = 30;
+ TileMapCell.TID_HALFr = 31;
+ TileMapCell.TID_HALFu = 32;
+ TileMapCell.TID_HALFl = 33;
+ TileMapCell.CTYPE_EMPTY = 0;
+ TileMapCell.CTYPE_FULL = 1;
+ TileMapCell.CTYPE_45DEG = 2;
+ TileMapCell.CTYPE_CONCAVE = 6;
+ TileMapCell.CTYPE_CONVEX = 10;
+ TileMapCell.CTYPE_22DEGs = 14;
+ TileMapCell.CTYPE_22DEGb = 18;
+ TileMapCell.CTYPE_67DEGs = 22;
+ TileMapCell.CTYPE_67DEGb = 26;
+ TileMapCell.CTYPE_HALF = 30;
+ TileMapCell.prototype.SetState = //these functions are used to update the cell
+ //note: ID is assumed to NOT be "empty" state..
+ //if it IS the empty state, the tile clears itself
+ function (ID) {
+ if(ID == TileMapCell.TID_EMPTY) {
+ this.Clear();
+ } else {
+ //set tile state to a non-emtpy value, and update it's edges and those of the neighbors
+ this.ID = ID;
+ this.UpdateType();
+ //this.Draw();
+ }
+ };
+ TileMapCell.prototype.Clear = function () {
+ //tile was on, turn it off
+ this.ID = TileMapCell.TID_EMPTY;
+ this.UpdateType();
+ //this.Draw();
+ };
+ TileMapCell.prototype.render = function (context) {
+ context.beginPath();
+ context.strokeStyle = 'rgb(255,255,0)';
+ context.strokeRect(this.minx, this.miny, this.xw * 2, this.yw * 2);
+ context.strokeRect(this.pos.x, this.pos.y, 2, 2);
+ context.closePath();
+ };
+ TileMapCell.prototype.UpdateType = //this converts a tile from implicitly-defined (via ID), to explicit (via properties)
+ function () {
+ if(0 < this.ID) {
+ //tile is non-empty; collide
+ if(this.ID < TileMapCell.CTYPE_45DEG) {
+ //TID_FULL
+ this.CTYPE = TileMapCell.CTYPE_FULL;
+ this.signx = 0;
+ this.signy = 0;
+ this.sx = 0;
+ this.sy = 0;
+ } else if(this.ID < TileMapCell.CTYPE_CONCAVE) {
+ //45deg
+ this.CTYPE = TileMapCell.CTYPE_45DEG;
+ if(this.ID == TileMapCell.TID_45DEGpn) {
+ console.log('set tile as 45deg pn');
+ this.signx = 1;
+ this.signy = -1;
+ this.sx = this.signx / Math.SQRT2//get slope _unit_ normal
+ ;
+ this.sy = this.signy / Math.SQRT2//since normal is (1,-1), length is sqrt(1*1 + -1*-1) = sqrt(2)
+ ;
+ } else if(this.ID == TileMapCell.TID_45DEGnn) {
+ this.signx = -1;
+ this.signy = -1;
+ this.sx = this.signx / Math.SQRT2//get slope _unit_ normal
+ ;
+ this.sy = this.signy / Math.SQRT2//since normal is (1,-1), length is sqrt(1*1 + -1*-1) = sqrt(2)
+ ;
+ } else if(this.ID == TileMapCell.TID_45DEGnp) {
+ this.signx = -1;
+ this.signy = 1;
+ this.sx = this.signx / Math.SQRT2//get slope _unit_ normal
+ ;
+ this.sy = this.signy / Math.SQRT2//since normal is (1,-1), length is sqrt(1*1 + -1*-1) = sqrt(2)
+ ;
+ } else if(this.ID == TileMapCell.TID_45DEGpp) {
+ this.signx = 1;
+ this.signy = 1;
+ this.sx = this.signx / Math.SQRT2//get slope _unit_ normal
+ ;
+ this.sy = this.signy / Math.SQRT2//since normal is (1,-1), length is sqrt(1*1 + -1*-1) = sqrt(2)
+ ;
+ } else {
+ //trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
+ return false;
+ }
+ } else if(this.ID < TileMapCell.CTYPE_CONVEX) {
+ //concave
+ this.CTYPE = TileMapCell.CTYPE_CONCAVE;
+ if(this.ID == TileMapCell.TID_CONCAVEpn) {
+ this.signx = 1;
+ this.signy = -1;
+ this.sx = 0;
+ this.sy = 0;
+ } else if(this.ID == TileMapCell.TID_CONCAVEnn) {
+ this.signx = -1;
+ this.signy = -1;
+ this.sx = 0;
+ this.sy = 0;
+ } else if(this.ID == TileMapCell.TID_CONCAVEnp) {
+ this.signx = -1;
+ this.signy = 1;
+ this.sx = 0;
+ this.sy = 0;
+ } else if(this.ID == TileMapCell.TID_CONCAVEpp) {
+ this.signx = 1;
+ this.signy = 1;
+ this.sx = 0;
+ this.sy = 0;
+ } else {
+ //trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
+ return false;
+ }
+ } else if(this.ID < TileMapCell.CTYPE_22DEGs) {
+ //convex
+ this.CTYPE = TileMapCell.CTYPE_CONVEX;
+ if(this.ID == TileMapCell.TID_CONVEXpn) {
+ this.signx = 1;
+ this.signy = -1;
+ this.sx = 0;
+ this.sy = 0;
+ } else if(this.ID == TileMapCell.TID_CONVEXnn) {
+ this.signx = -1;
+ this.signy = -1;
+ this.sx = 0;
+ this.sy = 0;
+ } else if(this.ID == TileMapCell.TID_CONVEXnp) {
+ this.signx = -1;
+ this.signy = 1;
+ this.sx = 0;
+ this.sy = 0;
+ } else if(this.ID == TileMapCell.TID_CONVEXpp) {
+ this.signx = 1;
+ this.signy = 1;
+ this.sx = 0;
+ this.sy = 0;
+ } else {
+ //trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
+ return false;
+ }
+ } else if(this.ID < TileMapCell.CTYPE_22DEGb) {
+ //22deg small
+ this.CTYPE = TileMapCell.CTYPE_22DEGs;
+ if(this.ID == TileMapCell.TID_22DEGpnS) {
+ this.signx = 1;
+ this.signy = -1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 1) / slen;
+ this.sy = (this.signy * 2) / slen;
+ } else if(this.ID == TileMapCell.TID_22DEGnnS) {
+ this.signx = -1;
+ this.signy = -1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 1) / slen;
+ this.sy = (this.signy * 2) / slen;
+ } else if(this.ID == TileMapCell.TID_22DEGnpS) {
+ this.signx = -1;
+ this.signy = 1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 1) / slen;
+ this.sy = (this.signy * 2) / slen;
+ } else if(this.ID == TileMapCell.TID_22DEGppS) {
+ this.signx = 1;
+ this.signy = 1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 1) / slen;
+ this.sy = (this.signy * 2) / slen;
+ } else {
+ //trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
+ return false;
+ }
+ } else if(this.ID < TileMapCell.CTYPE_67DEGs) {
+ //22deg big
+ this.CTYPE = TileMapCell.CTYPE_22DEGb;
+ if(this.ID == TileMapCell.TID_22DEGpnB) {
+ this.signx = 1;
+ this.signy = -1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 1) / slen;
+ this.sy = (this.signy * 2) / slen;
+ } else if(this.ID == TileMapCell.TID_22DEGnnB) {
+ this.signx = -1;
+ this.signy = -1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 1) / slen;
+ this.sy = (this.signy * 2) / slen;
+ } else if(this.ID == TileMapCell.TID_22DEGnpB) {
+ this.signx = -1;
+ this.signy = 1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 1) / slen;
+ this.sy = (this.signy * 2) / slen;
+ } else if(this.ID == TileMapCell.TID_22DEGppB) {
+ this.signx = 1;
+ this.signy = 1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 1) / slen;
+ this.sy = (this.signy * 2) / slen;
+ } else {
+ //trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
+ return false;
+ }
+ } else if(this.ID < TileMapCell.CTYPE_67DEGb) {
+ //67deg small
+ this.CTYPE = TileMapCell.CTYPE_67DEGs;
+ if(this.ID == TileMapCell.TID_67DEGpnS) {
+ this.signx = 1;
+ this.signy = -1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 2) / slen;
+ this.sy = (this.signy * 1) / slen;
+ } else if(this.ID == TileMapCell.TID_67DEGnnS) {
+ this.signx = -1;
+ this.signy = -1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 2) / slen;
+ this.sy = (this.signy * 1) / slen;
+ } else if(this.ID == TileMapCell.TID_67DEGnpS) {
+ this.signx = -1;
+ this.signy = 1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 2) / slen;
+ this.sy = (this.signy * 1) / slen;
+ } else if(this.ID == TileMapCell.TID_67DEGppS) {
+ this.signx = 1;
+ this.signy = 1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 2) / slen;
+ this.sy = (this.signy * 1) / slen;
+ } else {
+ //trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
+ return false;
+ }
+ } else if(this.ID < TileMapCell.CTYPE_HALF) {
+ //67deg big
+ this.CTYPE = TileMapCell.CTYPE_67DEGb;
+ if(this.ID == TileMapCell.TID_67DEGpnB) {
+ this.signx = 1;
+ this.signy = -1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 2) / slen;
+ this.sy = (this.signy * 1) / slen;
+ } else if(this.ID == TileMapCell.TID_67DEGnnB) {
+ this.signx = -1;
+ this.signy = -1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 2) / slen;
+ this.sy = (this.signy * 1) / slen;
+ } else if(this.ID == TileMapCell.TID_67DEGnpB) {
+ this.signx = -1;
+ this.signy = 1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 2) / slen;
+ this.sy = (this.signy * 1) / slen;
+ } else if(this.ID == TileMapCell.TID_67DEGppB) {
+ this.signx = 1;
+ this.signy = 1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 2) / slen;
+ this.sy = (this.signy * 1) / slen;
+ } else {
+ //trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
+ return false;
+ }
+ } else {
+ //half-full tile
+ this.CTYPE = TileMapCell.CTYPE_HALF;
+ if(this.ID == TileMapCell.TID_HALFd) {
+ this.signx = 0;
+ this.signy = -1;
+ this.sx = this.signx;
+ this.sy = this.signy;
+ } else if(this.ID == TileMapCell.TID_HALFu) {
+ this.signx = 0;
+ this.signy = 1;
+ this.sx = this.signx;
+ this.sy = this.signy;
+ } else if(this.ID == TileMapCell.TID_HALFl) {
+ this.signx = 1;
+ this.signy = 0;
+ this.sx = this.signx;
+ this.sy = this.signy;
+ } else if(this.ID == TileMapCell.TID_HALFr) {
+ this.signx = -1;
+ this.signy = 0;
+ this.sx = this.signx;
+ this.sy = this.signy;
+ } else {
+ //trace("BAAD TILE!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
+ return false;
+ }
+ }
+ } else {
+ //TID_EMPTY
+ this.CTYPE = TileMapCell.CTYPE_EMPTY;
+ this.signx = 0;
+ this.signy = 0;
+ this.sx = 0;
+ this.sy = 0;
+ }
+ };
+ return TileMapCell;
+})();
+var Circle = (function () {
+ function Circle(x, y, radius) {
+ this.type = 1;
+ this.pos = new Phaser.Vector2(x, y);
+ this.oldpos = this.pos.clone();
+ this.radius = radius;
+ this.circleTileProjections = {
+ }//hash object to hold tile-specific collision functions
+ ;
+ this.circleTileProjections[TileMapCell.CTYPE_FULL] = this.ProjCircle_Full;
+ this.circleTileProjections[TileMapCell.CTYPE_45DEG] = this.ProjCircle_45Deg;
+ this.circleTileProjections[TileMapCell.CTYPE_CONCAVE] = this.ProjCircle_Concave;
+ this.circleTileProjections[TileMapCell.CTYPE_CONVEX] = this.ProjCircle_Convex;
+ //Proj_CircleTile[CTYPE_22DEGs] = ProjCircle_22DegS;
+ //Proj_CircleTile[CTYPE_22DEGb] = ProjCircle_22DegB;
+ //Proj_CircleTile[CTYPE_67DEGs] = ProjCircle_67DegS;
+ //Proj_CircleTile[CTYPE_67DEGb] = ProjCircle_67DegB;
+ //Proj_CircleTile[CTYPE_HALF] = ProjCircle_Half;
+ }
+ Circle.prototype.IntegrateVerlet = function () {
+ //var d = DRAG;
+ //var g = GRAV;
+ var d = 1;
+ var g = 0.2;
+ var p = this.pos;
+ var o = this.oldpos;
+ var px, py;
+ var ox = o.x;//we can't swap buffers since mcs/sticks point directly to vector2s..
+
+ var oy = o.y;
+ o.x = px = p.x//get vector values
+ ;
+ o.y = py = p.y//p = position
+ ;
+ //o = oldposition
+ //integrate
+ p.x += (d * px) - (d * ox);
+ p.y += (d * py) - (d * oy) + g;
+ };
+ Circle.prototype.ReportCollisionVsWorld = function (px, py, dx, dy, obj) {
+ var p = this.pos;
+ var o = this.oldpos;
+ //calc velocity
+ var vx = p.x - o.x;
+ var vy = p.y - o.y;
+ //find component of velocity parallel to collision normal
+ var dp = (vx * dx + vy * dy);
+ var nx = dp * dx;//project velocity onto collision normal
+
+ var ny = dp * dy;//nx,ny is normal velocity
+
+ var tx = vx - nx;//px,py is tangent velocity
+
+ var ty = vy - ny;
+ //we only want to apply collision response forces if the object is travelling into, and not out of, the collision
+ var b, bx, by, f, fx, fy;
+ if(dp < 0) {
+ //f = FRICTION;
+ f = 0.05;
+ fx = tx * f;
+ fy = ty * f;
+ //b = 1 + BOUNCE;//this bounce constant should be elsewhere, i.e inside the object/tile/etc..
+ b = 1 + 0.3//this bounce constant should be elsewhere, i.e inside the object/tile/etc..
+ ;
+ bx = (nx * b);
+ by = (ny * b);
+ } else {
+ //moving out of collision, do not apply forces
+ bx = by = fx = fy = 0;
+ }
+ p.x += px//project object out of collision
+ ;
+ p.y += py;
+ o.x += px + bx + fx//apply bounce+friction impulses which alter velocity
+ ;
+ o.y += py + by + fy;
+ };
+ Circle.prototype.CollideCircleVsWorldBounds = function () {
+ var p = this.pos;
+ var r = this.radius;
+ var XMIN = 0;
+ var XMAX = 800;
+ var YMIN = 0;
+ var YMAX = 600;
+ //collide vs. x-bounds
+ //test XMIN
+ var dx = XMIN - (p.x - r);
+ if(0 < dx) {
+ //object is colliding with XMIN
+ this.ReportCollisionVsWorld(dx, 0, 1, 0, null);
+ } else {
+ //test XMAX
+ dx = (p.x + r) - XMAX;
+ if(0 < dx) {
+ //object is colliding with XMAX
+ this.ReportCollisionVsWorld(-dx, 0, -1, 0, null);
+ }
+ }
+ //collide vs. y-bounds
+ //test YMIN
+ var dy = YMIN - (p.y - r);
+ if(0 < dy) {
+ //object is colliding with YMIN
+ this.ReportCollisionVsWorld(0, dy, 0, 1, null);
+ } else {
+ //test YMAX
+ dy = (p.y + r) - YMAX;
+ if(0 < dy) {
+ //object is colliding with YMAX
+ this.ReportCollisionVsWorld(0, -dy, 0, -1, null);
+ }
+ }
+ };
+ Circle.prototype.render = function (context) {
+ context.beginPath();
+ context.strokeStyle = 'rgb(0,255,0)';
+ context.arc(this.pos.x, this.pos.y, this.radius, 0, Math.PI * 2);
+ context.stroke();
+ context.closePath();
+ if(this.oH == 1) {
+ context.beginPath();
+ context.strokeStyle = 'rgb(255,0,0)';
+ context.moveTo(this.pos.x - this.radius, this.pos.y - this.radius);
+ context.lineTo(this.pos.x - this.radius, this.pos.y + this.radius);
+ context.stroke();
+ context.closePath();
+ } else if(this.oH == -1) {
+ context.beginPath();
+ context.strokeStyle = 'rgb(255,0,0)';
+ context.moveTo(this.pos.x + this.radius, this.pos.y - this.radius);
+ context.lineTo(this.pos.x + this.radius, this.pos.y + this.radius);
+ context.stroke();
+ context.closePath();
+ }
+ if(this.oV == 1) {
+ context.beginPath();
+ context.strokeStyle = 'rgb(255,0,0)';
+ context.moveTo(this.pos.x - this.radius, this.pos.y - this.radius);
+ context.lineTo(this.pos.x + this.radius, this.pos.y - this.radius);
+ context.stroke();
+ context.closePath();
+ } else if(this.oV == -1) {
+ context.beginPath();
+ context.strokeStyle = 'rgb(255,0,0)';
+ context.moveTo(this.pos.x - this.radius, this.pos.y + this.radius);
+ context.lineTo(this.pos.x + this.radius, this.pos.y + this.radius);
+ context.stroke();
+ context.closePath();
+ }
+ };
+ Circle.prototype.CollideCircleVsTile = function (tile) {
+ var pos = this.pos;
+ var r = this.radius;
+ var c = tile;
+ var tx = c.pos.x;
+ var ty = c.pos.y;
+ var txw = c.xw;
+ var tyw = c.yw;
+ var dx = pos.x - tx;//tile->obj delta
+
+ var px = (txw + r) - Math.abs(dx);//penetration depth in x
+
+ if(0 < px) {
+ var dy = pos.y - ty;//tile->obj delta
+
+ var py = (tyw + r) - Math.abs(dy);//pen depth in y
+
+ if(0 < py) {
+ //object may be colliding with tile
+ //determine grid/voronoi region of circle center
+ this.oH = 0;
+ this.oV = 0;
+ if(dx < -txw) {
+ //circle is on left side of tile
+ this.oH = -1;
+ } else if(txw < dx) {
+ //circle is on right side of tile
+ this.oH = 1;
+ }
+ if(dy < -tyw) {
+ //circle is on top side of tile
+ this.oV = -1;
+ } else if(tyw < dy) {
+ //circle is on bottom side of tile
+ this.oV = 1;
+ }
+ this.ResolveCircleTile(px, py, this.oH, this.oV, this, c);
+ }
+ }
+ };
+ Circle.prototype.ResolveCircleTile = function (x, y, oH, oV, obj, t) {
+ if(0 < t.ID) {
+ return this.circleTileProjections[t.CTYPE](x, y, oH, oV, obj, t);
+ } else {
+ console.log("ResolveCircleTile() was called with an empty (or unknown) tile!: ID=" + t.ID + " (" + t.i + "," + t.j + ")");
+ return false;
+ }
+ };
+ Circle.COL_NONE = 0;
+ Circle.COL_AXIS = 1;
+ Circle.COL_OTHER = 2;
+ Circle.prototype.ProjCircle_Full = function (x, y, oH, oV, obj, t) {
+ //if we're colliding vs. the current cell, we need to project along the
+ //smallest penetration vector.
+ //if we're colliding vs. horiz. or vert. neighb, we simply project horiz/vert
+ //if we're colliding diagonally, we need to collide vs. tile corner
+ if(oH == 0) {
+ if(oV == 0) {
+ //collision with current cell
+ if(x < y) {
+ //penetration in x is smaller; project in x
+ var dx = obj.pos.x - t.pos.x;//get sign for projection along x-axis
+
+ //NOTE: should we handle the delta == 0 case?! and how? (project towards oldpos?)
+ if(dx < 0) {
+ obj.ReportCollisionVsWorld(-x, 0, -1, 0, t);
+ return Circle.COL_AXIS;
+ } else {
+ obj.ReportCollisionVsWorld(x, 0, 1, 0, t);
+ return Circle.COL_AXIS;
+ }
+ } else {
+ //penetration in y is smaller; project in y
+ var dy = obj.pos.y - t.pos.y;//get sign for projection along y-axis
+
+ //NOTE: should we handle the delta == 0 case?! and how? (project towards oldpos?)
+ if(dy < 0) {
+ obj.ReportCollisionVsWorld(0, -y, 0, -1, t);
+ return Circle.COL_AXIS;
+ } else {
+ obj.ReportCollisionVsWorld(0, y, 0, 1, t);
+ return Circle.COL_AXIS;
+ }
+ }
+ } else {
+ //collision with vertical neighbor
+ obj.ReportCollisionVsWorld(0, y * oV, 0, oV, t);
+ return Circle.COL_AXIS;
+ }
+ } else if(oV == 0) {
+ //collision with horizontal neighbor
+ obj.ReportCollisionVsWorld(x * oH, 0, oH, 0, t);
+ return Circle.COL_AXIS;
+ } else {
+ //diagonal collision
+ //get diag vertex position
+ var vx = t.pos.x + (oH * t.xw);
+ var vy = t.pos.y + (oV * t.yw);
+ var dx = obj.pos.x - vx;//calc vert->circle vector
+
+ var dy = obj.pos.y - vy;
+ var len = Math.sqrt(dx * dx + dy * dy);
+ var pen = obj.radius - len;
+ if(0 < pen) {
+ //vertex is in the circle; project outward
+ if(len == 0) {
+ //project out by 45deg
+ dx = oH / Math.SQRT2;
+ dy = oV / Math.SQRT2;
+ } else {
+ dx /= len;
+ dy /= len;
+ }
+ obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
+ return Circle.COL_OTHER;
+ }
+ }
+ return Circle.COL_NONE;
+ };
+ Circle.prototype.ProjCircle_45Deg = function (x, y, oH, oV, obj, t) {
+ //if we're colliding diagonally:
+ // -if obj is in the diagonal pointed to by the slope normal: we can't collide, do nothing
+ // -else, collide vs. the appropriate vertex
+ //if obj is in this tile: perform collision as for aabb-ve-45deg
+ //if obj is horiz OR very neighb in direction of slope: collide only vs. slope
+ //if obj is horiz or vert neigh against direction of slope: collide vs. face
+ var signx = t.signx;
+ var signy = t.signy;
+ var lenP;
+ if(oH == 0) {
+ if(oV == 0) {
+ //colliding with current tile
+ var sx = t.sx;
+ var sy = t.sy;
+ var ox = (obj.pos.x - (sx * obj.radius)) - t.pos.x;//this gives is the coordinates of the innermost
+
+ var oy = (obj.pos.y - (sy * obj.radius)) - t.pos.y;//point on the circle, relative to the tile center
+
+ //if the dotprod of (ox,oy) and (sx,sy) is negative, the innermost point is in the slope
+ //and we need toproject it out by the magnitude of the projection of (ox,oy) onto (sx,sy)
+ var dp = (ox * sx) + (oy * sy);
+ if(dp < 0) {
+ //collision; project delta onto slope and use this as the slope penetration vector
+ sx *= -dp//(sx,sy) is now the penetration vector
+ ;
+ sy *= -dp;
+ //find the smallest axial projection vector
+ if(x < y) {
+ //penetration in x is smaller
+ lenP = x;
+ y = 0;
+ //get sign for projection along x-axis
+ if((obj.pos.x - t.pos.x) < 0) {
+ x *= -1;
+ }
+ } else {
+ //penetration in y is smaller
+ lenP = y;
+ x = 0;
+ //get sign for projection along y-axis
+ if((obj.pos.y - t.pos.y) < 0) {
+ y *= -1;
+ }
+ }
+ var lenN = Math.sqrt(sx * sx + sy * sy);
+ if(lenP < lenN) {
+ obj.ReportCollisionVsWorld(x, y, x / lenP, y / lenP, t);
+ return Circle.COL_AXIS;
+ } else {
+ obj.ReportCollisionVsWorld(sx, sy, t.sx, t.sy, t);
+ return Circle.COL_OTHER;
+ }
+ }
+ } else {
+ //colliding vertically
+ if((signy * oV) < 0) {
+ //colliding with face/edge
+ obj.ReportCollisionVsWorld(0, y * oV, 0, oV, t);
+ return Circle.COL_AXIS;
+ } else {
+ //we could only be colliding vs the slope OR a vertex
+ //look at the vector form the closest vert to the circle to decide
+ var sx = t.sx;
+ var sy = t.sy;
+ var ox = obj.pos.x - (t.pos.x - (signx * t.xw));//this gives is the coordinates of the innermost
+
+ var oy = obj.pos.y - (t.pos.y + (oV * t.yw));//point on the circle, relative to the closest tile vert
+
+ //if the component of (ox,oy) parallel to the normal's righthand normal
+ //has the same sign as the slope of the slope (the sign of the slope's slope is signx*signy)
+ //then we project by the vertex, otherwise by the normal.
+ //note that this is simply a VERY tricky/weird method of determining
+ //if the circle is in side the slope/face's voronoi region, or that of the vertex.
+ var perp = (ox * -sy) + (oy * sx);
+ if(0 < (perp * signx * signy)) {
+ //collide vs. vertex
+ var len = Math.sqrt(ox * ox + oy * oy);
+ var pen = obj.radius - len;
+ if(0 < pen) {
+ //note: if len=0, then perp=0 and we'll never reach here, so don't worry about div-by-0
+ ox /= len;
+ oy /= len;
+ obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
+ return Circle.COL_OTHER;
+ }
+ } else {
+ //collide vs. slope
+ //if the component of (ox,oy) parallel to the normal is less than the circle radius, we're
+ //penetrating the slope. note that this method of penetration calculation doesn't hold
+ //in general (i.e it won't work if the circle is in the slope), but works in this case
+ //because we know the circle is in a neighboring cell
+ var dp = (ox * sx) + (oy * sy);
+ var pen = obj.radius - Math.abs(dp);//note: we don't need the abs because we know the dp will be positive, but just in case..
+
+ if(0 < pen) {
+ //collision; circle out along normal by penetration amount
+ obj.ReportCollisionVsWorld(sx * pen, sy * pen, sx, sy, t);
+ return Circle.COL_OTHER;
+ }
+ }
+ }
+ }
+ } else if(oV == 0) {
+ //colliding horizontally
+ if((signx * oH) < 0) {
+ //colliding with face/edge
+ obj.ReportCollisionVsWorld(x * oH, 0, oH, 0, t);
+ return Circle.COL_AXIS;
+ } else {
+ //we could only be colliding vs the slope OR a vertex
+ //look at the vector form the closest vert to the circle to decide
+ var sx = t.sx;
+ var sy = t.sy;
+ var ox = obj.pos.x - (t.pos.x + (oH * t.xw));//this gives is the coordinates of the innermost
+
+ var oy = obj.pos.y - (t.pos.y - (signy * t.yw));//point on the circle, relative to the closest tile vert
+
+ //if the component of (ox,oy) parallel to the normal's righthand normal
+ //has the same sign as the slope of the slope (the sign of the slope's slope is signx*signy)
+ //then we project by the normal, otherwise by the vertex.
+ //(NOTE: this is the opposite logic of the vertical case;
+ // for vertical, if the perp prod and the slope's slope agree, it's outside.
+ // for horizontal, if the perp prod and the slope's slope agree, circle is inside.
+ // ..but this is only a property of flahs' coord system (i.e the rules might swap
+ // in righthanded systems))
+ //note that this is simply a VERY tricky/weird method of determining
+ //if the circle is in side the slope/face's voronio region, or that of the vertex.
+ var perp = (ox * -sy) + (oy * sx);
+ if((perp * signx * signy) < 0) {
+ //collide vs. vertex
+ var len = Math.sqrt(ox * ox + oy * oy);
+ var pen = obj.radius - len;
+ if(0 < pen) {
+ //note: if len=0, then perp=0 and we'll never reach here, so don't worry about div-by-0
+ ox /= len;
+ oy /= len;
+ obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
+ return Circle.COL_OTHER;
+ }
+ } else {
+ //collide vs. slope
+ //if the component of (ox,oy) parallel to the normal is less than the circle radius, we're
+ //penetrating the slope. note that this method of penetration calculation doesn't hold
+ //in general (i.e it won't work if the circle is in the slope), but works in this case
+ //because we know the circle is in a neighboring cell
+ var dp = (ox * sx) + (oy * sy);
+ var pen = obj.radius - Math.abs(dp);//note: we don't need the abs because we know the dp will be positive, but just in case..
+
+ if(0 < pen) {
+ //collision; circle out along normal by penetration amount
+ obj.ReportCollisionVsWorld(sx * pen, sy * pen, sx, sy, t);
+ return Circle.COL_OTHER;
+ }
+ }
+ }
+ } else {
+ //colliding diagonally
+ if(0 < ((signx * oH) + (signy * oV))) {
+ //the dotprod of slope normal and cell offset is strictly positive,
+ //therefore obj is in the diagonal neighb pointed at by the normal, and
+ //it cannot possibly reach/touch/penetrate the slope
+ return Circle.COL_NONE;
+ } else {
+ //collide vs. vertex
+ //get diag vertex position
+ var vx = t.pos.x + (oH * t.xw);
+ var vy = t.pos.y + (oV * t.yw);
+ var dx = obj.pos.x - vx;//calc vert->circle vector
+
+ var dy = obj.pos.y - vy;
+ var len = Math.sqrt(dx * dx + dy * dy);
+ var pen = obj.radius - len;
+ if(0 < pen) {
+ //vertex is in the circle; project outward
+ if(len == 0) {
+ //project out by 45deg
+ dx = oH / Math.SQRT2;
+ dy = oV / Math.SQRT2;
+ } else {
+ dx /= len;
+ dy /= len;
+ }
+ obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
+ return Circle.COL_OTHER;
+ }
+ }
+ }
+ return Circle.COL_NONE;
+ };
+ Circle.prototype.ProjCircle_Concave = function (x, y, oH, oV, obj, t) {
+ //if we're colliding diagonally:
+ // -if obj is in the diagonal pointed to by the slope normal: we can't collide, do nothing
+ // -else, collide vs. the appropriate vertex
+ //if obj is in this tile: perform collision as for aabb
+ //if obj is horiz OR very neighb in direction of slope: collide vs vert
+ //if obj is horiz or vert neigh against direction of slope: collide vs. face
+ var signx = t.signx;
+ var signy = t.signy;
+ var lenP;
+ if(oH == 0) {
+ if(oV == 0) {
+ //colliding with current tile
+ var ox = (t.pos.x + (signx * t.xw)) - obj.pos.x;//(ox,oy) is the vector from the circle to
+
+ var oy = (t.pos.y + (signy * t.yw)) - obj.pos.y;//tile-circle's center
+
+ var twid = t.xw * 2;
+ var trad = Math.sqrt(twid * twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
+
+ //note that this should be precomputed at compile-time since it's constant
+ var len = Math.sqrt(ox * ox + oy * oy);
+ var pen = (len + obj.radius) - trad;
+ if(0 < pen) {
+ //find the smallest axial projection vector
+ if(x < y) {
+ //penetration in x is smaller
+ lenP = x;
+ y = 0;
+ //get sign for projection along x-axis
+ if((obj.pos.x - t.pos.x) < 0) {
+ x *= -1;
+ }
+ } else {
+ //penetration in y is smaller
+ lenP = y;
+ x = 0;
+ //get sign for projection along y-axis
+ if((obj.pos.y - t.pos.y) < 0) {
+ y *= -1;
+ }
+ }
+ if(lenP < pen) {
+ obj.ReportCollisionVsWorld(x, y, x / lenP, y / lenP, t);
+ return Circle.COL_AXIS;
+ } else {
+ //we can assume that len >0, because if we're here then
+ //(len + obj.radius) > trad, and since obj.radius <= trad
+ //len MUST be > 0
+ ox /= len;
+ oy /= len;
+ obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
+ return Circle.COL_OTHER;
+ }
+ } else {
+ return Circle.COL_NONE;
+ }
+ } else {
+ //colliding vertically
+ if((signy * oV) < 0) {
+ //colliding with face/edge
+ obj.ReportCollisionVsWorld(0, y * oV, 0, oV, t);
+ return Circle.COL_AXIS;
+ } else {
+ //we could only be colliding vs the vertical tip
+ //get diag vertex position
+ var vx = t.pos.x - (signx * t.xw);
+ var vy = t.pos.y + (oV * t.yw);
+ var dx = obj.pos.x - vx;//calc vert->circle vector
+
+ var dy = obj.pos.y - vy;
+ var len = Math.sqrt(dx * dx + dy * dy);
+ var pen = obj.radius - len;
+ if(0 < pen) {
+ //vertex is in the circle; project outward
+ if(len == 0) {
+ //project out vertically
+ dx = 0;
+ dy = oV;
+ } else {
+ dx /= len;
+ dy /= len;
+ }
+ obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
+ return Circle.COL_OTHER;
+ }
+ }
+ }
+ } else if(oV == 0) {
+ //colliding horizontally
+ if((signx * oH) < 0) {
+ //colliding with face/edge
+ obj.ReportCollisionVsWorld(x * oH, 0, oH, 0, t);
+ return Circle.COL_AXIS;
+ } else {
+ //we could only be colliding vs the horizontal tip
+ //get diag vertex position
+ var vx = t.pos.x + (oH * t.xw);
+ var vy = t.pos.y - (signy * t.yw);
+ var dx = obj.pos.x - vx;//calc vert->circle vector
+
+ var dy = obj.pos.y - vy;
+ var len = Math.sqrt(dx * dx + dy * dy);
+ var pen = obj.radius - len;
+ if(0 < pen) {
+ //vertex is in the circle; project outward
+ if(len == 0) {
+ //project out horizontally
+ dx = oH;
+ dy = 0;
+ } else {
+ dx /= len;
+ dy /= len;
+ }
+ obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
+ return Circle.COL_OTHER;
+ }
+ }
+ } else {
+ //colliding diagonally
+ if(0 < ((signx * oH) + (signy * oV))) {
+ //the dotprod of slope normal and cell offset is strictly positive,
+ //therefore obj is in the diagonal neighb pointed at by the normal, and
+ //it cannot possibly reach/touch/penetrate the slope
+ return Circle.COL_NONE;
+ } else {
+ //collide vs. vertex
+ //get diag vertex position
+ var vx = t.pos.x + (oH * t.xw);
+ var vy = t.pos.y + (oV * t.yw);
+ var dx = obj.pos.x - vx;//calc vert->circle vector
+
+ var dy = obj.pos.y - vy;
+ var len = Math.sqrt(dx * dx + dy * dy);
+ var pen = obj.radius - len;
+ if(0 < pen) {
+ //vertex is in the circle; project outward
+ if(len == 0) {
+ //project out by 45deg
+ dx = oH / Math.SQRT2;
+ dy = oV / Math.SQRT2;
+ } else {
+ dx /= len;
+ dy /= len;
+ }
+ obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
+ return Circle.COL_OTHER;
+ }
+ }
+ }
+ return Circle.COL_NONE;
+ };
+ Circle.prototype.ProjCircle_Convex = function (x, y, oH, oV, obj, t) {
+ //if the object is horiz AND/OR vertical neighbor in the normal (signx,signy)
+ //direction, collide vs. tile-circle only.
+ //if we're colliding diagonally:
+ // -else, collide vs. the appropriate vertex
+ //if obj is in this tile: perform collision as for aabb
+ //if obj is horiz or vert neigh against direction of slope: collide vs. face
+ var signx = t.signx;
+ var signy = t.signy;
+ var lenP;
+ if(oH == 0) {
+ if(oV == 0) {
+ //colliding with current tile
+ var ox = obj.pos.x - (t.pos.x - (signx * t.xw));//(ox,oy) is the vector from the tile-circle to
+
+ var oy = obj.pos.y - (t.pos.y - (signy * t.yw));//the circle's center
+
+ var twid = t.xw * 2;
+ var trad = Math.sqrt(twid * twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
+
+ //note that this should be precomputed at compile-time since it's constant
+ var len = Math.sqrt(ox * ox + oy * oy);
+ var pen = (trad + obj.radius) - len;
+ if(0 < pen) {
+ //find the smallest axial projection vector
+ if(x < y) {
+ //penetration in x is smaller
+ lenP = x;
+ y = 0;
+ //get sign for projection along x-axis
+ if((obj.pos.x - t.pos.x) < 0) {
+ x *= -1;
+ }
+ } else {
+ //penetration in y is smaller
+ lenP = y;
+ x = 0;
+ //get sign for projection along y-axis
+ if((obj.pos.y - t.pos.y) < 0) {
+ y *= -1;
+ }
+ }
+ if(lenP < pen) {
+ obj.ReportCollisionVsWorld(x, y, x / lenP, y / lenP, t);
+ return Circle.COL_AXIS;
+ } else {
+ //note: len should NEVER be == 0, because if it is,
+ //projeciton by an axis shoudl always be shorter, and we should
+ //never arrive here
+ ox /= len;
+ oy /= len;
+ obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
+ return Circle.COL_OTHER;
+ }
+ }
+ } else {
+ //colliding vertically
+ if((signy * oV) < 0) {
+ //colliding with face/edge
+ obj.ReportCollisionVsWorld(0, y * oV, 0, oV, t);
+ return Circle.COL_AXIS;
+ } else {
+ //obj in neighboring cell pointed at by tile normal;
+ //we could only be colliding vs the tile-circle surface
+ var ox = obj.pos.x - (t.pos.x - (signx * t.xw));//(ox,oy) is the vector from the tile-circle to
+
+ var oy = obj.pos.y - (t.pos.y - (signy * t.yw));//the circle's center
+
+ var twid = t.xw * 2;
+ var trad = Math.sqrt(twid * twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
+
+ //note that this should be precomputed at compile-time since it's constant
+ var len = Math.sqrt(ox * ox + oy * oy);
+ var pen = (trad + obj.radius) - len;
+ if(0 < pen) {
+ //note: len should NEVER be == 0, because if it is,
+ //obj is not in a neighboring cell!
+ ox /= len;
+ oy /= len;
+ obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
+ return Circle.COL_OTHER;
+ }
+ }
+ }
+ } else if(oV == 0) {
+ //colliding horizontally
+ if((signx * oH) < 0) {
+ //colliding with face/edge
+ obj.ReportCollisionVsWorld(x * oH, 0, oH, 0, t);
+ return Circle.COL_AXIS;
+ } else {
+ //obj in neighboring cell pointed at by tile normal;
+ //we could only be colliding vs the tile-circle surface
+ var ox = obj.pos.x - (t.pos.x - (signx * t.xw));//(ox,oy) is the vector from the tile-circle to
+
+ var oy = obj.pos.y - (t.pos.y - (signy * t.yw));//the circle's center
+
+ var twid = t.xw * 2;
+ var trad = Math.sqrt(twid * twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
+
+ //note that this should be precomputed at compile-time since it's constant
+ var len = Math.sqrt(ox * ox + oy * oy);
+ var pen = (trad + obj.radius) - len;
+ if(0 < pen) {
+ //note: len should NEVER be == 0, because if it is,
+ //obj is not in a neighboring cell!
+ ox /= len;
+ oy /= len;
+ obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
+ return Circle.COL_OTHER;
+ }
+ }
+ } else {
+ //colliding diagonally
+ if(0 < ((signx * oH) + (signy * oV))) {
+ //obj in diag neighb cell pointed at by tile normal;
+ //we could only be colliding vs the tile-circle surface
+ var ox = obj.pos.x - (t.pos.x - (signx * t.xw));//(ox,oy) is the vector from the tile-circle to
+
+ var oy = obj.pos.y - (t.pos.y - (signy * t.yw));//the circle's center
+
+ var twid = t.xw * 2;
+ var trad = Math.sqrt(twid * twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
+
+ //note that this should be precomputed at compile-time since it's constant
+ var len = Math.sqrt(ox * ox + oy * oy);
+ var pen = (trad + obj.radius) - len;
+ if(0 < pen) {
+ //note: len should NEVER be == 0, because if it is,
+ //obj is not in a neighboring cell!
+ ox /= len;
+ oy /= len;
+ obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
+ return Circle.COL_OTHER;
+ }
+ } else {
+ //collide vs. vertex
+ //get diag vertex position
+ var vx = t.pos.x + (oH * t.xw);
+ var vy = t.pos.y + (oV * t.yw);
+ var dx = obj.pos.x - vx;//calc vert->circle vector
+
+ var dy = obj.pos.y - vy;
+ var len = Math.sqrt(dx * dx + dy * dy);
+ var pen = obj.radius - len;
+ if(0 < pen) {
+ //vertex is in the circle; project outward
+ if(len == 0) {
+ //project out by 45deg
+ dx = oH / Math.SQRT2;
+ dy = oV / Math.SQRT2;
+ } else {
+ dx /= len;
+ dy /= len;
+ }
+ obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
+ return Circle.COL_OTHER;
+ }
+ }
+ }
+ return Circle.COL_NONE;
+ };
+ return Circle;
+})();
+(function () {
+ var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update, render);
+ function init() {
+ myGame.loader.addImageFile('atari1', 'assets/sprites/atari130xe.png');
+ myGame.loader.load();
+ }
+ physics:
+NPhysics
+ c:
+Circle
+ t:
+TileMapCell
+ function create() {
+ this.physics = new NPhysics();
+ this.c = new Circle(200, 100, 25);
+ // pos is center, not upper-left
+ this.t = new TileMapCell(200, 500, 100, 100);
+ //this.t.SetState(TileMapCell.TID_FULL);
+ //this.t.SetState(TileMapCell.TID_45DEGpn);
+ //this.t.SetState(TileMapCell.TID_CONCAVEpn);
+ this.t.SetState(TileMapCell.TID_CONVEXpn);
+ }
+ function update() {
+ var fx = 0;
+ var fy = 0;
+ if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
+ fx -= 0.2;
+ } else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
+ fx += 0.2;
+ }
+ if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
+ fy -= 0.2 + 0.2;
+ } else if(myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
+ fy += 0.2;
+ }
+ var p = this.c.pos;
+ var o = this.c.oldpos;
+ var vx = p.x - o.x;
+ var vy = p.y - o.y;
+ var newx = Math.min(20, Math.max(-20, vx + fx));
+ var newy = Math.min(20, Math.max(-20, vy + fy));
+ p.x = o.x + newx;
+ p.y = o.y + newy;
+ this.c.IntegrateVerlet();
+ this.c.CollideCircleVsTile(this.t);
+ this.c.CollideCircleVsWorldBounds();
+ }
+ function render() {
+ this.c.render(myGame.stage.context);
+ this.t.render(myGame.stage.context);
+ }
+})();
diff --git a/Tests/physics/temp2.ts b/Tests/physics/temp2.ts
new file mode 100644
index 00000000..459680c5
--- /dev/null
+++ b/Tests/physics/temp2.ts
@@ -0,0 +1,1683 @@
+///
+
+class NPhysics {
+
+ grav: number = 0.2;
+ drag: number = 1;
+ bounce: number = 0.3;
+ friction: number = 0.05;
+
+ min_f: number = 0;
+ max_f: number = 1;
+
+ min_b: number = 0;
+ max_b: number = 1;
+
+ min_g: number = 0;
+ max_g = 1;
+
+ xmin: number = 0;
+ xmax: number = 800;
+ ymin: number = 0;
+ ymax: number = 600;
+
+ objrad: number = 24;
+ tilerad: number = 24*2;
+ objspeed: number = 0.2;
+ maxspeed: number = 20;
+
+ public update() {
+ // demoObj.Verlet();
+ // demoObj.CollideVsWorldBounds();
+ }
+
+}
+
+class AABB {
+
+ constructor(pos: Phaser.Vector2, xw, yw) {
+ this.pos = pos.clone();
+ this.oldpos = pos.clone();
+ this.xw = Math.abs(xw);
+ this.yw = Math.abs(yw);
+ }
+
+ type:number = 0;
+ pos: Phaser.Vector2;
+ oldpos: Phaser.Vector2;
+ xw: number;
+ yw: number;
+
+}
+
+class TileMapCell {
+
+ //TILETYPE ENUMERATION
+ static TID_EMPTY = 0;
+ static TID_FULL = 1;//fullAABB tile
+ static TID_45DEGpn = 2;//45-degree triangle, whose normal is (+ve,-ve)
+ static TID_45DEGnn = 3;//(+ve,+ve)
+ static TID_45DEGnp = 4;//(-ve,+ve)
+ static TID_45DEGpp = 5;//(-ve,-ve)
+ static TID_CONCAVEpn = 6;//1/4-circle cutout
+ static TID_CONCAVEnn = 7;
+ static TID_CONCAVEnp = 8;
+ static TID_CONCAVEpp = 9;
+ static TID_CONVEXpn = 10;//1/4/circle
+ static TID_CONVEXnn = 11;
+ static TID_CONVEXnp = 12;
+ static TID_CONVEXpp = 13;
+ static TID_22DEGpnS = 14;//22.5 degree slope
+ static TID_22DEGnnS = 15;
+ static TID_22DEGnpS = 16;
+ static TID_22DEGppS = 17;
+ static TID_22DEGpnB = 18;
+ static TID_22DEGnnB = 19;
+ static TID_22DEGnpB = 20;
+ static TID_22DEGppB = 21;
+ static TID_67DEGpnS = 22;//67.5 degree slope
+ static TID_67DEGnnS = 23;
+ static TID_67DEGnpS = 24;
+ static TID_67DEGppS = 25;
+ static TID_67DEGpnB = 26;
+ static TID_67DEGnnB = 27;
+ static TID_67DEGnpB = 28;
+ static TID_67DEGppB = 29;
+ static TID_HALFd = 30;//half-full tiles
+ static TID_HALFr = 31;
+ static TID_HALFu = 32;
+ static TID_HALFl = 33;
+
+ //collision shape "types"
+ static CTYPE_EMPTY = 0;
+ static CTYPE_FULL = 1;
+ static CTYPE_45DEG = 2;
+ static CTYPE_CONCAVE = 6;
+ static CTYPE_CONVEX = 10;
+ static CTYPE_22DEGs = 14;
+ static CTYPE_22DEGb = 18;
+ static CTYPE_67DEGs = 22;
+ static CTYPE_67DEGb = 26;
+ static CTYPE_HALF = 30;
+
+ ID;
+ CTYPE;
+ pos: Phaser.Vector2;
+ xw;
+ yw;
+ minx;
+ maxx;
+ miny;
+ maxy;
+ signx;
+ signy;
+ sx;
+ sy;
+
+ constructor(x,y,xw,yw) {
+
+ this.ID = TileMapCell.TID_EMPTY; //all tiles start empty
+ this.CTYPE = TileMapCell.CTYPE_EMPTY;
+
+ this.pos = new Phaser.Vector2(x,y); //setup collision properties
+ this.xw = xw;
+ this.yw = yw;
+ this.minx = this.pos.x - this.xw;
+ this.maxx = this.pos.x + this.xw;
+ this.miny = this.pos.y - this.yw;
+ this.maxy = this.pos.y + this.yw;
+
+ //this stores tile-specific collision information
+ this.signx = 0;
+ this.signy = 0;
+ this.sx = 0;
+ this.sy = 0;
+ }
+
+ //these functions are used to update the cell
+ //note: ID is assumed to NOT be "empty" state..
+ //if it IS the empty state, the tile clears itself
+ SetState(ID) {
+ if (ID == TileMapCell.TID_EMPTY)
+ {
+ this.Clear();
+ }
+ else
+ {
+ //set tile state to a non-emtpy value, and update it's edges and those of the neighbors
+ this.ID = ID;
+ this.UpdateType();
+ //this.Draw();
+ }
+ }
+
+ Clear() {
+ //tile was on, turn it off
+ this.ID = TileMapCell.TID_EMPTY
+ this.UpdateType();
+ //this.Draw();
+ }
+
+ public render(context: CanvasRenderingContext2D) {
+
+ context.beginPath();
+ context.strokeStyle = 'rgb(255,255,0)';
+ context.strokeRect(this.minx, this.miny, this.xw * 2, this.yw * 2);
+ context.strokeRect(this.pos.x, this.pos.y, 2, 2);
+ context.closePath();
+
+ }
+
+ //this converts a tile from implicitly-defined (via ID), to explicit (via properties)
+ UpdateType() {
+ if (0 < this.ID)
+ {
+ //tile is non-empty; collide
+ if (this.ID < TileMapCell.CTYPE_45DEG)
+ {
+ //TID_FULL
+ this.CTYPE = TileMapCell.CTYPE_FULL;
+ this.signx = 0;
+ this.signy = 0;
+ this.sx = 0;
+ this.sy = 0;
+
+ }
+ else if (this.ID < TileMapCell.CTYPE_CONCAVE)
+ {
+
+ //45deg
+ this.CTYPE = TileMapCell.CTYPE_45DEG;
+ if (this.ID == TileMapCell.TID_45DEGpn)
+ {
+ console.log('set tile as 45deg pn');
+ this.signx = 1;
+ this.signy = -1;
+ this.sx = this.signx / Math.SQRT2;//get slope _unit_ normal
+ this.sy = this.signy / Math.SQRT2;//since normal is (1,-1), length is sqrt(1*1 + -1*-1) = sqrt(2)
+
+ }
+ else if (this.ID == TileMapCell.TID_45DEGnn)
+ {
+ this.signx = -1;
+ this.signy = -1;
+ this.sx = this.signx / Math.SQRT2;//get slope _unit_ normal
+ this.sy = this.signy / Math.SQRT2;//since normal is (1,-1), length is sqrt(1*1 + -1*-1) = sqrt(2)
+
+ }
+ else if (this.ID == TileMapCell.TID_45DEGnp)
+ {
+ this.signx = -1;
+ this.signy = 1;
+ this.sx = this.signx / Math.SQRT2;//get slope _unit_ normal
+ this.sy = this.signy / Math.SQRT2;//since normal is (1,-1), length is sqrt(1*1 + -1*-1) = sqrt(2)
+ }
+ else if (this.ID == TileMapCell.TID_45DEGpp)
+ {
+ this.signx = 1;
+ this.signy = 1;
+ this.sx = this.signx / Math.SQRT2;//get slope _unit_ normal
+ this.sy = this.signy / Math.SQRT2;//since normal is (1,-1), length is sqrt(1*1 + -1*-1) = sqrt(2)
+ }
+ else
+ {
+ //trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
+ return false;
+ }
+ }
+ else if (this.ID < TileMapCell.CTYPE_CONVEX)
+ {
+
+ //concave
+ this.CTYPE = TileMapCell.CTYPE_CONCAVE;
+ if (this.ID == TileMapCell.TID_CONCAVEpn)
+ {
+ this.signx = 1;
+ this.signy = -1;
+ this.sx = 0;
+ this.sy = 0;
+ }
+ else if (this.ID == TileMapCell.TID_CONCAVEnn)
+ {
+ this.signx = -1;
+ this.signy = -1;
+ this.sx = 0;
+ this.sy = 0;
+ }
+ else if (this.ID == TileMapCell.TID_CONCAVEnp)
+ {
+ this.signx = -1;
+ this.signy = 1;
+ this.sx = 0;
+ this.sy = 0;
+ }
+ else if (this.ID == TileMapCell.TID_CONCAVEpp)
+ {
+ this.signx = 1;
+ this.signy = 1;
+ this.sx = 0;
+ this.sy = 0;
+ }
+ else
+ {
+ //trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
+ return false;
+ }
+ }
+ else if (this.ID < TileMapCell.CTYPE_22DEGs)
+ {
+
+ //convex
+ this.CTYPE = TileMapCell.CTYPE_CONVEX;
+ if (this.ID == TileMapCell.TID_CONVEXpn)
+ {
+ this.signx = 1;
+ this.signy = -1;
+ this.sx = 0;
+ this.sy = 0;
+ }
+ else if (this.ID == TileMapCell.TID_CONVEXnn)
+ {
+ this.signx = -1;
+ this.signy = -1;
+ this.sx = 0;
+ this.sy = 0;
+ }
+ else if (this.ID == TileMapCell.TID_CONVEXnp)
+ {
+ this.signx = -1;
+ this.signy = 1;
+ this.sx = 0;
+ this.sy = 0;
+ }
+ else if (this.ID == TileMapCell.TID_CONVEXpp)
+ {
+ this.signx = 1;
+ this.signy = 1;
+ this.sx = 0;
+ this.sy = 0;
+ }
+ else
+ {
+ //trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
+ return false;
+ }
+ }
+ else if (this.ID < TileMapCell.CTYPE_22DEGb)
+ {
+
+ //22deg small
+ this.CTYPE = TileMapCell.CTYPE_22DEGs;
+ if (this.ID == TileMapCell.TID_22DEGpnS)
+ {
+ this.signx = 1;
+ this.signy = -1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 1) / slen;
+ this.sy = (this.signy * 2) / slen;
+ }
+ else if (this.ID == TileMapCell.TID_22DEGnnS)
+ {
+ this.signx = -1;
+ this.signy = -1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 1) / slen;
+ this.sy = (this.signy * 2) / slen;
+ }
+ else if (this.ID == TileMapCell.TID_22DEGnpS)
+ {
+ this.signx = -1;
+ this.signy = 1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 1) / slen;
+ this.sy = (this.signy * 2) / slen;
+ }
+ else if (this.ID == TileMapCell.TID_22DEGppS)
+ {
+ this.signx = 1;
+ this.signy = 1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 1) / slen;
+ this.sy = (this.signy * 2) / slen;
+ }
+ else
+ {
+ //trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
+ return false;
+ }
+ }
+ else if (this.ID < TileMapCell.CTYPE_67DEGs)
+ {
+
+ //22deg big
+ this.CTYPE = TileMapCell.CTYPE_22DEGb;
+ if (this.ID == TileMapCell.TID_22DEGpnB)
+ {
+ this.signx = 1;
+ this.signy = -1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 1) / slen;
+ this.sy = (this.signy * 2) / slen;
+ }
+ else if (this.ID == TileMapCell.TID_22DEGnnB)
+ {
+ this.signx = -1;
+ this.signy = -1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 1) / slen;
+ this.sy = (this.signy * 2) / slen;
+ }
+ else if (this.ID == TileMapCell.TID_22DEGnpB)
+ {
+ this.signx = -1;
+ this.signy = 1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 1) / slen;
+ this.sy = (this.signy * 2) / slen;
+ }
+ else if (this.ID == TileMapCell.TID_22DEGppB)
+ {
+ this.signx = 1;
+ this.signy = 1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 1) / slen;
+ this.sy = (this.signy * 2) / slen;
+ }
+ else
+ {
+ //trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
+ return false;
+ }
+ }
+ else if (this.ID < TileMapCell.CTYPE_67DEGb)
+ {
+
+ //67deg small
+ this.CTYPE = TileMapCell.CTYPE_67DEGs;
+ if (this.ID == TileMapCell.TID_67DEGpnS)
+ {
+ this.signx = 1;
+ this.signy = -1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 2) / slen;
+ this.sy = (this.signy * 1) / slen;
+ }
+ else if (this.ID == TileMapCell.TID_67DEGnnS)
+ {
+ this.signx = -1;
+ this.signy = -1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 2) / slen;
+ this.sy = (this.signy * 1) / slen;
+ }
+ else if (this.ID == TileMapCell.TID_67DEGnpS)
+ {
+ this.signx = -1;
+ this.signy = 1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 2) / slen;
+ this.sy = (this.signy * 1) / slen;
+ }
+ else if (this.ID == TileMapCell.TID_67DEGppS)
+ {
+ this.signx = 1;
+ this.signy = 1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 2) / slen;
+ this.sy = (this.signy * 1) / slen;
+ }
+ else
+ {
+ //trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
+ return false;
+ }
+ }
+ else if (this.ID < TileMapCell.CTYPE_HALF)
+ {
+
+ //67deg big
+ this.CTYPE = TileMapCell.CTYPE_67DEGb;
+ if (this.ID == TileMapCell.TID_67DEGpnB)
+ {
+ this.signx = 1;
+ this.signy = -1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 2) / slen;
+ this.sy = (this.signy * 1) / slen;
+ }
+ else if (this.ID == TileMapCell.TID_67DEGnnB)
+ {
+ this.signx = -1;
+ this.signy = -1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 2) / slen;
+ this.sy = (this.signy * 1) / slen;
+ }
+ else if (this.ID == TileMapCell.TID_67DEGnpB)
+ {
+ this.signx = -1;
+ this.signy = 1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 2) / slen;
+ this.sy = (this.signy * 1) / slen;
+ }
+ else if (this.ID == TileMapCell.TID_67DEGppB)
+ {
+ this.signx = 1;
+ this.signy = 1;
+ var slen = Math.sqrt(2 * 2 + 1 * 1);
+ this.sx = (this.signx * 2) / slen;
+ this.sy = (this.signy * 1) / slen;
+ }
+ else
+ {
+ //trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
+ return false;
+ }
+ }
+ else
+ {
+ //half-full tile
+ this.CTYPE = TileMapCell.CTYPE_HALF;
+ if (this.ID == TileMapCell.TID_HALFd)
+ {
+ this.signx = 0;
+ this.signy = -1;
+ this.sx = this.signx;
+ this.sy = this.signy;
+ }
+ else if (this.ID == TileMapCell.TID_HALFu)
+ {
+ this.signx = 0;
+ this.signy = 1;
+ this.sx = this.signx;
+ this.sy = this.signy;
+ }
+ else if (this.ID == TileMapCell.TID_HALFl)
+ {
+ this.signx = 1;
+ this.signy = 0;
+ this.sx = this.signx;
+ this.sy = this.signy;
+ }
+ else if (this.ID == TileMapCell.TID_HALFr)
+ {
+ this.signx = -1;
+ this.signy = 0;
+ this.sx = this.signx;
+ this.sy = this.signy;
+ }
+ else
+ {
+ //trace("BAAD TILE!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
+ return false;
+ }
+
+ }
+
+ }
+ else
+ {
+ //TID_EMPTY
+ this.CTYPE = TileMapCell.CTYPE_EMPTY;
+ this.signx = 0;
+ this.signy = 0;
+ this.sx = 0;
+ this.sy = 0;
+ }
+ }
+
+}
+
+class Circle {
+
+ constructor(x, y, radius) {
+
+ this.pos = new Phaser.Vector2(x, y);
+ this.oldpos = this.pos.clone();
+ this.radius = radius;
+ this.circleTileProjections = {};//hash object to hold tile-specific collision functions
+ this.circleTileProjections[TileMapCell.CTYPE_FULL] = this.ProjCircle_Full;
+ this.circleTileProjections[TileMapCell.CTYPE_45DEG] = this.ProjCircle_45Deg;
+ this.circleTileProjections[TileMapCell.CTYPE_CONCAVE] = this.ProjCircle_Concave;
+ this.circleTileProjections[TileMapCell.CTYPE_CONVEX] = this.ProjCircle_Convex;
+
+ //Proj_CircleTile[CTYPE_22DEGs] = ProjCircle_22DegS;
+ //Proj_CircleTile[CTYPE_22DEGb] = ProjCircle_22DegB;
+ //Proj_CircleTile[CTYPE_67DEGs] = ProjCircle_67DegS;
+ //Proj_CircleTile[CTYPE_67DEGb] = ProjCircle_67DegB;
+ //Proj_CircleTile[CTYPE_HALF] = ProjCircle_Half;
+
+ }
+
+ type:number = 1;
+ pos: Phaser.Vector2;
+ oldpos: Phaser.Vector2;
+ radius: number;
+ circleTileProjections;
+
+ public IntegrateVerlet() {
+
+ //var d = DRAG;
+ //var g = GRAV;
+ var d = 1;
+ var g = 0.2;
+
+ var p = this.pos;
+ var o = this.oldpos;
+ var px, py;
+
+ var ox = o.x; //we can't swap buffers since mcs/sticks point directly to vector2s..
+ var oy = o.y;
+ o.x = px = p.x; //get vector values
+ o.y = py = p.y; //p = position
+ //o = oldposition
+
+ //integrate
+ p.x += (d * px) - (d * ox);
+ p.y += (d * py) - (d * oy) + g;
+
+ }
+
+ public ReportCollisionVsWorld(px, py, dx, dy, obj: TileMapCell) {
+
+ var p = this.pos;
+ var o = this.oldpos;
+
+ //calc velocity
+ var vx = p.x - o.x;
+ var vy = p.y - o.y;
+
+ //find component of velocity parallel to collision normal
+ var dp = (vx * dx + vy * dy);
+ var nx = dp * dx;//project velocity onto collision normal
+
+ var ny = dp * dy;//nx,ny is normal velocity
+
+ var tx = vx - nx;//px,py is tangent velocity
+ var ty = vy - ny;
+
+ //we only want to apply collision response forces if the object is travelling into, and not out of, the collision
+ var b, bx, by, f, fx, fy;
+
+ if (dp < 0)
+ {
+ //f = FRICTION;
+ f = 0.05;
+ fx = tx * f;
+ fy = ty * f;
+
+ //b = 1 + BOUNCE;//this bounce constant should be elsewhere, i.e inside the object/tile/etc..
+ b = 1 + 0.3;//this bounce constant should be elsewhere, i.e inside the object/tile/etc..
+
+ bx = (nx * b);
+ by = (ny * b);
+
+ }
+ else
+ {
+ //moving out of collision, do not apply forces
+ bx = by = fx = fy = 0;
+ }
+
+ p.x += px;//project object out of collision
+ p.y += py;
+
+ o.x += px + bx + fx;//apply bounce+friction impulses which alter velocity
+ o.y += py + by + fy;
+
+ }
+
+ public CollideCircleVsWorldBounds() {
+ var p = this.pos;
+ var r = this.radius;
+ var XMIN = 0;
+ var XMAX = 800;
+ var YMIN = 0;
+ var YMAX = 600;
+
+ //collide vs. x-bounds
+ //test XMIN
+ var dx = XMIN - (p.x - r);
+ if (0 < dx)
+ {
+ //object is colliding with XMIN
+ this.ReportCollisionVsWorld(dx, 0, 1, 0, null);
+ }
+ else
+ {
+ //test XMAX
+ dx = (p.x + r) - XMAX;
+ if (0 < dx)
+ {
+ //object is colliding with XMAX
+ this.ReportCollisionVsWorld(-dx, 0, -1, 0, null);
+ }
+ }
+
+ //collide vs. y-bounds
+ //test YMIN
+ var dy = YMIN - (p.y - r);
+ if (0 < dy)
+ {
+ //object is colliding with YMIN
+ this.ReportCollisionVsWorld(0, dy, 0, 1, null);
+ }
+ else
+ {
+ //test YMAX
+ dy = (p.y + r) - YMAX;
+ if (0 < dy)
+ {
+ //object is colliding with YMAX
+ this.ReportCollisionVsWorld(0, -dy, 0, -1, null);
+ }
+ }
+ }
+
+ public render(context:CanvasRenderingContext2D) {
+
+ context.beginPath();
+ context.strokeStyle = 'rgb(0,255,0)';
+ context.arc(this.pos.x, this.pos.y, this.radius, 0, Math.PI * 2);
+ context.stroke();
+ context.closePath();
+
+ if (this.oH == 1)
+ {
+ context.beginPath();
+ context.strokeStyle = 'rgb(255,0,0)';
+ context.moveTo(this.pos.x - this.radius, this.pos.y - this.radius);
+ context.lineTo(this.pos.x - this.radius, this.pos.y + this.radius);
+ context.stroke();
+ context.closePath();
+ }
+ else if (this.oH == -1)
+ {
+ context.beginPath();
+ context.strokeStyle = 'rgb(255,0,0)';
+ context.moveTo(this.pos.x + this.radius, this.pos.y - this.radius);
+ context.lineTo(this.pos.x + this.radius, this.pos.y + this.radius);
+ context.stroke();
+ context.closePath();
+ }
+
+ if (this.oV == 1)
+ {
+ context.beginPath();
+ context.strokeStyle = 'rgb(255,0,0)';
+ context.moveTo(this.pos.x - this.radius, this.pos.y - this.radius);
+ context.lineTo(this.pos.x + this.radius, this.pos.y - this.radius);
+ context.stroke();
+ context.closePath();
+ }
+ else if (this.oV == -1)
+ {
+ context.beginPath();
+ context.strokeStyle = 'rgb(255,0,0)';
+ context.moveTo(this.pos.x - this.radius, this.pos.y + this.radius);
+ context.lineTo(this.pos.x + this.radius, this.pos.y + this.radius);
+ context.stroke();
+ context.closePath();
+ }
+
+ }
+
+ public oH: number;
+ public oV: number;
+
+ public CollideCircleVsTile(tile) {
+ var pos = this.pos;
+ var r = this.radius;
+ var c = tile;
+
+ var tx = c.pos.x;
+ var ty = c.pos.y;
+ var txw = c.xw;
+ var tyw = c.yw;
+
+ var dx = pos.x - tx;//tile->obj delta
+ var px = (txw + r) - Math.abs(dx);//penetration depth in x
+
+ if (0 < px)
+ {
+ var dy = pos.y - ty;//tile->obj delta
+ var py = (tyw + r) - Math.abs(dy);//pen depth in y
+
+ if (0 < py)
+ {
+ //object may be colliding with tile
+
+ //determine grid/voronoi region of circle center
+ this.oH = 0;
+ this.oV = 0;
+ if (dx < -txw)
+ {
+ //circle is on left side of tile
+ this.oH = -1;
+ }
+ else if (txw < dx)
+ {
+ //circle is on right side of tile
+ this.oH = 1;
+ }
+
+ if (dy < -tyw)
+ {
+ //circle is on top side of tile
+ this.oV = -1;
+ }
+ else if (tyw < dy)
+ {
+ //circle is on bottom side of tile
+ this.oV = 1;
+ }
+
+ this.ResolveCircleTile(px, py, this.oH, this.oV, this, c);
+
+ }
+ }
+ }
+
+ public ResolveCircleTile(x, y, oH, oV, obj, t) {
+
+ if (0 < t.ID)
+ {
+ return this.circleTileProjections[t.CTYPE](x, y, oH, oV, obj, t);
+ }
+ else
+ {
+ console.log("ResolveCircleTile() was called with an empty (or unknown) tile!: ID=" + t.ID + " (" + t.i + "," + t.j + ")");
+ return false;
+ }
+ }
+
+ static COL_NONE = 0;
+ static COL_AXIS = 1;
+ static COL_OTHER = 2;
+
+ public ProjCircle_Full(x, y, oH, oV, obj:Circle, t:TileMapCell) {
+
+ //if we're colliding vs. the current cell, we need to project along the
+ //smallest penetration vector.
+ //if we're colliding vs. horiz. or vert. neighb, we simply project horiz/vert
+ //if we're colliding diagonally, we need to collide vs. tile corner
+
+ if (oH == 0)
+ {
+ if (oV == 0)
+ {
+ //collision with current cell
+ if (x < y)
+ {
+ //penetration in x is smaller; project in x
+ var dx = obj.pos.x - t.pos.x;//get sign for projection along x-axis
+
+ //NOTE: should we handle the delta == 0 case?! and how? (project towards oldpos?)
+ if (dx < 0)
+ {
+ obj.ReportCollisionVsWorld(-x, 0, -1, 0, t);
+ return Circle.COL_AXIS;
+ }
+ else
+ {
+ obj.ReportCollisionVsWorld(x, 0, 1, 0, t);
+ return Circle.COL_AXIS;
+ }
+ }
+ else
+ {
+ //penetration in y is smaller; project in y
+ var dy = obj.pos.y - t.pos.y;//get sign for projection along y-axis
+
+ //NOTE: should we handle the delta == 0 case?! and how? (project towards oldpos?)
+ if (dy < 0)
+ {
+ obj.ReportCollisionVsWorld(0, -y, 0, -1, t);
+ return Circle.COL_AXIS;
+ }
+ else
+ {
+ obj.ReportCollisionVsWorld(0, y, 0, 1, t);
+ return Circle.COL_AXIS;
+ }
+ }
+ }
+ else
+ {
+ //collision with vertical neighbor
+ obj.ReportCollisionVsWorld(0, y * oV, 0, oV, t);
+
+ return Circle.COL_AXIS;
+ }
+ }
+ else if (oV == 0)
+ {
+ //collision with horizontal neighbor
+ obj.ReportCollisionVsWorld(x * oH, 0, oH, 0, t);
+ return Circle.COL_AXIS;
+ }
+ else
+ {
+ //diagonal collision
+
+ //get diag vertex position
+ var vx = t.pos.x + (oH * t.xw);
+ var vy = t.pos.y + (oV * t.yw);
+
+ var dx = obj.pos.x - vx;//calc vert->circle vector
+ var dy = obj.pos.y - vy;
+
+ var len = Math.sqrt(dx * dx + dy * dy);
+ var pen = obj.radius - len;
+ if (0 < pen)
+ {
+ //vertex is in the circle; project outward
+ if (len == 0)
+ {
+ //project out by 45deg
+ dx = oH / Math.SQRT2;
+ dy = oV / Math.SQRT2;
+ }
+ else
+ {
+ dx /= len;
+ dy /= len;
+ }
+
+ obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
+
+ return Circle.COL_OTHER;
+ }
+ }
+
+ return Circle.COL_NONE;
+
+ }
+
+ public ProjCircle_45Deg(x, y, oH, oV, obj: Circle, t: TileMapCell) {
+
+ //if we're colliding diagonally:
+ // -if obj is in the diagonal pointed to by the slope normal: we can't collide, do nothing
+ // -else, collide vs. the appropriate vertex
+ //if obj is in this tile: perform collision as for aabb-ve-45deg
+ //if obj is horiz OR very neighb in direction of slope: collide only vs. slope
+ //if obj is horiz or vert neigh against direction of slope: collide vs. face
+
+ var signx = t.signx;
+ var signy = t.signy;
+ var lenP;
+
+ if (oH == 0)
+ {
+ if (oV == 0)
+ {
+ //colliding with current tile
+
+ var sx = t.sx;
+ var sy = t.sy;
+
+ var ox = (obj.pos.x - (sx * obj.radius)) - t.pos.x;//this gives is the coordinates of the innermost
+ var oy = (obj.pos.y - (sy * obj.radius)) - t.pos.y;//point on the circle, relative to the tile center
+
+ //if the dotprod of (ox,oy) and (sx,sy) is negative, the innermost point is in the slope
+ //and we need toproject it out by the magnitude of the projection of (ox,oy) onto (sx,sy)
+ var dp = (ox * sx) + (oy * sy);
+ if (dp < 0)
+ {
+ //collision; project delta onto slope and use this as the slope penetration vector
+ sx *= -dp;//(sx,sy) is now the penetration vector
+ sy *= -dp;
+
+ //find the smallest axial projection vector
+ if (x < y)
+ {
+ //penetration in x is smaller
+ lenP = x;
+ y = 0;
+
+ //get sign for projection along x-axis
+ if ((obj.pos.x - t.pos.x) < 0)
+ {
+ x *= -1;
+ }
+ }
+ else
+ {
+ //penetration in y is smaller
+ lenP = y;
+ x = 0;
+
+ //get sign for projection along y-axis
+ if ((obj.pos.y - t.pos.y) < 0)
+ {
+ y *= -1;
+ }
+ }
+
+ var lenN = Math.sqrt(sx * sx + sy * sy);
+
+ if (lenP < lenN)
+ {
+ obj.ReportCollisionVsWorld(x, y, x / lenP, y / lenP, t);
+
+ return Circle.COL_AXIS;
+ }
+ else
+ {
+ obj.ReportCollisionVsWorld(sx, sy, t.sx, t.sy, t);
+
+ return Circle.COL_OTHER;
+ }
+ }
+
+ }
+ else
+ {
+ //colliding vertically
+ if ((signy * oV) < 0)
+ {
+ //colliding with face/edge
+ obj.ReportCollisionVsWorld(0, y * oV, 0, oV, t);
+
+ return Circle.COL_AXIS;
+ }
+ else
+ {
+ //we could only be colliding vs the slope OR a vertex
+ //look at the vector form the closest vert to the circle to decide
+
+ var sx = t.sx;
+ var sy = t.sy;
+
+ var ox = obj.pos.x - (t.pos.x - (signx * t.xw));//this gives is the coordinates of the innermost
+ var oy = obj.pos.y - (t.pos.y + (oV * t.yw));//point on the circle, relative to the closest tile vert
+
+ //if the component of (ox,oy) parallel to the normal's righthand normal
+ //has the same sign as the slope of the slope (the sign of the slope's slope is signx*signy)
+ //then we project by the vertex, otherwise by the normal.
+ //note that this is simply a VERY tricky/weird method of determining
+ //if the circle is in side the slope/face's voronoi region, or that of the vertex.
+ var perp = (ox * -sy) + (oy * sx);
+ if (0 < (perp * signx * signy))
+ {
+ //collide vs. vertex
+ var len = Math.sqrt(ox * ox + oy * oy);
+ var pen = obj.radius - len;
+ if (0 < pen)
+ {
+ //note: if len=0, then perp=0 and we'll never reach here, so don't worry about div-by-0
+ ox /= len;
+ oy /= len;
+
+ obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
+
+ return Circle.COL_OTHER;
+ }
+ }
+ else
+ {
+ //collide vs. slope
+
+ //if the component of (ox,oy) parallel to the normal is less than the circle radius, we're
+ //penetrating the slope. note that this method of penetration calculation doesn't hold
+ //in general (i.e it won't work if the circle is in the slope), but works in this case
+ //because we know the circle is in a neighboring cell
+ var dp = (ox * sx) + (oy * sy);
+ var pen = obj.radius - Math.abs(dp);//note: we don't need the abs because we know the dp will be positive, but just in case..
+ if (0 < pen)
+ {
+ //collision; circle out along normal by penetration amount
+ obj.ReportCollisionVsWorld(sx * pen, sy * pen, sx, sy, t);
+
+ return Circle.COL_OTHER;
+ }
+ }
+ }
+ }
+ }
+ else if (oV == 0)
+ {
+ //colliding horizontally
+ if ((signx * oH) < 0)
+ {
+ //colliding with face/edge
+ obj.ReportCollisionVsWorld(x * oH, 0, oH, 0, t);
+
+ return Circle.COL_AXIS;
+ }
+ else
+ {
+ //we could only be colliding vs the slope OR a vertex
+ //look at the vector form the closest vert to the circle to decide
+
+ var sx = t.sx;
+ var sy = t.sy;
+
+ var ox = obj.pos.x - (t.pos.x + (oH * t.xw));//this gives is the coordinates of the innermost
+ var oy = obj.pos.y - (t.pos.y - (signy * t.yw));//point on the circle, relative to the closest tile vert
+
+ //if the component of (ox,oy) parallel to the normal's righthand normal
+ //has the same sign as the slope of the slope (the sign of the slope's slope is signx*signy)
+ //then we project by the normal, otherwise by the vertex.
+ //(NOTE: this is the opposite logic of the vertical case;
+ // for vertical, if the perp prod and the slope's slope agree, it's outside.
+ // for horizontal, if the perp prod and the slope's slope agree, circle is inside.
+ // ..but this is only a property of flahs' coord system (i.e the rules might swap
+ // in righthanded systems))
+ //note that this is simply a VERY tricky/weird method of determining
+ //if the circle is in side the slope/face's voronio region, or that of the vertex.
+ var perp = (ox * -sy) + (oy * sx);
+ if ((perp * signx * signy) < 0)
+ {
+ //collide vs. vertex
+ var len = Math.sqrt(ox * ox + oy * oy);
+ var pen = obj.radius - len;
+ if (0 < pen)
+ {
+ //note: if len=0, then perp=0 and we'll never reach here, so don't worry about div-by-0
+ ox /= len;
+ oy /= len;
+
+ obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
+
+ return Circle.COL_OTHER;
+ }
+ }
+ else
+ {
+ //collide vs. slope
+
+ //if the component of (ox,oy) parallel to the normal is less than the circle radius, we're
+ //penetrating the slope. note that this method of penetration calculation doesn't hold
+ //in general (i.e it won't work if the circle is in the slope), but works in this case
+ //because we know the circle is in a neighboring cell
+ var dp = (ox * sx) + (oy * sy);
+ var pen = obj.radius - Math.abs(dp);//note: we don't need the abs because we know the dp will be positive, but just in case..
+ if (0 < pen)
+ {
+ //collision; circle out along normal by penetration amount
+ obj.ReportCollisionVsWorld(sx * pen, sy * pen, sx, sy, t);
+
+ return Circle.COL_OTHER;
+ }
+ }
+ }
+ }
+ else
+ {
+ //colliding diagonally
+ if (0 < ((signx * oH) + (signy * oV)))
+ {
+ //the dotprod of slope normal and cell offset is strictly positive,
+ //therefore obj is in the diagonal neighb pointed at by the normal, and
+ //it cannot possibly reach/touch/penetrate the slope
+ return Circle.COL_NONE;
+ }
+ else
+ {
+ //collide vs. vertex
+ //get diag vertex position
+ var vx = t.pos.x + (oH * t.xw);
+ var vy = t.pos.y + (oV * t.yw);
+
+ var dx = obj.pos.x - vx;//calc vert->circle vector
+ var dy = obj.pos.y - vy;
+
+ var len = Math.sqrt(dx * dx + dy * dy);
+ var pen = obj.radius - len;
+ if (0 < pen)
+ {
+ //vertex is in the circle; project outward
+ if (len == 0)
+ {
+ //project out by 45deg
+ dx = oH / Math.SQRT2;
+ dy = oV / Math.SQRT2;
+ }
+ else
+ {
+ dx /= len;
+ dy /= len;
+ }
+
+ obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
+ return Circle.COL_OTHER;
+ }
+
+ }
+
+ }
+
+ return Circle.COL_NONE;
+ }
+
+ public ProjCircle_Concave(x, y, oH, oV, obj: Circle, t: TileMapCell) {
+
+ //if we're colliding diagonally:
+ // -if obj is in the diagonal pointed to by the slope normal: we can't collide, do nothing
+ // -else, collide vs. the appropriate vertex
+ //if obj is in this tile: perform collision as for aabb
+ //if obj is horiz OR very neighb in direction of slope: collide vs vert
+ //if obj is horiz or vert neigh against direction of slope: collide vs. face
+
+ var signx = t.signx;
+ var signy = t.signy;
+ var lenP;
+
+ if (oH == 0)
+ {
+ if (oV == 0)
+ {
+ //colliding with current tile
+
+ var ox = (t.pos.x + (signx * t.xw)) - obj.pos.x;//(ox,oy) is the vector from the circle to
+ var oy = (t.pos.y + (signy * t.yw)) - obj.pos.y;//tile-circle's center
+
+ var twid = t.xw * 2;
+ var trad = Math.sqrt(twid * twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
+ //note that this should be precomputed at compile-time since it's constant
+
+ var len = Math.sqrt(ox * ox + oy * oy);
+ var pen = (len + obj.radius) - trad;
+
+ if (0 < pen)
+ {
+ //find the smallest axial projection vector
+ if (x < y)
+ {
+ //penetration in x is smaller
+ lenP = x;
+ y = 0;
+
+ //get sign for projection along x-axis
+ if ((obj.pos.x - t.pos.x) < 0)
+ {
+ x *= -1;
+ }
+ }
+ else
+ {
+ //penetration in y is smaller
+ lenP = y;
+ x = 0;
+
+ //get sign for projection along y-axis
+ if ((obj.pos.y - t.pos.y) < 0)
+ {
+ y *= -1;
+ }
+ }
+
+
+ if (lenP < pen)
+ {
+ obj.ReportCollisionVsWorld(x, y, x / lenP, y / lenP, t);
+
+ return Circle.COL_AXIS;
+ }
+ else
+ {
+ //we can assume that len >0, because if we're here then
+ //(len + obj.radius) > trad, and since obj.radius <= trad
+ //len MUST be > 0
+ ox /= len;
+ oy /= len;
+
+ obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
+
+ return Circle.COL_OTHER;
+ }
+ }
+ else
+ {
+ return Circle.COL_NONE;
+ }
+
+ }
+ else
+ {
+ //colliding vertically
+ if ((signy * oV) < 0)
+ {
+ //colliding with face/edge
+ obj.ReportCollisionVsWorld(0, y * oV, 0, oV, t);
+
+ return Circle.COL_AXIS;
+ }
+ else
+ {
+ //we could only be colliding vs the vertical tip
+
+ //get diag vertex position
+ var vx = t.pos.x - (signx * t.xw);
+ var vy = t.pos.y + (oV * t.yw);
+
+ var dx = obj.pos.x - vx;//calc vert->circle vector
+ var dy = obj.pos.y - vy;
+
+ var len = Math.sqrt(dx * dx + dy * dy);
+ var pen = obj.radius - len;
+ if (0 < pen)
+ {
+ //vertex is in the circle; project outward
+ if (len == 0)
+ {
+ //project out vertically
+ dx = 0;
+ dy = oV;
+ }
+ else
+ {
+ dx /= len;
+ dy /= len;
+ }
+
+ obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
+
+ return Circle.COL_OTHER;
+ }
+ }
+ }
+ }
+ else if (oV == 0)
+ {
+ //colliding horizontally
+ if ((signx * oH) < 0)
+ {
+ //colliding with face/edge
+ obj.ReportCollisionVsWorld(x * oH, 0, oH, 0, t);
+
+ return Circle.COL_AXIS;
+ }
+ else
+ {
+ //we could only be colliding vs the horizontal tip
+
+ //get diag vertex position
+ var vx = t.pos.x + (oH * t.xw);
+ var vy = t.pos.y - (signy * t.yw);
+
+ var dx = obj.pos.x - vx;//calc vert->circle vector
+ var dy = obj.pos.y - vy;
+
+ var len = Math.sqrt(dx * dx + dy * dy);
+ var pen = obj.radius - len;
+ if (0 < pen)
+ {
+ //vertex is in the circle; project outward
+ if (len == 0)
+ {
+ //project out horizontally
+ dx = oH;
+ dy = 0;
+ }
+ else
+ {
+ dx /= len;
+ dy /= len;
+ }
+
+ obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
+
+ return Circle.COL_OTHER;
+ }
+ }
+ }
+ else
+ {
+ //colliding diagonally
+ if (0 < ((signx * oH) + (signy * oV)))
+ {
+ //the dotprod of slope normal and cell offset is strictly positive,
+ //therefore obj is in the diagonal neighb pointed at by the normal, and
+ //it cannot possibly reach/touch/penetrate the slope
+ return Circle.COL_NONE;
+ }
+ else
+ {
+ //collide vs. vertex
+ //get diag vertex position
+ var vx = t.pos.x + (oH * t.xw);
+ var vy = t.pos.y + (oV * t.yw);
+
+ var dx = obj.pos.x - vx;//calc vert->circle vector
+ var dy = obj.pos.y - vy;
+
+ var len = Math.sqrt(dx * dx + dy * dy);
+ var pen = obj.radius - len;
+ if (0 < pen)
+ {
+ //vertex is in the circle; project outward
+ if (len == 0)
+ {
+ //project out by 45deg
+ dx = oH / Math.SQRT2;
+ dy = oV / Math.SQRT2;
+ }
+ else
+ {
+ dx /= len;
+ dy /= len;
+ }
+
+ obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
+
+ return Circle.COL_OTHER;
+ }
+
+ }
+
+ }
+
+ return Circle.COL_NONE;
+
+ }
+
+ public ProjCircle_Convex(x, y, oH, oV, obj: Circle, t: TileMapCell) {
+ //if the object is horiz AND/OR vertical neighbor in the normal (signx,signy)
+ //direction, collide vs. tile-circle only.
+ //if we're colliding diagonally:
+ // -else, collide vs. the appropriate vertex
+ //if obj is in this tile: perform collision as for aabb
+ //if obj is horiz or vert neigh against direction of slope: collide vs. face
+
+ var signx = t.signx;
+ var signy = t.signy;
+ var lenP;
+
+ if (oH == 0)
+ {
+ if (oV == 0)
+ {
+ //colliding with current tile
+
+
+ var ox = obj.pos.x - (t.pos.x - (signx * t.xw));//(ox,oy) is the vector from the tile-circle to
+ var oy = obj.pos.y - (t.pos.y - (signy * t.yw));//the circle's center
+
+ var twid = t.xw * 2;
+ var trad = Math.sqrt(twid * twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
+ //note that this should be precomputed at compile-time since it's constant
+
+ var len = Math.sqrt(ox * ox + oy * oy);
+ var pen = (trad + obj.radius) - len;
+
+ if (0 < pen)
+ {
+ //find the smallest axial projection vector
+ if (x < y)
+ {
+ //penetration in x is smaller
+ lenP = x;
+ y = 0;
+
+ //get sign for projection along x-axis
+ if ((obj.pos.x - t.pos.x) < 0)
+ {
+ x *= -1;
+ }
+ }
+ else
+ {
+ //penetration in y is smaller
+ lenP = y;
+ x = 0;
+
+ //get sign for projection along y-axis
+ if ((obj.pos.y - t.pos.y) < 0)
+ {
+ y *= -1;
+ }
+ }
+
+
+ if (lenP < pen)
+ {
+ obj.ReportCollisionVsWorld(x, y, x / lenP, y / lenP, t);
+
+ return Circle.COL_AXIS;
+ }
+ else
+ {
+ //note: len should NEVER be == 0, because if it is,
+ //projeciton by an axis shoudl always be shorter, and we should
+ //never arrive here
+ ox /= len;
+ oy /= len;
+
+ obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
+
+ return Circle.COL_OTHER;
+
+ }
+ }
+ }
+ else
+ {
+ //colliding vertically
+ if ((signy * oV) < 0)
+ {
+ //colliding with face/edge
+ obj.ReportCollisionVsWorld(0, y * oV, 0, oV, t);
+
+ return Circle.COL_AXIS;
+ }
+ else
+ {
+ //obj in neighboring cell pointed at by tile normal;
+ //we could only be colliding vs the tile-circle surface
+
+ var ox = obj.pos.x - (t.pos.x - (signx * t.xw));//(ox,oy) is the vector from the tile-circle to
+ var oy = obj.pos.y - (t.pos.y - (signy * t.yw));//the circle's center
+
+ var twid = t.xw * 2;
+ var trad = Math.sqrt(twid * twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
+ //note that this should be precomputed at compile-time since it's constant
+
+ var len = Math.sqrt(ox * ox + oy * oy);
+ var pen = (trad + obj.radius) - len;
+
+ if (0 < pen)
+ {
+
+ //note: len should NEVER be == 0, because if it is,
+ //obj is not in a neighboring cell!
+ ox /= len;
+ oy /= len;
+
+ obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
+
+ return Circle.COL_OTHER;
+ }
+ }
+ }
+ }
+ else if (oV == 0)
+ {
+ //colliding horizontally
+ if ((signx * oH) < 0)
+ {
+ //colliding with face/edge
+ obj.ReportCollisionVsWorld(x * oH, 0, oH, 0, t);
+
+ return Circle.COL_AXIS;
+ }
+ else
+ {
+ //obj in neighboring cell pointed at by tile normal;
+ //we could only be colliding vs the tile-circle surface
+
+ var ox = obj.pos.x - (t.pos.x - (signx * t.xw));//(ox,oy) is the vector from the tile-circle to
+ var oy = obj.pos.y - (t.pos.y - (signy * t.yw));//the circle's center
+
+ var twid = t.xw * 2;
+ var trad = Math.sqrt(twid * twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
+ //note that this should be precomputed at compile-time since it's constant
+
+ var len = Math.sqrt(ox * ox + oy * oy);
+ var pen = (trad + obj.radius) - len;
+
+ if (0 < pen)
+ {
+
+ //note: len should NEVER be == 0, because if it is,
+ //obj is not in a neighboring cell!
+ ox /= len;
+ oy /= len;
+
+ obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
+
+ return Circle.COL_OTHER;
+ }
+ }
+ }
+ else
+ {
+ //colliding diagonally
+ if (0 < ((signx * oH) + (signy * oV)))
+ {
+ //obj in diag neighb cell pointed at by tile normal;
+ //we could only be colliding vs the tile-circle surface
+
+ var ox = obj.pos.x - (t.pos.x - (signx * t.xw));//(ox,oy) is the vector from the tile-circle to
+ var oy = obj.pos.y - (t.pos.y - (signy * t.yw));//the circle's center
+
+ var twid = t.xw * 2;
+ var trad = Math.sqrt(twid * twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
+ //note that this should be precomputed at compile-time since it's constant
+
+ var len = Math.sqrt(ox * ox + oy * oy);
+ var pen = (trad + obj.radius) - len;
+
+ if (0 < pen)
+ {
+
+ //note: len should NEVER be == 0, because if it is,
+ //obj is not in a neighboring cell!
+ ox /= len;
+ oy /= len;
+
+ obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
+
+ return Circle.COL_OTHER;
+ }
+ }
+ else
+ {
+ //collide vs. vertex
+ //get diag vertex position
+ var vx = t.pos.x + (oH * t.xw);
+ var vy = t.pos.y + (oV * t.yw);
+
+ var dx = obj.pos.x - vx;//calc vert->circle vector
+ var dy = obj.pos.y - vy;
+
+ var len = Math.sqrt(dx * dx + dy * dy);
+ var pen = obj.radius - len;
+ if (0 < pen)
+ {
+ //vertex is in the circle; project outward
+ if (len == 0)
+ {
+ //project out by 45deg
+ dx = oH / Math.SQRT2;
+ dy = oV / Math.SQRT2;
+ }
+ else
+ {
+ dx /= len;
+ dy /= len;
+ }
+
+ obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
+
+ return Circle.COL_OTHER;
+ }
+
+ }
+
+ }
+
+ return Circle.COL_NONE;
+
+ }
+
+}
+
+
+
+(function () {
+
+ var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update, render);
+
+ function init() {
+
+ myGame.loader.addImageFile('atari1', 'assets/sprites/atari130xe.png');
+ myGame.loader.load();
+
+ }
+
+ physics: NPhysics;
+ c: Circle;
+ t: TileMapCell;
+
+ function create() {
+
+ this.physics = new NPhysics();
+ this.c = new Circle(200, 100, 25);
+ // pos is center, not upper-left
+ this.t = new TileMapCell(200, 500, 100, 100);
+ //this.t.SetState(TileMapCell.TID_FULL);
+ //this.t.SetState(TileMapCell.TID_45DEGpn);
+ //this.t.SetState(TileMapCell.TID_CONCAVEpn);
+ this.t.SetState(TileMapCell.TID_CONVEXpn);
+
+ }
+
+ function update() {
+
+ var fx = 0;
+ var fy = 0;
+
+ if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
+ {
+ fx -= 0.2;
+ }
+ else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
+ {
+ fx += 0.2;
+ }
+
+ if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
+ {
+ fy -= 0.2 + 0.2;
+ }
+ else if (myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN))
+ {
+ fy += 0.2;
+ }
+
+ var p = this.c.pos;
+ var o = this.c.oldpos;
+ var vx = p.x - o.x;
+ var vy = p.y - o.y;
+ var newx = Math.min(20, Math.max(-20, vx+fx));
+ var newy = Math.min(20, Math.max(-20, vy+fy));
+ p.x = o.x + newx;
+ p.y = o.y + newy;
+
+ this.c.IntegrateVerlet();
+ this.c.CollideCircleVsTile(this.t);
+ this.c.CollideCircleVsWorldBounds();
+
+ }
+
+ function render() {
+
+ this.c.render(myGame.stage.context);
+ this.t.render(myGame.stage.context);
+
+ }
+
+})();
diff --git a/Tests/scrollzones/blasteroids.js b/Tests/scrollzones/blasteroids.js
index f484ec2d..24f88c11 100644
--- a/Tests/scrollzones/blasteroids.js
+++ b/Tests/scrollzones/blasteroids.js
@@ -23,6 +23,7 @@
emitter.setRotation(0, 0);
// Looks like a smoke trail!
//emitter.globalCompositeOperation = 'xor';
+ // Looks way cool :)
emitter.globalCompositeOperation = 'lighter';
bullets = myGame.createGroup(50);
// Create our bullet pool
diff --git a/Tests/tilemap/collide with tile.ts b/Tests/tilemap/collide with tile.ts
index 396ed9e3..0653c725 100644
--- a/Tests/tilemap/collide with tile.ts
+++ b/Tests/tilemap/collide with tile.ts
@@ -16,7 +16,8 @@
myGame.loader.load();
}
-
+ var CACTUS = 31;
+ var SIGN_POST = 46;
var map: Phaser.Tilemap;
var car: Phaser.Sprite;
var tile: Phaser.Tile;
@@ -28,10 +29,10 @@
// When the car collides with the cactus tile we'll flash the screen red briefly,
// but it won't stop the car (the separateX/Y values are set to false)
- map.setCollisionByIndex([31], Phaser.Collision.ANY, true, false, false);
+ map.setCollisionByIndex([CACTUS], Phaser.Collision.ANY, true, false, false);
// When the car collides with the sign post tile we'll stop the car moving (separation is set to true)
- map.setCollisionByIndex([46], Phaser.Collision.ANY, true, true, true);
+ map.setCollisionByIndex([SIGN_POST], Phaser.Collision.ANY, true, true, true);
// This is the callback that will be called every time map.collide() returns true
map.collisionCallback = collide;
@@ -79,12 +80,12 @@
// collisionData is an array containing all of the tiles the object overlapped with (can be more than 1)
for (var i = 0; i < collisionData.length; i++)
{
- if (collisionData[i].tile.index == 31)
+ if (collisionData[i].tile.index == CACTUS)
{
console.log('you hit a cactus!');
flash.start(0xff0000, 1);
}
- else if (collisionData[i].tile.index == 31)
+ else if (collisionData[i].tile.index == SIGN_POST)
{
console.log('you hit a sign post!');
}
diff --git a/Tests/tilemap/collision.js b/Tests/tilemap/collision.js
index 86b1c3d1..31d7de69 100644
--- a/Tests/tilemap/collision.js
+++ b/Tests/tilemap/collision.js
@@ -11,7 +11,7 @@
myGame.loader.load();
}
var map;
- var car;
+ var ufo;
var tile;
var emitter;
var test;
@@ -19,6 +19,7 @@
map = myGame.createTilemap('tiles', 'platform', Phaser.Tilemap.FORMAT_TILED_JSON);
map.setCollisionRange(21, 53);
map.setCollisionRange(105, 109);
+ myGame.camera.opaque = true;
myGame.camera.backgroundColor = 'rgb(47,154,204)';
myGame.input.keyboard.addKeyCapture([
Phaser.Keyboard.LEFT,
@@ -26,36 +27,37 @@
Phaser.Keyboard.UP,
Phaser.Keyboard.DOWN
]);
- emitter = myGame.createEmitter(32, 80);
- emitter.width = 700;
- emitter.makeParticles('chunk', 100, false, 1);
- emitter.gravity = 200;
- emitter.bounce = 0.8;
- emitter.start(false, 10, 0.05);
- car = myGame.createSprite(250, 64, 'ufo');
- car.renderRotation = false;
+ //emitter = myGame.createEmitter(32, 80);
+ //emitter.width = 700;
+ //emitter.makeParticles('chunk', 100, false, 1);
+ //emitter.gravity = 200;
+ //emitter.bounce = 0.8;
+ //emitter.start(false, 10, 0.05);
+ ufo = myGame.createSprite(250, 64, 'ufo');
+ ufo.renderDebug = true;
+ ufo.renderRotation = false;
test = myGame.createSprite(200, 64, 'ufo');
test.elasticity = 1;
test.velocity.x = 50;
test.velocity.y = 100;
- car.setBounds(0, 0, map.widthInPixels - 32, map.heightInPixels - 32);
+ ufo.setBounds(0, 0, map.widthInPixels - 32, map.heightInPixels - 32);
}
function update() {
// Collide everything with the map
map.collide();
// And collide everything in the game :)
myGame.collide();
- car.velocity.x = 0;
- car.velocity.y = 0;
+ ufo.velocity.x = 0;
+ ufo.velocity.y = 0;
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
- car.velocity.x = -200;
+ ufo.velocity.x = -200;
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
- car.velocity.x = 200;
+ ufo.velocity.x = 200;
}
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
- car.velocity.y = -200;
+ ufo.velocity.y = -200;
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
- car.velocity.y = 200;
+ ufo.velocity.y = 200;
}
}
})();
diff --git a/Tests/tilemap/collision.ts b/Tests/tilemap/collision.ts
index a3d37616..48d3c91b 100644
--- a/Tests/tilemap/collision.ts
+++ b/Tests/tilemap/collision.ts
@@ -18,7 +18,7 @@
}
var map: Phaser.Tilemap;
- var car: Phaser.Sprite;
+ var ufo: Phaser.Sprite;
var tile: Phaser.Tile;
var emitter: Phaser.Emitter;
var test: Phaser.Sprite;
@@ -29,26 +29,28 @@
map.setCollisionRange(21,53);
map.setCollisionRange(105,109);
+ myGame.camera.opaque = true;
myGame.camera.backgroundColor = 'rgb(47,154,204)';
myGame.input.keyboard.addKeyCapture([Phaser.Keyboard.LEFT, Phaser.Keyboard.RIGHT, Phaser.Keyboard.UP, Phaser.Keyboard.DOWN]);
- emitter = myGame.createEmitter(32, 80);
- emitter.width = 700;
- emitter.makeParticles('chunk', 100, false, 1);
- emitter.gravity = 200;
- emitter.bounce = 0.8;
- emitter.start(false, 10, 0.05);
+ //emitter = myGame.createEmitter(32, 80);
+ //emitter.width = 700;
+ //emitter.makeParticles('chunk', 100, false, 1);
+ //emitter.gravity = 200;
+ //emitter.bounce = 0.8;
+ //emitter.start(false, 10, 0.05);
- car = myGame.createSprite(250, 64, 'ufo');
- car.renderRotation = false;
+ ufo = myGame.createSprite(250, 64, 'ufo');
+ ufo.renderDebug = true;
+ ufo.renderRotation = false;
test = myGame.createSprite(200, 64, 'ufo');
test.elasticity = 1;
test.velocity.x = 50;
test.velocity.y = 100;
- car.setBounds(0, 0, map.widthInPixels - 32, map.heightInPixels - 32);
+ ufo.setBounds(0, 0, map.widthInPixels - 32, map.heightInPixels - 32);
}
@@ -60,25 +62,25 @@
// And collide everything in the game :)
myGame.collide();
- car.velocity.x = 0;
- car.velocity.y = 0;
+ ufo.velocity.x = 0;
+ ufo.velocity.y = 0;
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
- car.velocity.x = -200;
+ ufo.velocity.x = -200;
}
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
- car.velocity.x = 200;
+ ufo.velocity.x = 200;
}
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
{
- car.velocity.y = -200;
+ ufo.velocity.y = -200;
}
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN))
{
- car.velocity.y = 200;
+ ufo.velocity.y = 200;
}
}
diff --git a/build/phaser.d.ts b/build/phaser.d.ts
index 6fcb1ad4..d139098b 100644
--- a/build/phaser.d.ts
+++ b/build/phaser.d.ts
@@ -460,6 +460,8 @@ module Phaser {
* Destroy all objects and references belonging to this CollisionMask
*/
public destroy(): void;
+ public intersectsRaw(left: number, right: number, top: number, bottom: number): bool;
+ public intersectsVector(vector: Vector2): bool;
/**
* 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.
@@ -916,6 +918,7 @@ module Phaser {
* Clean up memory.
*/
public destroy(): void;
+ public setPosition(x: number, y: number): void;
public x : number;
public y : number;
public rotation : number;
@@ -1235,9 +1238,10 @@ module Phaser {
/**
* Load graphic for this sprite. (graphic can be SpriteSheet or Texture)
* @param key {string} Key of the graphic you want to load for this sprite.
+ * @param clearAnimations {boolean} If this Sprite has a set of animation data already loaded you can choose to keep or clear it with this boolean
* @return {Sprite} Sprite instance itself.
*/
- public loadGraphic(key: string): Sprite;
+ public loadGraphic(key: string, clearAnimations?: bool): Sprite;
/**
* Load a DynamicTexture as its texture.
* @param texture {DynamicTexture} The texture object to be used by this sprite.
@@ -1696,6 +1700,10 @@ module Phaser {
public frameTotal : number;
public frame : number;
public frameName : string;
+ /**
+ * Removes all related references
+ */
+ public destroy(): void;
}
}
/**
@@ -1840,9 +1848,6 @@ module Phaser {
*
* Your game only has one CameraManager instance and it's responsible for looking after, creating and destroying
* all of the cameras in the world.
-*
-* TODO: If the Camera is larger than the Stage size then the rotation offset isn't correct
-* TODO: Texture Repeat doesn't scroll, because it's part of the camera not the world, need to think about this more
*/
module Phaser {
class CameraManager {
@@ -2573,6 +2578,33 @@ module Phaser {
}
}
/**
+* Phaser - Polygon
+*
+*/
+module Phaser {
+ class Polygon {
+ /**
+ * A *convex* clockwise polygon
+ * @class Polygon
+ * @constructor
+ * @param {Vector2} pos A vector representing the origin of the polygon (all other points are relative to this one)
+ * @param {Array.} points An Array of vectors representing the points in the polygon, in clockwise order.
+ **/
+ constructor(pos?: Vector2, points?: Vector2[], parent?: any);
+ public parent: any;
+ public pos: Vector2;
+ public points: Vector2[];
+ public edges: Vector2[];
+ public normals: Vector2[];
+ /**
+ * Recalculate the edges and normals of the polygon. This
+ * MUST be called if the points array is modified at all and
+ * the edges or normals are to be accessed.
+ */
+ public recalc(): void;
+ }
+}
+/**
* Phaser - Quad
*
* A Quad object is an area defined by its position, as indicated by its top-left corner (x,y) and width and height.
@@ -2621,6 +2653,17 @@ module Phaser {
**/
public intersects(quad, tolerance?: number): bool;
/**
+ * Determines whether the object specified intersects (overlaps) with the given values.
+ * @method intersectsProps
+ * @param {Number} left
+ * @param {Number} right
+ * @param {Number} top
+ * @param {Number} bottomt
+ * @param {Number} tolerance 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 Quad; otherwise false.
+ **/
+ public intersectsRaw(left: number, right: number, top: number, bottom: number, tolerance?: number): bool;
+ /**
* Determines whether the specified coordinates are contained within the region defined by this Quad object.
* @method contains
* @param {Number} x The x coordinate of the point to test.
@@ -2643,6 +2686,12 @@ module Phaser {
**/
public copyTo(target): any;
/**
+ * Creates and returns a Polygon that is the same as this Quad.
+ * @method toPolygon
+ * @return {Polygon} A new Polygon that represents this quad.
+ **/
+ public toPolygon(): Polygon;
+ /**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the object.
@@ -2669,6 +2718,7 @@ module Phaser {
constructor(x?: number, y?: number, diameter?: number);
private _diameter;
private _radius;
+ private _pos;
/**
* The x coordinate of the center of the circle
* @property x
@@ -2682,6 +2732,12 @@ module Phaser {
**/
public y: number;
/**
+ * The position of this Circle object represented by a Vector2
+ * @property pos
+ * @type Vector2
+ **/
+ public pos : Vector2;
+ /**
* The diameter of the circle. The largest distance between any two points on the circle. The same as the radius * 2.
* @method diameter
* @return {Number}
@@ -3100,6 +3156,274 @@ module Phaser {
}
}
/**
+* Phaser - Response
+*
+*/
+module Phaser {
+ class Response {
+ /**
+ * An object representing the result of an intersection. Contain information about:
+ * - The two objects participating in the intersection
+ * - The vector representing the minimum change necessary to extract the first object
+ * from the second one.
+ * - Whether the first object is entirely inside the second, or vice versa.
+ *
+ * @constructor
+ */
+ constructor();
+ /**
+ * The first object in the collision
+ */
+ public a;
+ /**
+ * The second object in the collision
+ */
+ public b;
+ /**
+ * The shortest colliding axis (unit-vector)
+ */
+ public overlapN: Vector2;
+ /**
+ * The overlap vector (i.e. overlapN.scale(overlap, overlap)).
+ * If this vector is subtracted from the position of `a`, `a` and `b` will no longer be colliding.
+ */
+ public overlapV: Vector2;
+ /**
+ * Whether the first object is completely inside the second.
+ */
+ public aInB: bool;
+ /**
+ * Whether the second object is completely inside the first.
+ */
+ public bInA: bool;
+ /**
+ * Magnitude of the overlap on the shortest colliding axis
+ */
+ public overlap: number;
+ /**
+ * Set some values of the response back to their defaults. Call this between tests if
+ * you are going to reuse a single Response object for multiple intersection tests (recommented)
+ *
+ * @return {Response} This for chaining
+ */
+ public clear(): Response;
+ }
+}
+/**
+* Phaser - Vector2
+*
+* A two dimensional vector.
+* Contains methods and ideas from verlet-js by Sub Protocol, SAT.js by Jim Riecken and N by Metanet Software.
+*/
+module Phaser {
+ class Vector2 {
+ /**
+ * Creates a new Vector2 object.
+ * @class Vector2
+ * @constructor
+ * @param {Number} x The x position of the vector
+ * @param {Number} y The y position of the vector
+ * @return {Vector2} This object
+ **/
+ constructor(x?: number, y?: number);
+ public x: number;
+ public y: number;
+ public setTo(x: number, y: number): Vector2;
+ /**
+ * Add this vector to the given one and return the result.
+ *
+ * @param {Vector2} v The other Vector.
+ * @param {Vector2} The output Vector.
+ * @return {Vector2} The new Vector
+ */
+ public add(v: Vector2, output?: Vector2): Vector2;
+ /**
+ * Subtract this vector to the given one and return the result.
+ *
+ * @param {Vector2} v The other Vector.
+ * @param {Vector2} The output Vector.
+ * @return {Vector2} The new Vector
+ */
+ public sub(v: Vector2, output?: Vector2): Vector2;
+ /**
+ * Multiply this vector with the given one and return the result.
+ *
+ * @param {Vector2} v The other Vector.
+ * @param {Vector2} The output Vector.
+ * @return {Vector2} The new Vector
+ */
+ public mul(v: Vector2, output?: Vector2): Vector2;
+ /**
+ * Divide this vector by the given one and return the result.
+ *
+ * @param {Vector2} v The other Vector.
+ * @param {Vector2} The output Vector.
+ * @return {Vector2} The new Vector
+ */
+ public div(v: Vector2, output?: Vector2): Vector2;
+ /**
+ * Scale this vector by the given values and return the result.
+ *
+ * @param {number} x The scaling factor in the x direction.
+ * @param {?number=} y The scaling factor in the y direction. If this
+ * is not specified, the x scaling factor will be used.
+ * @return {Vector} The new Vector
+ */
+ public scale(x: number, y?: number, output?: Vector2): Vector2;
+ /**
+ * Rotate this vector by 90 degrees
+ *
+ * @return {Vector} This for chaining.
+ */
+ public perp(output?: Vector2): Vector2;
+ public mutableSet(v: Vector2): Vector2;
+ /**
+ * Add another vector to this one.
+ *
+ * @param {Vector} other The other Vector.
+ * @return {Vector} This for chaining.
+ */
+ public mutableAdd(v: Vector2): Vector2;
+ /**
+ * Subtract another vector from this one.
+ *
+ * @param {Vector} other The other Vector.
+ * @return {Vector} This for chaining.
+ */
+ public mutableSub(v: Vector2): Vector2;
+ /**
+ * Multiply another vector with this one.
+ *
+ * @param {Vector} other The other Vector.
+ * @return {Vector} This for chaining.
+ */
+ public mutableMul(v: Vector2): Vector2;
+ /**
+ * Divide this vector by another one.
+ *
+ * @param {Vector} other The other Vector.
+ * @return {Vector} This for chaining.
+ */
+ public mutableDiv(v: Vector2): Vector2;
+ /**
+ * Scale this vector.
+ *
+ * @param {number} x The scaling factor in the x direction.
+ * @param {?number=} y The scaling factor in the y direction. If this
+ * is not specified, the x scaling factor will be used.
+ * @return {Vector} This for chaining.
+ */
+ public mutableScale(x: number, y?: number): Vector2;
+ /**
+ * Reverse this vector.
+ *
+ * @return {Vector} This for chaining.
+ */
+ public reverse(): Vector2;
+ public edge(v: Vector2, output?: Vector2): Vector2;
+ public equals(v: Vector2): bool;
+ public epsilonEquals(v: Vector2, epsilon: number): bool;
+ /**
+ * Get the length of this vector.
+ *
+ * @return {number} The length of this vector.
+ */
+ public length(): number;
+ /**
+ * Get the length^2 of this vector.
+ *
+ * @return {number} The length^2 of this vector.
+ */
+ public length2(): number;
+ /**
+ * Get the distance between this vector and the given vector.
+ *
+ * @return {Vector2} v The vector to check
+ */
+ public distance(v: Vector2): number;
+ /**
+ * Get the distance^2 between this vector and the given vector.
+ *
+ * @return {Vector2} v The vector to check
+ */
+ public distance2(v: Vector2): number;
+ /**
+ * Project this vector on to another vector.
+ *
+ * @param {Vector} other The vector to project onto.
+ * @return {Vector} This for chaining.
+ */
+ public project(other: Vector2): Vector2;
+ /**
+ * Project this vector onto a vector of unit length.
+ *
+ * @param {Vector} other The unit vector to project onto.
+ * @return {Vector} This for chaining.
+ */
+ public projectN(other: Vector2): Vector2;
+ /**
+ * Reflect this vector on an arbitrary axis.
+ *
+ * @param {Vector} axis The vector representing the axis.
+ * @return {Vector} This for chaining.
+ */
+ public reflect(axis): Vector2;
+ /**
+ * Reflect this vector on an arbitrary axis (represented by a unit vector)
+ *
+ * @param {Vector} axis The unit vector representing the axis.
+ * @return {Vector} This for chaining.
+ */
+ public reflectN(axis): Vector2;
+ public getProjectionMagnitude(v: Vector2): number;
+ public direction(output?: Vector2): Vector2;
+ public normalRightHand(output?: Vector2): Vector2;
+ /**
+ * Normalize (make unit length) this vector.
+ *
+ * @return {Vector} This for chaining.
+ */
+ public normalize(output?: Vector2): Vector2;
+ public getMagnitude(): number;
+ /**
+ * Get the dot product of this vector against another.
+ *
+ * @param {Vector} other The vector to dot this one against.
+ * @return {number} The dot product.
+ */
+ public dot(v: Vector2): number;
+ /**
+ * Get the cross product of this vector against another.
+ *
+ * @param {Vector} other The vector to cross this one against.
+ * @return {number} The cross product.
+ */
+ public cross(v: Vector2): number;
+ /**
+ * Get the angle between this vector and the given vector.
+ *
+ * @return {Vector2} v The vector to check
+ */
+ public angle(v: Vector2): number;
+ public angle2(vLeft: Vector2, vRight: Vector2): number;
+ /**
+ * Rotate this vector around the origin to the given angle (theta) and return the result in a new Vector
+ *
+ * @return {Vector2} v The vector to check
+ */
+ public rotate(origin, theta, output?: Vector2): Vector2;
+ public clone(output?: Vector2): Vector2;
+ public copyFrom(v: Vector2): Vector2;
+ public copyTo(v: Vector2): Vector2;
+ /**
+ * Returns a string representation of this object.
+ * @method toString
+ * @return {string} a string representation of the object.
+ **/
+ public toString(): string;
+ }
+}
+/**
* Phaser - LinkedList
*
* A miniature linked list class. Useful for optimizing time-critical or highly repetitive tasks!
@@ -3576,6 +3900,20 @@ module Phaser {
static separateTileY(object: GameObject, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool;
/**
* Separates the two objects on their x axis
+ * @param object The GameObject to separate
+ * @param tile The Tile to separate
+ * @returns {boolean} Whether the objects in fact touched and were separated along the X axis.
+ */
+ static NEWseparateTileX(object: GameObject, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool;
+ /**
+ * Separates the two objects on their y axis
+ * @param object The first GameObject to separate
+ * @param tile The second GameObject to separate
+ * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis.
+ */
+ static NEWseparateTileY(object: GameObject, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool;
+ /**
+ * Separates the two objects on their x axis
* @param object1 The first GameObject to separate
* @param object2 The second GameObject to separate
* @returns {boolean} Whether the objects in fact touched and were separated along the X axis.
@@ -3589,20 +3927,6 @@ module Phaser {
*/
static separateY(object1, object2): bool;
/**
- * Separates the two objects on their x axis
- * @param object1 The first GameObject to separate
- * @param object2 The second GameObject to separate
- * @returns {boolean} Whether the objects in fact touched and were separated along the X axis.
- */
- static OLDseparateX(object1, object2): bool;
- /**
- * Separates the two objects on their y axis
- * @param object1 The first GameObject to separate
- * @param object2 The second GameObject to separate
- * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis.
- */
- static OLDseparateY(object1, object2): bool;
- /**
* Returns the distance between the two given coordinates.
* @param x1 The X value of the first coordinate
* @param y1 The Y value of the first coordinate
@@ -3620,6 +3944,108 @@ module Phaser {
* @returns {number} The distance between the two coordinates
*/
static distanceSquared(x1: number, y1: number, x2: number, y2: number): number;
+ /**
+ * Flattens the specified array of points onto a unit vector axis,
+ * resulting in a one dimensional range of the minimum and
+ * maximum value on that axis.
+ *
+ * @param {Array.} points The points to flatten.
+ * @param {Vector} normal The unit vector axis to flatten on.
+ * @param {Array.} result An array. After calling this function,
+ * result[0] will be the minimum value,
+ * result[1] will be the maximum value.
+ */
+ static flattenPointsOn(points, normal, result): void;
+ /**
+ * Pool of Vectors used in calculations.
+ *
+ * @type {Array.}
+ */
+ static T_VECTORS: Vector2[];
+ /**
+ * Pool of Arrays used in calculations.
+ *
+ * @type {Array.>}
+ */
+ static T_ARRAYS;
+ /**
+ * Check whether two convex clockwise polygons are separated by the specified
+ * axis (must be a unit vector).
+ *
+ * @param {Vector} aPos The position of the first polygon.
+ * @param {Vector} bPos The position of the second polygon.
+ * @param {Array.} aPoints The points in the first polygon.
+ * @param {Array.} bPoints The points in the second polygon.
+ * @param {Vector} axis The axis (unit sized) to test against. The points of both polygons
+ * will be projected onto this axis.
+ * @param {Response=} response A Response object (optional) which will be populated
+ * if the axis is not a separating axis.
+ * @return {boolean} true if it is a separating axis, false otherwise. If false,
+ * and a response is passed in, information about how much overlap and
+ * the direction of the overlap will be populated.
+ */
+ static isSeparatingAxis(aPos, bPos, aPoints, bPoints, axis, response?: Response): bool;
+ static LEFT_VORNOI_REGION: number;
+ static MIDDLE_VORNOI_REGION: number;
+ static RIGHT_VORNOI_REGION: number;
+ /**
+ * Calculates which Vornoi region a point is on a line segment.
+ * It is assumed that both the line and the point are relative to (0, 0)
+ *
+ * | (0) |
+ * (-1) [0]--------------[1] (1)
+ * | (0) |
+ *
+ * @param {Vector} line The line segment.
+ * @param {Vector} point The point.
+ * @return {number} LEFT_VORNOI_REGION (-1) if it is the left region,
+ * MIDDLE_VORNOI_REGION (0) if it is the middle region,
+ * RIGHT_VORNOI_REGION (1) if it is the right region.
+ */
+ static vornoiRegion(line: Vector2, point: Vector2): number;
+ /**
+ * Check if two circles intersect.
+ *
+ * @param {Circle} a The first circle.
+ * @param {Circle} b The second circle.
+ * @param {Response=} response Response object (optional) that will be populated if
+ * the circles intersect.
+ * @return {boolean} true if the circles intersect, false if they don't.
+ */
+ static testCircleCircle(a: Circle, b: Circle, response?: Response): bool;
+ /**
+ * Check if a polygon and a circle intersect.
+ *
+ * @param {Polygon} polygon The polygon.
+ * @param {Circle} circle The circle.
+ * @param {Response=} response Response object (optional) that will be populated if
+ * they interset.
+ * @return {boolean} true if they intersect, false if they don't.
+ */
+ static testPolygonCircle(polygon: Polygon, circle: Circle, response?: Response): bool;
+ /**
+ * Check if a circle and a polygon intersect.
+ *
+ * NOTE: This runs slightly slower than polygonCircle as it just
+ * runs polygonCircle and reverses everything at the end.
+ *
+ * @param {Circle} circle The circle.
+ * @param {Polygon} polygon The polygon.
+ * @param {Response=} response Response object (optional) that will be populated if
+ * they interset.
+ * @return {boolean} true if they intersect, false if they don't.
+ */
+ static testCirclePolygon(circle: Circle, polygon: Polygon, response?: Response): bool;
+ /**
+ * Checks whether two convex, clockwise polygons intersect.
+ *
+ * @param {Polygon} a The first polygon.
+ * @param {Polygon} b The second polygon.
+ * @param {Response=} response Response object (optional) that will be populated if
+ * they interset.
+ * @return {boolean} true if they intersect, false if they don't.
+ */
+ static testPolygonPolygon(a: Polygon, b: Polygon, response?: Response): bool;
}
}
/**
@@ -4269,14 +4695,173 @@ module Phaser {
**/
static distanceBetween(x1: number, y1: number, x2: number, y2: number): number;
/**
- * Rotates a point around the x/y coordinates given to the desired angle
+ * Rotates the point around the x/y coordinates given to the desired angle and distance
+ * @param point {Object} Any object with exposed x and y properties
* @param x {number} The x coordinate of the anchor point
* @param y {number} The y coordinate of the anchor point
- * @param angle {number} The angle of the rotation in radians
- * @param point {Point} The point object to perform the rotation on
+ * @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from.
+ * @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)?
+ * @param {Number} distance An optional distance constraint between the point and the anchor
* @return The modified point object
*/
- public rotatePoint(x: number, y: number, angle: number, point);
+ public rotatePoint(point, x1: number, y1: number, angle: number, asDegrees?: bool, distance?: number);
+ }
+}
+/**
+* Phaser - GameObjectFactory
+*
+* A quick way to create new world objects and add existing objects to the current world.
+*/
+module Phaser {
+ class GameObjectFactory {
+ /**
+ * GameObjectFactory constructor
+ * @param game {Game} A reference to the current Game.
+ */
+ constructor(game: Game);
+ /**
+ * Local private reference to Game
+ */
+ private _game;
+ /**
+ * Local private reference to World
+ */
+ private _world;
+ /**
+ * Create a new camera with specific position and size.
+ *
+ * @param x {number} X position of the new camera.
+ * @param y {number} Y position of the new camera.
+ * @param width {number} Width of the new camera.
+ * @param height {number} Height of the new camera.
+ * @returns {Camera} The newly created camera object.
+ */
+ public camera(x: number, y: number, width: number, height: number): Camera;
+ /**
+ * Create a new GeomSprite with specific position.
+ *
+ * @param x {number} X position of the new geom sprite.
+ * @param y {number} Y position of the new geom sprite.
+ * @returns {GeomSprite} The newly created geom sprite object.
+ */
+ public geomSprite(x: number, y: number): GeomSprite;
+ /**
+ * Create a new Sprite with specific position and sprite sheet key.
+ *
+ * @param x {number} X position of the new sprite.
+ * @param y {number} Y position of the new sprite.
+ * @param key {string} Optional, key for the sprite sheet you want it to use.
+ * @returns {Sprite} The newly created sprite object.
+ */
+ public sprite(x: number, y: number, key?: string): Sprite;
+ /**
+ * Create a new DynamicTexture with specific size.
+ *
+ * @param width {number} Width of the texture.
+ * @param height {number} Height of the texture.
+ * @returns {DynamicTexture} The newly created dynamic texture object.
+ */
+ public dynamicTexture(width: number, height: number): DynamicTexture;
+ /**
+ * Create a new object container.
+ *
+ * @param maxSize {number} Optional, capacity of this group.
+ * @returns {Group} The newly created group.
+ */
+ public group(maxSize?: number): Group;
+ /**
+ * Create a new Particle.
+ *
+ * @return {Particle} The newly created particle object.
+ */
+ public particle(): Particle;
+ /**
+ * Create a new Emitter.
+ *
+ * @param x {number} Optional, x position of the emitter.
+ * @param y {number} Optional, y position of the emitter.
+ * @param size {number} Optional, size of this emitter.
+ * @return {Emitter} The newly created emitter object.
+ */
+ public emitter(x?: number, y?: number, size?: number): Emitter;
+ /**
+ * Create a new ScrollZone object with image key, position and size.
+ *
+ * @param key {string} Key to a image you wish this object to use.
+ * @param x {number} X position of this object.
+ * @param y {number} Y position of this object.
+ * @param width number} Width of this object.
+ * @param height {number} Height of this object.
+ * @returns {ScrollZone} The newly created scroll zone object.
+ */
+ public scrollZone(key: string, x?: number, y?: number, width?: number, height?: number): ScrollZone;
+ /**
+ * Create a new Tilemap.
+ *
+ * @param key {string} Key for tileset image.
+ * @param mapData {string} Data of this tilemap.
+ * @param format {number} Format of map data. (Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON)
+ * @param [resizeWorld] {boolean} resize the world to make same as tilemap?
+ * @param [tileWidth] {number} width of each tile.
+ * @param [tileHeight] {number} height of each tile.
+ * @return {Tilemap} The newly created tilemap object.
+ */
+ public tilemap(key: string, mapData: string, format: number, resizeWorld?: bool, tileWidth?: number, tileHeight?: number): Tilemap;
+ /**
+ * Create a tween object for a specific object.
+ *
+ * @param obj Object you wish the tween will affect.
+ * @return {Phaser.Tween} The newly created tween object.
+ */
+ public tween(obj): Tween;
+ /**
+ * Add an existing Sprite to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param sprite The Sprite to add to the Game World
+ * @return {Phaser.Sprite} The Sprite object
+ */
+ public existingSprite(sprite: Sprite): Sprite;
+ /**
+ * Add an existing GeomSprite to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param sprite The GeomSprite to add to the Game World
+ * @return {Phaser.GeomSprite} The GeomSprite object
+ */
+ public existingGeomSprite(sprite: GeomSprite): GeomSprite;
+ /**
+ * Add an existing Emitter to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param emitter The Emitter to add to the Game World
+ * @return {Phaser.Emitter} The Emitter object
+ */
+ public existingEmitter(emitter: Emitter): Emitter;
+ /**
+ * Add an existing ScrollZone to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param scrollZone The ScrollZone to add to the Game World
+ * @return {Phaser.ScrollZone} The ScrollZone object
+ */
+ public existingScrollZone(scrollZone: ScrollZone): ScrollZone;
+ /**
+ * Add an existing Tilemap to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param tilemap The Tilemap to add to the Game World
+ * @return {Phaser.Tilemap} The Tilemap object
+ */
+ public existingTilemap(tilemap: Tilemap): Tilemap;
+ /**
+ * Add an existing Tween to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param tween The Tween to add to the Game World
+ * @return {Phaser.Tween} The Tween object
+ */
+ public existingTween(tween: Tween): Tween;
}
}
/**
@@ -4336,6 +4921,27 @@ module Phaser {
*/
public alpha: number;
/**
+ * An Array of Cameras to which this Group, or any of its children, won't render
+ * @type {Array}
+ */
+ public cameraBlacklist: number[];
+ /**
+ * If you do not wish this object to be visible to a specific camera, pass the camera here.
+ *
+ * @param camera {Camera} The specific camera.
+ */
+ public hideFromCamera(camera: Camera): void;
+ /**
+ * Make this object only visible to a specific camera.
+ *
+ * @param camera {Camera} The camera you wish it to be visible.
+ */
+ public showToCamera(camera: Camera): void;
+ /**
+ * This clears the camera black list, making the GameObject visible to all cameras.
+ */
+ public clearCameraList(): void;
+ /**
* Override this function to handle any deleting or "shutdown" type operations you might need,
* such as removing traditional Flash children like Basic objects.
*/
@@ -4581,6 +5187,11 @@ module Phaser {
*/
public progress: number;
/**
+ * The crossOrigin value applied to loaded images
+ * @type {string}
+ */
+ public crossOrigin: string;
+ /**
* Reset loader, this will remove all loaded assets.
*/
public reset(): void;
@@ -4962,7 +5573,7 @@ module Phaser {
/**
* Phaser
*
-* v0.9.5 - April 28th 2013
+* v0.9.6 - May 21st 2013
*
* A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi.
*
@@ -5307,6 +5918,8 @@ module Phaser {
* This method is called when the canvas elements visibility is changed.
*/
private visibilityChange(event);
+ public pauseGame(): void;
+ public resumeGame(): void;
/**
* Get the DOM offset values of the given element
*/
@@ -5771,55 +6384,6 @@ module Phaser {
}
}
/**
-* Phaser - Vector2
-*
-* A simple 2-dimensional vector class. Based on the one included with verlet-js by Sub Protocol released under MIT
-*/
-module Phaser {
- class Vector2 {
- /**
- * Creates a new Vector2 object.
- * @class Vector2
- * @constructor
- * @param {Number} x The x coordinate of vector2
- * @param {Number} y The y coordinate of vector2
- * @return {Vector2} This object
- **/
- constructor(x?: number, y?: number);
- public x: number;
- public y: number;
- public setTo(x: number, y: number): Vector2;
- public add(v: Vector2, output?: Vector2): Vector2;
- public sub(v: Vector2, output?: Vector2): Vector2;
- public mul(v: Vector2, output?: Vector2): Vector2;
- public div(v: Vector2, output?: Vector2): Vector2;
- public scale(coef: number, output?: Vector2): Vector2;
- public mutableSet(v: Vector2): Vector2;
- public mutableAdd(v: Vector2): Vector2;
- public mutableSub(v: Vector2): Vector2;
- public mutableMul(v: Vector2): Vector2;
- public mutableDiv(v: Vector2): Vector2;
- public mutableScale(coef: number): Vector2;
- public equals(v: Vector2): bool;
- public epsilonEquals(v: Vector2, epsilon: number): bool;
- public length(): number;
- public length2(): number;
- public dist(v: Vector2): number;
- public dist2(v: Vector2): number;
- public normal(output?: Vector2): Vector2;
- public dot(v: Vector2): number;
- public angle(v: Vector2): number;
- public angle2(vLeft: Vector2, vRight: Vector2): number;
- public rotate(origin, theta, output?: Vector2): Vector2;
- /**
- * Returns a string representation of this object.
- * @method toString
- * @return {string} a string representation of the object.
- **/
- public toString(): string;
- }
-}
-/**
* Phaser - Verlet - Particle
*
*
@@ -5879,6 +6443,26 @@ module Phaser.Verlet {
**/
constructor(game: Game);
private _game;
+ /**
+ * Texture of the particles to be rendered.
+ */
+ private _texture;
+ /**
+ * Rendering bounds for the texture
+ * @type {Quad}
+ */
+ private frameBounds;
+ private _sx;
+ private _sy;
+ private _sw;
+ private _sh;
+ private _dx;
+ private _dy;
+ private _dw;
+ private _dh;
+ private _hw;
+ private _hh;
+ public sprites: Sprite[];
public particles: Particle[];
public constraints;
public drawParticles;
@@ -5886,6 +6470,16 @@ module Phaser.Verlet {
public createDistanceConstraint(a: Particle, b: Particle, stiffness: number, distance?: number): DistanceConstraint;
public createAngleConstraint(a: Particle, b: Particle, c: Particle, stiffness: number): AngleConstraint;
public createPinConstraint(a: Particle, pos: Vector2): PinConstraint;
+ /**
+ * Load a graphic for this Composite. The graphic cannot be a SpriteSheet yet.
+ * @param key {string} Key of the graphic you want to load for this sprite.
+ * @return {Composite} This object
+ */
+ public loadGraphic(key: string): Composite;
+ public hideConstraints: bool;
+ public constraintLineColor: string;
+ private renderConstraints(context);
+ private render(context);
public pin(index, pos?): PinConstraint;
}
}
@@ -5955,6 +6549,7 @@ module Phaser.Verlet {
**/
constructor(game: Game, width: number, height: number);
private _game;
+ private _v;
public composites: any[];
public width: number;
public height: number;
@@ -5966,28 +6561,26 @@ module Phaser.Verlet {
public draggedEntity;
public highlightColor: string;
/**
- * This class is actually a wrapper of canvas.
+ * A reference to the canvas this renders to
* @type {HTMLCanvasElement}
*/
public canvas: HTMLCanvasElement;
/**
- * Canvas context of this object.
+ * A reference to the context this renders to
* @type {CanvasRenderingContext2D}
*/
public context: CanvasRenderingContext2D;
/**
* Computes time of intersection of a particle with a wall
*
- * @param {Vec2} line wall's root position
- * @param {Vec2} p particle's position
- * @param {Vec2} dir walls's direction
- * @param {Vec2} v particle's velocity
+ * @param {Vec2} line walls root position
+ * @param {Vec2} p particle position
+ * @param {Vec2} dir walls direction
+ * @param {Vec2} v particles velocity
*/
public intersectionTime(wall, p, dir, v): number;
public intersectionPoint(wall, p, dir, v): Vector2;
- private v;
public bounds(particle: Particle): void;
- public OLDbounds(particle: Particle): void;
public createPoint(pos: Vector2): Composite;
public createLineSegments(vertices, stiffness): Composite;
public createCloth(origin, width, height, segments, pinMod, stiffness): Composite;
@@ -5996,6 +6589,7 @@ module Phaser.Verlet {
private mouseDownHandler();
private mouseUpHandler();
public nearestEntity();
+ public hideNearestEntityCircle: bool;
public render(): void;
}
}
@@ -6055,13 +6649,14 @@ module Phaser {
public destroy(): void;
/**
* Update size of this world with specific width and height.
- * You can choose update camera bounds automatically or not.
+ * You can choose update camera bounds and verlet manager automatically or not.
*
* @param width {number} New width of the world.
* @param height {number} New height of the world.
* @param [updateCameraBounds] {boolean} update camera bounds automatically or not. Default to true.
+ * @param [updateVerletBounds] {boolean} update verlet bounds automatically or not. Default to true.
*/
- public setSize(width: number, height: number, updateCameraBounds?: bool): void;
+ public setSize(width: number, height: number, updateCameraBounds?: bool, updateVerletBounds?: bool): void;
public width : number;
public height : number;
public centerX : number;
@@ -6672,17 +7267,17 @@ module Phaser {
*/
public active: bool;
/**
- * A Point object representing the x/y screen coordinates of the Pointer.
- * @property pointA
- * @type {Point}
+ * A Vector object containing the initial position when the Pointer was engaged with the screen.
+ * @property positionDown
+ * @type {Vector2}
**/
- public pointA: Point;
+ public positionDown: Vector2;
/**
- * A Point object representing the x/y screen coordinates of the Pointer.
- * @property pointB
- * @type {Point}
+ * A Vector object containing the current position of the Pointer on the screen.
+ * @property position
+ * @type {Vector2}
**/
- public pointB: Point;
+ public position: Vector2;
/**
* A Circle object centered on the x/y screen coordinates of the Pointer.
* Default size of 44px (Apple's recommended "finger tip" size)
@@ -7026,11 +7621,11 @@ module Phaser {
*/
public gestures: Gestures;
/**
- * A Point object representing the x/y screen coordinates of the Pointer.
- * @property point
- * @type {Point}
+ * A vector object representing the current position of the Pointer.
+ * @property vector
+ * @type {Vector2}
**/
- public point: Point;
+ public position: Vector2;
/**
* A Circle object centered on the x/y screen coordinates of the Input.
* Default size of 44px (Apples recommended "finger tip" size) but can be changed to anything
@@ -7221,7 +7816,22 @@ module Phaser {
* @type {Number}
**/
public y : number;
+ /**
+ * Add a new Pointer object to the Input Manager. By default Input creates 5 pointer objects for you. If you need more
+ * use this to create a new one, up to a maximum of 10.
+ * @method addPointer
+ * @return {Pointer} A reference to the new Pointer object
+ **/
+ public addPointer(): Pointer;
+ /**
+ * Starts the Input Manager running
+ * @method start
+ **/
public start(): void;
+ /**
+ * Updates the Input Manager. Called by the core Game loop.
+ * @method update
+ **/
public update(): void;
/**
* Reset all of the Pointers and Input states
@@ -7290,6 +7900,20 @@ module Phaser {
* @param {String} [color]
*/
public renderDebugInfo(x: number, y: number, color?: string): void;
+ /**
+ * Get the distance between two Pointer objects
+ * @method getDistance
+ * @param {Pointer} pointer1
+ * @param {Pointer} pointer2
+ **/
+ public getDistance(pointer1: Pointer, pointer2: Pointer): number;
+ /**
+ * Get the angle between two Pointer objects
+ * @method getAngle
+ * @param {Pointer} pointer1
+ * @param {Pointer} pointer2
+ **/
+ public getAngle(pointer1: Pointer, pointer2: Pointer): number;
}
}
/**
@@ -7812,6 +8436,11 @@ module Phaser {
*/
static RECTANGLE: number;
/**
+ * Polygon.
+ * @type {number}
+ */
+ static POLYGON: number;
+ /**
* Circle shape container. A Circle instance.
* @type {Circle}
*/
@@ -7832,6 +8461,11 @@ module Phaser {
*/
public rect: Rectangle;
/**
+ * Polygon shape container. A Polygon instance.
+ * @type {Polygon}
+ */
+ public polygon: Polygon;
+ /**
* Render outline of this sprite or not. (default is true)
* @type {boolean}
*/
@@ -7906,6 +8540,13 @@ module Phaser {
*/
public createRectangle(width: number, height: number): GeomSprite;
/**
+ * Create a polygon object
+ * @param width {Number} Width of the rectangle
+ * @param height {Number} Height of the rectangle
+ * @return {GeomSprite} GeomSprite instance.
+ */
+ public createPolygon(points?: Vector2[]): GeomSprite;
+ /**
* Destroy all geom shapes of this sprite.
*/
public refresh(): void;
@@ -8809,6 +9450,11 @@ module Phaser {
*/
public onDestroyCallback;
/**
+ * Reference to the GameObject Factory.
+ * @type {GameObjectFactory}
+ */
+ public add: GameObjectFactory;
+ /**
* Reference to the assets cache.
* @type {Cache}
*/
@@ -8874,7 +9520,7 @@ module Phaser {
*/
public rnd: RandomDataGenerator;
/**
- * Device detector.
+ * Contains device information and capabilities.
* @type {Device}
*/
public device: Device;
@@ -8938,93 +9584,6 @@ module Phaser {
public paused : bool;
public framerate : number;
/**
- * Create a new camera with specific position and size.
- *
- * @param x {number} X position of the new camera.
- * @param y {number} Y position of the new camera.
- * @param width {number} Width of the new camera.
- * @param height {number} Height of the new camera.
- * @returns {Camera} The newly created camera object.
- */
- public createCamera(x: number, y: number, width: number, height: number): Camera;
- /**
- * Create a new GeomSprite with specific position.
- *
- * @param x {number} X position of the new geom sprite.
- * @param y {number} Y position of the new geom sprite.
- * @returns {GeomSprite} The newly created geom sprite object.
- */
- public createGeomSprite(x: number, y: number): GeomSprite;
- /**
- * Create a new Sprite with specific position and sprite sheet key.
- *
- * @param x {number} X position of the new sprite.
- * @param y {number} Y position of the new sprite.
- * @param key {string} Optional, key for the sprite sheet you want it to use.
- * @returns {Sprite} The newly created sprite object.
- */
- public createSprite(x: number, y: number, key?: string): Sprite;
- /**
- * Create a new DynamicTexture with specific size.
- *
- * @param width {number} Width of the texture.
- * @param height {number} Height of the texture.
- * @returns {DynamicTexture} The newly created dynamic texture object.
- */
- public createDynamicTexture(width: number, height: number): DynamicTexture;
- /**
- * Create a new object container.
- *
- * @param maxSize {number} Optional, capacity of this group.
- * @returns {Group} The newly created group.
- */
- public createGroup(maxSize?: number): Group;
- /**
- * Create a new Particle.
- *
- * @return {Particle} The newly created particle object.
- */
- public createParticle(): Particle;
- /**
- * Create a new Emitter.
- *
- * @param x {number} Optional, x position of the emitter.
- * @param y {number} Optional, y position of the emitter.
- * @param size {number} Optional, size of this emitter.
- * @return {Emitter} The newly created emitter object.
- */
- public createEmitter(x?: number, y?: number, size?: number): Emitter;
- /**
- * Create a new ScrollZone object with image key, position and size.
- *
- * @param key {string} Key to a image you wish this object to use.
- * @param x {number} X position of this object.
- * @param y {number} Y position of this object.
- * @param width number} Width of this object.
- * @param height {number} Height of this object.
- * @returns {ScrollZone} The newly created scroll zone object.
- */
- public createScrollZone(key: string, x?: number, y?: number, width?: number, height?: number): ScrollZone;
- /**
- * Create a new Tilemap.
- *
- * @param key {string} Key for tileset image.
- * @param mapData {string} Data of this tilemap.
- * @param format {number} Format of map data. (Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON)
- * @param [resizeWorld] {boolean} resize the world to make same as tilemap?
- * @param [tileWidth] {number} width of each tile.
- * @param [tileHeight] {number} height of each tile.
- * @return {Tilemap} The newly created tilemap object.
- */
- public createTilemap(key: string, mapData: string, format: number, resizeWorld?: bool, tileWidth?: number, tileHeight?: number): Tilemap;
- /**
- * Create a tween object for a specific object.
- *
- * @param obj Object you wish the tween will affect.
- * @return {Phaser.Tween} The newly created tween object.
- */
- public createTween(obj): Tween;
- /**
* Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group.
* Note: Does not take the objects scrollFactor into account. All overlaps are check in world space.
* @param object1 The first GameObject or Group to check. If null the world.group is used.
@@ -9148,6 +9707,11 @@ module Phaser {
*/
public collision: Collision;
/**
+ * Reference to the GameObject Factory.
+ * @type {GameObjectFactory}
+ */
+ public add: GameObjectFactory;
+ /**
* Reference to the input manager
* @type {Input}
*/
@@ -9219,93 +9783,6 @@ module Phaser {
*/
public destroy(): void;
/**
- * Create a new camera with specific position and size.
- *
- * @param x {number} X position of the new camera.
- * @param y {number} Y position of the new camera.
- * @param width {number} Width of the new camera.
- * @param height {number} Height of the new camera.
- * @returns {Camera} The newly created camera object.
- */
- public createCamera(x: number, y: number, width: number, height: number): Camera;
- /**
- * Create a new GeomSprite with specific position.
- *
- * @param x {number} X position of the new geom sprite.
- * @param y {number} Y position of the new geom sprite.
- * @returns {GeomSprite} The newly created geom sprite object.
- */
- public createGeomSprite(x: number, y: number): GeomSprite;
- /**
- * Create a new Sprite with specific position and sprite sheet key.
- *
- * @param x {number} X position of the new sprite.
- * @param y {number} Y position of the new sprite.
- * @param key {string} [optional] key for the sprite sheet you want it to use.
- * @returns {Sprite} The newly created sprite object.
- */
- public createSprite(x: number, y: number, key?: string): Sprite;
- /**
- * Create a new DynamicTexture with specific size.
- *
- * @param width {number} Width of the texture.
- * @param height {number} Height of the texture.
- * @returns {DynamicTexture} The newly created dynamic texture object.
- */
- public createDynamicTexture(width: number, height: number): DynamicTexture;
- /**
- * Create a new object container.
- *
- * @param maxSize {number} [optional] capacity of this group.
- * @returns {Group} The newly created group.
- */
- public createGroup(maxSize?: number): Group;
- /**
- * Create a new Particle.
- *
- * @return {Particle} The newly created particle object.
- */
- public createParticle(): Particle;
- /**
- * Create a new Emitter.
- *
- * @param x {number} [optional] x position of the emitter.
- * @param y {number} [optional] y position of the emitter.
- * @param size {number} [optional] size of this emitter.
- * @return {Emitter} The newly created emitter object.
- */
- public createEmitter(x?: number, y?: number, size?: number): Emitter;
- /**
- * Create a new ScrollZone object with image key, position and size.
- *
- * @param key {string} Key to a image you wish this object to use.
- * @param x {number} X position of this object.
- * @param y {number} Y position of this object.
- * @param width {number} Width of this object.
- * @param height {number} Height of this object.
- * @returns {ScrollZone} The newly created scroll zone object.
- */
- public createScrollZone(key: string, x?: number, y?: number, width?: number, height?: number): ScrollZone;
- /**
- * Create a new Tilemap.
- *
- * @param key {string} Key for tileset image.
- * @param mapData {string} Data of this tilemap.
- * @param format {number} Format of map data. (Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON)
- * @param resizeWorld {boolean} [optional] resize the world to make same as tilemap?
- * @param tileWidth {number} [optional] width of each tile.
- * @param tileHeight number} [optional] height of each tile.
- * @return {Tilemap} The newly created tilemap object.
- */
- public createTilemap(key: string, mapData: string, format: number, resizeWorld?: bool, tileWidth?: number, tileHeight?: number): Tilemap;
- /**
- * Create a tween object for a specific object.
- *
- * @param obj Object you wish the tween will affect.
- * @return {Phaser.Tween} The newly created tween object.
- */
- public createTween(obj): Tween;
- /**
* Call this method to see if one object collids another.
* @return {boolean} Whether the given objects or groups collids.
*/
diff --git a/build/phaser.js b/build/phaser.js
index 1d5e6f54..e4136383 100644
--- a/build/phaser.js
+++ b/build/phaser.js
@@ -504,8 +504,6 @@ var Phaser;
this.last.y = this.y;
};
CollisionMask.prototype.update = function () {
- //this.quad.x = this._parent.x + this.offset.x;
- //this.quad.y = this._parent.y + this.offset.y;
this._ref.x = this._parent.x + this.offset.x;
this._ref.y = this._parent.y + this.offset.y;
};
@@ -518,8 +516,7 @@ var Phaser;
function (camera, cameraOffsetX, cameraOffsetY) {
var _dx = cameraOffsetX + (this.x - camera.worldView.x);
var _dy = cameraOffsetY + (this.y - camera.worldView.y);
- //this._parent.context.fillStyle = this._parent.renderDebugColor;
- this._parent.context.fillStyle = 'rgba(255,0,0,0.4)';
+ 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) {
@@ -543,6 +540,15 @@ var Phaser;
this.line = null;
this.offset = null;
};
+ CollisionMask.prototype.intersectsRaw = function (left, right, top, bottom) {
+ //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height))
+ return true;
+ };
+ CollisionMask.prototype.intersectsVector = function (vector) {
+ if(this.type == CollisionMask.QUAD) {
+ return this.quad.contains(vector.x, vector.y);
+ }
+ };
CollisionMask.prototype.intersects = /**
* 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.
@@ -556,7 +562,6 @@ var Phaser;
}
// Circle vs. Circle
if(this.type == CollisionMask.CIRCLE && source.type == CollisionMask.CIRCLE) {
- console.log('c vs c');
return Phaser.Collision.circleToCircle(this.circle, source.circle).result;
}
// Circle vs. Rect
@@ -889,7 +894,6 @@ var Phaser;
this.alpha = 1;
this.scale = new Phaser.MicroPoint(1, 1);
this.last = new Phaser.MicroPoint(x, y);
- //this.origin = new MicroPoint(this.frameBounds.halfWidth, this.frameBounds.halfHeight);
this.align = GameObject.ALIGN_TOP_LEFT;
this.mass = 1;
this.elasticity = 0;
@@ -1273,6 +1277,10 @@ var Phaser;
*/
function () {
};
+ GameObject.prototype.setPosition = function (x, y) {
+ this.x = x;
+ this.y = y;
+ };
Object.defineProperty(GameObject.prototype, "x", {
get: function () {
return this.frameBounds.x;
@@ -1554,7 +1562,7 @@ var Phaser;
this.fx.preUpdate();
if(this._target !== null) {
if(this.deadzone == null) {
- this.focusOnXY(this._target.x + this._target.origin.x, this._target.y + this._target.origin.y);
+ this.focusOnXY(this._target.x, this._target.y);
} else {
var edge;
var targetX = this._target.x + ((this._target.x > 0) ? 0.0000001 : -0.0000001);
@@ -1893,9 +1901,14 @@ var Phaser;
Sprite.prototype.loadGraphic = /**
* Load graphic for this sprite. (graphic can be SpriteSheet or Texture)
* @param key {string} Key of the graphic you want to load for this sprite.
+ * @param clearAnimations {boolean} If this Sprite has a set of animation data already loaded you can choose to keep or clear it with this boolean
* @return {Sprite} Sprite instance itself.
*/
- function (key) {
+ function (key, clearAnimations) {
+ if (typeof clearAnimations === "undefined") { clearAnimations = true; }
+ if(clearAnimations && this.animations.frameData !== null) {
+ this.animations.destroy();
+ }
if(this._game.cache.getImage(key) !== null) {
if(this._game.cache.isSpriteSheet(key) == false) {
this._texture = this._game.cache.getImage(key);
@@ -1906,9 +1919,9 @@ var Phaser;
} else {
this._texture = this._game.cache.getImage(key);
this.animations.loadFrameData(this._game.cache.getFrameData(key));
- //this.collisionMask.width = this._texture.width;
- //this.collisionMask.height = this._texture.height;
- }
+ this.collisionMask.width = this.animations.currentFrame.width;
+ this.collisionMask.height = this.animations.currentFrame.height;
+ }
this._dynamicTexture = false;
}
return this;
@@ -1947,14 +1960,20 @@ var Phaser;
* @return {boolean} Return true if bounds of this sprite intersects the given rectangle, otherwise return false.
*/
function (camera) {
- if(this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) {
- this._dx = this.frameBounds.x - (camera.x * this.scrollFactor.x);
- this._dy = this.frameBounds.y - (camera.y * this.scrollFactor.x);
+ // Object fixed in place regardless of the camera scrolling? Then it's always visible
+ if(this.scrollFactor.x == 0 && this.scrollFactor.y == 0) {
+ return true;
+ }
+ // Otherwise, if it's scrolling perfectly in sync with the camera (1 to 1) then it's a simple bounds check on world coordinates
+ if(this.scrollFactor.x == 1 && this.scrollFactor.y == 1) {
+ return camera.intersects(this.frameBounds, this.frameBounds.length);
+ } else {
+ // Else apply the offsets
+ this._dx = (this.frameBounds.x - camera.x) * this.scrollFactor.x;
+ this._dy = (this.frameBounds.y - camera.y) * this.scrollFactor.y;
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.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.intersects(this.frameBounds, this.frameBounds.length);
}
};
Sprite.prototype.postUpdate = /**
@@ -2005,8 +2024,8 @@ var Phaser;
this._sy = 0;
this._sw = this.frameBounds.width;
this._sh = this.frameBounds.height;
- this._dx = cameraOffsetX + (this.frameBounds.topLeft.x - camera.worldView.x);
- this._dy = cameraOffsetY + (this.frameBounds.topLeft.y - camera.worldView.y);
+ this._dx = (cameraOffsetX * this.scrollFactor.x) + this.frameBounds.topLeft.x - (camera.worldView.x * this.scrollFactor.x);
+ this._dy = (cameraOffsetY * this.scrollFactor.y) + this.frameBounds.topLeft.y - (camera.worldView.y * this.scrollFactor.y);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
if(this.align == Phaser.GameObject.ALIGN_TOP_CENTER) {
@@ -2039,10 +2058,10 @@ var Phaser;
}
}
// Apply camera difference
- if(this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) {
- this._dx -= (camera.worldView.x * this.scrollFactor.x);
- this._dy -= (camera.worldView.y * this.scrollFactor.y);
- }
+ if(this.scrollFactor.x !== 1 || this.scrollFactor.y !== 1) {
+ //this._dx -= (camera.worldView.x * this.scrollFactor.x);
+ //this._dy -= (camera.worldView.y * this.scrollFactor.y);
+ }
// Rotation - needs to work from origin point really, but for now from center
if(this.angle !== 0 || this.rotationOffset !== 0 || this.flipped == true) {
this.context.save();
@@ -2711,7 +2730,11 @@ var Phaser;
});
Object.defineProperty(AnimationManager.prototype, "frameTotal", {
get: function () {
- return this._frameData.total;
+ if(this._frameData) {
+ return this._frameData.total;
+ } else {
+ return -1;
+ }
},
enumerable: true,
configurable: true
@@ -2746,6 +2769,17 @@ var Phaser;
enumerable: true,
configurable: true
});
+ AnimationManager.prototype.destroy = /**
+ * Removes all related references
+ */
+ function () {
+ this._anims = {
+ };
+ this._frameData = null;
+ this._frameIndex = 0;
+ this.currentAnim = null;
+ this.currentFrame = null;
+ };
return AnimationManager;
})();
Phaser.AnimationManager = AnimationManager;
@@ -2971,9 +3005,6 @@ var Phaser;
*
* Your game only has one CameraManager instance and it's responsible for looking after, creating and destroying
* all of the cameras in the world.
-*
-* TODO: If the Camera is larger than the Stage size then the rotation offset isn't correct
-* TODO: Texture Repeat doesn't scroll, because it's part of the camera not the world, need to think about this more
*/
var Phaser;
(function (Phaser) {
@@ -4086,6 +4117,54 @@ var Phaser;
})(Phaser || (Phaser = {}));
///
/**
+* Phaser - Polygon
+*
+*/
+var Phaser;
+(function (Phaser) {
+ var Polygon = (function () {
+ /**
+ * A *convex* clockwise polygon
+ * @class Polygon
+ * @constructor
+ * @param {Vector2} pos A vector representing the origin of the polygon (all other points are relative to this one)
+ * @param {Array.} points An Array of vectors representing the points in the polygon, in clockwise order.
+ **/
+ function Polygon(pos, points, parent) {
+ if (typeof pos === "undefined") { pos = new Phaser.Vector2(); }
+ if (typeof points === "undefined") { points = []; }
+ if (typeof parent === "undefined") { parent = null; }
+ this.pos = pos;
+ this.points = points;
+ this.parent = parent;
+ this.recalc();
+ }
+ Polygon.prototype.recalc = /**
+ * Recalculate the edges and normals of the polygon. This
+ * MUST be called if the points array is modified at all and
+ * the edges or normals are to be accessed.
+ */
+ function () {
+ var points = this.points;
+ var len = points.length;
+ this.edges = [];
+ this.normals = [];
+ for(var i = 0; i < len; i++) {
+ var p1 = points[i];
+ var p2 = i < len - 1 ? points[i + 1] : points[0];
+ var e = new Phaser.Vector2().copyFrom(p2).sub(p1);
+ var n = new Phaser.Vector2().copyFrom(e).perp().normalize();
+ this.edges.push(e);
+ this.normals.push(n);
+ }
+ };
+ return Polygon;
+ })();
+ Phaser.Polygon = Polygon;
+})(Phaser || (Phaser = {}));
+///
+///
+/**
* Phaser - Quad
*
* A Quad object is an area defined by its position, as indicated by its top-left corner (x,y) and width and height.
@@ -4181,6 +4260,20 @@ var Phaser;
if (typeof tolerance === "undefined") { tolerance = 0; }
return !(quad.left > this.right + tolerance || quad.right < this.left - tolerance || quad.top > this.bottom + tolerance || quad.bottom < this.top - tolerance);
};
+ Quad.prototype.intersectsRaw = /**
+ * Determines whether the object specified intersects (overlaps) with the given values.
+ * @method intersectsProps
+ * @param {Number} left
+ * @param {Number} right
+ * @param {Number} top
+ * @param {Number} bottomt
+ * @param {Number} tolerance 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 Quad; otherwise false.
+ **/
+ function (left, right, top, bottom, tolerance) {
+ if (typeof tolerance === "undefined") { tolerance = 0; }
+ return !(left > this.right + tolerance || right < this.left - tolerance || top > this.bottom + tolerance || bottom < this.top - tolerance);
+ };
Quad.prototype.contains = /**
* Determines whether the specified coordinates are contained within the region defined by this Quad object.
* @method contains
@@ -4212,6 +4305,19 @@ var Phaser;
function (target) {
return target.copyFrom(this);
};
+ Quad.prototype.toPolygon = /**
+ * Creates and returns a Polygon that is the same as this Quad.
+ * @method toPolygon
+ * @return {Polygon} A new Polygon that represents this quad.
+ **/
+ function () {
+ return new Phaser.Polygon(new Phaser.Vector2(this.x, this.y), [
+ new Phaser.Vector2(),
+ new Phaser.Vector2(this.width, 0),
+ new Phaser.Vector2(this.width, this.height),
+ new Phaser.Vector2(0, this.height)
+ ]);
+ };
Quad.prototype.toString = /**
* Returns a string representation of this object.
* @method toString
@@ -4260,8 +4366,21 @@ var Phaser;
* @type Number
**/
this.y = 0;
+ this._pos = new Phaser.Vector2();
this.setTo(x, y, diameter);
}
+ Object.defineProperty(Circle.prototype, "pos", {
+ get: /**
+ * The position of this Circle object represented by a Vector2
+ * @property pos
+ * @type Vector2
+ **/
+ function () {
+ return this._pos.setTo(this.x, this.y);
+ },
+ enumerable: true,
+ configurable: true
+ });
Object.defineProperty(Circle.prototype, "diameter", {
get: /**
* The diameter of the circle. The largest distance between any two points on the circle. The same as the radius * 2.
@@ -4952,6 +5071,414 @@ var Phaser;
Phaser.IntersectResult = IntersectResult;
})(Phaser || (Phaser = {}));
///
+///
+/**
+* Phaser - Response
+*
+*/
+var Phaser;
+(function (Phaser) {
+ var Response = (function () {
+ /**
+ * An object representing the result of an intersection. Contain information about:
+ * - The two objects participating in the intersection
+ * - The vector representing the minimum change necessary to extract the first object
+ * from the second one.
+ * - Whether the first object is entirely inside the second, or vice versa.
+ *
+ * @constructor
+ */
+ function Response() {
+ this.a = null;
+ this.b = null;
+ this.overlapN = new Phaser.Vector2();
+ this.overlapV = new Phaser.Vector2();
+ this.clear();
+ }
+ Response.prototype.clear = /**
+ * Set some values of the response back to their defaults. Call this between tests if
+ * you are going to reuse a single Response object for multiple intersection tests (recommented)
+ *
+ * @return {Response} This for chaining
+ */
+ function () {
+ this.aInB = true;
+ this.bInA = true;
+ this.overlap = Number.MAX_VALUE;
+ return this;
+ };
+ return Response;
+ })();
+ Phaser.Response = Response;
+})(Phaser || (Phaser = {}));
+///
+/**
+* Phaser - Vector2
+*
+* A two dimensional vector.
+* Contains methods and ideas from verlet-js by Sub Protocol, SAT.js by Jim Riecken and N by Metanet Software.
+*/
+var Phaser;
+(function (Phaser) {
+ var Vector2 = (function () {
+ /**
+ * Creates a new Vector2 object.
+ * @class Vector2
+ * @constructor
+ * @param {Number} x The x position of the vector
+ * @param {Number} y The y position of the vector
+ * @return {Vector2} This object
+ **/
+ function Vector2(x, y) {
+ if (typeof x === "undefined") { x = 0; }
+ if (typeof y === "undefined") { y = 0; }
+ this.x = x;
+ this.y = y;
+ }
+ Vector2.prototype.setTo = function (x, y) {
+ this.x = x;
+ this.y = y;
+ return this;
+ };
+ Vector2.prototype.add = /**
+ * Add this vector to the given one and return the result.
+ *
+ * @param {Vector2} v The other Vector.
+ * @param {Vector2} The output Vector.
+ * @return {Vector2} The new Vector
+ */
+ function (v, output) {
+ if (typeof output === "undefined") { output = new Vector2(); }
+ return output.setTo(this.x + v.x, this.y + v.y);
+ };
+ Vector2.prototype.sub = /**
+ * Subtract this vector to the given one and return the result.
+ *
+ * @param {Vector2} v The other Vector.
+ * @param {Vector2} The output Vector.
+ * @return {Vector2} The new Vector
+ */
+ function (v, output) {
+ if (typeof output === "undefined") { output = new Vector2(); }
+ return output.setTo(this.x - v.x, this.y - v.y);
+ };
+ Vector2.prototype.mul = /**
+ * Multiply this vector with the given one and return the result.
+ *
+ * @param {Vector2} v The other Vector.
+ * @param {Vector2} The output Vector.
+ * @return {Vector2} The new Vector
+ */
+ function (v, output) {
+ if (typeof output === "undefined") { output = new Vector2(); }
+ return output.setTo(this.x * v.x, this.y * v.y);
+ };
+ Vector2.prototype.div = /**
+ * Divide this vector by the given one and return the result.
+ *
+ * @param {Vector2} v The other Vector.
+ * @param {Vector2} The output Vector.
+ * @return {Vector2} The new Vector
+ */
+ function (v, output) {
+ if (typeof output === "undefined") { output = new Vector2(); }
+ return output.setTo(this.x / v.x, this.y / v.y);
+ };
+ Vector2.prototype.scale = /**
+ * Scale this vector by the given values and return the result.
+ *
+ * @param {number} x The scaling factor in the x direction.
+ * @param {?number=} y The scaling factor in the y direction. If this
+ * is not specified, the x scaling factor will be used.
+ * @return {Vector} The new Vector
+ */
+ function (x, y, output) {
+ if (typeof y === "undefined") { y = null; }
+ if (typeof output === "undefined") { output = new Vector2(); }
+ if(y === null) {
+ y = x;
+ }
+ return output.setTo(this.x * x, this.y * y);
+ };
+ Vector2.prototype.perp = /**
+ * Rotate this vector by 90 degrees
+ *
+ * @return {Vector} This for chaining.
+ */
+ function (output) {
+ if (typeof output === "undefined") { output = this; }
+ var x = this.x;
+ return output.setTo(this.y, -x);
+ };
+ Vector2.prototype.mutableSet = // Same as copyFrom, used by VerletManager
+ function (v) {
+ this.x = v.x;
+ this.y = v.y;
+ return this;
+ };
+ Vector2.prototype.mutableAdd = /**
+ * Add another vector to this one.
+ *
+ * @param {Vector} other The other Vector.
+ * @return {Vector} This for chaining.
+ */
+ function (v) {
+ this.x += v.x;
+ this.y += v.y;
+ return this;
+ };
+ Vector2.prototype.mutableSub = /**
+ * Subtract another vector from this one.
+ *
+ * @param {Vector} other The other Vector.
+ * @return {Vector} This for chaining.
+ */
+ function (v) {
+ this.x -= v.x;
+ this.y -= v.y;
+ return this;
+ };
+ Vector2.prototype.mutableMul = /**
+ * Multiply another vector with this one.
+ *
+ * @param {Vector} other The other Vector.
+ * @return {Vector} This for chaining.
+ */
+ function (v) {
+ this.x *= v.x;
+ this.y *= v.y;
+ return this;
+ };
+ Vector2.prototype.mutableDiv = /**
+ * Divide this vector by another one.
+ *
+ * @param {Vector} other The other Vector.
+ * @return {Vector} This for chaining.
+ */
+ function (v) {
+ this.x /= v.x;
+ this.y /= v.y;
+ return this;
+ };
+ Vector2.prototype.mutableScale = /**
+ * Scale this vector.
+ *
+ * @param {number} x The scaling factor in the x direction.
+ * @param {?number=} y The scaling factor in the y direction. If this
+ * is not specified, the x scaling factor will be used.
+ * @return {Vector} This for chaining.
+ */
+ function (x, y) {
+ this.x *= x;
+ this.y *= y || x;
+ return this;
+ };
+ Vector2.prototype.reverse = /**
+ * Reverse this vector.
+ *
+ * @return {Vector} This for chaining.
+ */
+ function () {
+ this.x = -this.x;
+ this.y = -this.y;
+ return this;
+ };
+ Vector2.prototype.edge = function (v, output) {
+ if (typeof output === "undefined") { output = new Vector2(); }
+ return this.sub(v, output);
+ };
+ Vector2.prototype.equals = function (v) {
+ return this.x == v.x && this.y == v.y;
+ };
+ Vector2.prototype.epsilonEquals = function (v, epsilon) {
+ return Math.abs(this.x - v.x) <= epsilon && Math.abs(this.y - v.y) <= epsilon;
+ };
+ Vector2.prototype.length = /**
+ * Get the length of this vector.
+ *
+ * @return {number} The length of this vector.
+ */
+ function () {
+ return Math.sqrt((this.x * this.x) + (this.y * this.y));
+ };
+ Vector2.prototype.length2 = /**
+ * Get the length^2 of this vector.
+ *
+ * @return {number} The length^2 of this vector.
+ */
+ function () {
+ return (this.x * this.x) + (this.y * this.y);
+ };
+ Vector2.prototype.distance = /**
+ * Get the distance between this vector and the given vector.
+ *
+ * @return {Vector2} v The vector to check
+ */
+ function (v) {
+ return Math.sqrt(this.distance2(v));
+ };
+ Vector2.prototype.distance2 = /**
+ * Get the distance^2 between this vector and the given vector.
+ *
+ * @return {Vector2} v The vector to check
+ */
+ function (v) {
+ return ((v.x - this.x) * (v.x - this.x)) + ((v.y - this.y) * (v.y - this.y));
+ };
+ Vector2.prototype.project = /**
+ * Project this vector on to another vector.
+ *
+ * @param {Vector} other The vector to project onto.
+ * @return {Vector} This for chaining.
+ */
+ function (other) {
+ var amt = this.dot(other) / other.length2();
+ if(amt != 0) {
+ this.x = amt * other.x;
+ this.y = amt * other.y;
+ }
+ return this;
+ };
+ Vector2.prototype.projectN = /**
+ * Project this vector onto a vector of unit length.
+ *
+ * @param {Vector} other The unit vector to project onto.
+ * @return {Vector} This for chaining.
+ */
+ function (other) {
+ var amt = this.dot(other);
+ if(amt != 0) {
+ this.x = amt * other.x;
+ this.y = amt * other.y;
+ }
+ return this;
+ };
+ Vector2.prototype.reflect = /**
+ * Reflect this vector on an arbitrary axis.
+ *
+ * @param {Vector} axis The vector representing the axis.
+ * @return {Vector} This for chaining.
+ */
+ function (axis) {
+ var x = this.x;
+ var y = this.y;
+ this.project(axis).scale(2);
+ this.x -= x;
+ this.y -= y;
+ return this;
+ };
+ Vector2.prototype.reflectN = /**
+ * Reflect this vector on an arbitrary axis (represented by a unit vector)
+ *
+ * @param {Vector} axis The unit vector representing the axis.
+ * @return {Vector} This for chaining.
+ */
+ function (axis) {
+ var x = this.x;
+ var y = this.y;
+ this.projectN(axis).scale(2);
+ this.x -= x;
+ this.y -= y;
+ return this;
+ };
+ Vector2.prototype.getProjectionMagnitude = function (v) {
+ var den = v.dot(v);
+ if(den == 0) {
+ return 0;
+ } else {
+ return Math.abs(this.dot(v) / den);
+ }
+ };
+ Vector2.prototype.direction = function (output) {
+ if (typeof output === "undefined") { output = new Vector2(); }
+ output.copyFrom(this);
+ return this.normalize(output);
+ };
+ Vector2.prototype.normalRightHand = function (output) {
+ if (typeof output === "undefined") { output = this; }
+ return output.setTo(this.y * -1, this.x);
+ };
+ Vector2.prototype.normalize = /**
+ * Normalize (make unit length) this vector.
+ *
+ * @return {Vector} This for chaining.
+ */
+ function (output) {
+ if (typeof output === "undefined") { output = this; }
+ var m = this.length();
+ if(m != 0) {
+ output.setTo(this.x / m, this.y / m);
+ }
+ return output;
+ };
+ Vector2.prototype.getMagnitude = function () {
+ return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
+ };
+ Vector2.prototype.dot = /**
+ * Get the dot product of this vector against another.
+ *
+ * @param {Vector} other The vector to dot this one against.
+ * @return {number} The dot product.
+ */
+ function (v) {
+ return ((this.x * v.x) + (this.y * v.y));
+ };
+ Vector2.prototype.cross = /**
+ * Get the cross product of this vector against another.
+ *
+ * @param {Vector} other The vector to cross this one against.
+ * @return {number} The cross product.
+ */
+ function (v) {
+ return ((this.x * v.y) - (this.y * v.x));
+ };
+ Vector2.prototype.angle = /**
+ * Get the angle between this vector and the given vector.
+ *
+ * @return {Vector2} v The vector to check
+ */
+ function (v) {
+ return Math.atan2(this.x * v.y - this.y * v.x, this.x * v.x + this.y * v.y);
+ };
+ Vector2.prototype.angle2 = function (vLeft, vRight) {
+ return vLeft.sub(this).angle(vRight.sub(this));
+ };
+ Vector2.prototype.rotate = /**
+ * Rotate this vector around the origin to the given angle (theta) and return the result in a new Vector
+ *
+ * @return {Vector2} v The vector to check
+ */
+ function (origin, theta, output) {
+ if (typeof output === "undefined") { output = new Vector2(); }
+ var x = this.x - origin.x;
+ var y = this.y - origin.y;
+ return output.setTo(x * Math.cos(theta) - y * Math.sin(theta) + origin.x, x * Math.sin(theta) + y * Math.cos(theta) + origin.y);
+ };
+ Vector2.prototype.clone = function (output) {
+ if (typeof output === "undefined") { output = new Vector2(); }
+ return output.setTo(this.x, this.y);
+ };
+ Vector2.prototype.copyFrom = function (v) {
+ this.x = v.x;
+ this.y = v.y;
+ return this;
+ };
+ Vector2.prototype.copyTo = function (v) {
+ return v.setTo(this.x, this.y);
+ };
+ Vector2.prototype.toString = /**
+ * Returns a string representation of this object.
+ * @method toString
+ * @return {string} a string representation of the object.
+ **/
+ function () {
+ return "[{Vector2 (x=" + this.x + " y=" + this.y + ")}]";
+ };
+ return Vector2;
+ })();
+ Phaser.Vector2 = Vector2;
+})(Phaser || (Phaser = {}));
+///
/**
* Phaser - LinkedList
*
@@ -5338,6 +5865,8 @@ var Phaser;
///
///
///
+///
+///
///
/**
* Phaser - Collision
@@ -5353,6 +5882,14 @@ var Phaser;
*/
function Collision(game) {
this._game = game;
+ Collision.T_VECTORS = [];
+ for(var i = 0; i < 10; i++) {
+ Collision.T_VECTORS.push(new Phaser.Vector2());
+ }
+ Collision.T_ARRAYS = [];
+ for(var i = 0; i < 5; i++) {
+ Collision.T_ARRAYS.push([]);
+ }
}
Collision.LEFT = 0x0001;
Collision.RIGHT = 0x0010;
@@ -5703,20 +6240,7 @@ var Phaser;
output.result = ((circle1.radius + circle2.radius) * (circle1.radius + circle2.radius)) >= Collision.distanceSquared(circle1.x, circle1.y, circle2.x, circle2.y);
return output;
};
- Collision.circleToRectangle = /*
- public static circleToQuad(circle: Circle, quad: Quad): bool {
-
- // Check if the center of the circle is within the Quad
- if (quad.contains(circle.x, circle.y))
- {
- return true;
- }
-
- // Failing that let's check each line of the quad against the circle
- return false;
- }
- */
- /**
+ Collision.circleToRectangle = /**
* Checks if the Circle object intersects with the Rectangle and returns the result in an IntersectResult object.
* @param circle The Circle object to check
* @param rect The Rectangle object to check
@@ -5779,7 +6303,6 @@ var Phaser;
* @returns {boolean} Returns true if the objects were separated, otherwise false.
*/
function separate(object1, object2) {
- console.log('sep o');
object1.collisionMask.update();
object2.collisionMask.update();
var separatedX = Collision.separateX(object1, object2);
@@ -5793,6 +6316,7 @@ var Phaser;
* @returns {boolean} Whether the objects in fact touched and were separated
*/
function separateTile(object, x, y, width, height, mass, collideLeft, collideRight, collideUp, collideDown, separateX, separateY) {
+ object.collisionMask.update();
var separatedX = Collision.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separateX);
var separatedY = Collision.separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separateY);
return separatedX || separatedY;
@@ -5811,9 +6335,11 @@ var Phaser;
// First, get the object delta
var overlap = 0;
var objDelta = object.x - object.last.x;
+ //var objDelta: number = object.collisionMask.deltaX;
if(objDelta != 0) {
// Check if the X hulls actually overlap
var objDeltaAbs = (objDelta > 0) ? objDelta : -objDelta;
+ //var objDeltaAbs: number = object.collisionMask.deltaXAbs;
var objBounds = new Phaser.Quad(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height);
if((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) {
var maxOverlap = objDeltaAbs + Collision.OVERLAP_BIAS;
@@ -5838,6 +6364,7 @@ var Phaser;
// Then adjust their positions and velocities accordingly (if there was any overlap)
if(overlap != 0) {
if(separate == true) {
+ //console.log('
object.x = object.x - overlap;
object.velocity.x = -(object.velocity.x * object.elasticity);
}
@@ -5898,6 +6425,113 @@ var Phaser;
return false;
}
};
+ Collision.NEWseparateTileX = /**
+ * Separates the two objects on their x axis
+ * @param object The GameObject to separate
+ * @param tile The Tile to separate
+ * @returns {boolean} Whether the objects in fact touched and were separated along the X axis.
+ */
+ function NEWseparateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separate) {
+ // Can't separate two immovable objects (tiles are always immovable)
+ if(object.immovable) {
+ return false;
+ }
+ // First, get the object delta
+ var overlap = 0;
+ if(object.collisionMask.deltaX != 0) {
+ // Check if the X hulls actually overlap
+ //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta;
+ //var objBounds: Quad = new Quad(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height);
+ //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height))
+ if(object.collisionMask.intersectsRaw(x, x + width, y, y + height)) {
+ var maxOverlap = object.collisionMask.deltaXAbs + Collision.OVERLAP_BIAS;
+ // If they did overlap (and can), figure out by how much and flip the corresponding flags
+ if(object.collisionMask.deltaX > 0) {
+ //overlap = object.x + object.width - x;
+ overlap = object.collisionMask.right - x;
+ if((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) {
+ overlap = 0;
+ } else {
+ object.touching |= Collision.RIGHT;
+ }
+ } else if(object.collisionMask.deltaX < 0) {
+ //overlap = object.x - width - x;
+ overlap = object.collisionMask.x - width - x;
+ if((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) {
+ overlap = 0;
+ } else {
+ object.touching |= Collision.LEFT;
+ }
+ }
+ }
+ }
+ // Then adjust their positions and velocities accordingly (if there was any overlap)
+ if(overlap != 0) {
+ if(separate == true) {
+ object.x = object.x - overlap;
+ object.velocity.x = -(object.velocity.x * object.elasticity);
+ }
+ Collision.TILE_OVERLAP = true;
+ return true;
+ } else {
+ return false;
+ }
+ };
+ Collision.NEWseparateTileY = /**
+ * Separates the two objects on their y axis
+ * @param object The first GameObject to separate
+ * @param tile The second GameObject to separate
+ * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis.
+ */
+ function NEWseparateTileY(object, x, y, width, height, mass, collideUp, collideDown, separate) {
+ // Can't separate two immovable objects (tiles are always immovable)
+ if(object.immovable) {
+ return false;
+ }
+ // First, get the two object deltas
+ var overlap = 0;
+ //var objDelta: number = object.y - object.last.y;
+ if(object.collisionMask.deltaY != 0) {
+ // Check if the Y hulls actually overlap
+ //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta;
+ //var objBounds: Quad = new Quad(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs);
+ //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height))
+ if(object.collisionMask.intersectsRaw(x, x + width, y, y + height)) {
+ //var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS;
+ var maxOverlap = object.collisionMask.deltaYAbs + Collision.OVERLAP_BIAS;
+ // If they did overlap (and can), figure out by how much and flip the corresponding flags
+ if(object.collisionMask.deltaY > 0) {
+ //overlap = object.y + object.height - y;
+ overlap = object.collisionMask.bottom - y;
+ if((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) {
+ overlap = 0;
+ } else {
+ object.touching |= Collision.DOWN;
+ }
+ } else if(object.collisionMask.deltaY < 0) {
+ //overlap = object.y - height - y;
+ overlap = object.collisionMask.y - height - y;
+ if((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) {
+ overlap = 0;
+ } else {
+ object.touching |= Collision.UP;
+ }
+ }
+ }
+ }
+ // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here
+ // Then adjust their positions and velocities accordingly (if there was any overlap)
+ if(overlap != 0) {
+ if(separate == true) {
+ object.y = object.y - overlap;
+ object.velocity.y = -(object.velocity.y * object.elasticity);
+ }
+ Collision.TILE_OVERLAP = true;
+ return true;
+ } else {
+ return false;
+ }
+ };
Collision.separateX = /**
* Separates the two objects on their x axis
* @param object1 The first GameObject to separate
@@ -6033,159 +6667,6 @@ var Phaser;
return false;
}
};
- Collision.OLDseparateX = /**
- * Separates the two objects on their x axis
- * @param object1 The first GameObject to separate
- * @param object2 The second GameObject to separate
- * @returns {boolean} Whether the objects in fact touched and were separated along the X axis.
- */
- function OLDseparateX(object1, object2) {
- // Can't separate two immovable objects
- if(object1.immovable && object2.immovable) {
- return false;
- }
- // First, get the two object deltas
- var overlap = 0;
- var obj1Delta = object1.x - object1.last.x;
- var obj2Delta = object2.x - object2.last.x;
- if(obj1Delta != obj2Delta) {
- // Check if the X hulls actually overlap
- var obj1DeltaAbs = (obj1Delta > 0) ? obj1Delta : -obj1Delta;
- var obj2DeltaAbs = (obj2Delta > 0) ? obj2Delta : -obj2Delta;
- var obj1Bounds = new Phaser.Quad(object1.x - ((obj1Delta > 0) ? obj1Delta : 0), object1.last.y, object1.width + ((obj1Delta > 0) ? obj1Delta : -obj1Delta), object1.height);
- var obj2Bounds = new Phaser.Quad(object2.x - ((obj2Delta > 0) ? obj2Delta : 0), object2.last.y, object2.width + ((obj2Delta > 0) ? obj2Delta : -obj2Delta), object2.height);
- if((obj1Bounds.x + obj1Bounds.width > obj2Bounds.x) && (obj1Bounds.x < obj2Bounds.x + obj2Bounds.width) && (obj1Bounds.y + obj1Bounds.height > obj2Bounds.y) && (obj1Bounds.y < obj2Bounds.y + obj2Bounds.height)) {
- var maxOverlap = obj1DeltaAbs + obj2DeltaAbs + Collision.OVERLAP_BIAS;
- // If they did overlap (and can), figure out by how much and flip the corresponding flags
- if(obj1Delta > obj2Delta) {
- overlap = object1.x + object1.width - object2.x;
- if((overlap > maxOverlap) || !(object1.allowCollisions & Collision.RIGHT) || !(object2.allowCollisions & Collision.LEFT)) {
- overlap = 0;
- } else {
- object1.touching |= Collision.RIGHT;
- object2.touching |= Collision.LEFT;
- }
- } else if(obj1Delta < obj2Delta) {
- overlap = object1.x - object2.width - object2.x;
- if((-overlap > maxOverlap) || !(object1.allowCollisions & Collision.LEFT) || !(object2.allowCollisions & Collision.RIGHT)) {
- overlap = 0;
- } else {
- object1.touching |= Collision.LEFT;
- object2.touching |= Collision.RIGHT;
- }
- }
- }
- }
- // Then adjust their positions and velocities accordingly (if there was any overlap)
- if(overlap != 0) {
- var obj1Velocity = object1.velocity.x;
- var obj2Velocity = object2.velocity.x;
- if(!object1.immovable && !object2.immovable) {
- overlap *= 0.5;
- object1.x = object1.x - overlap;
- object2.x += overlap;
- var obj1NewVelocity = Math.sqrt((obj2Velocity * obj2Velocity * object2.mass) / object1.mass) * ((obj2Velocity > 0) ? 1 : -1);
- var obj2NewVelocity = Math.sqrt((obj1Velocity * obj1Velocity * object1.mass) / object2.mass) * ((obj1Velocity > 0) ? 1 : -1);
- var average = (obj1NewVelocity + obj2NewVelocity) * 0.5;
- obj1NewVelocity -= average;
- obj2NewVelocity -= average;
- object1.velocity.x = average + obj1NewVelocity * object1.elasticity;
- object2.velocity.x = average + obj2NewVelocity * object2.elasticity;
- } else if(!object1.immovable) {
- object1.x = object1.x - overlap;
- object1.velocity.x = obj2Velocity - obj1Velocity * object1.elasticity;
- } else if(!object2.immovable) {
- object2.x += overlap;
- object2.velocity.x = obj1Velocity - obj2Velocity * object2.elasticity;
- }
- return true;
- } else {
- return false;
- }
- };
- Collision.OLDseparateY = /**
- * Separates the two objects on their y axis
- * @param object1 The first GameObject to separate
- * @param object2 The second GameObject to separate
- * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis.
- */
- function OLDseparateY(object1, object2) {
- // Can't separate two immovable objects
- if(object1.immovable && object2.immovable) {
- return false;
- }
- // First, get the two object deltas
- var overlap = 0;
- var obj1Delta = object1.y - object1.last.y;
- var obj2Delta = object2.y - object2.last.y;
- if(obj1Delta != obj2Delta) {
- // Check if the Y hulls actually overlap
- var obj1DeltaAbs = (obj1Delta > 0) ? obj1Delta : -obj1Delta;
- var obj2DeltaAbs = (obj2Delta > 0) ? obj2Delta : -obj2Delta;
- var obj1Bounds = new Phaser.Quad(object1.x, object1.y - ((obj1Delta > 0) ? obj1Delta : 0), object1.width, object1.height + obj1DeltaAbs);
- var obj2Bounds = new Phaser.Quad(object2.x, object2.y - ((obj2Delta > 0) ? obj2Delta : 0), object2.width, object2.height + obj2DeltaAbs);
- console.log(obj1Bounds.toString(), obj2Bounds.toString());
- if((obj1Bounds.x + obj1Bounds.width > obj2Bounds.x) && (obj1Bounds.x < obj2Bounds.x + obj2Bounds.width) && (obj1Bounds.y + obj1Bounds.height > obj2Bounds.y) && (obj1Bounds.y < obj2Bounds.y + obj2Bounds.height)) {
- var maxOverlap = obj1DeltaAbs + obj2DeltaAbs + Collision.OVERLAP_BIAS;
- console.log('max33', maxOverlap, obj1Delta, obj2Delta, obj1DeltaAbs, obj2DeltaAbs);
- // If they did overlap (and can), figure out by how much and flip the corresponding flags
- if(obj1Delta > obj2Delta) {
- overlap = object1.y + object1.height - object2.y;
- if((overlap > maxOverlap) || !(object1.allowCollisions & Collision.DOWN) || !(object2.allowCollisions & Collision.UP)) {
- overlap = 0;
- } else {
- object1.touching |= Collision.DOWN;
- object2.touching |= Collision.UP;
- }
- } else if(obj1Delta < obj2Delta) {
- overlap = object1.y - object2.height - object2.y;
- if((-overlap > maxOverlap) || !(object1.allowCollisions & Collision.UP) || !(object2.allowCollisions & Collision.DOWN)) {
- overlap = 0;
- } else {
- object1.touching |= Collision.UP;
- object2.touching |= Collision.DOWN;
- }
- }
- }
- }
- // Then adjust their positions and velocities accordingly (if there was any overlap)
- if(overlap != 0) {
- console.log('y overlap', overlap);
- var obj1Velocity = object1.velocity.y;
- var obj2Velocity = object2.velocity.y;
- if(!object1.immovable && !object2.immovable) {
- overlap *= 0.5;
- object1.y = object1.y - overlap;
- object2.y += overlap;
- var obj1NewVelocity = Math.sqrt((obj2Velocity * obj2Velocity * object2.mass) / object1.mass) * ((obj2Velocity > 0) ? 1 : -1);
- var obj2NewVelocity = Math.sqrt((obj1Velocity * obj1Velocity * object1.mass) / object2.mass) * ((obj1Velocity > 0) ? 1 : -1);
- var average = (obj1NewVelocity + obj2NewVelocity) * 0.5;
- obj1NewVelocity -= average;
- obj2NewVelocity -= average;
- object1.velocity.y = average + obj1NewVelocity * object1.elasticity;
- object2.velocity.y = average + obj2NewVelocity * object2.elasticity;
- } else if(!object1.immovable) {
- object1.y = object1.y - overlap;
- object1.velocity.y = obj2Velocity - obj1Velocity * object1.elasticity;
- // This is special case code that handles things like horizontal moving platforms you can ride
- if(object2.active && object2.moves && (obj1Delta > obj2Delta)) {
- object1.x += object2.x - object2.last.x;
- }
- console.log('y2', object1.y, object1.velocity.y);
- } else if(!object2.immovable) {
- object2.y += overlap;
- object2.velocity.y = obj1Velocity - obj2Velocity * object2.elasticity;
- // This is special case code that handles things like horizontal moving platforms you can ride
- if(object1.active && object1.moves && (obj1Delta < obj2Delta)) {
- object2.x += object1.x - object1.last.x;
- }
- console.log('y3', object2.y, object2.velocity.y);
- }
- return true;
- } else {
- return false;
- }
- };
Collision.distance = /**
* Returns the distance between the two given coordinates.
* @param x1 The X value of the first coordinate
@@ -6208,6 +6689,369 @@ var Phaser;
function distanceSquared(x1, y1, x2, y2) {
return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
};
+ Collision.flattenPointsOn = // SAT
+ /**
+ * Flattens the specified array of points onto a unit vector axis,
+ * resulting in a one dimensional range of the minimum and
+ * maximum value on that axis.
+ *
+ * @param {Array.} points The points to flatten.
+ * @param {Vector} normal The unit vector axis to flatten on.
+ * @param {Array.} result An array. After calling this function,
+ * result[0] will be the minimum value,
+ * result[1] will be the maximum value.
+ */
+ function flattenPointsOn(points, normal, result) {
+ var min = Number.MAX_VALUE;
+ var max = -Number.MAX_VALUE;
+ var len = points.length;
+ for(var i = 0; i < len; i++) {
+ // Get the magnitude of the projection of the point onto the normal
+ var dot = points[i].dot(normal);
+ if(dot < min) {
+ min = dot;
+ }
+ if(dot > max) {
+ max = dot;
+ }
+ }
+ result[0] = min;
+ result[1] = max;
+ };
+ Collision.isSeparatingAxis = /**
+ * Check whether two convex clockwise polygons are separated by the specified
+ * axis (must be a unit vector).
+ *
+ * @param {Vector} aPos The position of the first polygon.
+ * @param {Vector} bPos The position of the second polygon.
+ * @param {Array.} aPoints The points in the first polygon.
+ * @param {Array.} bPoints The points in the second polygon.
+ * @param {Vector} axis The axis (unit sized) to test against. The points of both polygons
+ * will be projected onto this axis.
+ * @param {Response=} response A Response object (optional) which will be populated
+ * if the axis is not a separating axis.
+ * @return {boolean} true if it is a separating axis, false otherwise. If false,
+ * and a response is passed in, information about how much overlap and
+ * the direction of the overlap will be populated.
+ */
+ function isSeparatingAxis(aPos, bPos, aPoints, bPoints, axis, response) {
+ if (typeof response === "undefined") { response = null; }
+ var rangeA = Collision.T_ARRAYS.pop();
+ var rangeB = Collision.T_ARRAYS.pop();
+ // Get the magnitude of the offset between the two polygons
+ var offsetV = Collision.T_VECTORS.pop().copyFrom(bPos).sub(aPos);
+ var projectedOffset = offsetV.dot(axis);
+ // Project the polygons onto the axis.
+ Collision.flattenPointsOn(aPoints, axis, rangeA);
+ Collision.flattenPointsOn(bPoints, axis, rangeB);
+ // Move B's range to its position relative to A.
+ rangeB[0] += projectedOffset;
+ rangeB[1] += projectedOffset;
+ // Check if there is a gap. If there is, this is a separating axis and we can stop
+ if(rangeA[0] > rangeB[1] || rangeB[0] > rangeA[1]) {
+ Collision.T_VECTORS.push(offsetV);
+ Collision.T_ARRAYS.push(rangeA);
+ Collision.T_ARRAYS.push(rangeB);
+ return true;
+ }
+ // If we're calculating a response, calculate the overlap.
+ if(response) {
+ var overlap = 0;
+ // A starts further left than B
+ if(rangeA[0] < rangeB[0]) {
+ response.aInB = false;
+ // A ends before B does. We have to pull A out of B
+ if(rangeA[1] < rangeB[1]) {
+ overlap = rangeA[1] - rangeB[0];
+ response.bInA = false;
+ // B is fully inside A. Pick the shortest way out.
+ } else {
+ var option1 = rangeA[1] - rangeB[0];
+ var option2 = rangeB[1] - rangeA[0];
+ overlap = option1 < option2 ? option1 : -option2;
+ }
+ // B starts further left than A
+ } else {
+ response.bInA = false;
+ // B ends before A ends. We have to push A out of B
+ if(rangeA[1] > rangeB[1]) {
+ overlap = rangeA[0] - rangeB[1];
+ response.aInB = false;
+ // A is fully inside B. Pick the shortest way out.
+ } else {
+ var option1 = rangeA[1] - rangeB[0];
+ var option2 = rangeB[1] - rangeA[0];
+ overlap = option1 < option2 ? option1 : -option2;
+ }
+ }
+ // If this is the smallest amount of overlap we've seen so far, set it as the minimum overlap.
+ var absOverlap = Math.abs(overlap);
+ if(absOverlap < response.overlap) {
+ response.overlap = absOverlap;
+ response.overlapN.copyFrom(axis);
+ if(overlap < 0) {
+ response.overlapN.reverse();
+ }
+ }
+ }
+ Collision.T_VECTORS.push(offsetV);
+ Collision.T_ARRAYS.push(rangeA);
+ Collision.T_ARRAYS.push(rangeB);
+ return false;
+ };
+ Collision.LEFT_VORNOI_REGION = -1;
+ Collision.MIDDLE_VORNOI_REGION = 0;
+ Collision.RIGHT_VORNOI_REGION = 1;
+ Collision.vornoiRegion = /**
+ * Calculates which Vornoi region a point is on a line segment.
+ * It is assumed that both the line and the point are relative to (0, 0)
+ *
+ * | (0) |
+ * (-1) [0]--------------[1] (1)
+ * | (0) |
+ *
+ * @param {Vector} line The line segment.
+ * @param {Vector} point The point.
+ * @return {number} LEFT_VORNOI_REGION (-1) if it is the left region,
+ * MIDDLE_VORNOI_REGION (0) if it is the middle region,
+ * RIGHT_VORNOI_REGION (1) if it is the right region.
+ */
+ function vornoiRegion(line, point) {
+ var len2 = line.length2();
+ var dp = point.dot(line);
+ if(dp < 0) {
+ return Collision.LEFT_VORNOI_REGION;
+ } else if(dp > len2) {
+ return Collision.RIGHT_VORNOI_REGION;
+ } else {
+ return Collision.MIDDLE_VORNOI_REGION;
+ }
+ };
+ Collision.testCircleCircle = /**
+ * Check if two circles intersect.
+ *
+ * @param {Circle} a The first circle.
+ * @param {Circle} b The second circle.
+ * @param {Response=} response Response object (optional) that will be populated if
+ * the circles intersect.
+ * @return {boolean} true if the circles intersect, false if they don't.
+ */
+ function testCircleCircle(a, b, response) {
+ if (typeof response === "undefined") { response = null; }
+ var differenceV = Collision.T_VECTORS.pop().copyFrom(b.pos).sub(a.pos);
+ var totalRadius = a.radius + b.radius;
+ var totalRadiusSq = totalRadius * totalRadius;
+ var distanceSq = differenceV.length2();
+ if(distanceSq > totalRadiusSq) {
+ // They do not intersect
+ Collision.T_VECTORS.push(differenceV);
+ return false;
+ }
+ // They intersect. If we're calculating a response, calculate the overlap.
+ if(response) {
+ var dist = Math.sqrt(distanceSq);
+ response.a = a;
+ response.b = b;
+ response.overlap = totalRadius - dist;
+ response.overlapN.copyFrom(differenceV.normalize());
+ response.overlapV.copyFrom(differenceV).scale(response.overlap);
+ response.aInB = a.radius <= b.radius && dist <= b.radius - a.radius;
+ response.bInA = b.radius <= a.radius && dist <= a.radius - b.radius;
+ }
+ Collision.T_VECTORS.push(differenceV);
+ return true;
+ };
+ Collision.testPolygonCircle = /**
+ * Check if a polygon and a circle intersect.
+ *
+ * @param {Polygon} polygon The polygon.
+ * @param {Circle} circle The circle.
+ * @param {Response=} response Response object (optional) that will be populated if
+ * they interset.
+ * @return {boolean} true if they intersect, false if they don't.
+ */
+ function testPolygonCircle(polygon, circle, response) {
+ if (typeof response === "undefined") { response = null; }
+ var circlePos = Collision.T_VECTORS.pop().copyFrom(circle.pos).sub(polygon.pos);
+ var radius = circle.radius;
+ var radius2 = radius * radius;
+ var points = polygon.points;
+ var len = points.length;
+ var edge = Collision.T_VECTORS.pop();
+ var point = Collision.T_VECTORS.pop();
+ // For each edge in the polygon
+ for(var i = 0; i < len; i++) {
+ var next = i === len - 1 ? 0 : i + 1;
+ var prev = i === 0 ? len - 1 : i - 1;
+ var overlap = 0;
+ var overlapN = null;
+ // Get the edge
+ edge.copyFrom(polygon.edges[i]);
+ // Calculate the center of the cirble relative to the starting point of the edge
+ point.copyFrom(circlePos).sub(points[i]);
+ // If the distance between the center of the circle and the point
+ // is bigger than the radius, the polygon is definitely not fully in
+ // the circle.
+ if(response && point.length2() > radius2) {
+ response.aInB = false;
+ }
+ // Calculate which Vornoi region the center of the circle is in.
+ var region = Collision.vornoiRegion(edge, point);
+ if(region === Collision.LEFT_VORNOI_REGION) {
+ // Need to make sure we're in the RIGHT_VORNOI_REGION of the previous edge.
+ edge.copyFrom(polygon.edges[prev]);
+ // Calculate the center of the circle relative the starting point of the previous edge
+ var point2 = Collision.T_VECTORS.pop().copyFrom(circlePos).sub(points[prev]);
+ region = Collision.vornoiRegion(edge, point2);
+ if(region === Collision.RIGHT_VORNOI_REGION) {
+ // It's in the region we want. Check if the circle intersects the point.
+ var dist = point.length2();
+ if(dist > radius) {
+ // No intersection
+ Collision.T_VECTORS.push(circlePos);
+ Collision.T_VECTORS.push(edge);
+ Collision.T_VECTORS.push(point);
+ Collision.T_VECTORS.push(point2);
+ return false;
+ } else if(response) {
+ // It intersects, calculate the overlap
+ response.bInA = false;
+ overlapN = point.normalize();
+ overlap = radius - dist;
+ }
+ }
+ Collision.T_VECTORS.push(point2);
+ } else if(region === Collision.RIGHT_VORNOI_REGION) {
+ // Need to make sure we're in the left region on the next edge
+ edge.copyFrom(polygon.edges[next]);
+ // Calculate the center of the circle relative to the starting point of the next edge
+ point.copyFrom(circlePos).sub(points[next]);
+ region = Collision.vornoiRegion(edge, point);
+ if(region === Collision.LEFT_VORNOI_REGION) {
+ // It's in the region we want. Check if the circle intersects the point.
+ var dist = point.length2();
+ if(dist > radius) {
+ // No intersection
+ Collision.T_VECTORS.push(circlePos);
+ Collision.T_VECTORS.push(edge);
+ Collision.T_VECTORS.push(point);
+ return false;
+ } else if(response) {
+ // It intersects, calculate the overlap
+ response.bInA = false;
+ overlapN = point.normalize();
+ overlap = radius - dist;
+ }
+ }
+ // MIDDLE_VORNOI_REGION
+ } else {
+ // Need to check if the circle is intersecting the edge,
+ // Change the edge into its "edge normal".
+ var normal = edge.perp().normalize();
+ // Find the perpendicular distance between the center of the
+ // circle and the edge.
+ var dist = point.dot(normal);
+ var distAbs = Math.abs(dist);
+ // If the circle is on the outside of the edge, there is no intersection
+ if(dist > 0 && distAbs > radius) {
+ Collision.T_VECTORS.push(circlePos);
+ Collision.T_VECTORS.push(normal);
+ Collision.T_VECTORS.push(point);
+ return false;
+ } else if(response) {
+ // It intersects, calculate the overlap.
+ overlapN = normal;
+ overlap = radius - dist;
+ // If the center of the circle is on the outside of the edge, or part of the
+ // circle is on the outside, the circle is not fully inside the polygon.
+ if(dist >= 0 || overlap < 2 * radius) {
+ response.bInA = false;
+ }
+ }
+ }
+ // If this is the smallest overlap we've seen, keep it.
+ // (overlapN may be null if the circle was in the wrong Vornoi region)
+ if(overlapN && response && Math.abs(overlap) < Math.abs(response.overlap)) {
+ response.overlap = overlap;
+ response.overlapN.copyFrom(overlapN);
+ }
+ }
+ // Calculate the final overlap vector - based on the smallest overlap.
+ if(response) {
+ response.a = polygon;
+ response.b = circle;
+ response.overlapV.copyFrom(response.overlapN).scale(response.overlap);
+ }
+ Collision.T_VECTORS.push(circlePos);
+ Collision.T_VECTORS.push(edge);
+ Collision.T_VECTORS.push(point);
+ return true;
+ };
+ Collision.testCirclePolygon = /**
+ * Check if a circle and a polygon intersect.
+ *
+ * NOTE: This runs slightly slower than polygonCircle as it just
+ * runs polygonCircle and reverses everything at the end.
+ *
+ * @param {Circle} circle The circle.
+ * @param {Polygon} polygon The polygon.
+ * @param {Response=} response Response object (optional) that will be populated if
+ * they interset.
+ * @return {boolean} true if they intersect, false if they don't.
+ */
+ function testCirclePolygon(circle, polygon, response) {
+ if (typeof response === "undefined") { response = null; }
+ var result = Collision.testPolygonCircle(polygon, circle, response);
+ if(result && response) {
+ // Swap A and B in the response.
+ var a = response.a;
+ var aInB = response.aInB;
+ response.overlapN.reverse();
+ response.overlapV.reverse();
+ response.a = response.b;
+ response.b = a;
+ response.aInB = response.bInA;
+ response.bInA = aInB;
+ }
+ return result;
+ };
+ Collision.testPolygonPolygon = /**
+ * Checks whether two convex, clockwise polygons intersect.
+ *
+ * @param {Polygon} a The first polygon.
+ * @param {Polygon} b The second polygon.
+ * @param {Response=} response Response object (optional) that will be populated if
+ * they interset.
+ * @return {boolean} true if they intersect, false if they don't.
+ */
+ function testPolygonPolygon(a, b, response) {
+ if (typeof response === "undefined") { response = null; }
+ var aPoints = a.points;
+ var aLen = aPoints.length;
+ var bPoints = b.points;
+ var bLen = bPoints.length;
+ // If any of the edge normals of A is a separating axis, no intersection.
+ for(var i = 0; i < aLen; i++) {
+ if(Collision.isSeparatingAxis(a.pos, b.pos, aPoints, bPoints, a.normals[i], response)) {
+ return false;
+ }
+ }
+ // If any of the edge normals of B is a separating axis, no intersection.
+ for(var i = 0; i < bLen; i++) {
+ if(Collision.isSeparatingAxis(a.pos, b.pos, aPoints, bPoints, b.normals[i], response)) {
+ return false;
+ }
+ }
+ // Since none of the edge normals of A or B are a separating axis, there is an intersection
+ // and we've already calculated the smallest overlap (in isSeparatingAxis). Calculate the
+ // final overlap vector.
+ if(response) {
+ response.a = a;
+ response.b = b;
+ response.overlapV.copyFrom(response.overlapN).scale(response.overlap);
+ }
+ return true;
+ };
return Collision;
})();
Phaser.Collision = Collision;
@@ -7345,26 +8189,233 @@ var Phaser;
return Math.sqrt(dx * dx + dy * dy);
};
GameMath.prototype.rotatePoint = /**
- * Rotates a point around the x/y coordinates given to the desired angle
+ * Rotates the point around the x/y coordinates given to the desired angle and distance
+ * @param point {Object} Any object with exposed x and y properties
* @param x {number} The x coordinate of the anchor point
* @param y {number} The y coordinate of the anchor point
- * @param angle {number} The angle of the rotation in radians
- * @param point {Point} The point object to perform the rotation on
+ * @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from.
+ * @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)?
+ * @param {Number} distance An optional distance constraint between the point and the anchor
* @return The modified point object
*/
- function (x, y, angle, point) {
- var s = Math.sin(angle);
- var c = Math.cos(angle);
- point.x -= x;
- point.y -= y;
- var newX = point.x * c - point.y * s;
- var newY = point.x * s - point.y * c;
- return point.setTo(newX + x, newY + y);
+ function (point, x1, y1, angle, asDegrees, distance) {
+ if (typeof asDegrees === "undefined") { asDegrees = false; }
+ if (typeof distance === "undefined") { distance = null; }
+ if(asDegrees) {
+ angle = angle * GameMath.DEG_TO_RAD;
+ }
+ // Get distance from origin to the point
+ if(distance === null) {
+ distance = Math.sqrt(((x1 - point.x) * (x1 - point.x)) + ((y1 - point.y) * (y1 - point.y)));
+ }
+ point.x = x1 + distance * Math.cos(angle);
+ point.y = y1 + distance * Math.sin(angle);
+ return point;
};
return GameMath;
})();
Phaser.GameMath = GameMath;
})(Phaser || (Phaser = {}));
+///
+/**
+* Phaser - GameObjectFactory
+*
+* A quick way to create new world objects and add existing objects to the current world.
+*/
+var Phaser;
+(function (Phaser) {
+ var GameObjectFactory = (function () {
+ /**
+ * GameObjectFactory constructor
+ * @param game {Game} A reference to the current Game.
+ */
+ function GameObjectFactory(game) {
+ this._game = game;
+ this._world = this._game.world;
+ }
+ GameObjectFactory.prototype.camera = /**
+ * Create a new camera with specific position and size.
+ *
+ * @param x {number} X position of the new camera.
+ * @param y {number} Y position of the new camera.
+ * @param width {number} Width of the new camera.
+ * @param height {number} Height of the new camera.
+ * @returns {Camera} The newly created camera object.
+ */
+ function (x, y, width, height) {
+ return this._world.createCamera(x, y, width, height);
+ };
+ GameObjectFactory.prototype.geomSprite = /**
+ * Create a new GeomSprite with specific position.
+ *
+ * @param x {number} X position of the new geom sprite.
+ * @param y {number} Y position of the new geom sprite.
+ * @returns {GeomSprite} The newly created geom sprite object.
+ */
+ function (x, y) {
+ return this._world.createGeomSprite(x, y);
+ };
+ GameObjectFactory.prototype.sprite = /**
+ * Create a new Sprite with specific position and sprite sheet key.
+ *
+ * @param x {number} X position of the new sprite.
+ * @param y {number} Y position of the new sprite.
+ * @param key {string} Optional, key for the sprite sheet you want it to use.
+ * @returns {Sprite} The newly created sprite object.
+ */
+ function (x, y, key) {
+ if (typeof key === "undefined") { key = ''; }
+ return this._world.createSprite(x, y, key);
+ };
+ GameObjectFactory.prototype.dynamicTexture = /**
+ * Create a new DynamicTexture with specific size.
+ *
+ * @param width {number} Width of the texture.
+ * @param height {number} Height of the texture.
+ * @returns {DynamicTexture} The newly created dynamic texture object.
+ */
+ function (width, height) {
+ return this._world.createDynamicTexture(width, height);
+ };
+ GameObjectFactory.prototype.group = /**
+ * Create a new object container.
+ *
+ * @param maxSize {number} Optional, capacity of this group.
+ * @returns {Group} The newly created group.
+ */
+ function (maxSize) {
+ if (typeof maxSize === "undefined") { maxSize = 0; }
+ return this._world.createGroup(maxSize);
+ };
+ GameObjectFactory.prototype.particle = /**
+ * Create a new Particle.
+ *
+ * @return {Particle} The newly created particle object.
+ */
+ function () {
+ return this._world.createParticle();
+ };
+ GameObjectFactory.prototype.emitter = /**
+ * Create a new Emitter.
+ *
+ * @param x {number} Optional, x position of the emitter.
+ * @param y {number} Optional, y position of the emitter.
+ * @param size {number} Optional, size of this emitter.
+ * @return {Emitter} The newly created emitter object.
+ */
+ function (x, y, size) {
+ if (typeof x === "undefined") { x = 0; }
+ if (typeof y === "undefined") { y = 0; }
+ if (typeof size === "undefined") { size = 0; }
+ return this._world.createEmitter(x, y, size);
+ };
+ GameObjectFactory.prototype.scrollZone = /**
+ * Create a new ScrollZone object with image key, position and size.
+ *
+ * @param key {string} Key to a image you wish this object to use.
+ * @param x {number} X position of this object.
+ * @param y {number} Y position of this object.
+ * @param width number} Width of this object.
+ * @param height {number} Height of this object.
+ * @returns {ScrollZone} The newly created scroll zone object.
+ */
+ function (key, x, y, width, height) {
+ if (typeof x === "undefined") { x = 0; }
+ if (typeof y === "undefined") { y = 0; }
+ if (typeof width === "undefined") { width = 0; }
+ if (typeof height === "undefined") { height = 0; }
+ return this._world.createScrollZone(key, x, y, width, height);
+ };
+ GameObjectFactory.prototype.tilemap = /**
+ * Create a new Tilemap.
+ *
+ * @param key {string} Key for tileset image.
+ * @param mapData {string} Data of this tilemap.
+ * @param format {number} Format of map data. (Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON)
+ * @param [resizeWorld] {boolean} resize the world to make same as tilemap?
+ * @param [tileWidth] {number} width of each tile.
+ * @param [tileHeight] {number} height of each tile.
+ * @return {Tilemap} The newly created tilemap object.
+ */
+ function (key, mapData, format, resizeWorld, tileWidth, tileHeight) {
+ if (typeof resizeWorld === "undefined") { resizeWorld = true; }
+ if (typeof tileWidth === "undefined") { tileWidth = 0; }
+ if (typeof tileHeight === "undefined") { tileHeight = 0; }
+ return this._world.createTilemap(key, mapData, format, resizeWorld, tileWidth, tileHeight);
+ };
+ GameObjectFactory.prototype.tween = /**
+ * Create a tween object for a specific object.
+ *
+ * @param obj Object you wish the tween will affect.
+ * @return {Phaser.Tween} The newly created tween object.
+ */
+ function (obj) {
+ return this._game.tweens.create(obj);
+ };
+ GameObjectFactory.prototype.existingSprite = /**
+ * Add an existing Sprite to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param sprite The Sprite to add to the Game World
+ * @return {Phaser.Sprite} The Sprite object
+ */
+ function (sprite) {
+ return this._world.group.add(sprite);
+ };
+ GameObjectFactory.prototype.existingGeomSprite = /**
+ * Add an existing GeomSprite to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param sprite The GeomSprite to add to the Game World
+ * @return {Phaser.GeomSprite} The GeomSprite object
+ */
+ function (sprite) {
+ return this._world.group.add(sprite);
+ };
+ GameObjectFactory.prototype.existingEmitter = /**
+ * Add an existing Emitter to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param emitter The Emitter to add to the Game World
+ * @return {Phaser.Emitter} The Emitter object
+ */
+ function (emitter) {
+ return this._world.group.add(emitter);
+ };
+ GameObjectFactory.prototype.existingScrollZone = /**
+ * Add an existing ScrollZone to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param scrollZone The ScrollZone to add to the Game World
+ * @return {Phaser.ScrollZone} The ScrollZone object
+ */
+ function (scrollZone) {
+ return this._world.group.add(scrollZone);
+ };
+ GameObjectFactory.prototype.existingTilemap = /**
+ * Add an existing Tilemap to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param tilemap The Tilemap to add to the Game World
+ * @return {Phaser.Tilemap} The Tilemap object
+ */
+ function (tilemap) {
+ return this._world.group.add(tilemap);
+ };
+ GameObjectFactory.prototype.existingTween = /**
+ * Add an existing Tween to the current world.
+ * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
+ *
+ * @param tween The Tween to add to the Game World
+ * @return {Phaser.Tween} The Tween object
+ */
+ function (tween) {
+ return this._game.tweens.add(tween);
+ };
+ return GameObjectFactory;
+ })();
+ Phaser.GameObjectFactory = GameObjectFactory;
+})(Phaser || (Phaser = {}));
///
///
/**
@@ -7398,9 +8449,36 @@ var Phaser;
this._maxSize = MaxSize;
this._marker = 0;
this._sortIndex = null;
+ this.cameraBlacklist = [];
}
Group.ASCENDING = -1;
Group.DESCENDING = 1;
+ Group.prototype.hideFromCamera = /**
+ * If you do not wish this object to be visible to a specific camera, pass the camera here.
+ *
+ * @param camera {Camera} The specific camera.
+ */
+ function (camera) {
+ if(this.cameraBlacklist.indexOf(camera.ID) == -1) {
+ this.cameraBlacklist.push(camera.ID);
+ }
+ };
+ Group.prototype.showToCamera = /**
+ * Make this object only visible to a specific camera.
+ *
+ * @param camera {Camera} The camera you wish it to be visible.
+ */
+ function (camera) {
+ if(this.cameraBlacklist.indexOf(camera.ID) !== -1) {
+ this.cameraBlacklist.slice(this.cameraBlacklist.indexOf(camera.ID), 1);
+ }
+ };
+ Group.prototype.clearCameraList = /**
+ * This clears the camera black list, making the GameObject visible to all cameras.
+ */
+ function () {
+ this.cameraBlacklist.length = 0;
+ };
Group.prototype.destroy = /**
* Override this function to handle any deleting or "shutdown" type operations you might need,
* such as removing traditional Flash children like Basic objects.
@@ -7443,6 +8521,9 @@ var Phaser;
*/
function (camera, cameraOffsetX, cameraOffsetY, forceRender) {
if (typeof forceRender === "undefined") { forceRender = false; }
+ if(this.cameraBlacklist.indexOf(camera.ID) !== -1) {
+ return;
+ }
if(this.ignoreGlobalRender && forceRender == false) {
return;
}
@@ -7945,6 +9026,11 @@ var Phaser;
* @param callback {function} This will be called when assets completely loaded.
*/
function Loader(game, callback) {
+ /**
+ * The crossOrigin value applied to loaded images
+ * @type {string}
+ */
+ this.crossOrigin = '';
this._game = game;
this._gameCreateComplete = callback;
this._keys = [];
@@ -8174,6 +9260,7 @@ var Phaser;
file.data.onerror = function () {
return _this.fileError(file.key);
};
+ file.data.crossOrigin = this.crossOrigin;
file.data.src = file.url;
break;
case 'audio':
@@ -8844,7 +9931,7 @@ var Phaser;
/**
* Phaser
*
-* v0.9.5 - April 28th 2013
+* v0.9.6 - May 21st 2013
*
* A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi.
*
@@ -8858,7 +9945,7 @@ var Phaser;
*/
var Phaser;
(function (Phaser) {
- Phaser.VERSION = 'Phaser version 0.9.5';
+ Phaser.VERSION = 'Phaser version 0.9.6';
})(Phaser || (Phaser = {}));
///
/**
@@ -9185,7 +10272,7 @@ var Phaser;
* Start color fading cycle.
*/
function () {
- this._fade = this._game.createTween(this._color2);
+ this._fade = this._game.add.tween(this._color2);
this._fade.to({
r: Math.random() * 250,
g: Math.random() * 250,
@@ -9274,7 +10361,7 @@ var Phaser;
* Start fadeOut effect.
*/
function () {
- this._fade = this._game.createTween(this._color);
+ this._fade = this._game.add.tween(this._color);
this._fade.to({
r: 50,
g: 50,
@@ -9287,7 +10374,7 @@ var Phaser;
* Start fadeIn effect.
*/
function () {
- this._fade = this._game.createTween(this._color);
+ this._fade = this._game.add.tween(this._color);
this._fade.to({
r: 255,
g: 255,
@@ -9414,18 +10501,24 @@ var Phaser;
}
if(event.type == 'blur' || document['hidden'] == true || document['webkitHidden'] == true) {
if(this._game.paused == false) {
- this._pauseScreen.onPaused();
- this.saveCanvasValues();
- this._game.paused = true;
+ this.pauseGame();
}
} else {
if(this._game.paused == true) {
- this._pauseScreen.onResume();
- this._game.paused = false;
- this.restoreCanvasValues();
+ this.resumeGame();
}
}
};
+ Stage.prototype.pauseGame = function () {
+ this._pauseScreen.onPaused();
+ this.saveCanvasValues();
+ this._game.paused = true;
+ };
+ Stage.prototype.resumeGame = function () {
+ this._pauseScreen.onResume();
+ this.restoreCanvasValues();
+ this._game.paused = false;
+ };
Stage.prototype.getOffset = /**
* Get the DOM offset values of the given element
*/
@@ -10357,134 +11450,6 @@ var Phaser;
})();
Phaser.TweenManager = TweenManager;
})(Phaser || (Phaser = {}));
-///
-/**
-* Phaser - Vector2
-*
-* A simple 2-dimensional vector class. Based on the one included with verlet-js by Sub Protocol released under MIT
-*/
-var Phaser;
-(function (Phaser) {
- var Vector2 = (function () {
- /**
- * Creates a new Vector2 object.
- * @class Vector2
- * @constructor
- * @param {Number} x The x coordinate of vector2
- * @param {Number} y The y coordinate of vector2
- * @return {Vector2} This object
- **/
- function Vector2(x, y) {
- if (typeof x === "undefined") { x = 0; }
- if (typeof y === "undefined") { y = 0; }
- this.x = x;
- this.y = y;
- }
- Vector2.prototype.setTo = function (x, y) {
- this.x = x;
- this.y = y;
- return this;
- };
- Vector2.prototype.add = function (v, output) {
- if (typeof output === "undefined") { output = new Vector2(); }
- return output.setTo(this.x + v.x, this.y + v.y);
- };
- Vector2.prototype.sub = function (v, output) {
- if (typeof output === "undefined") { output = new Vector2(); }
- return output.setTo(this.x - v.x, this.y - v.y);
- };
- Vector2.prototype.mul = function (v, output) {
- if (typeof output === "undefined") { output = new Vector2(); }
- return output.setTo(this.x * v.x, this.y * v.y);
- };
- Vector2.prototype.div = function (v, output) {
- if (typeof output === "undefined") { output = new Vector2(); }
- return output.setTo(this.x / v.x, this.y / v.y);
- };
- Vector2.prototype.scale = function (coef, output) {
- if (typeof output === "undefined") { output = new Vector2(); }
- return output.setTo(this.x * coef, this.y * coef);
- };
- Vector2.prototype.mutableSet = function (v) {
- this.x = v.x;
- this.y = v.y;
- return this;
- };
- Vector2.prototype.mutableAdd = function (v) {
- this.x += v.x;
- this.y += v.y;
- return this;
- };
- Vector2.prototype.mutableSub = function (v) {
- this.x -= v.x;
- this.y -= v.y;
- return this;
- };
- Vector2.prototype.mutableMul = function (v) {
- this.x *= v.x;
- this.y *= v.y;
- return this;
- };
- Vector2.prototype.mutableDiv = function (v) {
- this.x /= v.x;
- this.y /= v.y;
- return this;
- };
- Vector2.prototype.mutableScale = function (coef) {
- this.x *= coef;
- this.y *= coef;
- return this;
- };
- Vector2.prototype.equals = function (v) {
- return this.x == v.x && this.y == v.y;
- };
- Vector2.prototype.epsilonEquals = function (v, epsilon) {
- return Math.abs(this.x - v.x) <= epsilon && Math.abs(this.y - v.y) <= epsilon;
- };
- Vector2.prototype.length = function () {
- return Math.sqrt(this.x * this.x + this.y * this.y);
- };
- Vector2.prototype.length2 = function () {
- return this.x * this.x + this.y * this.y;
- };
- Vector2.prototype.dist = function (v) {
- return Math.sqrt(this.dist2(v));
- };
- Vector2.prototype.dist2 = function (v) {
- return ((v.x - this.x) * (v.x - this.x)) + ((v.y - this.y) * (v.y - this.y));
- };
- Vector2.prototype.normal = function (output) {
- if (typeof output === "undefined") { output = new Vector2(); }
- var m = Math.sqrt(this.x * this.x + this.y * this.y);
- return output.setTo(this.x / m, this.y / m);
- };
- Vector2.prototype.dot = function (v) {
- return this.x * v.x + this.y * v.y;
- };
- Vector2.prototype.angle = function (v) {
- return Math.atan2(this.x * v.y - this.y * v.x, this.x * v.x + this.y * v.y);
- };
- Vector2.prototype.angle2 = function (vLeft, vRight) {
- return vLeft.sub(this).angle(vRight.sub(this));
- };
- Vector2.prototype.rotate = function (origin, theta, output) {
- if (typeof output === "undefined") { output = new Vector2(); }
- var x = this.x - origin.x;
- var y = this.y - origin.y;
- return output.setTo(x * Math.cos(theta) - y * Math.sin(theta) + origin.x, x * Math.sin(theta) + y * Math.cos(theta) + origin.y);
- };
- Vector2.prototype.toString = /**
- * Returns a string representation of this object.
- * @method toString
- * @return {string} a string representation of the object.
- **/
- function () {
- return "[{Vector2 (x=" + this.x + " y=" + this.y + ")}]";
- };
- return Vector2;
- })();
- Phaser.Vector2 = Vector2;
-})(Phaser || (Phaser = {}));
var Phaser;
(function (Phaser) {
///
@@ -10581,13 +11546,32 @@ var Phaser;
* @return {Composite} This object
**/
function Composite(game) {
+ /**
+ * Texture of the particles to be rendered.
+ */
+ this._texture = null;
+ // local rendering related temp vars to help avoid gc spikes
+ this._sx = 0;
+ this._sy = 0;
+ this._sw = 0;
+ this._sh = 0;
+ this._dx = 0;
+ this._dy = 0;
+ this._dw = 0;
+ this._dh = 0;
+ this._hw = 0;
+ this._hh = 0;
this.drawParticles = null;
this.drawConstraints = null;
+ this.hideConstraints = true;
+ this.constraintLineColor = 'rgba(200,200,200,1)';
this._game = game;
+ this.sprites = [];
this.particles = [];
this.constraints = [];
+ this.frameBounds = new Phaser.Quad();
}
- Composite.prototype.createDistanceConstraint = // Map sprites to particles
+ Composite.prototype.createDistanceConstraint = // Create Constraints
function (a, b, stiffness, distance) {
if (typeof distance === "undefined") { distance = null; }
this.constraints.push(new Phaser.Verlet.DistanceConstraint(a, b, stiffness, distance));
@@ -10601,6 +11585,74 @@ var Phaser;
this.constraints.push(new Phaser.Verlet.PinConstraint(a, pos));
return this.constraints[this.constraints.length - 1];
};
+ Composite.prototype.loadGraphic = /**
+ * Load a graphic for this Composite. The graphic cannot be a SpriteSheet yet.
+ * @param key {string} Key of the graphic you want to load for this sprite.
+ * @return {Composite} This object
+ */
+ function (key) {
+ if(this._game.cache.getImage(key) !== null) {
+ if(this._game.cache.isSpriteSheet(key) == false) {
+ this._texture = this._game.cache.getImage(key);
+ this.frameBounds.width = this._texture.width;
+ this.frameBounds.height = this._texture.height;
+ this._hw = Math.floor(this.frameBounds.width / 2);
+ this._hh = Math.floor(this.frameBounds.width / 2);
+ this.drawParticles = this.render;
+ this.drawConstraints = this.renderConstraints;
+ }
+ }
+ return this;
+ };
+ Composite.prototype.renderConstraints = function (context) {
+ if(this.hideConstraints == true || this.constraints.length == 0) {
+ return;
+ }
+ var i;
+ context.beginPath();
+ for(i in this.constraints) {
+ if(this.constraints[i].b) {
+ context.moveTo(this.constraints[i].a.pos.x, this.constraints[i].a.pos.y);
+ context.lineTo(this.constraints[i].b.pos.x, this.constraints[i].b.pos.y);
+ }
+ }
+ context.strokeStyle = this.constraintLineColor;
+ context.stroke();
+ context.closePath();
+ };
+ Composite.prototype.render = function (context) {
+ this._sx = 0;
+ this._sy = 0;
+ this._sw = this.frameBounds.width;
+ this._sh = this.frameBounds.height;
+ this._dw = this.frameBounds.width;
+ this._dh = this.frameBounds.height;
+ this._sx = Math.round(this._sx);
+ this._sy = Math.round(this._sy);
+ this._sw = Math.round(this._sw);
+ this._sh = Math.round(this._sh);
+ this._dw = Math.round(this._dw);
+ this._dh = Math.round(this._dh);
+ var i;
+ for(i in this.particles) {
+ //this._dx = cameraOffsetX + (this.frameBounds.topLeft.x - camera.worldView.x);
+ //this._dy = cameraOffsetY + (this.frameBounds.topLeft.y - camera.worldView.y);
+ this._dx = this.particles[i].pos.x - this._hw;
+ this._dy = this.particles[i].pos.y - this._hh;
+ this._dx = Math.round(this._dx);
+ this._dy = Math.round(this._dy);
+ context.drawImage(this._texture, // Source Image
+ this._sx, // Source X (location within the source image)
+ this._sy, // Source Y
+ this._sw, // Source Width
+ this._sh, // Source Height
+ this._dx, // Destination X (where on the canvas it'll be drawn)
+ this._dy, // Destination Y
+ this._dw, // Destination Width (always same as Source Width unless scaled)
+ this._dh);
+ // Destination Height (always same as Source Height unless scaled)
+ }
+ };
Composite.prototype.pin = function (index, pos) {
if (typeof pos === "undefined") { pos = null; }
if(pos == null) {
@@ -10660,6 +11712,7 @@ var Phaser;
ctx.lineTo(this.b.pos.x, this.b.pos.y);
ctx.strokeStyle = "#d8dde2";
ctx.stroke();
+ ctx.closePath();
};
return DistanceConstraint;
})();
@@ -10750,12 +11803,13 @@ var Phaser;
* @return {Vector2} This object
**/
function VerletManager(game, width, height) {
+ this._v = new Phaser.Vector2();
this.composites = [];
- this.step = 32;
+ this.step = 16;
this.selectionRadius = 20;
this.draggedEntity = null;
this.highlightColor = '#4f545c';
- this.v = new Phaser.Vector2();
+ this.hideNearestEntityCircle = false;
this._game = game;
this.width = width;
this.height = height;
@@ -10770,10 +11824,10 @@ var Phaser;
VerletManager.prototype.intersectionTime = /**
* Computes time of intersection of a particle with a wall
*
- * @param {Vec2} line wall's root position
- * @param {Vec2} p particle's position
- * @param {Vec2} dir walls's direction
- * @param {Vec2} v particle's velocity
+ * @param {Vec2} line walls root position
+ * @param {Vec2} p particle position
+ * @param {Vec2} dir walls direction
+ * @param {Vec2} v particles velocity
*/
function (wall, p, dir, v) {
if(dir.x != 0) {
@@ -10799,35 +11853,16 @@ var Phaser;
return new Phaser.Vector2(p.x + v.x * t, p.y + v.y * t);
};
VerletManager.prototype.bounds = function (particle) {
- this.v.mutableSet(particle.pos);
- this.v.mutableSub(particle.lastPos);
+ this._v.mutableSet(particle.pos);
+ this._v.mutableSub(particle.lastPos);
if(particle.pos.y > this.height - 1) {
- particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, this.height - 1), particle.lastPos, new Phaser.Vector2(1, 0), this.v));
+ particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, this.height - 1), particle.lastPos, new Phaser.Vector2(1, 0), this._v));
}
if(particle.pos.x < 0) {
- particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, 0), particle.pos, new Phaser.Vector2(0, 1), this.v));
+ particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, 0), particle.pos, new Phaser.Vector2(0, 1), this._v));
}
if(particle.pos.x > this.width - 1) {
- particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(this.width - 1, 0), particle.pos, new Phaser.Vector2(0, 1), this.v));
- }
- };
- VerletManager.prototype.OLDbounds = function (particle) {
- if(particle.pos.y > this.height - 1) {
- particle.pos.y = this.height - 1;
- }
- if(particle.pos.x < 0) {
- var vx = particle.pos.x - particle.lastPos.x;
- var vy = particle.pos.y - particle.lastPos.y;
- if(vx == 0) {
- particle.pos.x = 0;
- } else {
- var t = -particle.lastPos.x / vx;
- particle.pos.x = particle.lastPos.x + t * vx;
- particle.pos.y = particle.lastPos.y + t * vy;
- }
- }
- if(particle.pos.x > this.width - 1) {
- particle.pos.x = this.width - 1;
+ particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(this.width - 1, 0), particle.pos, new Phaser.Vector2(0, 1), this._v));
}
};
VerletManager.prototype.createPoint = function (pos) {
@@ -10837,8 +11872,8 @@ var Phaser;
return composite;
};
VerletManager.prototype.createLineSegments = function (vertices, stiffness) {
- var i;
var composite = new Phaser.Verlet.Composite(this._game);
+ var i;
for(i in vertices) {
composite.particles.push(new Phaser.Verlet.Particle(vertices[i]));
if(i > 0) {
@@ -10852,7 +11887,8 @@ var Phaser;
var composite = new Phaser.Verlet.Composite(this._game);
var xStride = width / segments;
var yStride = height / segments;
- var x, y;
+ var x;
+ var y;
for(y = 0; y < segments; ++y) {
for(x = 0; x < segments; ++x) {
var px = origin.x + x * xStride - width / 2 + xStride / 2;
@@ -10921,7 +11957,7 @@ var Phaser;
}
// handle dragging of entities
if(this.draggedEntity) {
- this.draggedEntity.pos.mutableSet(new Phaser.Vector2(this._game.input.x, this._game.input.y));
+ this.draggedEntity.pos.mutableSet(this._game.input.position);
}
// relax
var stepCoef = 1 / this.step;
@@ -10959,7 +11995,7 @@ var Phaser;
for(c in this.composites) {
var particles = this.composites[c].particles;
for(i in particles) {
- var d2 = particles[i].pos.dist2(new Phaser.Vector2(this._game.input.x, this._game.input.y));
+ var d2 = particles[i].pos.distance2(this._game.input.position);
if(d2 <= this.selectionRadius * this.selectionRadius && (entity == null || d2 < d2Nearest)) {
entity = particles[i];
constraintsNearest = this.composites[c].constraints;
@@ -10999,11 +12035,12 @@ var Phaser;
}
// highlight nearest / dragged entity
var nearest = this.draggedEntity || this.nearestEntity();
- if(nearest) {
+ if(nearest && this.hideNearestEntityCircle == false) {
this.context.beginPath();
this.context.arc(nearest.pos.x, nearest.pos.y, 8, 0, 2 * Math.PI);
this.context.strokeStyle = this.highlightColor;
this.context.stroke();
+ this.context.closePath();
}
};
return VerletManager;
@@ -11065,19 +12102,25 @@ var Phaser;
World.prototype.setSize = // World methods
/**
* Update size of this world with specific width and height.
- * You can choose update camera bounds automatically or not.
+ * You can choose update camera bounds and verlet manager automatically or not.
*
* @param width {number} New width of the world.
* @param height {number} New height of the world.
* @param [updateCameraBounds] {boolean} update camera bounds automatically or not. Default to true.
+ * @param [updateVerletBounds] {boolean} update verlet bounds automatically or not. Default to true.
*/
- function (width, height, updateCameraBounds) {
+ function (width, height, updateCameraBounds, updateVerletBounds) {
if (typeof updateCameraBounds === "undefined") { updateCameraBounds = true; }
+ if (typeof updateVerletBounds === "undefined") { updateVerletBounds = true; }
this.bounds.width = width;
this.bounds.height = height;
if(updateCameraBounds == true) {
this._game.camera.setBounds(0, 0, width, height);
}
+ if(updateVerletBounds == true) {
+ this._game.verlet.width = width;
+ this._game.verlet.height = height;
+ }
};
Object.defineProperty(World.prototype, "width", {
get: function () {
@@ -12030,6 +13073,7 @@ var Phaser;
Phaser.RequestAnimationFrame = RequestAnimationFrame;
})(Phaser || (Phaser = {}));
///
+///
/**
* Phaser - Pointer
*
@@ -12066,17 +13110,17 @@ var Phaser;
*/
this._nextDrop = 0;
/**
- * A Point object representing the x/y screen coordinates of the Pointer.
- * @property pointA
- * @type {Point}
+ * A Vector object containing the initial position when the Pointer was engaged with the screen.
+ * @property positionDown
+ * @type {Vector2}
**/
- this.pointA = null;
+ this.positionDown = null;
/**
- * A Point object representing the x/y screen coordinates of the Pointer.
- * @property pointB
- * @type {Point}
+ * A Vector object containing the current position of the Pointer on the screen.
+ * @property position
+ * @type {Vector2}
**/
- this.pointB = null;
+ this.position = null;
/**
* A Circle object centered on the x/y screen coordinates of the Pointer.
* Default size of 44px (Apple's recommended "finger tip" size)
@@ -12183,8 +13227,8 @@ var Phaser;
this._game = game;
this.id = id;
this.active = false;
- this.pointA = new Phaser.Point();
- this.pointB = new Phaser.Point();
+ this.position = new Phaser.Vector2();
+ this.positionDown = new Phaser.Vector2();
this.circle = new Phaser.Circle(0, 0, 44);
if(id == 0) {
this.isMouse = true;
@@ -12232,9 +13276,14 @@ var Phaser;
if(event.button) {
this.button = event.button;
}
+ // Fix to stop rogue browser plugins from blocking the visibility state event
+ if(this._game.paused == true) {
+ this._game.stage.resumeGame();
+ return this;
+ }
this._history.length = 0;
this.move(event);
- this.pointA.setTo(this.x, this.y);
+ this.positionDown.setTo(this.x, this.y);
this.active = true;
this.withinGame = true;
this.isDown = true;
@@ -12264,8 +13313,8 @@ var Phaser;
if(this._game.input.recordPointerHistory && this._game.time.now >= this._nextDrop) {
this._nextDrop = this._game.time.now + this._game.input.recordRate;
this._history.push({
- x: this.pointB.x,
- y: this.pointB.y
+ x: this.position.x,
+ y: this.position.y
});
if(this._history.length > this._game.input.recordLimit) {
this._history.shift();
@@ -12290,13 +13339,13 @@ var Phaser;
this.screenY = event.screenY;
this.x = this.pageX - this._game.stage.offset.x;
this.y = this.pageY - this._game.stage.offset.y;
- this.pointB.setTo(this.x, this.y);
+ this.position.setTo(this.x, this.y);
this.circle.x = this.x;
this.circle.y = this.y;
if(this._game.input.multiInputOverride == Phaser.Input.MOUSE_OVERRIDES_TOUCH || this._game.input.multiInputOverride == Phaser.Input.MOUSE_TOUCH_COMBINE || (this._game.input.multiInputOverride == Phaser.Input.TOUCH_OVERRIDES_MOUSE && this._game.input.currentPointers == 0)) {
this._game.input.x = this.x * this._game.input.scaleX;
this._game.input.y = this.y * this._game.input.scaleY;
- this._game.input.point.setTo(this._game.input.x, this._game.input.y);
+ this._game.input.position.setTo(this._game.input.x, this._game.input.y);
this._game.input.circle.x = this._game.input.x;
this._game.input.circle.y = this._game.input.y;
}
@@ -12405,8 +13454,8 @@ var Phaser;
this._game.stage.context.closePath();
// Render the points
this._game.stage.context.beginPath();
- this._game.stage.context.moveTo(this.pointA.x, this.pointA.y);
- this._game.stage.context.lineTo(this.pointB.x, this.pointB.y);
+ this._game.stage.context.moveTo(this.positionDown.x, this.positionDown.y);
+ this._game.stage.context.lineTo(this.position.x, this.position.y);
this._game.stage.context.lineWidth = 2;
this._game.stage.context.stroke();
this._game.stage.context.closePath();
@@ -12588,11 +13637,11 @@ var Phaser;
*/
this.multiInputOverride = Input.MOUSE_TOUCH_COMBINE;
/**
- * A Point object representing the x/y screen coordinates of the Pointer.
- * @property point
- * @type {Point}
+ * A vector object representing the current position of the Pointer.
+ * @property vector
+ * @type {Vector2}
**/
- this.point = null;
+ this.position = null;
/**
* A Circle object centered on the x/y screen coordinates of the Input.
* Default size of 44px (Apples recommended "finger tip" size) but can be changed to anything
@@ -12684,6 +13733,36 @@ var Phaser;
* @type {Number}
*/
this.recordLimit = 100;
+ /**
+ * A Pointer object
+ * @property pointer6
+ * @type {Pointer}
+ **/
+ this.pointer6 = null;
+ /**
+ * A Pointer object
+ * @property pointer7
+ * @type {Pointer}
+ **/
+ this.pointer7 = null;
+ /**
+ * A Pointer object
+ * @property pointer8
+ * @type {Pointer}
+ **/
+ this.pointer8 = null;
+ /**
+ * A Pointer object
+ * @property pointer9
+ * @type {Pointer}
+ **/
+ this.pointer9 = null;
+ /**
+ * A Pointer object
+ * @property pointer10
+ * @type {Pointer}
+ **/
+ this.pointer10 = null;
this._game = game;
this.mousePointer = new Phaser.Pointer(this._game, 0);
this.pointer1 = new Phaser.Pointer(this._game, 1);
@@ -12691,11 +13770,6 @@ var Phaser;
this.pointer3 = new Phaser.Pointer(this._game, 3);
this.pointer4 = new Phaser.Pointer(this._game, 4);
this.pointer5 = new Phaser.Pointer(this._game, 5);
- this.pointer6 = new Phaser.Pointer(this._game, 6);
- this.pointer7 = new Phaser.Pointer(this._game, 7);
- this.pointer8 = new Phaser.Pointer(this._game, 8);
- this.pointer9 = new Phaser.Pointer(this._game, 9);
- this.pointer10 = new Phaser.Pointer(this._game, 10);
this.mouse = new Phaser.Mouse(this._game);
this.keyboard = new Phaser.Keyboard(this._game);
this.touch = new Phaser.Touch(this._game);
@@ -12705,7 +13779,7 @@ var Phaser;
this.onUp = new Phaser.Signal();
this.onTap = new Phaser.Signal();
this.onHold = new Phaser.Signal();
- this.point = new Phaser.Point();
+ this.position = new Phaser.Vector2();
this.circle = new Phaser.Circle(0, 0, 44);
this.currentPointers = 0;
}
@@ -12742,25 +13816,74 @@ var Phaser;
enumerable: true,
configurable: true
});
- Input.prototype.start = function () {
+ Input.prototype.addPointer = /**
+ * Add a new Pointer object to the Input Manager. By default Input creates 5 pointer objects for you. If you need more
+ * use this to create a new one, up to a maximum of 10.
+ * @method addPointer
+ * @return {Pointer} A reference to the new Pointer object
+ **/
+ function () {
+ var next = 0;
+ if(this.pointer10 === null) {
+ next = 10;
+ }
+ if(this.pointer9 === null) {
+ next = 9;
+ }
+ if(this.pointer8 === null) {
+ next = 8;
+ }
+ if(this.pointer7 === null) {
+ next = 7;
+ }
+ if(this.pointer6 === null) {
+ next = 6;
+ }
+ if(next == 0) {
+ throw new Error("You can only have 10 Pointer objects");
+ return null;
+ } else {
+ this['pointer' + next] = new Phaser.Pointer(this._game, next);
+ return this['pointer' + next];
+ }
+ };
+ Input.prototype.start = /**
+ * Starts the Input Manager running
+ * @method start
+ **/
+ function () {
this.mouse.start();
this.keyboard.start();
this.touch.start();
this.mspointer.start();
this.gestures.start();
};
- Input.prototype.update = function () {
+ Input.prototype.update = /**
+ * Updates the Input Manager. Called by the core Game loop.
+ * @method update
+ **/
+ function () {
this.mousePointer.update();
this.pointer1.update();
this.pointer2.update();
this.pointer3.update();
this.pointer4.update();
this.pointer5.update();
- this.pointer6.update();
- this.pointer7.update();
- this.pointer8.update();
- this.pointer9.update();
- this.pointer10.update();
+ if(this.pointer6) {
+ this.pointer6.update();
+ }
+ if(this.pointer7) {
+ this.pointer7.update();
+ }
+ if(this.pointer8) {
+ this.pointer8.update();
+ }
+ if(this.pointer9) {
+ this.pointer9.update();
+ }
+ if(this.pointer10) {
+ this.pointer10.update();
+ }
};
Input.prototype.reset = /**
* Reset all of the Pointers and Input states
@@ -12775,11 +13898,21 @@ var Phaser;
this.pointer3.reset();
this.pointer4.reset();
this.pointer5.reset();
- this.pointer6.reset();
- this.pointer7.reset();
- this.pointer8.reset();
- this.pointer9.reset();
- this.pointer10.reset();
+ if(this.pointer6) {
+ this.pointer6.reset();
+ }
+ if(this.pointer7) {
+ this.pointer7.reset();
+ }
+ if(this.pointer8) {
+ this.pointer8.reset();
+ }
+ if(this.pointer9) {
+ this.pointer9.reset();
+ }
+ if(this.pointer10) {
+ this.pointer10.reset();
+ }
this.currentPointers = 0;
if(hard == true) {
this.onDown = new Phaser.Signal();
@@ -12818,15 +13951,15 @@ var Phaser;
this.currentPointers++;
} else if(this.pointer5.active == true) {
this.currentPointers++;
- } else if(this.pointer6.active == true) {
+ } else if(this.pointer6 && this.pointer6.active == true) {
this.currentPointers++;
- } else if(this.pointer7.active == true) {
+ } else if(this.pointer7 && this.pointer7.active == true) {
this.currentPointers++;
- } else if(this.pointer8.active == true) {
+ } else if(this.pointer8 && this.pointer8.active == true) {
this.currentPointers++;
- } else if(this.pointer9.active == true) {
+ } else if(this.pointer9 && this.pointer9.active == true) {
this.currentPointers++;
- } else if(this.pointer10.active == true) {
+ } else if(this.pointer10 && this.pointer10.active == true) {
this.currentPointers++;
}
return this.currentPointers;
@@ -12855,15 +13988,15 @@ var Phaser;
return this.pointer4.start(event);
} else if(this.pointer5.active == false) {
return this.pointer5.start(event);
- } else if(this.pointer6.active == false) {
+ } else if(this.pointer6 && this.pointer6.active == false) {
return this.pointer6.start(event);
- } else if(this.pointer7.active == false) {
+ } else if(this.pointer7 && this.pointer7.active == false) {
return this.pointer7.start(event);
- } else if(this.pointer8.active == false) {
+ } else if(this.pointer8 && this.pointer8.active == false) {
return this.pointer8.start(event);
- } else if(this.pointer9.active == false) {
+ } else if(this.pointer9 && this.pointer9.active == false) {
return this.pointer9.start(event);
- } else if(this.pointer10.active == false) {
+ } else if(this.pointer10 && this.pointer10.active == false) {
return this.pointer10.start(event);
}
return null;
@@ -12886,15 +14019,15 @@ var Phaser;
return this.pointer4.move(event);
} else if(this.pointer5.active == true && this.pointer5.identifier == event.identifier) {
return this.pointer5.move(event);
- } else if(this.pointer6.active == true && this.pointer6.identifier == event.identifier) {
+ } else if(this.pointer6 && this.pointer6.active == true && this.pointer6.identifier == event.identifier) {
return this.pointer6.move(event);
- } else if(this.pointer7.active == true && this.pointer7.identifier == event.identifier) {
+ } else if(this.pointer7 && this.pointer7.active == true && this.pointer7.identifier == event.identifier) {
return this.pointer7.move(event);
- } else if(this.pointer8.active == true && this.pointer8.identifier == event.identifier) {
+ } else if(this.pointer8 && this.pointer8.active == true && this.pointer8.identifier == event.identifier) {
return this.pointer8.move(event);
- } else if(this.pointer9.active == true && this.pointer9.identifier == event.identifier) {
+ } else if(this.pointer9 && this.pointer9.active == true && this.pointer9.identifier == event.identifier) {
return this.pointer9.move(event);
- } else if(this.pointer10.active == true && this.pointer10.identifier == event.identifier) {
+ } else if(this.pointer10 && this.pointer10.active == true && this.pointer10.identifier == event.identifier) {
return this.pointer10.move(event);
}
return null;
@@ -12917,15 +14050,15 @@ var Phaser;
return this.pointer4.stop(event);
} else if(this.pointer5.active == true && this.pointer5.identifier == event.identifier) {
return this.pointer5.stop(event);
- } else if(this.pointer6.active == true && this.pointer6.identifier == event.identifier) {
+ } else if(this.pointer6 && this.pointer6.active == true && this.pointer6.identifier == event.identifier) {
return this.pointer6.stop(event);
- } else if(this.pointer7.active == true && this.pointer7.identifier == event.identifier) {
+ } else if(this.pointer7 && this.pointer7.active == true && this.pointer7.identifier == event.identifier) {
return this.pointer7.stop(event);
- } else if(this.pointer8.active == true && this.pointer8.identifier == event.identifier) {
+ } else if(this.pointer8 && this.pointer8.active == true && this.pointer8.identifier == event.identifier) {
return this.pointer8.stop(event);
- } else if(this.pointer9.active == true && this.pointer9.identifier == event.identifier) {
+ } else if(this.pointer9 && this.pointer9.active == true && this.pointer9.identifier == event.identifier) {
return this.pointer9.stop(event);
- } else if(this.pointer10.active == true && this.pointer10.identifier == event.identifier) {
+ } else if(this.pointer10 && this.pointer10.active == true && this.pointer10.identifier == event.identifier) {
return this.pointer10.stop(event);
}
return null;
@@ -12949,15 +14082,15 @@ var Phaser;
return this.pointer4;
} else if(this.pointer5.active == state) {
return this.pointer5;
- } else if(this.pointer6.active == state) {
+ } else if(this.pointer6 && this.pointer6.active == state) {
return this.pointer6;
- } else if(this.pointer7.active == state) {
+ } else if(this.pointer7 && this.pointer7.active == state) {
return this.pointer7;
- } else if(this.pointer8.active == state) {
+ } else if(this.pointer8 && this.pointer8.active == state) {
return this.pointer8;
- } else if(this.pointer9.active == state) {
+ } else if(this.pointer9 && this.pointer9.active == state) {
return this.pointer9;
- } else if(this.pointer10.active == state) {
+ } else if(this.pointer10 && this.pointer10.active == state) {
return this.pointer10;
}
return null;
@@ -12980,15 +14113,15 @@ var Phaser;
return this.pointer4;
} else if(this.pointer5.identifier == identifier) {
return this.pointer5;
- } else if(this.pointer6.identifier == identifier) {
+ } else if(this.pointer6 && this.pointer6.identifier == identifier) {
return this.pointer6;
- } else if(this.pointer7.identifier == identifier) {
+ } else if(this.pointer7 && this.pointer7.identifier == identifier) {
return this.pointer7;
- } else if(this.pointer8.identifier == identifier) {
+ } else if(this.pointer8 && this.pointer8.identifier == identifier) {
return this.pointer8;
- } else if(this.pointer9.identifier == identifier) {
+ } else if(this.pointer9 && this.pointer9.identifier == identifier) {
return this.pointer9;
- } else if(this.pointer10.identifier == identifier) {
+ } else if(this.pointer10 && this.pointer10.identifier == identifier) {
return this.pointer10;
}
return null;
@@ -13021,34 +14154,28 @@ var Phaser;
this._game.stage.context.fillText('World X: ' + this.getWorldX() + ' World Y: ' + this.getWorldY(), x, y + 28);
this._game.stage.context.fillText('Scale X: ' + this.scaleX.toFixed(1) + ' Scale Y: ' + this.scaleY.toFixed(1), x, y + 42);
};
+ Input.prototype.getDistance = /**
+ * Get the distance between two Pointer objects
+ * @method getDistance
+ * @param {Pointer} pointer1
+ * @param {Pointer} pointer2
+ **/
+ function (pointer1, pointer2) {
+ return pointer1.position.distance(pointer2.position);
+ };
+ Input.prototype.getAngle = /**
+ * Get the angle between two Pointer objects
+ * @method getAngle
+ * @param {Pointer} pointer1
+ * @param {Pointer} pointer2
+ **/
+ function (pointer1, pointer2) {
+ return pointer1.position.angle(pointer2.position);
+ };
return Input;
})();
Phaser.Input = Input;
- /**
- *
- * @method calculateDistance
- * @param {Finger} finger1
- * @param {Finger} finger2
- **/
- //public calculateDistance(finger1: Finger, finger2: Finger) {
- //}
- /**
- *
- * @method calculateAngle
- * @param {Finger} finger1
- * @param {Finger} finger2
- **/
- //public calculateAngle(finger1: Finger, finger2: Finger) {
- //}
- /**
- *
- * @method checkOverlap
- * @param {Finger} finger1
- * @param {Finger} finger2
- **/
- //public checkOverlap(finger1: Finger, finger2: Finger) {
- //}
- })(Phaser || (Phaser = {}));
+})(Phaser || (Phaser = {}));
///
/**
* Phaser - Keyboard
@@ -13822,6 +14949,7 @@ var Phaser;
Phaser.Emitter = Emitter;
})(Phaser || (Phaser = {}));
///
+///
/**
* Phaser - GeomSprite
*
@@ -13888,6 +15016,7 @@ var Phaser;
GeomSprite.LINE = 2;
GeomSprite.POINT = 3;
GeomSprite.RECTANGLE = 4;
+ GeomSprite.POLYGON = 5;
GeomSprite.prototype.loadCircle = /**
* Just like Sprite.loadGraphic(), this will load a circle and set its shape to Circle.
* @param circle {Circle} Circle geometry define.
@@ -13982,6 +15111,20 @@ var Phaser;
this.frameBounds.copyFrom(this.rect);
return this;
};
+ GeomSprite.prototype.createPolygon = /**
+ * Create a polygon object
+ * @param width {Number} Width of the rectangle
+ * @param height {Number} Height of the rectangle
+ * @return {GeomSprite} GeomSprite instance.
+ */
+ function (points) {
+ if (typeof points === "undefined") { points = []; }
+ this.refresh();
+ this.polygon = new Phaser.Polygon(new Phaser.Vector2(this.x, this.y), points);
+ this.type = GeomSprite.POLYGON;
+ //this.frameBounds.copyFrom(this.rect);
+ return this;
+ };
GeomSprite.prototype.refresh = /**
* Destroy all geom shapes of this sprite.
*/
@@ -15572,6 +16715,7 @@ var Phaser;
///
///
///
+///
///
///
///
@@ -15751,6 +16895,7 @@ var Phaser;
this.math = new Phaser.GameMath(this);
this.stage = new Phaser.Stage(this, parent, width, height);
this.world = new Phaser.World(this, width, height);
+ this.add = new Phaser.GameObjectFactory(this);
this.sound = new Phaser.SoundManager(this);
this.cache = new Phaser.Cache(this);
this.collision = new Phaser.Collision(this);
@@ -15989,126 +17134,6 @@ var Phaser;
enumerable: true,
configurable: true
});
- Game.prototype.createCamera = // Handy Proxy methods
- /**
- * Create a new camera with specific position and size.
- *
- * @param x {number} X position of the new camera.
- * @param y {number} Y position of the new camera.
- * @param width {number} Width of the new camera.
- * @param height {number} Height of the new camera.
- * @returns {Camera} The newly created camera object.
- */
- function (x, y, width, height) {
- return this.world.createCamera(x, y, width, height);
- };
- Game.prototype.createGeomSprite = /**
- * Create a new GeomSprite with specific position.
- *
- * @param x {number} X position of the new geom sprite.
- * @param y {number} Y position of the new geom sprite.
- * @returns {GeomSprite} The newly created geom sprite object.
- */
- function (x, y) {
- return this.world.createGeomSprite(x, y);
- };
- Game.prototype.createSprite = /**
- * Create a new Sprite with specific position and sprite sheet key.
- *
- * @param x {number} X position of the new sprite.
- * @param y {number} Y position of the new sprite.
- * @param key {string} Optional, key for the sprite sheet you want it to use.
- * @returns {Sprite} The newly created sprite object.
- */
- function (x, y, key) {
- if (typeof key === "undefined") { key = ''; }
- return this.world.createSprite(x, y, key);
- };
- Game.prototype.createDynamicTexture = /**
- * Create a new DynamicTexture with specific size.
- *
- * @param width {number} Width of the texture.
- * @param height {number} Height of the texture.
- * @returns {DynamicTexture} The newly created dynamic texture object.
- */
- function (width, height) {
- return this.world.createDynamicTexture(width, height);
- };
- Game.prototype.createGroup = /**
- * Create a new object container.
- *
- * @param maxSize {number} Optional, capacity of this group.
- * @returns {Group} The newly created group.
- */
- function (maxSize) {
- if (typeof maxSize === "undefined") { maxSize = 0; }
- return this.world.createGroup(maxSize);
- };
- Game.prototype.createParticle = /**
- * Create a new Particle.
- *
- * @return {Particle} The newly created particle object.
- */
- function () {
- return this.world.createParticle();
- };
- Game.prototype.createEmitter = /**
- * Create a new Emitter.
- *
- * @param x {number} Optional, x position of the emitter.
- * @param y {number} Optional, y position of the emitter.
- * @param size {number} Optional, size of this emitter.
- * @return {Emitter} The newly created emitter object.
- */
- function (x, y, size) {
- if (typeof x === "undefined") { x = 0; }
- if (typeof y === "undefined") { y = 0; }
- if (typeof size === "undefined") { size = 0; }
- return this.world.createEmitter(x, y, size);
- };
- Game.prototype.createScrollZone = /**
- * Create a new ScrollZone object with image key, position and size.
- *
- * @param key {string} Key to a image you wish this object to use.
- * @param x {number} X position of this object.
- * @param y {number} Y position of this object.
- * @param width number} Width of this object.
- * @param height {number} Height of this object.
- * @returns {ScrollZone} The newly created scroll zone object.
- */
- function (key, x, y, width, height) {
- if (typeof x === "undefined") { x = 0; }
- if (typeof y === "undefined") { y = 0; }
- if (typeof width === "undefined") { width = 0; }
- if (typeof height === "undefined") { height = 0; }
- return this.world.createScrollZone(key, x, y, width, height);
- };
- Game.prototype.createTilemap = /**
- * Create a new Tilemap.
- *
- * @param key {string} Key for tileset image.
- * @param mapData {string} Data of this tilemap.
- * @param format {number} Format of map data. (Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON)
- * @param [resizeWorld] {boolean} resize the world to make same as tilemap?
- * @param [tileWidth] {number} width of each tile.
- * @param [tileHeight] {number} height of each tile.
- * @return {Tilemap} The newly created tilemap object.
- */
- function (key, mapData, format, resizeWorld, tileWidth, tileHeight) {
- if (typeof resizeWorld === "undefined") { resizeWorld = true; }
- if (typeof tileWidth === "undefined") { tileWidth = 0; }
- if (typeof tileHeight === "undefined") { tileHeight = 0; }
- return this.world.createTilemap(key, mapData, format, resizeWorld, tileWidth, tileHeight);
- };
- Game.prototype.createTween = /**
- * Create a tween object for a specific object.
- *
- * @param obj Object you wish the tween will affect.
- * @return {Phaser.Tween} The newly created tween object.
- */
- function (obj) {
- return this.tweens.create(obj);
- };
Game.prototype.collide = /**
* Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group.
* Note: Does not take the objects scrollFactor into account. All overlaps are check in world space.
@@ -16302,6 +17327,7 @@ var Phaser;
*/
function State(game) {
this.game = game;
+ this.add = game.add;
this.camera = game.camera;
this.cache = game.cache;
this.collision = game.collision;
@@ -16348,126 +17374,6 @@ var Phaser;
*/
function () {
};
- State.prototype.createCamera = // Handy Proxy methods
- /**
- * Create a new camera with specific position and size.
- *
- * @param x {number} X position of the new camera.
- * @param y {number} Y position of the new camera.
- * @param width {number} Width of the new camera.
- * @param height {number} Height of the new camera.
- * @returns {Camera} The newly created camera object.
- */
- function (x, y, width, height) {
- return this.game.world.createCamera(x, y, width, height);
- };
- State.prototype.createGeomSprite = /**
- * Create a new GeomSprite with specific position.
- *
- * @param x {number} X position of the new geom sprite.
- * @param y {number} Y position of the new geom sprite.
- * @returns {GeomSprite} The newly created geom sprite object.
- */
- function (x, y) {
- return this.world.createGeomSprite(x, y);
- };
- State.prototype.createSprite = /**
- * Create a new Sprite with specific position and sprite sheet key.
- *
- * @param x {number} X position of the new sprite.
- * @param y {number} Y position of the new sprite.
- * @param key {string} [optional] key for the sprite sheet you want it to use.
- * @returns {Sprite} The newly created sprite object.
- */
- function (x, y, key) {
- if (typeof key === "undefined") { key = ''; }
- return this.game.world.createSprite(x, y, key);
- };
- State.prototype.createDynamicTexture = /**
- * Create a new DynamicTexture with specific size.
- *
- * @param width {number} Width of the texture.
- * @param height {number} Height of the texture.
- * @returns {DynamicTexture} The newly created dynamic texture object.
- */
- function (width, height) {
- return this.game.world.createDynamicTexture(width, height);
- };
- State.prototype.createGroup = /**
- * Create a new object container.
- *
- * @param maxSize {number} [optional] capacity of this group.
- * @returns {Group} The newly created group.
- */
- function (maxSize) {
- if (typeof maxSize === "undefined") { maxSize = 0; }
- return this.game.world.createGroup(maxSize);
- };
- State.prototype.createParticle = /**
- * Create a new Particle.
- *
- * @return {Particle} The newly created particle object.
- */
- function () {
- return this.game.world.createParticle();
- };
- State.prototype.createEmitter = /**
- * Create a new Emitter.
- *
- * @param x {number} [optional] x position of the emitter.
- * @param y {number} [optional] y position of the emitter.
- * @param size {number} [optional] size of this emitter.
- * @return {Emitter} The newly created emitter object.
- */
- function (x, y, size) {
- if (typeof x === "undefined") { x = 0; }
- if (typeof y === "undefined") { y = 0; }
- if (typeof size === "undefined") { size = 0; }
- return this.game.world.createEmitter(x, y, size);
- };
- State.prototype.createScrollZone = /**
- * Create a new ScrollZone object with image key, position and size.
- *
- * @param key {string} Key to a image you wish this object to use.
- * @param x {number} X position of this object.
- * @param y {number} Y position of this object.
- * @param width {number} Width of this object.
- * @param height {number} Height of this object.
- * @returns {ScrollZone} The newly created scroll zone object.
- */
- function (key, x, y, width, height) {
- if (typeof x === "undefined") { x = 0; }
- if (typeof y === "undefined") { y = 0; }
- if (typeof width === "undefined") { width = 0; }
- if (typeof height === "undefined") { height = 0; }
- return this.game.world.createScrollZone(key, x, y, width, height);
- };
- State.prototype.createTilemap = /**
- * Create a new Tilemap.
- *
- * @param key {string} Key for tileset image.
- * @param mapData {string} Data of this tilemap.
- * @param format {number} Format of map data. (Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON)
- * @param resizeWorld {boolean} [optional] resize the world to make same as tilemap?
- * @param tileWidth {number} [optional] width of each tile.
- * @param tileHeight number} [optional] height of each tile.
- * @return {Tilemap} The newly created tilemap object.
- */
- function (key, mapData, format, resizeWorld, tileWidth, tileHeight) {
- if (typeof resizeWorld === "undefined") { resizeWorld = true; }
- if (typeof tileWidth === "undefined") { tileWidth = 0; }
- if (typeof tileHeight === "undefined") { tileHeight = 0; }
- return this.game.world.createTilemap(key, mapData, format, resizeWorld, tileWidth, tileHeight);
- };
- State.prototype.createTween = /**
- * Create a tween object for a specific object.
- *
- * @param obj Object you wish the tween will affect.
- * @return {Phaser.Tween} The newly created tween object.
- */
- function (obj) {
- return this.game.tweens.create(obj);
- };
State.prototype.collide = /**
* Call this method to see if one object collids another.
* @return {boolean} Whether the given objects or groups collids.