diff --git a/Phaser/Collision.ts b/Phaser/Collision.ts
index 441b8bf7..81d0af44 100644
--- a/Phaser/Collision.ts
+++ b/Phaser/Collision.ts
@@ -645,10 +645,10 @@ module Phaser {
* @param tile The Tile to separate
* @returns {boolean} Whether the objects in fact touched and were separated
*/
- public static separateTile(object:GameObject, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, collideUp: bool, collideDown: bool): bool {
+ 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 {
- var separatedX: bool = Collision.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight);
- var separatedY: bool = Collision.separateTileY(object, x, y, width, height, mass, collideUp, collideDown);
+ 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);
return separatedX || separatedY;
@@ -660,7 +660,7 @@ module Phaser {
* @param tile The Tile to separate
* @returns {boolean} Whether the objects in fact touched and were separated along the X axis.
*/
- public static separateTileX(object:GameObject, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool): bool {
+ public static separateTileX(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)
@@ -717,8 +717,12 @@ module Phaser {
// Then adjust their positions and velocities accordingly (if there was any overlap)
if (overlap != 0)
{
- object.x = object.x - overlap;
- object.velocity.x = -(object.velocity.x * object.elasticity);
+ if (separate == true)
+ {
+ object.x = object.x - overlap;
+ object.velocity.x = -(object.velocity.x * object.elasticity);
+ }
+
Collision.TILE_OVERLAP = true;
return true;
}
@@ -735,7 +739,7 @@ module Phaser {
* @param tile The second GameObject to separate
* @returns {boolean} Whether the objects in fact touched and were separated along the Y axis.
*/
- public static separateTileY(object: GameObject, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool): bool {
+ public static separateTileY(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)
@@ -792,8 +796,12 @@ module Phaser {
// Then adjust their positions and velocities accordingly (if there was any overlap)
if (overlap != 0)
{
- object.y = object.y - overlap;
- object.velocity.y = -(object.velocity.y * object.elasticity);
+ if (separate == true)
+ {
+ object.y = object.y - overlap;
+ object.velocity.y = -(object.velocity.y * object.elasticity);
+ }
+
Collision.TILE_OVERLAP = true;
return true;
}
diff --git a/Phaser/Group.ts b/Phaser/Group.ts
index 4ad0dd7f..1b6ea0bd 100644
--- a/Phaser/Group.ts
+++ b/Phaser/Group.ts
@@ -321,21 +321,21 @@ module Phaser {
/**
* Removes an object from the group.
*
- * @param Object The Basic you want to remove.
- * @param Splice Whether the object should be cut from the array entirely or not.
+ * @param object The Basic you want to remove.
+ * @param splice Whether the object should be cut from the array entirely or not.
*
* @return The removed object.
*/
- public remove(Object: Basic, Splice: bool = false): Basic {
+ public remove(object: Basic, splice: bool = false): Basic {
- var index: number = this.members.indexOf(Object);
+ var index: number = this.members.indexOf(object);
if ((index < 0) || (index >= this.members.length))
{
return null;
}
- if (Splice)
+ if (splice)
{
this.members.splice(index, 1);
this.length--;
@@ -345,30 +345,30 @@ module Phaser {
this.members[index] = null;
}
- return Object;
+ return object;
}
/**
* Replaces an existing Basic with a new one.
*
- * @param OldObject The object you want to replace.
- * @param NewObject The new object you want to use instead.
+ * @param oldObject The object you want to replace.
+ * @param newObject The new object you want to use instead.
*
* @return The new object.
*/
- public replace(OldObject: Basic, NewObject: Basic): Basic {
+ public replace(oldObject: Basic, newObject: Basic): Basic {
- var index: number = this.members.indexOf(OldObject);
+ var index: number = this.members.indexOf(oldObject);
if ((index < 0) || (index >= this.members.length))
{
return null;
}
- this.members[index] = NewObject;
+ this.members[index] = newObject;
- return NewObject;
+ return newObject;
}
@@ -379,13 +379,13 @@ module Phaser {
* State.update() override. To sort all existing objects after
* a big explosion or bomb attack, you might call myGroup.sort("exists",Group.DESCENDING).
*
- * @param Index The string name of the member variable you want to sort on. Default value is "y".
- * @param Order A Group constant that defines the sort order. Possible values are Group.ASCENDING and Group.DESCENDING. Default value is Group.ASCENDING.
+ * @param index The string name of the member variable you want to sort on. Default value is "y".
+ * @param order A Group constant that defines the sort order. Possible values are Group.ASCENDING and Group.DESCENDING. Default value is Group.ASCENDING.
*/
- public sort(Index: string = "y", Order: number = Group.ASCENDING) {
+ public sort(index: string = "y", order: number = Group.ASCENDING) {
- this._sortIndex = Index;
- this._sortOrder = Order;
+ this._sortIndex = index;
+ this._sortOrder = order;
this.members.sort(this.sortHandler);
}
diff --git a/Phaser/gameobjects/Tilemap.ts b/Phaser/gameobjects/Tilemap.ts
index 78d31d0e..9e24c3c5 100644
--- a/Phaser/gameobjects/Tilemap.ts
+++ b/Phaser/gameobjects/Tilemap.ts
@@ -43,6 +43,8 @@ module Phaser {
}
+ private _tempCollisionData;
+
public static FORMAT_CSV: number = 0;
public static FORMAT_TILED_JSON: number = 1;
@@ -50,6 +52,8 @@ module Phaser {
public layers : TilemapLayer[];
public currentLayer: TilemapLayer;
public collisionLayer: TilemapLayer;
+ public collisionCallback = null;
+ public collisionCallbackContext;
public mapFormat: number;
public update() {
@@ -170,26 +174,44 @@ module Phaser {
// Tile Collision
- public setCollisionRange(start: number, end: number, collision?:number = Collision.ANY, resetCollisions: bool = false) {
+ public setCollisionCallback(context, callback) {
+
+ this.collisionCallbackContext = context;
+ this.collisionCallback = callback;
+
+ }
+
+ public setCollisionRange(start: number, end: number, collision?:number = Collision.ANY, resetCollisions?: bool = false, separateX?: bool = true, separateY?: bool = true) {
for (var i = start; i < end; i++)
{
- this.tiles[i].setCollision(collision, resetCollisions);
+ this.tiles[i].setCollision(collision, resetCollisions, separateX, separateY);
}
}
- public setCollisionByIndex(values:number[], collision?:number = Collision.ANY, resetCollisions: bool = false) {
+ public setCollisionByIndex(values:number[], collision?:number = Collision.ANY, resetCollisions?: bool = false, separateX?: bool = true, separateY?: bool = true) {
for (var i = 0; i < values.length; i++)
{
- this.tiles[values[i]].setCollision(collision, resetCollisions);
+ this.tiles[values[i]].setCollision(collision, resetCollisions, separateX, separateY);
}
}
// Tile Management
+ public getTileByIndex(value: number):Tile {
+
+ if (this.tiles[value])
+ {
+ return this.tiles[value];
+ }
+
+ return null;
+
+ }
+
public getTile(x: number, y: number, layer?: number = 0):Tile {
return this.tiles[this.layers[layer].getTileIndex(x, y)];
@@ -215,7 +237,13 @@ module Phaser {
}
// COLLIDE
- public collide(objectOrGroup = null, callback = null): bool {
+ public collide(objectOrGroup = null, callback = null, context = null) {
+
+ if (callback !== null && context !== null)
+ {
+ this.collisionCallback = callback;
+ this.collisionCallbackContext = context;
+ }
if (objectOrGroup == null)
{
@@ -225,24 +253,27 @@ module Phaser {
// Group?
if (objectOrGroup.isGroup == false)
{
- return this.collideGameObject(objectOrGroup);
+ this.collideGameObject(objectOrGroup);
}
else
{
objectOrGroup.forEachAlive(this, this.collideGameObject, true);
}
- return true;
-
}
public collideGameObject(object: GameObject): bool {
- if (object == this) { return false; }
-
- if (object.immovable == false && object.exists == true && object.allowCollisions != Collision.NONE)
+ if (object !== this && object.immovable == false && object.exists == true && object.allowCollisions != Collision.NONE)
{
- return this.collisionLayer.getTileOverlaps(object);
+ this._tempCollisionData = this.collisionLayer.getTileOverlaps(object);
+
+ if (this.collisionCallback !== null && this._tempCollisionData.length > 0)
+ {
+ this.collisionCallback.call(this.collisionCallbackContext, object, this._tempCollisionData);
+ }
+
+ return true;
}
else
{
@@ -251,7 +282,6 @@ module Phaser {
}
-
// Set current layer
// Set layer order?
// Get block of tiles
@@ -259,7 +289,6 @@ module Phaser {
// Delete tiles of certain type
// Erase tiles
-
}
}
\ No newline at end of file
diff --git a/Phaser/system/Tile.ts b/Phaser/system/Tile.ts
index 748e7cfe..426bf03b 100644
--- a/Phaser/system/Tile.ts
+++ b/Phaser/system/Tile.ts
@@ -38,6 +38,9 @@ module Phaser {
public collideUp: bool = false;
public collideDown: bool = false;
+ public separateX: bool = true;
+ public separateY: bool = true;
+
/**
* A reference to the tilemap this tile object belongs to.
*/
@@ -59,13 +62,16 @@ module Phaser {
}
- public setCollision(collision: number, resetCollisions: bool) {
+ public setCollision(collision: number, resetCollisions: bool, separateX: bool, separateY: bool) {
if (resetCollisions)
{
this.resetCollision();
}
+ this.separateX = separateX;
+ this.separateY = separateY;
+
this.allowCollisions = collision;
if (collision & Collision.ANY)
diff --git a/Phaser/system/TilemapLayer.ts b/Phaser/system/TilemapLayer.ts
index f334469e..95657e81 100644
--- a/Phaser/system/TilemapLayer.ts
+++ b/Phaser/system/TilemapLayer.ts
@@ -23,6 +23,7 @@ module Phaser {
//this.scrollFactor = new MicroPoint(1, 1);
this.mapData = [];
+ this._tempTileBlock = [];
this._texture = this._game.cache.getImage(key);
}
@@ -47,6 +48,8 @@ module Phaser {
private _tempTileY: number;
private _tempTileW: number;
private _tempTileH: number;
+ private _tempTileBlock;
+ private _tempBlockResults;
public name: string;
public alpha: number = 1;
@@ -95,20 +98,20 @@ module Phaser {
this._tempTileW = (this._game.math.snapToCeil(object.bounds.width, this.tileWidth) + this.tileWidth) / this.tileWidth;
this._tempTileH = (this._game.math.snapToCeil(object.bounds.height, this.tileHeight) + this.tileHeight) / this.tileHeight;
- // Loop through the tiles we've got and check overlaps accordingly
- var tiles = this.getTileBlock(this._tempTileX, this._tempTileY, this._tempTileW, this._tempTileH);
+ // Loop through the tiles we've got and check overlaps accordingly (the results are stored in this._tempTileBlock)
+ this.getTileBlock(this._tempTileX, this._tempTileY, this._tempTileW, this._tempTileH);
Collision.TILE_OVERLAP = false;
- for (var r = 0; r < tiles.length; r++)
+ for (var r = 0; r < this._tempTileBlock.length; r++)
{
- if (tiles[r].tile.allowCollisions != Collision.NONE)
+ if (Collision.separateTile(object, this._tempTileBlock[r].x * this.tileWidth, this._tempTileBlock[r].y * this.tileHeight, this.tileWidth, this.tileHeight, this._tempTileBlock[r].tile.mass, this._tempTileBlock[r].tile.collideLeft, this._tempTileBlock[r].tile.collideRight, this._tempTileBlock[r].tile.collideUp, this._tempTileBlock[r].tile.collideDown, this._tempTileBlock[r].tile.separateX, this._tempTileBlock[r].tile.separateY) == true)
{
- Collision.separateTile(object, tiles[r].x * this.tileWidth, tiles[r].y * this.tileHeight, this.tileWidth, this.tileHeight, tiles[r].tile.mass, tiles[r].tile.collideLeft, tiles[r].tile.collideRight, tiles[r].tile.collideUp, tiles[r].tile.collideDown);
+ this._tempBlockResults.push({ x: this._tempTileBlock[r].x, y: this._tempTileBlock[r].y, tile: this._tempTileBlock[r].tile });
}
}
- return Collision.TILE_OVERLAP;
+ return this._tempBlockResults;
}
@@ -134,21 +137,21 @@ module Phaser {
height = this.heightInTiles;
}
- var output = [];
+ this._tempTileBlock = [];
+ this._tempBlockResults = [];
for (var ty = y; ty < y + height; ty++)
{
for (var tx = x; tx < x + width; tx++)
{
- if (this.mapData[ty] && this.mapData[ty][tx])
+ // We only want to consider the tile for checking if you can actually collide with it
+ if (this.mapData[ty] && this.mapData[ty][tx] && this._parent.tiles[this.mapData[ty][tx]].allowCollisions != Collision.NONE)
{
- output.push({ x: tx, y: ty, tile: this._parent.tiles[this.mapData[ty][tx]] });
+ this._tempTileBlock.push({ x: tx, y: ty, tile: this._parent.tiles[this.mapData[ty][tx]] });
}
}
}
- return output;
-
}
public getTileIndex(x: number, y: number): number {
diff --git a/README.md b/README.md
index 69fc97dd..c25b7c06 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,13 @@ V0.9.5
* Fixed offset values being ignored in GeomSprite.renderPoint (thanks bapuna).
* Added new Mirror Camera FX. Can mirror the camera image horizontally, vertically or both with an optional fill color overlay.
* Added Camera.disableClipping for when you don't care about things being drawn outside the edge (usful for some FX).
-
+* Updated TilemapLayer so that collision data is now stored in _tempTileBlock to avoid constant array creation during game loop.
+* TilemapLayer.getTileOverlaps() now returns all tiles the object overlapped with rather than just a boolean.
+* Tilemap.collide now optionally takes callback and context parameters which are used if collision occurs.
+* Added Tilemap.collisionCallback and Tilemap.collisionCallbackContext so you can set them once and not re-set them on every call to collide.
+* Collision.separateTile now has 2 extra parameters: separateX and separateY. If true the object will be separated on overlap, otherwise just the overlap boolean result is returned.
+* Added Tile.separateX and Tile.separateY (both true by default), if true an object will be separated from the tile on overlap. Set to false if you don't want a tile to stop an object from moving, you just want it to return collision data to your callback.
+* Added Tilemap.getTileByIndex(value) to access a specific type of tile, rather than by its map index.
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index a33830a4..c68b56e8 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -152,6 +152,10 @@
+
+
+ collide with tile.ts
+
collision.ts
diff --git a/Tests/camera fx/mirror.js b/Tests/camera fx/mirror.js
index f32b4105..f5adab9e 100644
--- a/Tests/camera fx/mirror.js
+++ b/Tests/camera fx/mirror.js
@@ -3,26 +3,27 @@
(function () {
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
+ // Just set the world to be the size of the image we're loading in
myGame.world.setSize(1216, 896);
myGame.loader.addImageFile('backdrop', 'assets/pics/ninja-masters2.png');
myGame.loader.load();
}
var mirror;
- var cam;
function create() {
- // What we need is a camera 800x400 pixels in size, the mirror effect will sit below it.
+ // What we need is a camera 800x400 pixels in size as the mirror effect will be 200px tall and sit below it.
// So we resize our default camera to 400px
myGame.camera.height = 400;
- // Because it's our default camera we need to tell it to disable clipping, otherwise we'll never see the mirror effect
+ // Because it's our default camera we need to tell it to disable clipping, otherwise we'll never see the mirror effect render.
myGame.camera.disableClipping = true;
// Add our effect to the camera
mirror = myGame.camera.fx.add(Phaser.FX.Camera.Mirror);
- // The first 2 parameters are the x and y coordinates we're going to display the mirror effect in STAGE coordinates
- // The next is the rectangular region of the Camera that we'll create the effect from (in this case the whole camera)
- // Finally we set the fill color that is put over the top of the mirror effect
+ // The first 2 parameters are the x and y coordinates of where to display the effect. They are in STAGE coordinates, not World.
+ // The next is a Quad making up the rectangular region of the Camera that we'll create the effect from (in this case the whole camera).
+ // Finally we set the fill color that is put over the top of the mirror effect.
mirror.start(0, 400, new Phaser.Quad(0, 0, 800, 400), 'rgba(0, 0, 100, 0.7)');
- mirror.flipX = true;
- mirror.flipY = true;
+ // Experiment with variations on these to see the different mirror effects that can be achieved.
+ //mirror.flipX = true;
+ //mirror.flipY = true;
myGame.createSprite(0, 0, 'backdrop');
}
function update() {
diff --git a/Tests/camera fx/mirror.ts b/Tests/camera fx/mirror.ts
index 95158467..be6e0adb 100644
--- a/Tests/camera fx/mirror.ts
+++ b/Tests/camera fx/mirror.ts
@@ -20,19 +20,19 @@
function create() {
- // What we need is a camera 800x400 pixels in size, the mirror effect will sit below it.
+ // What we need is a camera 800x400 pixels in size as the mirror effect will be 200px tall and sit below it.
// So we resize our default camera to 400px
myGame.camera.height = 400;
- // Because it's our default camera we need to tell it to disable clipping, otherwise we'll never see the mirror effect
+ // Because it's our default camera we need to tell it to disable clipping, otherwise we'll never see the mirror effect render.
myGame.camera.disableClipping = true;
// Add our effect to the camera
mirror = myGame.camera.fx.add(Phaser.FX.Camera.Mirror);
- // The first 2 parameters are the x and y coordinates we're going to display the mirror effect in STAGE coordinates
- // The next is the rectangular region of the Camera that we'll create the effect from (in this case the whole camera)
- // Finally we set the fill color that is put over the top of the mirror effect
+ // The first 2 parameters are the x and y coordinates of where to display the effect. They are in STAGE coordinates, not World.
+ // The next is a Quad making up the rectangular region of the Camera that we'll create the effect from (in this case the whole camera).
+ // Finally we set the fill color that is put over the top of the mirror effect.
mirror.start(0, 400, new Phaser.Quad(0, 0, 800, 400), 'rgba(0, 0, 100, 0.7)');
// Experiment with variations on these to see the different mirror effects that can be achieved.
diff --git a/Tests/phaser.js b/Tests/phaser.js
index 5ac07e62..4f038bfb 100644
--- a/Tests/phaser.js
+++ b/Tests/phaser.js
@@ -4827,9 +4827,9 @@ var Phaser;
* @param tile The Tile to separate
* @returns {boolean} Whether the objects in fact touched and were separated
*/
- function separateTile(object, x, y, width, height, mass, collideLeft, collideRight, collideUp, collideDown) {
- var separatedX = Collision.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight);
- var separatedY = Collision.separateTileY(object, x, y, width, height, mass, collideUp, collideDown);
+ function separateTile(object, x, y, width, height, mass, collideLeft, collideRight, collideUp, collideDown, separateX, separateY) {
+ 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;
};
Collision.separateTileX = /**
@@ -4838,7 +4838,7 @@ var Phaser;
* @param tile The Tile to separate
* @returns {boolean} Whether the objects in fact touched and were separated along the X axis.
*/
- function separateTileX(object, x, y, width, height, mass, collideLeft, collideRight) {
+ function separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separate) {
// Can't separate two immovable objects (tiles are always immovable)
if(object.immovable) {
return false;
@@ -4872,8 +4872,10 @@ var Phaser;
}
// Then adjust their positions and velocities accordingly (if there was any overlap)
if(overlap != 0) {
- object.x = object.x - overlap;
- object.velocity.x = -(object.velocity.x * object.elasticity);
+ if(separate == true) {
+ object.x = object.x - overlap;
+ object.velocity.x = -(object.velocity.x * object.elasticity);
+ }
Collision.TILE_OVERLAP = true;
return true;
} else {
@@ -4886,7 +4888,7 @@ var Phaser;
* @param tile The second GameObject to separate
* @returns {boolean} Whether the objects in fact touched and were separated along the Y axis.
*/
- function separateTileY(object, x, y, width, height, mass, collideUp, collideDown) {
+ function separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separate) {
// Can't separate two immovable objects (tiles are always immovable)
if(object.immovable) {
return false;
@@ -4921,8 +4923,10 @@ var Phaser;
// 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) {
- object.y = object.y - overlap;
- object.velocity.y = -(object.velocity.y * object.elasticity);
+ if(separate == true) {
+ object.y = object.y - overlap;
+ object.velocity.y = -(object.velocity.y * object.elasticity);
+ }
Collision.TILE_OVERLAP = true;
return true;
} else {
@@ -6341,40 +6345,40 @@ var Phaser;
Group.prototype.remove = /**
* Removes an object from the group.
*
- * @param Object The Basic you want to remove.
- * @param Splice Whether the object should be cut from the array entirely or not.
+ * @param object The Basic you want to remove.
+ * @param splice Whether the object should be cut from the array entirely or not.
*
* @return The removed object.
*/
- function (Object, Splice) {
- if (typeof Splice === "undefined") { Splice = false; }
- var index = this.members.indexOf(Object);
+ function (object, splice) {
+ if (typeof splice === "undefined") { splice = false; }
+ var index = this.members.indexOf(object);
if((index < 0) || (index >= this.members.length)) {
return null;
}
- if(Splice) {
+ if(splice) {
this.members.splice(index, 1);
this.length--;
} else {
this.members[index] = null;
}
- return Object;
+ return object;
};
Group.prototype.replace = /**
* Replaces an existing Basic with a new one.
*
- * @param OldObject The object you want to replace.
- * @param NewObject The new object you want to use instead.
+ * @param oldObject The object you want to replace.
+ * @param newObject The new object you want to use instead.
*
* @return The new object.
*/
- function (OldObject, NewObject) {
- var index = this.members.indexOf(OldObject);
+ function (oldObject, newObject) {
+ var index = this.members.indexOf(oldObject);
if((index < 0) || (index >= this.members.length)) {
return null;
}
- this.members[index] = NewObject;
- return NewObject;
+ this.members[index] = newObject;
+ return newObject;
};
Group.prototype.sort = /**
* Call this function to sort the group according to a particular value and order.
@@ -6383,14 +6387,14 @@ var Phaser;
* State.update() override. To sort all existing objects after
* a big explosion or bomb attack, you might call myGroup.sort("exists",Group.DESCENDING).
*
- * @param Index The string name of the member variable you want to sort on. Default value is "y".
- * @param Order A Group constant that defines the sort order. Possible values are Group.ASCENDING and Group.DESCENDING. Default value is Group.ASCENDING.
+ * @param index The string name of the member variable you want to sort on. Default value is "y".
+ * @param order A Group constant that defines the sort order. Possible values are Group.ASCENDING and Group.DESCENDING. Default value is Group.ASCENDING.
*/
- function (Index, Order) {
- if (typeof Index === "undefined") { Index = "y"; }
- if (typeof Order === "undefined") { Order = Group.ASCENDING; }
- this._sortIndex = Index;
- this._sortOrder = Order;
+ function (index, order) {
+ if (typeof index === "undefined") { index = "y"; }
+ if (typeof order === "undefined") { order = Group.ASCENDING; }
+ this._sortIndex = index;
+ this._sortOrder = order;
this.members.sort(this.sortHandler);
};
Group.prototype.setAll = /**
@@ -11151,6 +11155,7 @@ var Phaser;
this.boundsInTiles = new Phaser.Rectangle();
//this.scrollFactor = new MicroPoint(1, 1);
this.mapData = [];
+ this._tempTileBlock = [];
this._texture = this._game.cache.getImage(key);
}
TilemapLayer.prototype.getTileFromWorldXY = function (x, y) {
@@ -11168,15 +11173,19 @@ var Phaser;
this._tempTileY = this._game.math.snapToFloor(object.bounds.y, this.tileHeight) / this.tileHeight;
this._tempTileW = (this._game.math.snapToCeil(object.bounds.width, this.tileWidth) + this.tileWidth) / this.tileWidth;
this._tempTileH = (this._game.math.snapToCeil(object.bounds.height, this.tileHeight) + this.tileHeight) / this.tileHeight;
- // Loop through the tiles we've got and check overlaps accordingly
- var tiles = this.getTileBlock(this._tempTileX, this._tempTileY, this._tempTileW, this._tempTileH);
+ // Loop through the tiles we've got and check overlaps accordingly (the results are stored in this._tempTileBlock)
+ this.getTileBlock(this._tempTileX, this._tempTileY, this._tempTileW, this._tempTileH);
Phaser.Collision.TILE_OVERLAP = false;
- for(var r = 0; r < tiles.length; r++) {
- if(tiles[r].tile.allowCollisions != Phaser.Collision.NONE) {
- Phaser.Collision.separateTile(object, tiles[r].x * this.tileWidth, tiles[r].y * this.tileHeight, this.tileWidth, this.tileHeight, tiles[r].tile.mass, tiles[r].tile.collideLeft, tiles[r].tile.collideRight, tiles[r].tile.collideUp, tiles[r].tile.collideDown);
+ for(var r = 0; r < this._tempTileBlock.length; r++) {
+ if(Phaser.Collision.separateTile(object, this._tempTileBlock[r].x * this.tileWidth, this._tempTileBlock[r].y * this.tileHeight, this.tileWidth, this.tileHeight, this._tempTileBlock[r].tile.mass, this._tempTileBlock[r].tile.collideLeft, this._tempTileBlock[r].tile.collideRight, this._tempTileBlock[r].tile.collideUp, this._tempTileBlock[r].tile.collideDown, this._tempTileBlock[r].tile.separateX, this._tempTileBlock[r].tile.separateY) == true) {
+ this._tempBlockResults.push({
+ x: this._tempTileBlock[r].x,
+ y: this._tempTileBlock[r].y,
+ tile: this._tempTileBlock[r].tile
+ });
}
}
- return Phaser.Collision.TILE_OVERLAP;
+ return this._tempBlockResults;
};
TilemapLayer.prototype.getTileBlock = function (x, y, width, height) {
if(x < 0) {
@@ -11191,11 +11200,13 @@ var Phaser;
if(height > this.heightInTiles) {
height = this.heightInTiles;
}
- var output = [];
+ this._tempTileBlock = [];
+ this._tempBlockResults = [];
for(var ty = y; ty < y + height; ty++) {
for(var tx = x; tx < x + width; tx++) {
- if(this.mapData[ty] && this.mapData[ty][tx]) {
- output.push({
+ // We only want to consider the tile for checking if you can actually collide with it
+ if(this.mapData[ty] && this.mapData[ty][tx] && this._parent.tiles[this.mapData[ty][tx]].allowCollisions != Phaser.Collision.NONE) {
+ this._tempTileBlock.push({
x: tx,
y: ty,
tile: this._parent.tiles[this.mapData[ty][tx]]
@@ -11203,7 +11214,6 @@ var Phaser;
}
}
}
- return output;
};
TilemapLayer.prototype.getTileIndex = function (x, y) {
if(y >= 0 && y < this.mapData.length) {
@@ -11350,6 +11360,8 @@ var Phaser;
this.collideRight = false;
this.collideUp = false;
this.collideDown = false;
+ this.separateX = true;
+ this.separateY = true;
this._game = game;
this.tilemap = tilemap;
this.index = index;
@@ -11363,10 +11375,12 @@ var Phaser;
function () {
this.tilemap = null;
};
- Tile.prototype.setCollision = function (collision, resetCollisions) {
+ Tile.prototype.setCollision = function (collision, resetCollisions, separateX, separateY) {
if(resetCollisions) {
this.resetCollision();
}
+ this.separateX = separateX;
+ this.separateY = separateY;
this.allowCollisions = collision;
if(collision & Phaser.Collision.ANY) {
this.collideLeft = true;
@@ -11426,6 +11440,7 @@ var Phaser;
if (typeof tileWidth === "undefined") { tileWidth = 0; }
if (typeof tileHeight === "undefined") { tileHeight = 0; }
_super.call(this, game);
+ this.collisionCallback = null;
this.isGroup = false;
this.tiles = [];
this.layers = [];
@@ -11522,23 +11537,37 @@ var Phaser;
enumerable: true,
configurable: true
});
- Tilemap.prototype.setCollisionRange = // Tile Collision
- function (start, end, collision, resetCollisions) {
+ Tilemap.prototype.setCollisionCallback = // Tile Collision
+ function (context, callback) {
+ this.collisionCallbackContext = context;
+ this.collisionCallback = callback;
+ };
+ Tilemap.prototype.setCollisionRange = function (start, end, collision, resetCollisions, separateX, separateY) {
if (typeof collision === "undefined") { collision = Phaser.Collision.ANY; }
if (typeof resetCollisions === "undefined") { resetCollisions = false; }
+ if (typeof separateX === "undefined") { separateX = true; }
+ if (typeof separateY === "undefined") { separateY = true; }
for(var i = start; i < end; i++) {
- this.tiles[i].setCollision(collision, resetCollisions);
+ this.tiles[i].setCollision(collision, resetCollisions, separateX, separateY);
}
};
- Tilemap.prototype.setCollisionByIndex = function (values, collision, resetCollisions) {
+ Tilemap.prototype.setCollisionByIndex = function (values, collision, resetCollisions, separateX, separateY) {
if (typeof collision === "undefined") { collision = Phaser.Collision.ANY; }
if (typeof resetCollisions === "undefined") { resetCollisions = false; }
+ if (typeof separateX === "undefined") { separateX = true; }
+ if (typeof separateY === "undefined") { separateY = true; }
for(var i = 0; i < values.length; i++) {
- this.tiles[values[i]].setCollision(collision, resetCollisions);
+ this.tiles[values[i]].setCollision(collision, resetCollisions, separateX, separateY);
}
};
- Tilemap.prototype.getTile = // Tile Management
- function (x, y, layer) {
+ Tilemap.prototype.getTileByIndex = // Tile Management
+ function (value) {
+ if(this.tiles[value]) {
+ return this.tiles[value];
+ }
+ return null;
+ };
+ Tilemap.prototype.getTile = function (x, y, layer) {
if (typeof layer === "undefined") { layer = 0; }
return this.tiles[this.layers[layer].getTileIndex(x, y)];
};
@@ -11554,26 +11583,31 @@ var Phaser;
return this.currentLayer.getTileOverlaps(object);
};
Tilemap.prototype.collide = // COLLIDE
- function (objectOrGroup, callback) {
+ function (objectOrGroup, callback, context) {
if (typeof objectOrGroup === "undefined") { objectOrGroup = null; }
if (typeof callback === "undefined") { callback = null; }
+ if (typeof context === "undefined") { context = null; }
+ if(callback !== null && context !== null) {
+ this.collisionCallback = callback;
+ this.collisionCallbackContext = context;
+ }
if(objectOrGroup == null) {
objectOrGroup = this._game.world.group;
}
// Group?
if(objectOrGroup.isGroup == false) {
- return this.collideGameObject(objectOrGroup);
+ this.collideGameObject(objectOrGroup);
} else {
objectOrGroup.forEachAlive(this, this.collideGameObject, true);
}
- return true;
};
Tilemap.prototype.collideGameObject = function (object) {
- if(object == this) {
- return false;
- }
- if(object.immovable == false && object.exists == true && object.allowCollisions != Phaser.Collision.NONE) {
- return this.collisionLayer.getTileOverlaps(object);
+ if(object !== this && object.immovable == false && object.exists == true && object.allowCollisions != Phaser.Collision.NONE) {
+ this._tempCollisionData = this.collisionLayer.getTileOverlaps(object);
+ if(this.collisionCallback !== null && this._tempCollisionData.length > 0) {
+ this.collisionCallback.call(this.collisionCallbackContext, object, this._tempCollisionData);
+ }
+ return true;
} else {
return false;
}
diff --git a/Tests/tilemap/collide with tile.js b/Tests/tilemap/collide with tile.js
new file mode 100644
index 00000000..0c2a3e9d
--- /dev/null
+++ b/Tests/tilemap/collide with tile.js
@@ -0,0 +1,64 @@
+///
+///
+///
+///
+(function () {
+ var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
+ function init() {
+ myGame.loader.addTextFile('desert', 'assets/maps/desert.json');
+ myGame.loader.addImageFile('tiles', 'assets/tiles/tmw_desert_spacing.png');
+ myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
+ myGame.loader.load();
+ }
+ var map;
+ var car;
+ var tile;
+ var flash;
+ function create() {
+ map = myGame.createTilemap('tiles', 'desert', Phaser.Tilemap.FORMAT_TILED_JSON);
+ // 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);
+ // 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);
+ // This is the callback that will be called every time map.collide() returns true
+ map.collisionCallback = collide;
+ // This is the context in which the callback is called (usually 'this' if you want to be able to access local vars)
+ map.collisionCallbackContext = this;
+ car = myGame.createSprite(250, 200, 'car');
+ car.setBounds(0, 0, map.widthInPixels - 32, map.heightInPixels - 32);
+ myGame.camera.follow(car);
+ flash = myGame.camera.fx.add(Phaser.FX.Camera.Flash);
+ }
+ function update() {
+ // Collide the car object with the tilemap
+ // It's important to do this BEFORE you adjust the object velocity (below) otherwise it can jitter around a lot
+ map.collide(car);
+ car.velocity.x = 0;
+ car.velocity.y = 0;
+ car.angularVelocity = 0;
+ if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
+ car.angularVelocity = -200;
+ } else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
+ car.angularVelocity = 200;
+ }
+ if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
+ car.velocity.copyFrom(myGame.motion.velocityFromAngle(car.angle, 300));
+ }
+ }
+ function collide(object, collisionData) {
+ // 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) {
+ console.log('you hit a cactus!');
+ flash.start(0xff0000, 1);
+ } else if(collisionData[i].tile.index == 31) {
+ console.log('you hit a sign post!');
+ }
+ }
+ }
+})();
diff --git a/Tests/tilemap/collide with tile.ts b/Tests/tilemap/collide with tile.ts
new file mode 100644
index 00000000..396ed9e3
--- /dev/null
+++ b/Tests/tilemap/collide with tile.ts
@@ -0,0 +1,95 @@
+///
+///
+///
+///
+
+(function () {
+
+ var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
+
+ function init() {
+
+ myGame.loader.addTextFile('desert', 'assets/maps/desert.json');
+ myGame.loader.addImageFile('tiles', 'assets/tiles/tmw_desert_spacing.png');
+ myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
+
+ myGame.loader.load();
+
+ }
+
+ var map: Phaser.Tilemap;
+ var car: Phaser.Sprite;
+ var tile: Phaser.Tile;
+ var flash: Phaser.FX.Camera.Flash;
+
+ function create() {
+
+ map = myGame.createTilemap('tiles', 'desert', Phaser.Tilemap.FORMAT_TILED_JSON);
+
+ // 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);
+
+ // 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);
+
+ // This is the callback that will be called every time map.collide() returns true
+ map.collisionCallback = collide;
+
+ // This is the context in which the callback is called (usually 'this' if you want to be able to access local vars)
+ map.collisionCallbackContext = this;
+
+ car = myGame.createSprite(250, 200, 'car');
+ car.setBounds(0, 0, map.widthInPixels - 32, map.heightInPixels - 32);
+
+ myGame.camera.follow(car);
+
+ flash = myGame.camera.fx.add(Phaser.FX.Camera.Flash);
+
+ }
+
+ function update() {
+
+ // Collide the car object with the tilemap
+ // It's important to do this BEFORE you adjust the object velocity (below) otherwise it can jitter around a lot
+ map.collide(car);
+
+ car.velocity.x = 0;
+ car.velocity.y = 0;
+ car.angularVelocity = 0;
+
+ if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
+ {
+ car.angularVelocity = -200;
+ }
+ else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
+ {
+ car.angularVelocity = 200;
+ }
+
+ if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
+ {
+ car.velocity.copyFrom(myGame.motion.velocityFromAngle(car.angle, 300));
+ }
+
+ }
+
+ function collide(object, collisionData) {
+
+ // 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)
+ {
+ console.log('you hit a cactus!');
+ flash.start(0xff0000, 1);
+ }
+ else if (collisionData[i].tile.index == 31)
+ {
+ console.log('you hit a sign post!');
+ }
+ }
+
+ }
+
+})();
diff --git a/Tests/tilemap/collision.js b/Tests/tilemap/collision.js
index ddde5001..45eddaa9 100644
--- a/Tests/tilemap/collision.js
+++ b/Tests/tilemap/collision.js
@@ -41,6 +41,10 @@
car.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;
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
@@ -53,9 +57,5 @@
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
car.velocity.y = 200;
}
- // Collide everything with the map
- map.collide();
- // And collide everything in the game :)
- myGame.collide();
}
})();
diff --git a/Tests/tilemap/collision.ts b/Tests/tilemap/collision.ts
index 2b719f38..744c7c08 100644
--- a/Tests/tilemap/collision.ts
+++ b/Tests/tilemap/collision.ts
@@ -54,6 +54,12 @@
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;
@@ -75,12 +81,6 @@
car.velocity.y = 200;
}
- // Collide everything with the map
- map.collide();
-
- // And collide everything in the game :)
- myGame.collide();
-
}
})();
diff --git a/build/phaser-fx.d.ts b/build/phaser-fx.d.ts
index da160062..87feeb0f 100644
--- a/build/phaser-fx.d.ts
+++ b/build/phaser-fx.d.ts
@@ -66,8 +66,8 @@ module Phaser.FX.Camera {
/**
* Phaser - FX - Camera - Mirror
*
-* A Template FX file you can use to create your own Camera FX.
-* If you don't use any of the methods below (i.e. preUpdate, render, etc) then DELETE THEM to avoid un-necessary calls by the FXManager.
+* Creates a mirror effect for a camera.
+* Can mirror the camera image horizontally, vertically or both with an optional fill color overlay.
*/
module Phaser.FX.Camera {
class Mirror {
diff --git a/build/phaser-fx.js b/build/phaser-fx.js
index bde85275..c784aa72 100644
--- a/build/phaser-fx.js
+++ b/build/phaser-fx.js
@@ -137,8 +137,8 @@ var Phaser;
/**
* Phaser - FX - Camera - Mirror
*
- * A Template FX file you can use to create your own Camera FX.
- * If you don't use any of the methods below (i.e. preUpdate, render, etc) then DELETE THEM to avoid un-necessary calls by the FXManager.
+ * Creates a mirror effect for a camera.
+ * Can mirror the camera image horizontally, vertically or both with an optional fill color overlay.
*/
(function (Camera) {
var Mirror = (function () {
@@ -159,7 +159,7 @@ var Phaser;
* It is rendered to the Stage at Mirror.x/y (note the use of Stage coordinates, not World coordinates)
*/
function (x, y, region, fillColor) {
- if (typeof fillColor === "undefined") { fillColor = 'rgba(0,0,100,0.5)'; }
+ if (typeof fillColor === "undefined") { fillColor = 'rgba(0, 0, 100, 0.5)'; }
this.x = x;
this.y = y;
this._mirrorX = region.x;
@@ -199,7 +199,6 @@ var Phaser;
if(this._mirrorColor) {
this._context.fillRect(0, 0, this._mirrorWidth, this._mirrorHeight);
}
- //this._game.stage.context.save();
if(this.flipX && this.flipY) {
this._game.stage.context.transform(-1, 0, 0, -1, this._mirrorWidth, this._mirrorHeight);
this._game.stage.context.drawImage(this._canvas, -this.x, -this.y);
@@ -210,8 +209,7 @@ var Phaser;
this._game.stage.context.transform(1, 0, 0, -1, 0, this._mirrorHeight);
this._game.stage.context.drawImage(this._canvas, this.x, -this.y);
}
- //this._game.stage.context.restore();
- };
+ };
return Mirror;
})();
Camera.Mirror = Mirror;
diff --git a/build/phaser.d.ts b/build/phaser.d.ts
index b088bca4..ff270381 100644
--- a/build/phaser.d.ts
+++ b/build/phaser.d.ts
@@ -2476,21 +2476,21 @@ module Phaser {
* @param tile The Tile to separate
* @returns {boolean} Whether the objects in fact touched and were separated
*/
- static separateTile(object: GameObject, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, collideUp: bool, collideDown: bool): bool;
+ 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;
/**
* 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 separateTileX(object: GameObject, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool): bool;
+ static separateTileX(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 separateTileY(object: GameObject, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool): bool;
+ 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 object1 The first GameObject to separate
@@ -3180,21 +3180,21 @@ module Phaser {
/**
* Removes an object from the group.
*
- * @param Object The Basic you want to remove.
- * @param Splice Whether the object should be cut from the array entirely or not.
+ * @param object The Basic you want to remove.
+ * @param splice Whether the object should be cut from the array entirely or not.
*
* @return The removed object.
*/
- public remove(Object: Basic, Splice?: bool): Basic;
+ public remove(object: Basic, splice?: bool): Basic;
/**
* Replaces an existing Basic with a new one.
*
- * @param OldObject The object you want to replace.
- * @param NewObject The new object you want to use instead.
+ * @param oldObject The object you want to replace.
+ * @param newObject The new object you want to use instead.
*
* @return The new object.
*/
- public replace(OldObject: Basic, NewObject: Basic): Basic;
+ public replace(oldObject: Basic, newObject: Basic): Basic;
/**
* Call this function to sort the group according to a particular value and order.
* For example, to sort game objects for Zelda-style overlaps you might call
@@ -3202,10 +3202,10 @@ module Phaser {
* State.update() override. To sort all existing objects after
* a big explosion or bomb attack, you might call myGroup.sort("exists",Group.DESCENDING).
*
- * @param Index The string name of the member variable you want to sort on. Default value is "y".
- * @param Order A Group constant that defines the sort order. Possible values are Group.ASCENDING and Group.DESCENDING. Default value is Group.ASCENDING.
+ * @param index The string name of the member variable you want to sort on. Default value is "y".
+ * @param order A Group constant that defines the sort order. Possible values are Group.ASCENDING and Group.DESCENDING. Default value is Group.ASCENDING.
*/
- public sort(Index?: string, Order?: number): void;
+ public sort(index?: string, order?: number): void;
/**
* Go through and set the specified variable to the specified value on all members of the group.
*
@@ -5344,6 +5344,8 @@ module Phaser {
private _tempTileY;
private _tempTileW;
private _tempTileH;
+ private _tempTileBlock;
+ private _tempBlockResults;
public name: string;
public alpha: number;
public exists: bool;
@@ -5362,8 +5364,8 @@ module Phaser {
public tileMargin: number;
public tileSpacing: number;
public getTileFromWorldXY(x: number, y: number): number;
- public getTileOverlaps(object: GameObject): bool;
- public getTileBlock(x: number, y: number, width: number, height: number): any[];
+ public getTileOverlaps(object: GameObject);
+ public getTileBlock(x: number, y: number, width: number, height: number): void;
public getTileIndex(x: number, y: number): number;
public addColumn(column): void;
public updateBounds(): void;
@@ -5390,6 +5392,8 @@ module Phaser {
public collideRight: bool;
public collideUp: bool;
public collideDown: bool;
+ public separateX: bool;
+ public separateY: bool;
/**
* A reference to the tilemap this tile object belongs to.
*/
@@ -5404,7 +5408,7 @@ module Phaser {
* Clean up memory.
*/
public destroy(): void;
- public setCollision(collision: number, resetCollisions: bool): void;
+ public setCollision(collision: number, resetCollisions: bool, separateX: bool, separateY: bool): void;
public resetCollision(): void;
/**
* Returns a string representation of this object.
@@ -5423,12 +5427,15 @@ module Phaser {
module Phaser {
class Tilemap extends GameObject {
constructor(game: Game, key: string, mapData: string, format: number, resizeWorld?: bool, tileWidth?: number, tileHeight?: number);
+ private _tempCollisionData;
static FORMAT_CSV: number;
static FORMAT_TILED_JSON: number;
public tiles: Tile[];
public layers: TilemapLayer[];
public currentLayer: TilemapLayer;
public collisionLayer: TilemapLayer;
+ public collisionCallback;
+ public collisionCallbackContext;
public mapFormat: number;
public update(): void;
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): void;
@@ -5437,13 +5444,15 @@ module Phaser {
private generateTiles(qty);
public widthInPixels : number;
public heightInPixels : number;
- public setCollisionRange(start: number, end: number, collision?: number, resetCollisions?: bool): void;
- public setCollisionByIndex(values: number[], collision?: number, resetCollisions?: bool): void;
+ public setCollisionCallback(context, callback): void;
+ public setCollisionRange(start: number, end: number, collision?: number, resetCollisions?: bool, separateX?: bool, separateY?: bool): void;
+ public setCollisionByIndex(values: number[], collision?: number, resetCollisions?: bool, separateX?: bool, separateY?: bool): void;
+ public getTileByIndex(value: number): Tile;
public getTile(x: number, y: number, layer?: number): Tile;
public getTileFromWorldXY(x: number, y: number, layer?: number): Tile;
public getTileFromInputXY(layer?: number): Tile;
- public getTileOverlaps(object: GameObject): bool;
- public collide(objectOrGroup?, callback?): bool;
+ public getTileOverlaps(object: GameObject);
+ public collide(objectOrGroup?, callback?, context?): void;
public collideGameObject(object: GameObject): bool;
}
}
diff --git a/build/phaser.js b/build/phaser.js
index 5ac07e62..4f038bfb 100644
--- a/build/phaser.js
+++ b/build/phaser.js
@@ -4827,9 +4827,9 @@ var Phaser;
* @param tile The Tile to separate
* @returns {boolean} Whether the objects in fact touched and were separated
*/
- function separateTile(object, x, y, width, height, mass, collideLeft, collideRight, collideUp, collideDown) {
- var separatedX = Collision.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight);
- var separatedY = Collision.separateTileY(object, x, y, width, height, mass, collideUp, collideDown);
+ function separateTile(object, x, y, width, height, mass, collideLeft, collideRight, collideUp, collideDown, separateX, separateY) {
+ 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;
};
Collision.separateTileX = /**
@@ -4838,7 +4838,7 @@ var Phaser;
* @param tile The Tile to separate
* @returns {boolean} Whether the objects in fact touched and were separated along the X axis.
*/
- function separateTileX(object, x, y, width, height, mass, collideLeft, collideRight) {
+ function separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separate) {
// Can't separate two immovable objects (tiles are always immovable)
if(object.immovable) {
return false;
@@ -4872,8 +4872,10 @@ var Phaser;
}
// Then adjust their positions and velocities accordingly (if there was any overlap)
if(overlap != 0) {
- object.x = object.x - overlap;
- object.velocity.x = -(object.velocity.x * object.elasticity);
+ if(separate == true) {
+ object.x = object.x - overlap;
+ object.velocity.x = -(object.velocity.x * object.elasticity);
+ }
Collision.TILE_OVERLAP = true;
return true;
} else {
@@ -4886,7 +4888,7 @@ var Phaser;
* @param tile The second GameObject to separate
* @returns {boolean} Whether the objects in fact touched and were separated along the Y axis.
*/
- function separateTileY(object, x, y, width, height, mass, collideUp, collideDown) {
+ function separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separate) {
// Can't separate two immovable objects (tiles are always immovable)
if(object.immovable) {
return false;
@@ -4921,8 +4923,10 @@ var Phaser;
// 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) {
- object.y = object.y - overlap;
- object.velocity.y = -(object.velocity.y * object.elasticity);
+ if(separate == true) {
+ object.y = object.y - overlap;
+ object.velocity.y = -(object.velocity.y * object.elasticity);
+ }
Collision.TILE_OVERLAP = true;
return true;
} else {
@@ -6341,40 +6345,40 @@ var Phaser;
Group.prototype.remove = /**
* Removes an object from the group.
*
- * @param Object The Basic you want to remove.
- * @param Splice Whether the object should be cut from the array entirely or not.
+ * @param object The Basic you want to remove.
+ * @param splice Whether the object should be cut from the array entirely or not.
*
* @return The removed object.
*/
- function (Object, Splice) {
- if (typeof Splice === "undefined") { Splice = false; }
- var index = this.members.indexOf(Object);
+ function (object, splice) {
+ if (typeof splice === "undefined") { splice = false; }
+ var index = this.members.indexOf(object);
if((index < 0) || (index >= this.members.length)) {
return null;
}
- if(Splice) {
+ if(splice) {
this.members.splice(index, 1);
this.length--;
} else {
this.members[index] = null;
}
- return Object;
+ return object;
};
Group.prototype.replace = /**
* Replaces an existing Basic with a new one.
*
- * @param OldObject The object you want to replace.
- * @param NewObject The new object you want to use instead.
+ * @param oldObject The object you want to replace.
+ * @param newObject The new object you want to use instead.
*
* @return The new object.
*/
- function (OldObject, NewObject) {
- var index = this.members.indexOf(OldObject);
+ function (oldObject, newObject) {
+ var index = this.members.indexOf(oldObject);
if((index < 0) || (index >= this.members.length)) {
return null;
}
- this.members[index] = NewObject;
- return NewObject;
+ this.members[index] = newObject;
+ return newObject;
};
Group.prototype.sort = /**
* Call this function to sort the group according to a particular value and order.
@@ -6383,14 +6387,14 @@ var Phaser;
* State.update() override. To sort all existing objects after
* a big explosion or bomb attack, you might call myGroup.sort("exists",Group.DESCENDING).
*
- * @param Index The string name of the member variable you want to sort on. Default value is "y".
- * @param Order A Group constant that defines the sort order. Possible values are Group.ASCENDING and Group.DESCENDING. Default value is Group.ASCENDING.
+ * @param index The string name of the member variable you want to sort on. Default value is "y".
+ * @param order A Group constant that defines the sort order. Possible values are Group.ASCENDING and Group.DESCENDING. Default value is Group.ASCENDING.
*/
- function (Index, Order) {
- if (typeof Index === "undefined") { Index = "y"; }
- if (typeof Order === "undefined") { Order = Group.ASCENDING; }
- this._sortIndex = Index;
- this._sortOrder = Order;
+ function (index, order) {
+ if (typeof index === "undefined") { index = "y"; }
+ if (typeof order === "undefined") { order = Group.ASCENDING; }
+ this._sortIndex = index;
+ this._sortOrder = order;
this.members.sort(this.sortHandler);
};
Group.prototype.setAll = /**
@@ -11151,6 +11155,7 @@ var Phaser;
this.boundsInTiles = new Phaser.Rectangle();
//this.scrollFactor = new MicroPoint(1, 1);
this.mapData = [];
+ this._tempTileBlock = [];
this._texture = this._game.cache.getImage(key);
}
TilemapLayer.prototype.getTileFromWorldXY = function (x, y) {
@@ -11168,15 +11173,19 @@ var Phaser;
this._tempTileY = this._game.math.snapToFloor(object.bounds.y, this.tileHeight) / this.tileHeight;
this._tempTileW = (this._game.math.snapToCeil(object.bounds.width, this.tileWidth) + this.tileWidth) / this.tileWidth;
this._tempTileH = (this._game.math.snapToCeil(object.bounds.height, this.tileHeight) + this.tileHeight) / this.tileHeight;
- // Loop through the tiles we've got and check overlaps accordingly
- var tiles = this.getTileBlock(this._tempTileX, this._tempTileY, this._tempTileW, this._tempTileH);
+ // Loop through the tiles we've got and check overlaps accordingly (the results are stored in this._tempTileBlock)
+ this.getTileBlock(this._tempTileX, this._tempTileY, this._tempTileW, this._tempTileH);
Phaser.Collision.TILE_OVERLAP = false;
- for(var r = 0; r < tiles.length; r++) {
- if(tiles[r].tile.allowCollisions != Phaser.Collision.NONE) {
- Phaser.Collision.separateTile(object, tiles[r].x * this.tileWidth, tiles[r].y * this.tileHeight, this.tileWidth, this.tileHeight, tiles[r].tile.mass, tiles[r].tile.collideLeft, tiles[r].tile.collideRight, tiles[r].tile.collideUp, tiles[r].tile.collideDown);
+ for(var r = 0; r < this._tempTileBlock.length; r++) {
+ if(Phaser.Collision.separateTile(object, this._tempTileBlock[r].x * this.tileWidth, this._tempTileBlock[r].y * this.tileHeight, this.tileWidth, this.tileHeight, this._tempTileBlock[r].tile.mass, this._tempTileBlock[r].tile.collideLeft, this._tempTileBlock[r].tile.collideRight, this._tempTileBlock[r].tile.collideUp, this._tempTileBlock[r].tile.collideDown, this._tempTileBlock[r].tile.separateX, this._tempTileBlock[r].tile.separateY) == true) {
+ this._tempBlockResults.push({
+ x: this._tempTileBlock[r].x,
+ y: this._tempTileBlock[r].y,
+ tile: this._tempTileBlock[r].tile
+ });
}
}
- return Phaser.Collision.TILE_OVERLAP;
+ return this._tempBlockResults;
};
TilemapLayer.prototype.getTileBlock = function (x, y, width, height) {
if(x < 0) {
@@ -11191,11 +11200,13 @@ var Phaser;
if(height > this.heightInTiles) {
height = this.heightInTiles;
}
- var output = [];
+ this._tempTileBlock = [];
+ this._tempBlockResults = [];
for(var ty = y; ty < y + height; ty++) {
for(var tx = x; tx < x + width; tx++) {
- if(this.mapData[ty] && this.mapData[ty][tx]) {
- output.push({
+ // We only want to consider the tile for checking if you can actually collide with it
+ if(this.mapData[ty] && this.mapData[ty][tx] && this._parent.tiles[this.mapData[ty][tx]].allowCollisions != Phaser.Collision.NONE) {
+ this._tempTileBlock.push({
x: tx,
y: ty,
tile: this._parent.tiles[this.mapData[ty][tx]]
@@ -11203,7 +11214,6 @@ var Phaser;
}
}
}
- return output;
};
TilemapLayer.prototype.getTileIndex = function (x, y) {
if(y >= 0 && y < this.mapData.length) {
@@ -11350,6 +11360,8 @@ var Phaser;
this.collideRight = false;
this.collideUp = false;
this.collideDown = false;
+ this.separateX = true;
+ this.separateY = true;
this._game = game;
this.tilemap = tilemap;
this.index = index;
@@ -11363,10 +11375,12 @@ var Phaser;
function () {
this.tilemap = null;
};
- Tile.prototype.setCollision = function (collision, resetCollisions) {
+ Tile.prototype.setCollision = function (collision, resetCollisions, separateX, separateY) {
if(resetCollisions) {
this.resetCollision();
}
+ this.separateX = separateX;
+ this.separateY = separateY;
this.allowCollisions = collision;
if(collision & Phaser.Collision.ANY) {
this.collideLeft = true;
@@ -11426,6 +11440,7 @@ var Phaser;
if (typeof tileWidth === "undefined") { tileWidth = 0; }
if (typeof tileHeight === "undefined") { tileHeight = 0; }
_super.call(this, game);
+ this.collisionCallback = null;
this.isGroup = false;
this.tiles = [];
this.layers = [];
@@ -11522,23 +11537,37 @@ var Phaser;
enumerable: true,
configurable: true
});
- Tilemap.prototype.setCollisionRange = // Tile Collision
- function (start, end, collision, resetCollisions) {
+ Tilemap.prototype.setCollisionCallback = // Tile Collision
+ function (context, callback) {
+ this.collisionCallbackContext = context;
+ this.collisionCallback = callback;
+ };
+ Tilemap.prototype.setCollisionRange = function (start, end, collision, resetCollisions, separateX, separateY) {
if (typeof collision === "undefined") { collision = Phaser.Collision.ANY; }
if (typeof resetCollisions === "undefined") { resetCollisions = false; }
+ if (typeof separateX === "undefined") { separateX = true; }
+ if (typeof separateY === "undefined") { separateY = true; }
for(var i = start; i < end; i++) {
- this.tiles[i].setCollision(collision, resetCollisions);
+ this.tiles[i].setCollision(collision, resetCollisions, separateX, separateY);
}
};
- Tilemap.prototype.setCollisionByIndex = function (values, collision, resetCollisions) {
+ Tilemap.prototype.setCollisionByIndex = function (values, collision, resetCollisions, separateX, separateY) {
if (typeof collision === "undefined") { collision = Phaser.Collision.ANY; }
if (typeof resetCollisions === "undefined") { resetCollisions = false; }
+ if (typeof separateX === "undefined") { separateX = true; }
+ if (typeof separateY === "undefined") { separateY = true; }
for(var i = 0; i < values.length; i++) {
- this.tiles[values[i]].setCollision(collision, resetCollisions);
+ this.tiles[values[i]].setCollision(collision, resetCollisions, separateX, separateY);
}
};
- Tilemap.prototype.getTile = // Tile Management
- function (x, y, layer) {
+ Tilemap.prototype.getTileByIndex = // Tile Management
+ function (value) {
+ if(this.tiles[value]) {
+ return this.tiles[value];
+ }
+ return null;
+ };
+ Tilemap.prototype.getTile = function (x, y, layer) {
if (typeof layer === "undefined") { layer = 0; }
return this.tiles[this.layers[layer].getTileIndex(x, y)];
};
@@ -11554,26 +11583,31 @@ var Phaser;
return this.currentLayer.getTileOverlaps(object);
};
Tilemap.prototype.collide = // COLLIDE
- function (objectOrGroup, callback) {
+ function (objectOrGroup, callback, context) {
if (typeof objectOrGroup === "undefined") { objectOrGroup = null; }
if (typeof callback === "undefined") { callback = null; }
+ if (typeof context === "undefined") { context = null; }
+ if(callback !== null && context !== null) {
+ this.collisionCallback = callback;
+ this.collisionCallbackContext = context;
+ }
if(objectOrGroup == null) {
objectOrGroup = this._game.world.group;
}
// Group?
if(objectOrGroup.isGroup == false) {
- return this.collideGameObject(objectOrGroup);
+ this.collideGameObject(objectOrGroup);
} else {
objectOrGroup.forEachAlive(this, this.collideGameObject, true);
}
- return true;
};
Tilemap.prototype.collideGameObject = function (object) {
- if(object == this) {
- return false;
- }
- if(object.immovable == false && object.exists == true && object.allowCollisions != Phaser.Collision.NONE) {
- return this.collisionLayer.getTileOverlaps(object);
+ if(object !== this && object.immovable == false && object.exists == true && object.allowCollisions != Phaser.Collision.NONE) {
+ this._tempCollisionData = this.collisionLayer.getTileOverlaps(object);
+ if(this.collisionCallback !== null && this._tempCollisionData.length > 0) {
+ this.collisionCallback.call(this.collisionCallbackContext, object, this._tempCollisionData);
+ }
+ return true;
} else {
return false;
}