Tilemap.createCollisionObjects will parse Tiled data for objectgroups and convert polyline instances into physics objects you can collide with in the world.

After defining tiles that collide on a Tilemap, you need to call Tilemap.generateCollisionData(layer) to populate the physics world with the data required.
Debug.renderPhysicsBody updated to take camera location and body rotation into account.
Body movement functions put back to velocity :)
Updated to latest dev version of pixi and latest p2.js
Updated docs
This commit is contained in:
photonstorm
2014-02-18 03:01:51 +00:00
parent 375e9e379a
commit 5d5c64d22f
201 changed files with 41296 additions and 47048 deletions
+140
View File
@@ -97,6 +97,11 @@ Phaser.Tilemap = function (game, key) {
*/
this.objects = data.objects;
/**
* @property {array} collision - An array of collision data (polylines, etc).
*/
this.collision = data.collision;
/**
* @property {array} images - An array of Tiled Image Layers.
*/
@@ -283,6 +288,141 @@ Phaser.Tilemap.prototype = {
},
/**
* Clears all physics bodies from the world for the given layer.
*
* @method Phaser.Tilemap#clearPhysicsBodies
* @param {number|string|Phaser.TilemapLayer} [layer] - The layer to operate on. If not given will default to this.currentLayer.
*/
clearPhysicsBodies: function (layer) {
layer = this.getLayer(layer);
var i = this.layers[layer].bodies.length;
while (i--)
{
this.layers[layer].bodies[i].destroy();
}
},
/**
* Goes through all tiles in the given layer and converts those set to collide into physics bodies in the world.
* Only call this *after* you have specified all of the tiles you wish to collide with calls like Tilemap.setCollisionBetween, etc.
* Every time you call this method it will destroy any previously created bodies and remove them from the world.
* Therefore understand it's an expensive operation and not to be done in a core game update loop.
*
* @method Phaser.Tilemap#generateCollisionData
* @param {number|string|Phaser.TilemapLayer} [layer] - The layer to operate on. If not given will default to this.currentLayer.
* @param {boolean} [addToWorld=true] - If true it will automatically add each body to the world, otherwise it's up to you to do so.
* @return {array} An array of the Phaser.Physics.Body objects that have been created.
*/
generateCollisionData: function (layer, addToWorld) {
layer = this.getLayer(layer);
if (typeof addToWorld === 'undefined') { addToWorld = true; }
// If the bodies array is already populated we need to nuke it
if (this.layers[layer].bodies.length > 0)
{
this.clearPhysicsBodies(layer);
}
this.layers[layer].bodies.length = [];
var width = 0;
var sx = 0;
var sy = 0;
for (var y = 0, h = this.layers[layer].height; y < h; y++)
{
width = 0;
for (var x = 0, w = this.layers[layer].width; x < w; x++)
{
var tile = this.layers[layer].data[y][x];
if (tile)
{
right = this.getTileRight(layer, x, y);
if (width === 0)
{
sx = tile.x * tile.width;
sy = tile.y * tile.height;
width = tile.width;
}
if (right && right.collides)
{
width += tile.width;
}
else
{
var body = this.game.physics.createBody(sx, sy, 0, false);
body.addRectangle(width, tile.height, width / 2, tile.height / 2, 0);
if (addToWorld)
{
this.game.physics.addBody(body.data);
}
this.layers[layer].bodies.push(body);
width = 0;
}
}
}
}
return this.layers[layer].bodies;
},
/**
* Converts all of the polylines inside a Tiled ObjectGroup into physics bodies that are added to the world.
* Note that the polylines must be created in such a way that they can withstand polygon decomposition.
*
* @method Phaser.Tilemap#createCollisionObjects
* @param {string} [layer] - The Tiled layer to operate on that contains the collision data.
* @param {boolean} [addToWorld=true] - If true it will automatically add each body to the world.
* @return {array} An array of the Phaser.Physics.Body objects that have been created.
*/
createCollisionObjects: function (layer, addToWorld) {
if (typeof addToWorld === 'undefined') { addToWorld = true; }
var output = [];
for (var i = 0, len = this.collision[layer].length; i < len; i++)
{
// name: json.layers[i].objects[v].name,
// x: json.layers[i].objects[v].x,
// y: json.layers[i].objects[v].y,
// width: json.layers[i].objects[v].width,
// height: json.layers[i].objects[v].height,
// visible: json.layers[i].objects[v].visible,
// properties: json.layers[i].objects[v].properties,
// polyline: json.layers[i].objects[v].polyline
var object = this.collision[layer][i];
var body = this.game.physics.createBody(object.x, object.y, 0, addToWorld, {}, object.polyline);
if (body)
{
output.push(body);
}
}
return output;
},
/**
* Creates a new TilemapLayer object. By default TilemapLayers are fixed to the camera.
* The `layer` parameter is important. If you've created your map in Tiled then you can get this by looking in Tiled and looking at the Layer name.
+85 -4
View File
@@ -89,7 +89,7 @@ Phaser.TilemapParser = {
}
else
{
return { layers: [], objects: [], images: [], tilesets: [] };
return this.getEmptyData();
}
},
@@ -133,6 +133,58 @@ Phaser.TilemapParser = {
},
/**
* Returns an empty map data object.
* @method Phaser.TilemapParser.getEmptyData
* @return {object} Generated map data.
*/
getEmptyData: function () {
var map = {};
map.width = 0;
map.height = 0;
map.tileWidth = 0;
map.tileHeight = 0;
map.orientation = 'orthogonal';
map.version = '1';
map.properties = {};
map.widthInPixels = 0;
map.heightInPixels = 0;
var layers = [];
var layer = {
name: 'layer',
x: 0,
y: 0,
width: 0,
height: 0,
widthInPixels: 0,
heightInPixels: 0,
alpha: 1,
visible: true,
properties: {},
indexes: [],
callbacks: [],
data: []
};
layers.push(layer);
map.layers = layers;
map.images = [];
map.objects = {};
map.collision = {};
map.tilesets = [];
map.tiles = [];
return map;
},
/**
* Parses a Tiled JSON file into valid map data.
* @method Phaser.TilemapParser.parseJSON
@@ -183,7 +235,8 @@ Phaser.TilemapParser = {
visible: json.layers[i].visible,
properties: {},
indexes: [],
callbacks: []
callbacks: [],
bodies: []
};
@@ -265,8 +318,9 @@ Phaser.TilemapParser = {
map.images = images;
// Objects
// Objects & Collision Data (polylines, etc)
var objects = {};
var collision = {};
for (var i = 0; i < json.layers.length; i++)
{
@@ -276,10 +330,11 @@ Phaser.TilemapParser = {
}
objects[json.layers[i].name] = [];
collision[json.layers[i].name] = [];
for (var v = 0, len = json.layers[i].objects.length; v < len; v++)
{
// For now we'll just support object tiles
// Object Tiles
if (json.layers[i].objects[v].gid)
{
var object = {
@@ -295,11 +350,37 @@ Phaser.TilemapParser = {
objects[json.layers[i].name].push(object);
}
else if (json.layers[i].objects[v].polyline)
{
var object = {
name: json.layers[i].objects[v].name,
x: json.layers[i].objects[v].x,
y: json.layers[i].objects[v].y,
width: json.layers[i].objects[v].width,
height: json.layers[i].objects[v].height,
visible: json.layers[i].objects[v].visible,
properties: json.layers[i].objects[v].properties
};
object.polyline = [];
// Parse the polyline into an array
for (var p = 0; p < json.layers[i].objects[v].polyline.length; p++)
{
object.polyline.push([ json.layers[i].objects[v].polyline[p].x, json.layers[i].objects[v].polyline[p].y ]);
}
collision[json.layers[i].name].push(object);
}
}
}
map.objects = objects;
map.collision = collision;
// Tilesets
var tilesets = [];