mirror of
https://github.com/wassname/phaser.git
synced 2026-09-09 11:28:47 +08:00
Large Tilemap collision overhaul. Proper callback support, optimised collision checks and lots more.
This commit is contained in:
+17
-9
@@ -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;
|
||||
}
|
||||
|
||||
+17
-17
@@ -321,21 +321,21 @@ module Phaser {
|
||||
/**
|
||||
* Removes an object from the group.
|
||||
*
|
||||
* @param Object The <code>Basic</code> you want to remove.
|
||||
* @param Splice Whether the object should be cut from the array entirely or not.
|
||||
* @param object The <code>Basic</code> 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 <code>Basic</code> 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 {
|
||||
* <code>State.update()</code> override. To sort all existing objects after
|
||||
* a big explosion or bomb attack, you might call <code>myGroup.sort("exists",Group.DESCENDING)</code>.
|
||||
*
|
||||
* @param Index The <code>string</code> name of the member variable you want to sort on. Default value is "y".
|
||||
* @param Order A <code>Group</code> constant that defines the sort order. Possible values are <code>Group.ASCENDING</code> and <code>Group.DESCENDING</code>. Default value is <code>Group.ASCENDING</code>.
|
||||
* @param index The <code>string</code> name of the member variable you want to sort on. Default value is "y".
|
||||
* @param order A <code>Group</code> constant that defines the sort order. Possible values are <code>Group.ASCENDING</code> and <code>Group.DESCENDING</code>. Default value is <code>Group.ASCENDING</code>.
|
||||
*/
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user