Merge remote-tracking branch 'origin/master'

This commit is contained in:
Pavle Goloskokovic 2017-12-04 22:05:43 +01:00
commit 0f6ac299e0
49 changed files with 767 additions and 434 deletions

View file

@ -1,7 +1,7 @@
{
"//": "npm publish --tag beta",
"name": "phaser",
"version": "3.0.0-beta.12",
"version": "3.0.0-beta.13",
"release": "Shadow Coast",
"description": "A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers.",
"author": "Richard Davey <rdavey@gmail.com> (http://www.photonstorm.com)",

View file

@ -246,7 +246,7 @@ var GameObject = new Class({
{
if (this.preDestroy)
{
this.preDestroy();
this.preDestroy.call(this);
}
this.scene.sys.displayList.remove(this);
@ -261,10 +261,15 @@ var GameObject = new Class({
if (this.body)
{
this.scene.sys.physicsManager.remove(this);
this.body = undefined;
}
// Tell the Scene to re-sort the children
this.scene.sys.sortChildrenFlag = true;
this.active = false;
this.Visible = false;
this.data = undefined;

View file

@ -3,6 +3,7 @@ var CanvasPool = require('../../display/canvas/CanvasPool');
var Class = require('../../utils/Class');
var Commands = require('./Commands');
var Components = require('../components');
var Ellipse = require('../../geom/ellipse/');
var GameObject = require('../GameObject');
var GetValue = require('../../utils/object/GetValue');
var MATH_CONST = require('../../math/const');
@ -340,8 +341,10 @@ var Graphics = new Class({
// STROKE LINES BETWEEN AN ARRAY OF POINTS
strokePoints: function (points)
strokePoints: function (points, autoClose)
{
if (autoClose === undefined) { autoClose = false; }
this.beginPath();
this.moveTo(points[0].x, points[0].y);
@ -351,6 +354,11 @@ var Graphics = new Class({
this.lineTo(points[i].x, points[i].y);
}
if (autoClose)
{
this.lineTo(points[0].x, points[0].y);
}
this.strokePath();
return this;
@ -364,7 +372,7 @@ var Graphics = new Class({
var points = ellipse.getPoints(smoothness);
return this.strokePoints(points);
return this.strokePoints(points, true);
},
strokeEllipse: function (x, y, width, height, smoothness)
@ -375,7 +383,7 @@ var Graphics = new Class({
var points = ellipse.getPoints(smoothness);
return this.strokePoints(points);
return this.strokePoints(points, true);
},
// ARC

View file

@ -38,6 +38,7 @@ var Group = new Class({
this.createCallback = GetFastValue(config, 'createCallback', null);
this.removeCallback = GetFastValue(config, 'removeCallback', null);
this.createMultipleCallback = GetFastValue(config, 'createMultipleCallback', null);
if (config)
{
@ -186,6 +187,11 @@ var Group = new Class({
Actions.GridAlign(entries, grid);
}
if (this.createMultipleCallback)
{
this.createMultipleCallback.call(this, entries);
}
return entries;
},
@ -338,13 +344,15 @@ var Group = new Class({
}
},
getTotalUsed: function ()
countActive: function (value)
{
if (value === undefined) { value = true; }
var total = 0;
for (var i = 0; i < this.children.size; i++)
{
if (this.children.entries[i].active)
if (this.children.entries[i].active === value)
{
total++;
}
@ -353,6 +361,11 @@ var Group = new Class({
return total;
},
getTotalUsed: function ()
{
return this.countActive();
},
getTotalFree: function ()
{
var used = this.getTotalUsed();

View file

@ -306,11 +306,6 @@ var Text = new Class({
var w = textSize.width + padding.left + padding.right;
var h = textSize.height + padding.top + padding.bottom;
// console.log(textSize);
// console.log(padding);
// console.log(w, 'x', h);
// console.log('');
if (!style.fixedWidth)
{
this.width = w;
@ -336,6 +331,8 @@ var Text = new Class({
context.clearRect(0, 0, w, h);
}
context.save();
if (style.backgroundColor)
{
context.fillStyle = style.backgroundColor;
@ -397,6 +394,8 @@ var Text = new Class({
}
}
context.restore();
this.dirty = true;
return this;

View file

@ -86,20 +86,22 @@ var Tile = new Class({
this.baseHeight = (baseHeight !== undefined) ? baseHeight : height;
/**
* The world x coordinate of the top left of this tile in pixels. This does not factor in
* camera scroll, layer scale or layer position.
* @property {number} x
* The x coordinate of the top left of this tile in pixels. This is relative to the top left
* of the layer this tile is being rendered within. This property does NOT factor in camera
* scroll, layer scale or layer position.
* @property {number} pixelX
*/
this.worldX = 0;
this.pixelX = 0;
/**
* The world y coordinate of the top left of this tile in pixels. This does not factor in
* camera scroll, layer scale or layer position.
* @property {number} y
* The y coordinate of the top left of this tile in pixels. This is relative to the top left
* of the layer this tile is being rendered within. This property does NOT factor in camera
* scroll, layer scale or layer position.
* @property {number} pixelY
*/
this.worldY = 0;
this.pixelY = 0;
this.updateWorldXY();
this.updatePixelXY();
/**
* Tile specific properties. These usually come from Tiled.
@ -192,7 +194,7 @@ var Tile = new Class({
*/
containsPoint: function (x, y)
{
return !(x < this.worldX || y < this.worldY || x > this.right || y > this.bottom);
return !(x < this.pixelX || y < this.pixelY || x > this.right || y > this.bottom);
},
/**
@ -244,7 +246,7 @@ var Tile = new Class({
intersects: function (x, y, right, bottom)
{
return !(
right <= this.worldX || bottom <= this.worldY ||
right <= this.pixelX || bottom <= this.pixelY ||
x >= this.right || y >= this.bottom
);
},
@ -354,7 +356,7 @@ var Tile = new Class({
},
/**
* Sets the size of the tile and updates its worldX and worldY.
* Sets the size of the tile and updates its pixelX and pixelY.
*
* @param {integer} tileWidth - The width of the tile in pixels.
* @param {integer} tileHeight - The height of the tile in pixels.
@ -369,7 +371,7 @@ var Tile = new Class({
if (baseWidth !== undefined) { this.baseWidth = baseWidth; }
if (baseHeight !== undefined) { this.baseHeight = baseHeight; }
this.updateWorldXY();
this.updatePixelXY();
return this;
},
@ -379,13 +381,13 @@ var Tile = new Class({
*
* @returns {this}
*/
updateWorldXY: function ()
updatePixelXY: function ()
{
// Tiled places tiles on a grid of baseWidth x baseHeight. The origin for a tile is the
// bottom left, while the Phaser renderer assumes the origin is the top left. The y
// coordinate needs to be adjusted by the difference.
this.worldX = this.x * this.baseWidth;
this.worldY = this.y * this.baseHeight - (this.height - this.baseHeight);
this.pixelX = this.x * this.baseWidth;
this.pixelY = this.y * this.baseHeight - (this.height - this.baseHeight);
return this;
},
@ -435,7 +437,7 @@ var Tile = new Class({
left: {
get: function ()
{
return this.worldX;
return this.pixelX;
}
},
@ -448,7 +450,7 @@ var Tile = new Class({
right: {
get: function ()
{
return this.worldX + this.width;
return this.pixelX + this.width;
}
},
@ -461,7 +463,7 @@ var Tile = new Class({
top: {
get: function ()
{
return this.worldY;
return this.pixelY;
}
},
@ -474,7 +476,7 @@ var Tile = new Class({
bottom: {
get: function ()
{
return this.worldY + this.height;
return this.pixelY + this.height;
}
},
@ -487,7 +489,7 @@ var Tile = new Class({
centerX: {
get: function ()
{
return this.worldX + this.width / 2;
return this.pixelX + this.width / 2;
}
},
@ -500,7 +502,7 @@ var Tile = new Class({
centerY: {
get: function ()
{
return this.worldY + this.height / 2;
return this.pixelY + this.height / 2;
}
}

View file

@ -589,6 +589,18 @@ var Tilemap = new Class({
return TilemapComponents.FindByIndex(findIndex, skip, reverse, layer);
},
/**
* See component documentation. If no layer specified, the map's current layer is used.
*
* @return {Tile|null} Returns a Tiles, or null if the layer given was invalid.
*/
findTile: function (callback, context, tileX, tileY, width, height, filteringOptions, layer)
{
layer = this.getLayer(layer);
if (layer === null) { return null; }
return TilemapComponents.FindTile(callback, context, tileX, tileY, width, height, filteringOptions, layer);
},
/**
* See component documentation. If no layer specified, the map's current layer is used.
*
@ -1061,9 +1073,12 @@ var Tilemap = new Class({
this.widthInPixels = this.width * tileWidth;
this.heightInPixels = this.height * tileHeight;
// Update the base tile size on all tiles
// Update the base tile size on all layers & tiles
for (var i = 0; i < this.layers.length; i++)
{
this.layers[i].baseWidth = tileWidth;
this.layers[i].baseHeight = tileHeight;
var mapData = this.layers[i].data;
var mapWidth = this.layers[i].width;
var mapHeight = this.layers[i].height;
@ -1190,6 +1205,23 @@ var Tilemap = new Class({
return TilemapComponents.TileToWorldXY(tileX, tileY, point, camera, layer);
},
/**
* See component documentation. If no layer specified, the map's current layer is used. This
* cannot be applied to StaticTilemapLayers.
*
* @return {this|null} Returns this, or null if the layer given was invalid.
*/
weightedRandomize: function (tileX, tileY, width, height, weightedIndexes, layer)
{
layer = this.getLayer(layer);
if (this._isStaticCall(layer, 'weightedRandomize')) { return this; }
if (layer !== null)
{
TilemapComponents.WeightedRandomize(tileX, tileY, width, height, weightedIndexes, layer);
}
return this;
},
/**
* See component documentation. If no layer specified, the map's current layer is used.
*

View file

@ -147,6 +147,20 @@ var Tileset = new Class({
return this.tileData[tileIndex - this.firstgid];
},
/**
* Get a tile's data that is stored in the Tileset. Returns null if tile index is not
* contained in this Tileset.
*
* @param {integer} tileIndex - The unique id of the tile across all tilesets in the map.
* @returns {object|null}
*/
getTileCollisionGroup: function (tileIndex)
{
var data = this.getTileData(tileIndex);
return (data && data.objectgroup) ? data.objectgroup : null;
},
/**
* Returns true if and only if this Tileset contains the given tile index.
*

View file

@ -30,10 +30,10 @@ var CullTiles = function (layer, camera, outputArray)
{
var tile = mapData[row][col];
if (tile === null || (tile.index <= 0 && tilemapLayer.skipIndexZero)) { continue; }
if (tile === null || tile.index === -1) { continue; }
var tileX = tile.worldX * sx - left;
var tileY = tile.worldY * sy - top;
var tileX = tile.pixelX * sx - left;
var tileY = tile.pixelY * sy - top;
var cullW = camera.width + tileWidth;
var cullH = camera.height + tileHeight;

View file

@ -0,0 +1,31 @@
var GetTilesWithin = require('./GetTilesWithin');
/**
* Find the first tile in the given rectangular area (in tile coordinates) of the layer that
* satisfies the provided testing function. I.e. finds the first tile for which `callback` returns
* true. Similar to Array.prototype.find in vanilla JS.
*
* @param {function} callback - The callback. Each tile in the given area will be passed to this
* callback as the first and only parameter.
* @param {object} [context] - The context under which the callback should be run.
* @param {integer} [tileX=0] - [description]
* @param {integer} [tileY=0] - [description]
* @param {integer} [width=max width based on tileX] - [description]
* @param {integer} [height=max height based on tileY] - [description]
* @param {object} [filteringOptions] - Optional filters to apply when getting the tiles.
* @param {boolean} [filteringOptions.isNotEmpty=false] - If true, only return tiles that don't have
* -1 for an index.
* @param {boolean} [filteringOptions.isColliding=false] - If true, only return tiles that collide
* on at least one side.
* @param {boolean} [filteringOptions.hasInterestingFace=false] - If true, only return tiles that
* have at least one interesting face.
* @param {LayerData} layer - [description]
* @return {Tile|null} A Tile that matches the search, or null if no Tile found
*/
var FindTile = function (callback, context, tileX, tileY, width, height, filteringOptions, layer)
{
var tiles = GetTilesWithin(tileX, tileY, width, height, filteringOptions, layer);
return tiles.find(callback, context) || null;
};
module.exports = FindTile;

View file

@ -40,8 +40,8 @@ var RenderDebug = function (graphics, styleConfig, layer)
var tw = tile.width;
var th = tile.height;
var x = tile.worldX;
var y = tile.worldY;
var x = tile.pixelX;
var y = tile.pixelY;
var color = tile.collides ? collidingTileColor : tileColor;
if (color !== null)

View file

@ -9,7 +9,7 @@
*/
var TileToWorldX = function (tileX, camera, layer)
{
var tileWidth = layer.tileWidth;
var tileWidth = layer.baseTileWidth;
var tilemapLayer = layer.tilemapLayer;
var layerWorldX = 0;

View file

@ -9,7 +9,7 @@
*/
var TileToWorldY = function (tileY, camera, layer)
{
var tileHeight = layer.tileHeight;
var tileHeight = layer.baseTileHeight;
var tilemapLayer = layer.tilemapLayer;
var layerWorldY = 0;

View file

@ -0,0 +1,60 @@
var GetTilesWithin = require('./GetTilesWithin');
/**
* Randomizes the indexes of a rectangular region of tiles (in tile coordinates) within the
* specified layer. Each tile will recieve a new index. New indexes are drawn from the given
* weightedIndexes array. An example weighted array:
*
* [
* { index: 6, weight: 4 }, // Probability of index 6 is 4 / 8
* { index: 7, weight: 2 }, // Probability of index 7 would be 2 / 8
* { index: 8, weight: 1.5 }, // Probability of index 8 would be 1.5 / 8
* { index: 26, weight: 0.5 } // Probability of index 27 would be 0.5 / 8
* ]
*
* The probability of any index being choose is (the index's weight) / (sum of all weights). This
* method only modifies tile indexes and does not change collisioninformation.
*
* @param {integer} [tileX=0] - [description]
* @param {integer} [tileY=0] - [description]
* @param {integer} [width=max width based on tileX] - [description]
* @param {integer} [height=max height based on tileY] - [description]
* @param {object[]} [weightedIndexes] - An array of objects to randomly draw from during
* randomization. They should be in the form: { index: 0, weight: 4 }.
* @param {LayerData} layer - [description]
*/
var WeightedRandomize = function (tileX, tileY, width, height, weightedIndexes, layer)
{
if (weightedIndexes === undefined) { return; }
var i;
var tiles = GetTilesWithin(tileX, tileY, width, height, null, layer);
var weightTotal = 0;
for (i = 0; i < weightedIndexes.length; i++)
{
weightTotal += weightedIndexes[i].weight;
}
if (weightTotal <= 0) { return; }
for (i = 0; i < tiles.length; i++)
{
var rand = Math.random() * weightTotal;
var sum = 0;
var randomIndex = -1;
for (var j = 0; j < weightedIndexes.length; j++)
{
sum += weightedIndexes[j].weight;
if (rand <= sum)
{
randomIndex = weightedIndexes[j].index;
break;
}
}
tiles[i].index = randomIndex;
}
};
module.exports = WeightedRandomize;

View file

@ -13,7 +13,7 @@ var WorldToTileX = function (worldX, snapToFloor, camera, layer)
{
if (snapToFloor === undefined) { snapToFloor = true; }
var tileWidth = layer.tileWidth;
var tileWidth = layer.baseTileWidth;
var tilemapLayer = layer.tilemapLayer;
if (tilemapLayer)

View file

@ -13,7 +13,7 @@ var WorldToTileY = function (worldY, snapToFloor, camera, layer)
{
if (snapToFloor === undefined) { snapToFloor = true; }
var tileHeight = layer.tileHeight;
var tileHeight = layer.baseTileHeight;
var tilemapLayer = layer.tilemapLayer;
if (tilemapLayer)

View file

@ -5,6 +5,7 @@ module.exports = {
CullTiles: require('./CullTiles'),
Fill: require('./Fill'),
FindByIndex: require('./FindByIndex'),
FindTile: require('./FindTile'),
FilterTiles: require('./FilterTiles'),
ForEachTile: require('./ForEachTile'),
GetTileAt: require('./GetTileAt'),
@ -34,6 +35,7 @@ module.exports = {
TileToWorldX: require('./TileToWorldX'),
TileToWorldXY: require('./TileToWorldXY'),
TileToWorldY: require('./TileToWorldY'),
WeightedRandomize: require('./WeightedRandomize'),
WorldToTileX: require('./WorldToTileX'),
WorldToTileXY: require('./WorldToTileXY'),
WorldToTileY: require('./WorldToTileY')

View file

@ -87,8 +87,6 @@ var DynamicTilemapLayer = new Class({
this.setSizeToFrame();
this.setOrigin();
this.setSize(this.layer.tileWidth * this.layer.width, this.layer.tileHeight * this.layer.height);
this.skipIndexZero = false;
},
/**
@ -183,6 +181,16 @@ var DynamicTilemapLayer = new Class({
return TilemapComponents.FindByIndex(findIndex, skip, reverse, this.layer);
},
/**
* See component documentation.
*
* @return {Tile|null}
*/
findTile: function (callback, context, tileX, tileY, width, height, filteringOptions)
{
return TilemapComponents.FindTile(callback, context, tileX, tileY, width, height, filteringOptions, this.layer);
},
/**
* See component documentation.
*
@ -455,6 +463,17 @@ var DynamicTilemapLayer = new Class({
return TilemapComponents.TileToWorldXY(tileX, tileY, point, camera, this.layer);
},
/**
* See component documentation.
*
* @return {this}
*/
weightedRandomize: function (tileX, tileY, width, height, weightedIndexes)
{
TilemapComponents.WeightedRandomize(tileX, tileY, width, height, weightedIndexes, this.layer);
return this;
},
/**
* See component documentation.
*

View file

@ -35,7 +35,7 @@ var DynamicTilemapLayerCanvasRenderer = function (renderer, gameObject, interpol
var halfHeight = tile.height / 2;
ctx.save();
ctx.translate(tile.worldX + halfWidth, tile.worldY + halfHeight);
ctx.translate(tile.pixelX + halfWidth, tile.pixelY + halfHeight);
if (tile.flipX || tile.flipY)
{

View file

@ -39,7 +39,7 @@ var DynamicTilemapLayerWebGLRenderer = function (renderer, gameObject, interpola
batch.addTileTextureRect(
texture,
x + tile.worldX * sx, y + tile.worldY * sy,
x + tile.pixelX * sx, y + tile.pixelY * sy,
tile.width * sx, tile.height * sy,
alpha * tile.alpha, tile.tint,
scrollFactorX, scrollFactorY,

View file

@ -26,8 +26,10 @@ var LayerData = new Class({
this.height = GetFastValue(config, 'height', 0);
this.tileWidth = GetFastValue(config, 'tileWidth', 0);
this.tileHeight = GetFastValue(config, 'tileHeight', 0);
this.widthInPixels = GetFastValue(config, 'widthInPixels', this.width * this.tileWidth);
this.heightInPixels = GetFastValue(config, 'heightInPixels', this.height * this.tileHeight);
this.baseTileWidth = GetFastValue(config, 'baseTileWidth', this.tileWidth);
this.baseTileHeight = GetFastValue(config, 'baseTileHeight', this.tileHeight);
this.widthInPixels = GetFastValue(config, 'widthInPixels', this.width * this.baseTileWidth);
this.heightInPixels = GetFastValue(config, 'heightInPixels', this.height * this.baseTileHeight);
this.alpha = GetFastValue(config, 'alpha', 1);
this.visible = GetFastValue(config, 'visible', true);
this.properties = GetFastValue(config, 'properties', {});

View file

@ -0,0 +1,55 @@
var Extend = require('../../../../utils/object/Extend');
var GetValue = require('../../../../utils/object/GetValue');
// Copy properties from tileset to tiles
var AssignTileProperties = function (mapData)
{
var layerData;
var tile;
var sid;
var set;
var row;
// go through each of the map data layers
for (var i = 0; i < mapData.layers.length; i++)
{
layerData = mapData.layers[i];
set = null;
// rows of tiles
for (var j = 0; j < layerData.data.length; j++)
{
row = layerData.data[j];
// individual tiles
for (var k = 0; k < row.length; k++)
{
tile = row[k];
if (tile === null || tile.index < 0)
{
continue;
}
// find the relevant tileset
sid = mapData.tiles[tile.index][2];
set = mapData.tilesets[sid];
// Ensure that a tile's size matches its tileset
tile.width = set.tileWidth;
tile.height = set.tileHeight;
// if that tile type has any properties, add them to the tile object
if (set.tileProperties && set.tileProperties[tile.index - set.firstgid])
{
tile.properties = Extend(
tile.properties, set.tileProperties[tile.index - set.firstgid]
);
}
}
}
}
};
module.exports = AssignTileProperties;

View file

@ -0,0 +1,52 @@
// Master list of tiles -> x, y, index in tileset
var BuildTilesetIndex = function (mapData)
{
var tiles = [];
for (var i = 0; i < mapData.tilesets.length; i++)
{
var set = mapData.tilesets[i];
var x = set.tileMargin;
var y = set.tileMargin;
var count = 0;
var countX = 0;
var countY = 0;
for (var t = set.firstgid; t < set.firstgid + set.total; t++)
{
// Can add extra properties here as needed
tiles[t] = [ x, y, i ];
x += set.tileWidth + set.tileSpacing;
count++;
if (count === set.total)
{
break;
}
countX++;
if (countX === set.columns)
{
x = set.tileMargin;
y += set.tileHeight + set.tileSpacing;
countX = 0;
countY++;
if (countY === set.rows)
{
break;
}
}
}
}
return tiles;
};
module.exports = BuildTilesetIndex;

View file

@ -0,0 +1,30 @@
var GetFastValue = require('../../../../utils/object/GetFastValue');
var ParseImageLayers = function (json)
{
var images = [];
for (var i = 0; i < json.layers.length; i++)
{
if (json.layers[i].type !== 'imagelayer')
{
continue;
}
var curi = json.layers[i];
images.push({
name: curi.name,
image: curi.image,
x: GetFastValue(curi, 'offsetx', 0) + curi.x,
y: GetFastValue(curi, 'offsety', 0) + curi.y,
alpha: curi.opacity,
visible: curi.visible,
properties: GetFastValue(curi, 'properties', {})
});
}
return images;
};
module.exports = ParseImageLayers;

View file

@ -0,0 +1,39 @@
var GetFastValue = require('../../../../utils/object/GetFastValue');
var ParseObject = require('./ParseObject');
// Objects & Collision Data (polylines, etc)
var ParseObjectLayers = function (json)
{
var objects = {};
var collision = {};
for (var i = 0; i < json.layers.length; i++)
{
if (json.layers[i].type !== 'objectgroup')
{
continue;
}
var curo = json.layers[i];
var layerName = curo.name;
var offsetX = GetFastValue(curo, 'offsetx', 0);
var offsetY = GetFastValue(curo, 'offsety', 0);
objects[layerName] = [];
collision[layerName] = [];
for (var j = 0; j < curo.objects.length; j++)
{
var parsedObject = ParseObject(curo.objects[j], offsetX, offsetY);
// Matching v2 where only polylines were added to collision prop of the map
if (parsedObject.polyline) { collision[layerName].push(parsedObject); }
objects[layerName].push(parsedObject);
}
}
return { objects: objects, collision: collision };
};
module.exports = ParseObjectLayers;

View file

@ -0,0 +1,104 @@
var Base64Decode = require('./Base64Decode');
var GetFastValue = require('../../../../utils/object/GetFastValue');
var LayerData = require('../../mapdata/LayerData');
var ParseGID = require('./ParseGID');
var Tile = require('../../Tile');
var ParseTileLayers = function (json, insertNull)
{
var tileLayers = [];
for (var i = 0; i < json.layers.length; i++)
{
if (json.layers[i].type !== 'tilelayer')
{
continue;
}
var curl = json.layers[i];
// Base64 decode data if necessary. NOTE: uncompressed base64 only.
if (curl.compression)
{
console.warn(
'TilemapParser.parseTiledJSON - Layer compression is unsupported, skipping layer \''
+ curl.name + '\''
);
continue;
}
else if (curl.encoding && curl.encoding === 'base64')
{
curl.data = Base64Decode(curl.data);
delete curl.encoding; // Allow the same map to be parsed multiple times
}
var layerData = new LayerData({
name: curl.name,
x: GetFastValue(curl, 'offsetx', 0) + curl.x,
y: GetFastValue(curl, 'offsety', 0) + curl.y,
width: curl.width,
height: curl.height,
tileWidth: json.tilewidth,
tileHeight: json.tileheight,
alpha: curl.opacity,
visible: curl.visible,
properties: GetFastValue(curl, 'properties', {})
});
var x = 0;
var row = [];
var output = [];
// Loop through the data field in the JSON.
// This is an array containing the tile indexes, one after the other. -1 = no tile,
// everything else = the tile index (starting at 1 for Tiled, 0 for CSV) If the map
// contains multiple tilesets then the indexes are relative to that which the set starts
// from. Need to set which tileset in the cache = which tileset in the JSON, if you do this
// manually it means you can use the same map data but a new tileset.
for (var t = 0, len = curl.data.length; t < len; t++)
{
var gidInfo = ParseGID(curl.data[t]);
// index, x, y, width, height
if (gidInfo.gid > 0)
{
var tile = new Tile(layerData, gidInfo.gid, x, output.length, json.tilewidth,
json.tileheight);
tile.rotation = gidInfo.rotation;
tile.flipped = gidInfo.flipped;
tile.flippedHorizontal = gidInfo.flippedHorizontal;
tile.flippedVertical = gidInfo.flippedVertical;
tile.flippedAntiDiagonal = gidInfo.flippedAntiDiagonal;
row.push(tile);
}
else
{
var blankTile = insertNull
? null
: new Tile(layerData, -1, x, output.length, json.tilewidth, json.tileheight);
row.push(blankTile);
}
x++;
if (x === curl.width)
{
output.push(row);
x = 0;
row = [];
}
}
layerData.data = output;
tileLayers.push(layerData);
}
return tileLayers;
};
module.exports = ParseTileLayers;

View file

@ -0,0 +1,84 @@
var Tileset = require('../../Tileset');
var ImageCollection = require('../../ImageCollection');
var ParseObject = require('./ParseObject');
// Tilesets & Image Collections
var ParseTilesets = function (json)
{
var tilesets = [];
var imageCollections = [];
var lastSet = null;
var stringID;
for (var i = 0; i < json.tilesets.length; i++)
{
// name, firstgid, width, height, margin, spacing, properties
var set = json.tilesets[i];
if (set.source)
{
console.warn('Phaser can\'t load external tilesets. Use the Embed Tileset button and then export the map again.');
}
else if (set.image)
{
var newSet = new Tileset(set.name, set.firstgid, set.tilewidth, set.tileheight, set.margin, set.spacing);
// Properties stored per-tile in object with string indexes starting at "0"
if (set.tileproperties)
{
newSet.tileProperties = set.tileproperties;
}
// Object & terrain shapes stored per-tile in object with string indexes starting at "0"
if (set.tiles)
{
newSet.tileData = set.tiles;
// Parse the objects into Phaser format to match handling of other Tiled objects
for (stringID in newSet.tileData)
{
var objectGroup = newSet.tileData[stringID].objectgroup;
if (objectGroup && objectGroup.objects)
{
var parsedObjects = objectGroup.objects.map(
function (obj) { return ParseObject(obj); }
);
newSet.tileData[stringID].objectgroup.objects = parsedObjects;
}
}
}
// For a normal sliced tileset the row/count/size information is computed when updated.
// This is done (again) after the image is set.
newSet.updateTileData(set.imagewidth, set.imageheight);
tilesets.push(newSet);
}
else
{
var newCollection = new ImageCollection(set.name, set.firstgid, set.tilewidth,
set.tileheight, set.margin, set.spacing, set.properties);
for (stringID in set.tiles)
{
var image = set.tiles[stringID].image;
var gid = set.firstgid + parseInt(stringID, 10);
newCollection.addImage(gid, image);
}
imageCollections.push(newCollection);
}
// We've got a new Tileset, so set the lastgid into the previous one
if (lastSet)
{
lastSet.lastgid = set.firstgid - 1;
}
lastSet = set;
}
return { tilesets: tilesets, imageCollections: imageCollections };
};
module.exports = ParseTilesets;

View file

@ -1,14 +1,11 @@
var Formats = require('../../Formats');
var Tileset = require('../../Tileset');
var Tile = require('../../Tile');
var Extend = require('../../../../utils/object/Extend');
var MapData = require('../../mapdata/MapData');
var LayerData = require('../../mapdata/LayerData');
var ImageCollection = require('../../ImageCollection');
var GetFastValue = require('../../../../utils/object/GetFastValue');
var ParseGID = require('./ParseGID');
var Base64Decode = require('./Base64Decode');
var ParseObject = require('./ParseObject');
var ParseTileLayers = require('./ParseTileLayers');
var ParseImageLayers = require('./ParseImageLayers');
var ParseTilesets = require('./ParseTilesets');
var ParseObjectLayers = require('./ParseObjectLayers');
var BuildTilesetIndex = require('./BuildTilesetIndex');
var AssignTileProperties = require('./AssignTileProperties');
/**
* Parses a Tiled JSON object into a new MapData object.
@ -43,315 +40,21 @@ var ParseJSONTiled = function (name, json, insertNull)
properties: json.properties
});
var tileLayers = [];
mapData.layers = ParseTileLayers(json, insertNull);
mapData.images = ParseImageLayers(json);
for (var i = 0; i < json.layers.length; i++)
{
if (json.layers[i].type !== 'tilelayer')
{
continue;
}
var sets = ParseTilesets(json);
mapData.tilesets = sets.tilesets;
mapData.imageCollections = sets.imageCollections;
var curl = json.layers[i];
var objs = ParseObjectLayers(json);
mapData.objects = objs.objects;
mapData.collision = objs.collision;
// Base64 decode data if necessary. NOTE: uncompressed base64 only.
if (curl.compression)
{
console.warn('TilemapParser.parseTiledJSON - Layer compression is unsupported, skipping layer \'' + curl.name + '\'');
continue;
}
else if (curl.encoding && curl.encoding === 'base64')
{
curl.data = Base64Decode(curl.data);
}
mapData.tiles = BuildTilesetIndex(mapData);
var layerData = new LayerData({
name: curl.name,
x: GetFastValue(curl, 'offsetx', 0) + curl.x,
y: GetFastValue(curl, 'offsety', 0) + curl.y,
width: curl.width,
height: curl.height,
tileWidth: json.tilewidth,
tileHeight: json.tileheight,
alpha: curl.opacity,
visible: curl.visible,
properties: GetFastValue(curl, 'properties', {})
});
AssignTileProperties(mapData);
var x = 0;
var row = [];
var output = [];
var gid;
// Loop through the data field in the JSON.
// This is an array containing the tile indexes, one after the other. -1 = no tile,
// everything else = the tile index (starting at 1 for Tiled, 0 for CSV) If the map
// contains multiple tilesets then the indexes are relative to that which the set starts
// from. Need to set which tileset in the cache = which tileset in the JSON, if you do this
// manually it means you can use the same map data but a new tileset.
for (var t = 0, len = curl.data.length; t < len; t++)
{
var gidInfo = ParseGID(curl.data[t]);
// index, x, y, width, height
if (gidInfo.gid > 0)
{
var tile = new Tile(layerData, gidInfo.gid, x, output.length, json.tilewidth, json.tileheight);
tile.rotation = gidInfo.rotation;
tile.flipped = gidInfo.flipped;
tile.flippedHorizontal = gidInfo.flippedHorizontal;
tile.flippedVertical = gidInfo.flippedVertical;
tile.flippedAntiDiagonal = gidInfo.flippedAntiDiagonal;
row.push(tile);
}
else
{
var blankTile = insertNull
? null
: new Tile(layerData, -1, x, output.length, json.tilewidth, json.tileheight);
row.push(blankTile);
}
x++;
if (x === curl.width)
{
output.push(row);
x = 0;
row = [];
}
}
layerData.data = output;
tileLayers.push(layerData);
}
mapData.layers = tileLayers;
var images = [];
for (var i = 0; i < json.layers.length; i++)
{
if (json.layers[i].type !== 'imagelayer')
{
continue;
}
var curi = json.layers[i];
images.push({
name: curi.name,
image: curi.image,
x: GetFastValue(curi, 'offsetx', 0) + curi.x,
y: GetFastValue(curi, 'offsety', 0) + curi.y,
alpha: curi.opacity,
visible: curi.visible,
properties: GetFastValue(curi, 'properties', {})
});
}
mapData.images = images;
// Tilesets & Image Collections
var tilesets = [];
var imageCollections = [];
var lastSet = null;
for (var i = 0; i < json.tilesets.length; i++)
{
// name, firstgid, width, height, margin, spacing, properties
var set = json.tilesets[i];
if (set.image)
{
var newSet = new Tileset(set.name, set.firstgid, set.tilewidth, set.tileheight, set.margin, set.spacing);
// Properties stored per-tile in object with string indexes starting at "0"
if (set.tileproperties)
{
newSet.tileProperties = set.tileproperties;
}
// Object & terrain shapes stored per-tile in object with string indexes starting at "0"
if (set.tiles)
{
newSet.tileData = set.tiles;
// Parse the objects into Phaser format to match handling of other Tiled objects
for (var stringID in newSet.tileData)
{
var objectGroup = newSet.tileData[stringID].objectgroup;
if (objectGroup && objectGroup.objects)
{
objectGroup.objects = objectGroup.objects.map(ParseObject);
}
}
}
// For a normal sliced tileset the row/count/size information is computed when updated.
// This is done (again) after the image is set.
newSet.updateTileData(set.imagewidth, set.imageheight);
tilesets.push(newSet);
}
else
{
var newCollection = new ImageCollection(set.name, set.firstgid, set.tilewidth, set.tileheight, set.margin, set.spacing, set.properties);
for (var stringID in set.tiles)
{
var image = set.tiles[stringID].image;
var gid = set.firstgid + parseInt(stringID, 10);
newCollection.addImage(gid, image);
}
imageCollections.push(newCollection);
}
// We've got a new Tileset, so set the lastgid into the previous one
if (lastSet)
{
lastSet.lastgid = set.firstgid - 1;
}
lastSet = set;
}
mapData.tilesets = tilesets;
mapData.imageCollections = imageCollections;
// Objects & Collision Data (polylines, etc)
var objects = {};
var collision = {};
for (var i = 0; i < json.layers.length; i++)
{
if (json.layers[i].type !== 'objectgroup')
{
continue;
}
var curo = json.layers[i];
var layerName = curo.name;
var offsetX = GetFastValue(curo, 'offsetx', 0);
var offsetY = GetFastValue(curo, 'offsety', 0);
objects[layerName] = [];
collision[layerName] = [];
for (var j = 0; j < curo.objects.length; j++)
{
var parsedObject = ParseObject(curo.objects[j], offsetX, offsetY);
// Matching v2 where only polylines were added to collision prop of the map
if (parsedObject.polyline) { collision[layerName].push(parsedObject); }
objects[layerName].push(parsedObject);
}
}
mapData.objects = objects;
mapData.collision = collision;
mapData.tiles = [];
// Finally lets build our super tileset index
for (var i = 0; i < mapData.tilesets.length; i++)
{
var set = mapData.tilesets[i];
var x = set.tileMargin;
var y = set.tileMargin;
var count = 0;
var countX = 0;
var countY = 0;
for (var t = set.firstgid; t < set.firstgid + set.total; t++)
{
// Can add extra properties here as needed
mapData.tiles[t] = [ x, y, i ];
x += set.tileWidth + set.tileSpacing;
count++;
if (count === set.total)
{
break;
}
countX++;
if (countX === set.columns)
{
x = set.tileMargin;
y += set.tileHeight + set.tileSpacing;
countX = 0;
countY++;
if (countY === set.rows)
{
break;
}
}
}
}
// assign tile properties
var layerData;
var tile;
var sid;
var set;
// go through each of the map data layers
for (var i = 0; i < mapData.layers.length; i++)
{
layerData = mapData.layers[i];
set = null;
// rows of tiles
for (var j = 0; j < layerData.data.length; j++)
{
row = layerData.data[j];
// individual tiles
for (var k = 0; k < row.length; k++)
{
tile = row[k];
if (tile === null || tile.index < 0)
{
continue;
}
// find the relevant tileset
sid = mapData.tiles[tile.index][2];
set = mapData.tilesets[sid];
// Ensure that a tile's size matches its tileset
tile.width = set.tileWidth;
tile.height = set.tileHeight;
// if that tile type has any properties, add them to the tile object
if (set.tileProperties && set.tileProperties[tile.index - set.firstgid])
{
tile.properties = Extend(tile.properties, set.tileProperties[tile.index - set.firstgid]);
}
}
}
}
return mapData;
};

View file

@ -97,8 +97,6 @@ var StaticTilemapLayer = new Class({
this.setOrigin();
this.setSize(this.layer.tileWidth * this.layer.width, this.layer.tileHeight * this.layer.height);
this.skipIndexZero = false;
scene.sys.game.renderer.addContextRestoredCallback(this.contextRestore.bind(this));
},
@ -166,10 +164,10 @@ var StaticTilemapLayer = new Class({
for (col = 0; col < mapWidth; ++col)
{
tile = mapData[row][col];
if (tile === null || (tile.index <= 0 && this.skipIndexZero)) { continue; }
if (tile === null || tile.index === -1) { continue; }
var tx = tile.worldX;
var ty = tile.worldY;
var tx = tile.pixelX;
var ty = tile.pixelY;
var txw = tx + tile.width;
var tyh = ty + tile.height;
@ -312,6 +310,16 @@ var StaticTilemapLayer = new Class({
return TilemapComponents.FindByIndex(findIndex, skip, reverse, this.layer);
},
/**
* See component documentation.
*
* @return {Tile|null}
*/
findTile: function (callback, context, tileX, tileY, width, height, filteringOptions)
{
return TilemapComponents.FindTile(callback, context, tileX, tileY, width, height, filteringOptions, this.layer);
},
/**
* See component documentation.
*

View file

@ -24,7 +24,7 @@ var StaticTilemapLayerCanvasRenderer = function (renderer, gameObject, interpola
ctx.rotate(gameObject.rotation);
ctx.scale(gameObject.scaleX, gameObject.scaleY);
ctx.scale(gameObject.flipX ? -1 : 1, gameObject.flipY ? -1 : 1);
renderer.setAlpha(gameObject.alpha);
ctx.globalAlpha = gameObject.alpha;
for (var index = 0; index < tileCount; ++index)
{
@ -37,7 +37,7 @@ var StaticTilemapLayerCanvasRenderer = function (renderer, gameObject, interpola
image,
tileTexCoords.x, tileTexCoords.y,
tile.width, tile.height,
tile.worldX, tile.worldY,
tile.pixelX, tile.pixelY,
tile.width, tile.height
);
}

View file

@ -17,11 +17,11 @@ var CircumferencePoint = function (ellipse, angle, out)
{
if (out === undefined) { out = new Point(); }
var a = ellipse.width / 2;
var b = ellipse.height / 2;
var halfWidth = ellipse.width / 2;
var halfHeight = ellipse.height / 2;
out.x = ellipse.x + a * Math.cos(angle);
out.y = ellipse.y + b * Math.sin(angle);
out.x = ellipse.x + halfWidth * Math.cos(angle);
out.y = ellipse.y + halfHeight * Math.sin(angle);
return out;
};

View file

@ -8,6 +8,7 @@ var Ellipse = new Class({
initialize:
// x/y = center of the ellipse
function Ellipse (x, y, width, height)
{
if (x === undefined) { x = 0; }
@ -100,21 +101,12 @@ var Ellipse = new Class({
get: function ()
{
return this.x;
return this.x - (this.width / 2);
},
set: function (value)
{
if (value >= this.right)
{
this.width = 0;
}
else
{
this.width = this.right - value;
}
this.x = value;
this.x = value + (this.width / 2);
}
},
@ -123,19 +115,12 @@ var Ellipse = new Class({
get: function ()
{
return this.x + this.width;
return this.x + (this.width / 2);
},
set: function (value)
{
if (value <= this.x)
{
this.width = 0;
}
else
{
this.width = value - this.x;
}
this.x = value - (this.width / 2);
}
},
@ -144,20 +129,12 @@ var Ellipse = new Class({
get: function ()
{
return this.y;
return this.y - (this.height / 2);
},
set: function (value)
{
if (value >= this.bottom)
{
this.height = 0;
this.y = value;
}
else
{
this.height = (this.bottom - value);
}
this.y = value + (this.height / 2);
}
},
@ -166,19 +143,12 @@ var Ellipse = new Class({
get: function ()
{
return this.y + this.height;
return this.y + (this.height / 2);
},
set: function (value)
{
if (value <= this.y)
{
this.height = 0;
}
else
{
this.height = value - this.y;
}
this.y = value - (this.height / 2);
}
}

View file

@ -12,6 +12,7 @@ var ArcadeImage = new Class({
Components.Bounce,
Components.Debug,
Components.Drag,
Components.Enable,
Components.Friction,
Components.Gravity,
Components.Immovable,

View file

@ -12,6 +12,7 @@ var ArcadeSprite = new Class({
Components.Bounce,
Components.Debug,
Components.Drag,
Components.Enable,
Components.Friction,
Components.Gravity,
Components.Immovable,

View file

@ -28,6 +28,7 @@ var PhysicsGroup = new Class({
config.createCallback = this.createCallback;
config.removeCallback = this.removeCallback;
config.classType = GetFastValue(config, 'classType', ArcadeSprite);
this.physicsType = CONST.DYNAMIC_BODY;

View file

@ -27,6 +27,8 @@ var StaticPhysicsGroup = new Class({
config.createCallback = this.createCallback;
config.removeCallback = this.removeCallback;
config.createMultipleCallback = this.createMultipleCallback;
config.classType = ArcadeSprite;
this.physicsType = CONST.STATIC_BODY;
@ -50,6 +52,11 @@ var StaticPhysicsGroup = new Class({
}
},
createMultipleCallback: function (entries)
{
this.refresh();
},
refresh: function ()
{
var children = this.children.entries;
@ -58,6 +65,8 @@ var StaticPhysicsGroup = new Class({
{
children[i].body.reset();
}
return this;
}
});

View file

@ -137,6 +137,11 @@ var World = new Class({
return object;
},
remove: function (object)
{
this.disableBody(object);
},
disable: function (object)
{
var i = 1;
@ -203,10 +208,30 @@ var World = new Class({
return graphic;
},
setBounds: function (x, y, width, height)
setBounds: function (x, y, width, height, checkLeft, checkRight, checkUp, checkDown)
{
this.bounds.setTo(x, y, width, height);
if (checkLeft !== undefined)
{
this.setBoundsCollision(checkLeft, checkRight, checkUp, checkDown);
}
return this;
},
setBoundsCollision: function (left, right, up, down)
{
if (left === undefined) { left = true; }
if (right === undefined) { right = true; }
if (up === undefined) { up = true; }
if (down === undefined) { down = true; }
this.checkCollision.left = left;
this.checkCollision.right = right;
this.checkCollision.up = up;
this.checkCollision.down = down;
return this;
},

View file

@ -0,0 +1,49 @@
var Enable = {
enableBody: function (reset, x, y, enableGameObject, showGameObject)
{
this.body.enable = true;
if (reset)
{
this.body.reset(x, y);
}
if (enableGameObject)
{
this.body.gameObject.active = true;
}
if (showGameObject)
{
this.body.gameObject.visible = true;
}
return this;
},
disableBody: function (disableGameObject, hideGameObject)
{
if (disableGameObject === undefined) { disableGameObject = false; }
if (hideGameObject === undefined) { hideGameObject = false; }
this.body.stop();
this.body.enable = false;
if (disableGameObject)
{
this.body.gameObject.active = false;
}
if (hideGameObject)
{
this.body.gameObject.visible = false;
}
return this;
}
};
module.exports = Enable;

View file

@ -2,6 +2,8 @@ var Immovable = {
setImmovable: function (value)
{
if (value === undefined) { value = true; }
this.body.immovable = value;
return this;

View file

@ -7,6 +7,7 @@ module.exports = {
Bounce: require('./Bounce'),
Debug: require('./Debug'),
Drag: require('./Drag'),
Enable: require('./Enable'),
Friction: require('./Friction'),
Gravity: require('./Gravity'),
Immovable: require('./Immovable'),

View file

@ -194,6 +194,11 @@ var World = new Class({
return body;
},
remove: function (object)
{
this.bodies.delete(object);
},
pause: function ()
{
this.enabled = false;

View file

@ -244,7 +244,9 @@ var World = new Class({
remove: function (object, deep)
{
MatterWorld.remove(this.localWorld, object, deep);
var body = (object.body) ? object.body : object;
Composite.removeBody(this.localWorld, body, deep);
return this;
},

View file

@ -13,10 +13,10 @@ var CollisionActiveEvent = new Class({
this.pairs = pairs;
if (pairs.length === 1)
if (pairs.pairs.length > 0)
{
this.bodyA = pairs[0].bodyA;
this.bodyB = pairs[0].bodyB;
this.bodyA = pairs.pairs[0].bodyA;
this.bodyB = pairs.pairs[0].bodyB;
}
}

View file

@ -13,10 +13,10 @@ var CollisionEndEvent = new Class({
this.pairs = pairs;
if (pairs.length === 1)
if (pairs.pairs.length > 0)
{
this.bodyA = pairs[0].bodyA;
this.bodyB = pairs[0].bodyB;
this.bodyA = pairs.pairs[0].bodyA;
this.bodyB = pairs.pairs[0].bodyB;
}
}

View file

@ -13,7 +13,7 @@ var CollisionStartEvent = new Class({
this.pairs = pairs;
if (pairs.length === 1)
if (pairs.length > 0)
{
this.bodyA = pairs[0].bodyA;
this.bodyB = pairs[0].bodyB;

View file

@ -80,9 +80,9 @@ var WebGLRenderer = new Class({
preserveDrawingBuffer: false,
WebGLContextOptions: {
alpha: false,
alpha: true,
antialias: true,
premultipliedAlpha: false,
premultipliedAlpha: true,
stencil: true,
preserveDrawingBuffer: false
}
@ -145,7 +145,6 @@ var WebGLRenderer = new Class({
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
// Map Blend Modes
this.blendModes = [];
for (var i = 0; i <= 16; i++)
@ -154,13 +153,13 @@ var WebGLRenderer = new Class({
}
// Add
this.blendModes[1].func = [ gl.SRC_ALPHA, gl.DST_ALPHA ];
this.blendModes[1].func = [ gl.ONE, gl.DST_ALPHA ];
// Multiply
this.blendModes[2].func = [ gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA ];
// Screen
this.blendModes[3].func = [ gl.SRC_ALPHA, gl.ONE ];
this.blendModes[3].func = [ gl.ONE, gl.ONE_MINUS_SRC_COLOR ];
this.blendMode = -1;
this.extensions = gl.getSupportedExtensions();
@ -550,12 +549,13 @@ var WebGLRenderer = new Class({
setBlendMode: function (newBlendMode)
{
var gl = this.gl;
if (newBlendMode === BlendModes.SKIP_CHECK)
{
return;
}
var gl = this.gl;
var renderer = this.currentRenderer;
if (this.blendMode !== newBlendMode)

View file

@ -19,7 +19,7 @@ module.exports = {
'varying float v_alpha;',
'void main() {',
' vec4 output_color = texture2D(u_sampler2D, v_tex_coord);',
' gl_FragColor = vec4(output_color.rgb * output_color.a, v_alpha * output_color.a);',
' gl_FragColor = vec4(output_color.rgb * v_alpha * output_color.a, v_alpha * output_color.a);',
'}'
].join('\n')
};

View file

@ -23,7 +23,7 @@ module.exports = {
'varying float v_alpha;',
'void main() {',
' vec4 sample_color = texture2D(u_sampler2D, v_tex_coord);',
' gl_FragColor = vec4((sample_color.rgb * v_color.rgb) * sample_color.a, sample_color.a * v_alpha);',
' gl_FragColor = vec4(sample_color.rgb * v_alpha * sample_color.a, v_alpha * sample_color.a);',
'}'
].join('\n')
};

View file

@ -62,6 +62,11 @@ var PhysicsManager = new Class({
}
},
remove: function (object)
{
this.world.remove(object);
},
update: function (time, delta)
{
this.world.update(time, delta);