mirror of
https://github.com/photonstorm/phaser
synced 2024-11-27 23:20:59 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
c253e01cac
44 changed files with 671 additions and 107 deletions
|
@ -3,8 +3,8 @@ var CalculateFacesWithin = require('./CalculateFacesWithin');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies the tiles in the source rectangular area to a new destination (all specified in tile
|
* Copies the tiles in the source rectangular area to a new destination (all specified in tile
|
||||||
* coordinates) within the layer. This copies all tile properties & recalculates interesting tile
|
* coordinates) within the layer. This copies all tile properties & recalculates collision
|
||||||
* faces in the destination region.
|
* information in the destination region.
|
||||||
*
|
*
|
||||||
* @param {number} srcTileX - [description]
|
* @param {number} srcTileX - [description]
|
||||||
* @param {number} srcTileY - [description]
|
* @param {number} srcTileY - [description]
|
||||||
|
@ -16,7 +16,6 @@ var CalculateFacesWithin = require('./CalculateFacesWithin');
|
||||||
* @param {boolean} [recalculateFaces=true] - [description]
|
* @param {boolean} [recalculateFaces=true] - [description]
|
||||||
* @param {LayerData} layer - [description]
|
* @param {LayerData} layer - [description]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var Copy = function (srcTileX, srcTileY, width, height, destTileX, destTileY, recalculateFaces, layer)
|
var Copy = function (srcTileX, srcTileY, width, height, destTileX, destTileY, recalculateFaces, layer)
|
||||||
{
|
{
|
||||||
if (srcTileX < 0) { srcTileX = 0; }
|
if (srcTileX < 0) { srcTileX = 0; }
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* internally.
|
* internally.
|
||||||
*
|
*
|
||||||
* @param {LayerData} layer - [description]
|
* @param {LayerData} layer - [description]
|
||||||
* @param {Camera} camera - [description]
|
* @param {Camera} [camera=main camera] - [description]
|
||||||
* @param {array} [outputArray] - [description]
|
* @param {array} [outputArray] - [description]
|
||||||
* @returns {array}
|
* @returns {array}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -4,13 +4,13 @@ var CalculateFacesWithin = require('./CalculateFacesWithin');
|
||||||
/**
|
/**
|
||||||
* Sets the tiles in the given rectangular area (in tile coordinates) of the layer with the
|
* Sets the tiles in the given rectangular area (in tile coordinates) of the layer with the
|
||||||
* specified index. Tiles will be set to collide if the given index is a colliding index.
|
* specified index. Tiles will be set to collide if the given index is a colliding index.
|
||||||
* Interesting tile faces in the region will be recalculated.
|
* Collision information in the region will be recalculated.
|
||||||
*
|
*
|
||||||
* @param {number} index - [description]
|
* @param {number} index - [description]
|
||||||
* @param {number} tileX - [description]
|
* @param {number} [tileX=0] - [description]
|
||||||
* @param {number} tileY - [description]
|
* @param {number} [tileY=0] - [description]
|
||||||
* @param {number} width - [description]
|
* @param {number} [width=max width based on tileX] - [description]
|
||||||
* @param {number} height - [description]
|
* @param {number} [height=max height based on tileY] - [description]
|
||||||
* @param {boolean} [recalculateFaces=true] - [description]
|
* @param {boolean} [recalculateFaces=true] - [description]
|
||||||
* @param {LayerData} layer - [description]
|
* @param {LayerData} layer - [description]
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
* @param {LayerData} layer - [description]
|
* @param {LayerData} layer - [description]
|
||||||
* @return {Tile|null} The first (or n skipped) tile with the matching index.
|
* @return {Tile|null} The first (or n skipped) tile with the matching index.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var FindByIndex = function (findIndex, skip, reverse, layer)
|
var FindByIndex = function (findIndex, skip, reverse, layer)
|
||||||
{
|
{
|
||||||
if (skip === undefined) { skip = 0; }
|
if (skip === undefined) { skip = 0; }
|
||||||
|
|
|
@ -1,26 +1,25 @@
|
||||||
var GetTilesWithin = require('./GetTilesWithin');
|
var GetTilesWithin = require('./GetTilesWithin');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For each tile in the given rectangular area (in tile coordinates) of the layer, run the given
|
* For each tile in the given rectangular area (in tile coordinates) of the layer, run the given
|
||||||
* callback.
|
* callback.
|
||||||
*
|
*
|
||||||
* @param {number} callback - The callback. Each tile in the given area will be passed to this
|
* @param {number} callback - The callback. Each tile in the given area will be passed to this
|
||||||
* callback as the first and only parameter.
|
* callback as the first and only parameter.
|
||||||
* @param {number} context - The context under which the callback should be run.
|
* @param {number} context - The context under which the callback should be run.
|
||||||
* @param {number} [tileX=0]
|
* @param {number} [tileX=0] - [description]
|
||||||
* @param {number} [tileY=0]
|
* @param {number} [tileY=0] - [description]
|
||||||
* @param {number} [width=max width based on tileX] - [description]
|
* @param {number} [width=max width based on tileX] - [description]
|
||||||
* @param {number} [height=max height based on tileY] - [description]
|
* @param {number} [height=max height based on tileY] - [description]
|
||||||
* @param {object} [filteringOptions] - Optional filters to apply when getting the tiles.
|
* @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
|
* @param {boolean} [filteringOptions.isNotEmpty=false] - If true, only return tiles that don't have
|
||||||
* -1 for an index.
|
* -1 for an index.
|
||||||
* @param {boolean} [filteringOptions.isColliding=false] - If true, only return tiles that collide on
|
* @param {boolean} [filteringOptions.isColliding=false] - If true, only return tiles that collide on
|
||||||
* at least one side.
|
* at least one side.
|
||||||
* @param {boolean} [filteringOptions.hasInterestingFace=false] - If true, only return tiles that
|
* @param {boolean} [filteringOptions.hasInterestingFace=false] - If true, only return tiles that
|
||||||
* have at least one interesting face.
|
* have at least one interesting face.
|
||||||
* @param {LayerData} layer - [description]
|
* @param {LayerData} layer - [description]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var ForEachTile = function (callback, context, tileX, tileY, width, height, filteringOptions, layer)
|
var ForEachTile = function (callback, context, tileX, tileY, width, height, filteringOptions, layer)
|
||||||
{
|
{
|
||||||
var tiles = GetTilesWithin(tileX, tileY, width, height, filteringOptions, layer);
|
var tiles = GetTilesWithin(tileX, tileY, width, height, filteringOptions, layer);
|
||||||
|
|
|
@ -1,5 +1,16 @@
|
||||||
var IsInLayerBounds = require('./IsInLayerBounds');
|
var IsInLayerBounds = require('./IsInLayerBounds');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a tile at the given tile coordinates from the given layer.
|
||||||
|
*
|
||||||
|
* @param {number} tileX - X position to get the tile from (given in tile units, not pixels)
|
||||||
|
* @param {number} tileY - Y position to get the tile from (given in tile units, not pixels)
|
||||||
|
* @param {boolean} [nonNull=false] - If true getTile won't return null for empty tiles, but a Tile
|
||||||
|
* object with an index of -1.
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
* @return {Tile} The tile at the given coordinates or null if no tile was found or the coordinates
|
||||||
|
* were invalid.
|
||||||
|
*/
|
||||||
var GetTileAt = function (tileX, tileY, nonNull, layer)
|
var GetTileAt = function (tileX, tileY, nonNull, layer)
|
||||||
{
|
{
|
||||||
if (nonNull === undefined) { nonNull = false; }
|
if (nonNull === undefined) { nonNull = false; }
|
||||||
|
|
|
@ -2,6 +2,18 @@ var GetTileAt = require('./GetTileAt');
|
||||||
var WorldToTileX = require('./WorldToTileX');
|
var WorldToTileX = require('./WorldToTileX');
|
||||||
var WorldToTileY = require('./WorldToTileY');
|
var WorldToTileY = require('./WorldToTileY');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a tile at the given world coordinates from the given layer.
|
||||||
|
*
|
||||||
|
* @param {number} worldX - X position to get the tile from (given in pixels)
|
||||||
|
* @param {number} worldY - Y position to get the tile from (given in pixels)
|
||||||
|
* @param {boolean} [nonNull=false] - If true, function won't return null for empty tiles, but a Tile
|
||||||
|
* object with an index of -1.
|
||||||
|
* @param {Camera} [camera=main camera] - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
* @return {Tile} The tile at the given coordinates or null if no tile was found or the coordinates
|
||||||
|
* were invalid.
|
||||||
|
*/
|
||||||
var GetTileAtWorldXY = function (worldX, worldY, nonNull, camera, layer)
|
var GetTileAtWorldXY = function (worldX, worldY, nonNull, camera, layer)
|
||||||
{
|
{
|
||||||
var tileX = WorldToTileX(worldX, true, camera, layer);
|
var tileX = WorldToTileX(worldX, true, camera, layer);
|
||||||
|
|
|
@ -2,14 +2,23 @@
|
||||||
|
|
||||||
var GetFastValue = require('../../../utils/object/GetFastValue');
|
var GetFastValue = require('../../../utils/object/GetFastValue');
|
||||||
|
|
||||||
// Get tiles within the rectangular area specified. Note: this clips the x, y, w & h to the map's
|
/**
|
||||||
// boundries.
|
* Gets the tiles in the given rectangular area (in tile coordinates) of the layer.
|
||||||
// Options:
|
*
|
||||||
// {
|
* @param {number} [tileX=0] - [description]
|
||||||
// isNotEmpty: false,
|
* @param {number} [tileY=0] - [description]
|
||||||
// isColliding: false,
|
* @param {number} [width=max width based on tileX] - [description]
|
||||||
// hasInterestingFace: false
|
* @param {number} [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 {array} Array of Tile objects.
|
||||||
|
*/
|
||||||
var GetTilesWithin = function (tileX, tileY, width, height, filteringOptions, layer)
|
var GetTilesWithin = function (tileX, tileY, width, height, filteringOptions, layer)
|
||||||
{
|
{
|
||||||
if (tileX === undefined) { tileX = 0; }
|
if (tileX === undefined) { tileX = 0; }
|
||||||
|
|
|
@ -13,9 +13,25 @@ var TriangleToRectangle = function (triangle, rect)
|
||||||
return Intersects.RectangleToTriangle(rect, triangle);
|
return Intersects.RectangleToTriangle(rect, triangle);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Circle, Line, Rect, Triangle in world coordinates.
|
|
||||||
// Note: Could possibly be optimized by copying the shape and shifting it into tilemapLayer
|
// Note: Could possibly be optimized by copying the shape and shifting it into tilemapLayer
|
||||||
// coordinates instead of shifting the tiles.
|
// coordinates instead of shifting the tiles.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the tiles that overlap with the given shape in the given layer. The shape must be a Circle,
|
||||||
|
* Line, Rectangle or Triangle. The shape should be in world coordinates.
|
||||||
|
*
|
||||||
|
* @param {Circle|Line|Rectangle|Triangle} shape - A shape in world (pixel) coordinates
|
||||||
|
* @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 {Camera} [camera=main camera] - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
* @return {array} Array of Tile objects.
|
||||||
|
*/
|
||||||
var GetTilesWithinShape = function (shape, filteringOptions, camera, layer)
|
var GetTilesWithinShape = function (shape, filteringOptions, camera, layer)
|
||||||
{
|
{
|
||||||
if (shape === undefined) { return []; }
|
if (shape === undefined) { return []; }
|
||||||
|
|
|
@ -2,6 +2,24 @@ var GetTilesWithin = require('./GetTilesWithin');
|
||||||
var WorldToTileX = require('./WorldToTileX');
|
var WorldToTileX = require('./WorldToTileX');
|
||||||
var WorldToTileY = require('./WorldToTileY');
|
var WorldToTileY = require('./WorldToTileY');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the tiles in the given rectangular area (in world coordinates) of the layer.
|
||||||
|
*
|
||||||
|
* @param {number} worldX - [description]
|
||||||
|
* @param {number} worldY - [description]
|
||||||
|
* @param {number} width - [description]
|
||||||
|
* @param {number} height - [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 {Camera} [camera=main camera] - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
* @return {array} Array of Tile objects.
|
||||||
|
*/
|
||||||
var GetTilesWithinWorldXY = function (worldX, worldY, width, height, filteringOptions, camera, layer)
|
var GetTilesWithinWorldXY = function (worldX, worldY, width, height, filteringOptions, camera, layer)
|
||||||
{
|
{
|
||||||
// Top left corner of the rect, rounded down to include partial tiles
|
// Top left corner of the rect, rounded down to include partial tiles
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
var IsInLayerBounds = require('./IsInLayerBounds');
|
var IsInLayerBounds = require('./IsInLayerBounds');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if there is a tile at the given location (in tile coordinates) in the given layer. Returns
|
||||||
|
* false if there is no tile or if the tile at that location has an index of -1.
|
||||||
|
*
|
||||||
|
* @param {number} tileX - [description]
|
||||||
|
* @param {number} tileY - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
var HasTileAt = function (tileX, tileY, layer)
|
var HasTileAt = function (tileX, tileY, layer)
|
||||||
{
|
{
|
||||||
if (IsInLayerBounds(tileX, tileY, layer))
|
if (IsInLayerBounds(tileX, tileY, layer))
|
||||||
|
|
|
@ -2,6 +2,16 @@ var HasTileAt = require('./HasTileAt');
|
||||||
var WorldToTileX = require('./WorldToTileX');
|
var WorldToTileX = require('./WorldToTileX');
|
||||||
var WorldToTileY = require('./WorldToTileY');
|
var WorldToTileY = require('./WorldToTileY');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if there is a tile at the given location (in world coordinates) in the given layer. Returns
|
||||||
|
* false if there is no tile or if the tile at that location has an index of -1.
|
||||||
|
*
|
||||||
|
* @param {number} worldX - [description]
|
||||||
|
* @param {number} worldY - [description]
|
||||||
|
* @param {Camera} [camera=main camera] - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
var HasTileAtWorldXY = function (worldX, worldY, camera, layer)
|
var HasTileAtWorldXY = function (worldX, worldY, camera, layer)
|
||||||
{
|
{
|
||||||
var tileX = WorldToTileX(worldX, true, camera, layer);
|
var tileX = WorldToTileX(worldX, true, camera, layer);
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/**
|
||||||
|
* Checks if the given tile coordinates are within the bounds of the layer.
|
||||||
|
*
|
||||||
|
* @param {number} tileX - [description]
|
||||||
|
* @param {number} tileY - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
var IsInLayerBounds = function (tileX, tileY, layer)
|
var IsInLayerBounds = function (tileX, tileY, layer)
|
||||||
{
|
{
|
||||||
return (tileX >= 0 && tileX < layer.width && tileY >= 0 && tileY < layer.height);
|
return (tileX >= 0 && tileX < layer.width && tileY >= 0 && tileY < layer.height);
|
||||||
|
|
|
@ -2,8 +2,19 @@ var Tile = require('../Tile');
|
||||||
var IsInLayerBounds = require('./IsInLayerBounds');
|
var IsInLayerBounds = require('./IsInLayerBounds');
|
||||||
var RecalculateFacesAt = require('./RecalculateFacesAt');
|
var RecalculateFacesAt = require('./RecalculateFacesAt');
|
||||||
|
|
||||||
// Put Phaser.Tile|number. Note: does not place a reference to tile, it copies the tile or creates a
|
/**
|
||||||
// new one.
|
* Puts a tile at the given tile coordinates in the specified layer. You can pass in either an index
|
||||||
|
* or a Tile object. If you pass in a Tile, all attributes will be copied over to the specified
|
||||||
|
* location. If you pass in an index, only the index at the specified location will be changed.
|
||||||
|
* Collision information will be recalculated at the specified location.
|
||||||
|
*
|
||||||
|
* @param {number|Tile} tile - The index of this tile to set or a Tile object.
|
||||||
|
* @param {number} tileX - [description]
|
||||||
|
* @param {number} tileY - [description]
|
||||||
|
* @param {boolean} [recalculateFaces=true] - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
* @return {Tile} The Tile object that was created or added to this map.
|
||||||
|
*/
|
||||||
var PutTileAt = function (tile, tileX, tileY, recalculateFaces, layer)
|
var PutTileAt = function (tile, tileX, tileY, recalculateFaces, layer)
|
||||||
{
|
{
|
||||||
if (!IsInLayerBounds(tileX, tileY, layer)) { return null; }
|
if (!IsInLayerBounds(tileX, tileY, layer)) { return null; }
|
||||||
|
@ -18,10 +29,7 @@ var PutTileAt = function (tile, tileX, tileY, recalculateFaces, layer)
|
||||||
{
|
{
|
||||||
layer.data[tileY][tileX] = new Tile(layer, tile.index, tileX, tileY, tile.width, tile.height);
|
layer.data[tileY][tileX] = new Tile(layer, tile.index, tileX, tileY, tile.width, tile.height);
|
||||||
}
|
}
|
||||||
else
|
layer.data[tileY][tileX].copy(tile);
|
||||||
{
|
|
||||||
layer.data[tileY][tileX].copy(tile);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,20 @@ var PutTileAt = require('./PutTileAt');
|
||||||
var WorldToTileX = require('./WorldToTileX');
|
var WorldToTileX = require('./WorldToTileX');
|
||||||
var WorldToTileY = require('./WorldToTileY');
|
var WorldToTileY = require('./WorldToTileY');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts a tile at the given world coordinates (pixels) in the specified layer. You can pass in either
|
||||||
|
* an index or a Tile object. If you pass in a Tile, all attributes will be copied over to the
|
||||||
|
* specified location. If you pass in an index, only the index at the specified location will be
|
||||||
|
* changed. Collision information will be recalculated at the specified location.
|
||||||
|
*
|
||||||
|
* @param {number|Tile} tile - The index of this tile to set or a Tile object.
|
||||||
|
* @param {number} worldX - [description]
|
||||||
|
* @param {number} worldY - [description]
|
||||||
|
* @param {boolean} [recalculateFaces=true] - [description]
|
||||||
|
* @param {Camera} [camera=main camera] - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
* @return {Tile} The Tile object that was created or added to this map.
|
||||||
|
*/
|
||||||
var PutTileAtWorldXY = function (tile, worldX, worldY, recalculateFaces, camera, layer)
|
var PutTileAtWorldXY = function (tile, worldX, worldY, recalculateFaces, camera, layer)
|
||||||
{
|
{
|
||||||
var tileX = WorldToTileX(worldX, true, camera, layer);
|
var tileX = WorldToTileX(worldX, true, camera, layer);
|
||||||
|
|
|
@ -1,7 +1,20 @@
|
||||||
var GetTilesWithin = require('./GetTilesWithin');
|
var GetTilesWithin = require('./GetTilesWithin');
|
||||||
var GetRandomElement = require('../../../utils/array/GetRandomElement');
|
var GetRandomElement = require('../../../utils/array/GetRandomElement');
|
||||||
|
|
||||||
// Randomizes indices, not other properties. Does not modify collisions. Matches v2 functionality.
|
/**
|
||||||
|
* Randomizes the indices of a rectangular region of tiles (in tile coordinates) within the
|
||||||
|
* specified layer. Each tile will recieve a new index. If an array of indices is passed in, then
|
||||||
|
* those will be used for randomly assigning new tile indices. If an array is not provided, the
|
||||||
|
* indices found within the region (excluding -1) will be used for randomly assigning new tile
|
||||||
|
* indices. This method only modifies tile indexes and does not change collision information.
|
||||||
|
*
|
||||||
|
* @param {number} [tileX=0] - [description]
|
||||||
|
* @param {number} [tileY=0] - [description]
|
||||||
|
* @param {number} [width=max width based on tileX] - [description]
|
||||||
|
* @param {number} [height=max height based on tileY] - [description]
|
||||||
|
* @param {array} [indices] - An array of indices to randomly draw from during randomization.
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
*/
|
||||||
var Randomize = function (tileX, tileY, width, height, indices, layer)
|
var Randomize = function (tileX, tileY, width, height, indices, layer)
|
||||||
{
|
{
|
||||||
var i;
|
var i;
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
var GetTileAt = require('./GetTileAt');
|
var GetTileAt = require('./GetTileAt');
|
||||||
|
|
||||||
// Recalculate the faces, assuming only one tile location has been changed
|
/**
|
||||||
// Used internally to update faces quickly for PutTileAt/RemoveTileAt/etc. Alternate approach to
|
* Calculates interesting faces at the given tile coordinates of the specified layer. Interesting
|
||||||
// 951.
|
* faces are used internally for optimizing collisions against tiles. This method is mostly used
|
||||||
|
* internally to optimize recalculating faces when only one tile has been changed.
|
||||||
|
*
|
||||||
|
* @param {number} tileX - [description]
|
||||||
|
* @param {number} tileY - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
*/
|
||||||
var RecalculateFacesAt = function (tileX, tileY, layer)
|
var RecalculateFacesAt = function (tileX, tileY, layer)
|
||||||
{
|
{
|
||||||
var tile = GetTileAt(tileX, tileY, true, layer);
|
var tile = GetTileAt(tileX, tileY, true, layer);
|
||||||
|
|
|
@ -2,7 +2,19 @@ var Tile = require('../Tile');
|
||||||
var IsInLayerBounds = require('./IsInLayerBounds');
|
var IsInLayerBounds = require('./IsInLayerBounds');
|
||||||
var RecalculateFacesAt = require('./RecalculateFacesAt');
|
var RecalculateFacesAt = require('./RecalculateFacesAt');
|
||||||
|
|
||||||
// Remove and return Tile with option for placing a -1 index tile or null.
|
/**
|
||||||
|
* Removes the tile at the given tile coordinates in the specified layer and updates the layer's
|
||||||
|
* collision information.
|
||||||
|
*
|
||||||
|
* @param {number|Tile} tile - The index of this tile to set or a Tile object.
|
||||||
|
* @param {number} tileX - [description]
|
||||||
|
* @param {number} tileY - [description]
|
||||||
|
* @param {boolean} [replaceWithNull=true] - If true, this will replace the tile at the specified
|
||||||
|
* location with null instead of a Tile with an index of -1.
|
||||||
|
* @param {boolean} [recalculateFaces=true] - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
* @return {Tile} The Tile object that was removed.
|
||||||
|
*/
|
||||||
var RemoveTileAt = function (tileX, tileY, replaceWithNull, recalculateFaces, layer)
|
var RemoveTileAt = function (tileX, tileY, replaceWithNull, recalculateFaces, layer)
|
||||||
{
|
{
|
||||||
if (replaceWithNull === undefined) { replaceWithNull = false; }
|
if (replaceWithNull === undefined) { replaceWithNull = false; }
|
||||||
|
|
|
@ -2,6 +2,20 @@ var RemoveTileAt = require('./RemoveTileAt');
|
||||||
var WorldToTileX = require('./WorldToTileX');
|
var WorldToTileX = require('./WorldToTileX');
|
||||||
var WorldToTileY = require('./WorldToTileY');
|
var WorldToTileY = require('./WorldToTileY');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the tile at the given world coordinates in the specified layer and updates the layer's
|
||||||
|
* collision information.
|
||||||
|
*
|
||||||
|
* @param {number|Tile} tile - The index of this tile to set or a Tile object.
|
||||||
|
* @param {number} worldX - [description]
|
||||||
|
* @param {number} worldY - [description]
|
||||||
|
* @param {boolean} [replaceWithNull=true] - If true, this will replace the tile at the specified
|
||||||
|
* location with null instead of a Tile with an index of -1.
|
||||||
|
* @param {boolean} [recalculateFaces=true] - [description]
|
||||||
|
* @param {Camera} [camera=main camera] - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
* @return {Tile} The Tile object that was removed.
|
||||||
|
*/
|
||||||
var RemoveTileAtWorldXY = function (worldX, worldY, replaceWithNull, recalculateFaces, camera, layer)
|
var RemoveTileAtWorldXY = function (worldX, worldY, replaceWithNull, recalculateFaces, camera, layer)
|
||||||
{
|
{
|
||||||
var tileX = WorldToTileX(worldX, true, camera, layer);
|
var tileX = WorldToTileX(worldX, true, camera, layer);
|
||||||
|
|
|
@ -1,6 +1,18 @@
|
||||||
var GetTilesWithin = require('./GetTilesWithin');
|
var GetTilesWithin = require('./GetTilesWithin');
|
||||||
|
|
||||||
// Replaces indices, not other properties. Does not modify collisions. Matches v2 functionality.
|
/**
|
||||||
|
* Scans the given rectangular area (given in tile coordinates) for tiles with an index matching
|
||||||
|
* `findIndex` and updates their index to match `newIndex`. This only modifies the index and does
|
||||||
|
* not change collision information.
|
||||||
|
*
|
||||||
|
* @param {number} findIndex - [description]
|
||||||
|
* @param {number} newIndex - [description]
|
||||||
|
* @param {number} [tileX=0] - [description]
|
||||||
|
* @param {number} [tileY=0] - [description]
|
||||||
|
* @param {number} [width=max width based on tileX] - [description]
|
||||||
|
* @param {number} [height=max height based on tileY] - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
*/
|
||||||
var ReplaceByIndex = function (findIndex, newIndex, tileX, tileY, width, height, layer)
|
var ReplaceByIndex = function (findIndex, newIndex, tileX, tileY, width, height, layer)
|
||||||
{
|
{
|
||||||
var tiles = GetTilesWithin(tileX, tileY, width, height, null, layer);
|
var tiles = GetTilesWithin(tileX, tileY, width, height, null, layer);
|
||||||
|
|
|
@ -2,6 +2,18 @@ var SetTileCollision = require('./SetTileCollision');
|
||||||
var CalculateFacesWithin = require('./CalculateFacesWithin');
|
var CalculateFacesWithin = require('./CalculateFacesWithin');
|
||||||
var SetLayerCollisionIndex = require('./SetLayerCollisionIndex');
|
var SetLayerCollisionIndex = require('./SetLayerCollisionIndex');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets collision on the given tile or tiles within a layer by index. You can pass in either a
|
||||||
|
* single numeric index or an array of indexes: [2, 3, 15, 20]. The `collides` parameter controls if
|
||||||
|
* collision will be enabled (true) or disabled (false).
|
||||||
|
*
|
||||||
|
* @param {number|array} indexes - Either a single tile index, or an array of tile indexes.
|
||||||
|
* @param {boolean} [collides=true] - If true it will enable collision. If false it will clear
|
||||||
|
* collision.
|
||||||
|
* @param {boolean} [recalculateFaces=true] - Whether or not to recalculate the tile faces after the
|
||||||
|
* update.
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
*/
|
||||||
var SetCollision = function (indexes, collides, recalculateFaces, layer)
|
var SetCollision = function (indexes, collides, recalculateFaces, layer)
|
||||||
{
|
{
|
||||||
if (collides === undefined) { collides = true; }
|
if (collides === undefined) { collides = true; }
|
||||||
|
|
|
@ -2,6 +2,20 @@ var SetTileCollision = require('./SetTileCollision');
|
||||||
var CalculateFacesWithin = require('./CalculateFacesWithin');
|
var CalculateFacesWithin = require('./CalculateFacesWithin');
|
||||||
var SetLayerCollisionIndex = require('./SetLayerCollisionIndex');
|
var SetLayerCollisionIndex = require('./SetLayerCollisionIndex');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets collision on a range of tiles in a layer whose index is between the specified `start` and
|
||||||
|
* `stop` (inclusive). Calling this with a start value of 10 and a stop value of 14 would set
|
||||||
|
* collision for tiles 10, 11, 12, 13 and 14. The `collides` parameter controls if collision will be
|
||||||
|
* enabled (true) or disabled (false).
|
||||||
|
*
|
||||||
|
* @param {number} start - The first index of the tile to be set for collision.
|
||||||
|
* @param {number} stop - The last index of the tile to be set for collision.
|
||||||
|
* @param {boolean} [collides=true] - If true it will enable collision. If false it will clear
|
||||||
|
* collision.
|
||||||
|
* @param {boolean} [recalculateFaces=true] - Whether or not to recalculate the tile faces after the
|
||||||
|
* update.
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
*/
|
||||||
var SetCollisionBetween = function (start, stop, collides, recalculateFaces, layer)
|
var SetCollisionBetween = function (start, stop, collides, recalculateFaces, layer)
|
||||||
{
|
{
|
||||||
if (collides === undefined) { collides = true; }
|
if (collides === undefined) { collides = true; }
|
||||||
|
|
|
@ -2,13 +2,25 @@ var SetTileCollision = require('./SetTileCollision');
|
||||||
var CalculateFacesWithin = require('./CalculateFacesWithin');
|
var CalculateFacesWithin = require('./CalculateFacesWithin');
|
||||||
var SetLayerCollisionIndex = require('./SetLayerCollisionIndex');
|
var SetLayerCollisionIndex = require('./SetLayerCollisionIndex');
|
||||||
|
|
||||||
// Note: this only updates layer.collideIndexes for tile indexes found currently in the layer
|
/**
|
||||||
|
* Sets collision on all tiles in the given layer, except for tiles that have an index specified in
|
||||||
|
* the given array. The `collides` parameter controls if collision will be enabled (true) or
|
||||||
|
* disabled (false).
|
||||||
|
*
|
||||||
|
* @param {array} indexes - An array of the tile indexes to not be counted for collision.
|
||||||
|
* @param {boolean} [collides=true] - If true it will enable collision. If false it will clear
|
||||||
|
* collision.
|
||||||
|
* @param {boolean} [recalculateFaces=true] - Whether or not to recalculate the tile faces after the
|
||||||
|
* update.
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
*/
|
||||||
var SetCollisionByExclusion = function (indexes, collides, recalculateFaces, layer)
|
var SetCollisionByExclusion = function (indexes, collides, recalculateFaces, layer)
|
||||||
{
|
{
|
||||||
if (collides === undefined) { collides = true; }
|
if (collides === undefined) { collides = true; }
|
||||||
if (recalculateFaces === undefined) { recalculateFaces = true; }
|
if (recalculateFaces === undefined) { recalculateFaces = true; }
|
||||||
if (!Array.isArray(indexes)) { indexes = [ indexes ]; }
|
if (!Array.isArray(indexes)) { indexes = [ indexes ]; }
|
||||||
|
|
||||||
|
// Note: this only updates layer.collideIndexes for tile indexes found currently in the layer
|
||||||
for (var ty = 0; ty < layer.height; ty++)
|
for (var ty = 0; ty < layer.height; ty++)
|
||||||
{
|
{
|
||||||
for (var tx = 0; tx < layer.width; tx++)
|
for (var tx = 0; tx < layer.width; tx++)
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
// Internal method
|
/**
|
||||||
// Update layer.collideIndexes to either contain or not contain tileIndex
|
* Internally used method to keep track of the tile indexes that collide within a layer. This
|
||||||
|
* updates LayerData.collideIndexes to either contain or not contain the given `tileIndex`.
|
||||||
|
*
|
||||||
|
* @param {number} tileIndex - [description]
|
||||||
|
* @param {boolean} [collides=true] - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
*/
|
||||||
var SetLayerCollisionIndex = function (tileIndex, collides, layer)
|
var SetLayerCollisionIndex = function (tileIndex, collides, layer)
|
||||||
{
|
{
|
||||||
var loc = layer.collideIndexes.indexOf(tileIndex);
|
var loc = layer.collideIndexes.indexOf(tileIndex);
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
/**
|
||||||
|
* Internally used method to set the colliding state of a tile.
|
||||||
|
*
|
||||||
|
* @param {Tile} tile - [description]
|
||||||
|
* @param {boolean} [collides=true] - [description]
|
||||||
|
*/
|
||||||
var SetTileCollision = function (tile, collides)
|
var SetTileCollision = function (tile, collides)
|
||||||
{
|
{
|
||||||
if (collides)
|
if (collides)
|
||||||
|
|
|
@ -1,7 +1,18 @@
|
||||||
var GetTilesWithin = require('./GetTilesWithin');
|
var GetTilesWithin = require('./GetTilesWithin');
|
||||||
var ShuffleArray = require('../../../utils/array/Shuffle');
|
var ShuffleArray = require('../../../utils/array/Shuffle');
|
||||||
|
|
||||||
// Shuffles indices, not other properties. Does not modify collisions. Matches v2 functionality.
|
/**
|
||||||
|
* Shuffles the tiles in a rectangular region (specified in tile coordinates) within the given
|
||||||
|
* layer. It will only randomize the tiles in that area, so if they're all the same nothing will
|
||||||
|
* appear to have changed! This method only modifies tile indexes and does not change collision
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* @param {number} [tileX=0] - [description]
|
||||||
|
* @param {number} [tileY=0] - [description]
|
||||||
|
* @param {number} [width=max width based on tileX] - [description]
|
||||||
|
* @param {number} [height=max height based on tileY] - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
*/
|
||||||
var Shuffle = function (tileX, tileY, width, height, layer)
|
var Shuffle = function (tileX, tileY, width, height, layer)
|
||||||
{
|
{
|
||||||
var tiles = GetTilesWithin(tileX, tileY, width, height, null, layer);
|
var tiles = GetTilesWithin(tileX, tileY, width, height, null, layer);
|
||||||
|
|
|
@ -1,6 +1,18 @@
|
||||||
var GetTilesWithin = require('./GetTilesWithin');
|
var GetTilesWithin = require('./GetTilesWithin');
|
||||||
|
|
||||||
// Swaps indices, not other properties. Does not modify collisions. Matches v2 functionality.
|
/**
|
||||||
|
* Scans the given rectangular area (given in tile coordinates) for tiles with an index matching
|
||||||
|
* `indexA` and swaps then with `indexB`. This only modifies the index and does not change collision
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* @param {number} tileA - First tile index.
|
||||||
|
* @param {number} tileB - Second tile index.
|
||||||
|
* @param {number} [tileX=0] - [description]
|
||||||
|
* @param {number} [tileY=0] - [description]
|
||||||
|
* @param {number} [width=max width based on tileX] - [description]
|
||||||
|
* @param {number} [height=max height based on tileY] - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
*/
|
||||||
var SwapByIndex = function (indexA, indexB, tileX, tileY, width, height, layer)
|
var SwapByIndex = function (indexA, indexB, tileX, tileY, width, height, layer)
|
||||||
{
|
{
|
||||||
var tiles = GetTilesWithin(tileX, tileY, width, height, null, layer);
|
var tiles = GetTilesWithin(tileX, tileY, width, height, null, layer);
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
/**
|
||||||
|
* Internally used method to convert from tile X coordinates to world X coordinates, factoring in
|
||||||
|
* layer position, scale and scroll.
|
||||||
|
*
|
||||||
|
* @param {number} tileX - [description]
|
||||||
|
* @param {Camera} [camera=main camera] - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
var TileToWorldX = function (tileX, camera, layer)
|
var TileToWorldX = function (tileX, camera, layer)
|
||||||
{
|
{
|
||||||
var tileWidth = layer.tileWidth;
|
var tileWidth = layer.tileWidth;
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
/**
|
||||||
|
* Internally used method to convert from tile Y coordinates to world Y coordinates, factoring in
|
||||||
|
* layer position, scale and scroll.
|
||||||
|
*
|
||||||
|
* @param {number} tileY - [description]
|
||||||
|
* @param {Camera} [camera=main camera] - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
var TileToWorldY = function (tileY, camera, layer)
|
var TileToWorldY = function (tileY, camera, layer)
|
||||||
{
|
{
|
||||||
var tileHeight = layer.tileHeight;
|
var tileHeight = layer.tileHeight;
|
||||||
|
|
|
@ -1,3 +1,14 @@
|
||||||
|
/**
|
||||||
|
* Converts from world X coordinates (pixels) to tile X coordinates (tile units), factoring in the
|
||||||
|
* layer's position, scale and scroll.
|
||||||
|
*
|
||||||
|
* @param {number} worldX - [description]
|
||||||
|
* @param {boolean} [snapToFloor=true] - Whether or not to round the tile coordinate down to the
|
||||||
|
* nearest integer.
|
||||||
|
* @param {Camera} [camera=main camera] - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
* @returns {number} The X location in tile units.
|
||||||
|
*/
|
||||||
var WorldToTileX = function (worldX, snapToFloor, camera, layer)
|
var WorldToTileX = function (worldX, snapToFloor, camera, layer)
|
||||||
{
|
{
|
||||||
if (snapToFloor === undefined) { snapToFloor = true; }
|
if (snapToFloor === undefined) { snapToFloor = true; }
|
||||||
|
|
|
@ -2,6 +2,20 @@ var WorldToTileX = require('./WorldToTileX');
|
||||||
var WorldToTileY = require('./WorldToTileY');
|
var WorldToTileY = require('./WorldToTileY');
|
||||||
var Vector2 = require('../../../math/Vector2');
|
var Vector2 = require('../../../math/Vector2');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts from world XY coordinates (pixels) to tile XY coordinates (tile units), factoring in the
|
||||||
|
* layer's position, scale and scroll. This will return a new Vector2 object or update the given
|
||||||
|
* `point` object.
|
||||||
|
*
|
||||||
|
* @param {number} worldX - [description]
|
||||||
|
* @param {number} worldY - [description]
|
||||||
|
* @param {boolean} [snapToFloor=true] - Whether or not to round the tile coordinate down to the
|
||||||
|
* nearest integer.
|
||||||
|
* @param {Vector2} [point] - [description]
|
||||||
|
* @param {Camera} [camera=main camera] - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
* @returns {Vector2} The XY location in tile units.
|
||||||
|
*/
|
||||||
var WorldToTileXY = function (worldX, worldY, snapToFloor, point, camera, layer)
|
var WorldToTileXY = function (worldX, worldY, snapToFloor, point, camera, layer)
|
||||||
{
|
{
|
||||||
if (point === undefined) { point = new Vector2(0, 0); }
|
if (point === undefined) { point = new Vector2(0, 0); }
|
||||||
|
|
|
@ -1,3 +1,14 @@
|
||||||
|
/**
|
||||||
|
* Converts from world Y coordinates (pixels) to tile Y coordinates (tile units), factoring in the
|
||||||
|
* layer's position, scale and scroll.
|
||||||
|
*
|
||||||
|
* @param {number} worldY - [description]
|
||||||
|
* @param {boolean} [snapToFloor=true] - Whether or not to round the tile coordinate down to the
|
||||||
|
* nearest integer.
|
||||||
|
* @param {Camera} [camera=main camera] - [description]
|
||||||
|
* @param {LayerData} layer - [description]
|
||||||
|
* @returns {number} The Y location in tile units.
|
||||||
|
*/
|
||||||
var WorldToTileY = function (worldY, snapToFloor, camera, layer)
|
var WorldToTileY = function (worldY, snapToFloor, camera, layer)
|
||||||
{
|
{
|
||||||
if (snapToFloor === undefined) { snapToFloor = true; }
|
if (snapToFloor === undefined) { snapToFloor = true; }
|
||||||
|
|
|
@ -5,7 +5,17 @@ var LayerData = new Class({
|
||||||
|
|
||||||
initialize:
|
initialize:
|
||||||
|
|
||||||
function MapLayerData (config)
|
/**
|
||||||
|
* A class for representing data about about a layer in a map. Maps are parsed from CSV, Tiled,
|
||||||
|
* etc. into this format. Tilemap, StaticTilemapLayer and DynamicTilemapLayer have a reference
|
||||||
|
* to this data and use it to look up and perform operations on tiles.
|
||||||
|
*
|
||||||
|
* @class LayerData
|
||||||
|
* @constructor
|
||||||
|
*
|
||||||
|
* @param {object} [config] - [description]
|
||||||
|
*/
|
||||||
|
function LayerData (config)
|
||||||
{
|
{
|
||||||
if (config === undefined) { config = {}; }
|
if (config === undefined) { config = {}; }
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,16 @@ var MapData = new Class({
|
||||||
|
|
||||||
initialize:
|
initialize:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class for representing data about a map. Maps are parsed from CSV, Tiled, etc. into this
|
||||||
|
* format. A Tilemap object get a copy of this data and then unpacks the needed properties into
|
||||||
|
* itself.
|
||||||
|
*
|
||||||
|
* @class MapData
|
||||||
|
* @constructor
|
||||||
|
*
|
||||||
|
* @param {object} [config] - [description]
|
||||||
|
*/
|
||||||
function MapData (config)
|
function MapData (config)
|
||||||
{
|
{
|
||||||
if (config === undefined) { config = {}; }
|
if (config === undefined) { config = {}; }
|
||||||
|
|
|
@ -4,20 +4,34 @@ var ParseCSV = require('./ParseCSV');
|
||||||
var ParseTiledJSON = require('./parsetiledjson/');
|
var ParseTiledJSON = require('./parsetiledjson/');
|
||||||
var Formats = require('../Formats');
|
var Formats = require('../Formats');
|
||||||
|
|
||||||
var Parse = function (key, mapFormat, mapData, tileWidth, tileHeight, insertNull)
|
/**
|
||||||
|
* Parses raw data of a given Tilemap format into a new MapData object.
|
||||||
|
*
|
||||||
|
* @param {string} name - The name of the tilemap, used to set the name on the MapData.
|
||||||
|
* @param {number} mapFormat - See ../Formats.js.
|
||||||
|
* @param {array|string|object} data - 2D array, CSV string or Tiled JSON object
|
||||||
|
* @param {number} tileWidth - Required for 2D array and CSV, but ignored for Tiled JSON.
|
||||||
|
* @param {number} tileHeight - Required for 2D array and CSV, but ignored for Tiled JSON.
|
||||||
|
* @param {boolean} [insertNull=false] - If true, instead of placing empty tiles at locations where
|
||||||
|
* the tile index is -1, this will place null. If you've a large sparsely populated map and the tile
|
||||||
|
* data doesn't need to change then setting this value to `true` will help with memory consumption.
|
||||||
|
* However if your map is small, or you need to update the tiles (perhaps the map dynamically
|
||||||
|
* changes during the game) then leave the default value set.
|
||||||
|
*/
|
||||||
|
var Parse = function (name, mapFormat, data, tileWidth, tileHeight, insertNull)
|
||||||
{
|
{
|
||||||
var newMap;
|
var newMap;
|
||||||
|
|
||||||
switch(mapFormat)
|
switch(mapFormat)
|
||||||
{
|
{
|
||||||
case (Formats.TILEMAP_2D_ARRAY):
|
case (Formats.TILEMAP_2D_ARRAY):
|
||||||
newMap = Parse2DArray(key, mapData, tileWidth, tileHeight, insertNull);
|
newMap = Parse2DArray(name, data, tileWidth, tileHeight, insertNull);
|
||||||
break;
|
break;
|
||||||
case (Formats.TILEMAP_CSV):
|
case (Formats.TILEMAP_CSV):
|
||||||
newMap = ParseCSV(key, mapData, tileWidth, tileHeight, insertNull);
|
newMap = ParseCSV(name, data, tileWidth, tileHeight, insertNull);
|
||||||
break;
|
break;
|
||||||
case (Formats.TILEMAP_TILED_JSON):
|
case (Formats.TILEMAP_TILED_JSON):
|
||||||
newMap = ParseTiledJSON(key, mapData, insertNull);
|
newMap = ParseTiledJSON(name, data, insertNull);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.warn('Unrecognized tilemap data format: ' + mapFormat);
|
console.warn('Unrecognized tilemap data format: ' + mapFormat);
|
||||||
|
|
|
@ -18,6 +18,7 @@ var MatterImage = new Class({
|
||||||
Components.Gravity,
|
Components.Gravity,
|
||||||
Components.Mass,
|
Components.Mass,
|
||||||
Components.Sensor,
|
Components.Sensor,
|
||||||
|
Components.SetBody,
|
||||||
Components.Sleep,
|
Components.Sleep,
|
||||||
Components.Static,
|
Components.Static,
|
||||||
Components.Transform,
|
Components.Transform,
|
||||||
|
@ -35,28 +36,26 @@ var MatterImage = new Class({
|
||||||
this.setSizeToFrame();
|
this.setSizeToFrame();
|
||||||
this.setOrigin();
|
this.setOrigin();
|
||||||
|
|
||||||
this._tempVec2 = new Vector2();
|
this.world = world;
|
||||||
|
|
||||||
var isCircle = GetFastValue(options, 'isCircle', false);
|
this._tempVec2 = new Vector2(x, y);
|
||||||
|
|
||||||
if (isCircle)
|
var shape = GetFastValue(options, 'shape', null);
|
||||||
|
|
||||||
|
if (!shape)
|
||||||
{
|
{
|
||||||
var radius = GetFastValue(options, 'radius', Math.max(this.width, this.height) / 2);
|
this.body = Bodies.rectangle(x, y, this.width, this.height, options);
|
||||||
|
|
||||||
this.body = Bodies.circle(x, y, radius, options);
|
this.body.gameObject = this;
|
||||||
|
|
||||||
|
if (GetFastValue(options, 'addToWorld', true))
|
||||||
|
{
|
||||||
|
world.add(this.body);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.body = Bodies.rectangle(x, y, this.width, this.height, options);
|
this.setBody(shape, options);
|
||||||
}
|
|
||||||
|
|
||||||
this.body.gameObject = this;
|
|
||||||
|
|
||||||
this.world = world;
|
|
||||||
|
|
||||||
if (GetFastValue(options, 'addToWorld', true))
|
|
||||||
{
|
|
||||||
world.add(this.body);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setPosition(x, y);
|
this.setPosition(x, y);
|
||||||
|
|
|
@ -19,6 +19,7 @@ var MatterSprite = new Class({
|
||||||
Components.Gravity,
|
Components.Gravity,
|
||||||
Components.Mass,
|
Components.Mass,
|
||||||
Components.Sensor,
|
Components.Sensor,
|
||||||
|
Components.SetBody,
|
||||||
Components.Sleep,
|
Components.Sleep,
|
||||||
Components.Static,
|
Components.Static,
|
||||||
Components.Transform,
|
Components.Transform,
|
||||||
|
@ -38,28 +39,26 @@ var MatterSprite = new Class({
|
||||||
this.setSizeToFrame();
|
this.setSizeToFrame();
|
||||||
this.setOrigin();
|
this.setOrigin();
|
||||||
|
|
||||||
this._tempVec2 = new Vector2();
|
this.world = world;
|
||||||
|
|
||||||
var isCircle = GetFastValue(options, 'isCircle', false);
|
this._tempVec2 = new Vector2(x, y);
|
||||||
|
|
||||||
if (isCircle)
|
var shape = GetFastValue(options, 'shape', null);
|
||||||
|
|
||||||
|
if (!shape)
|
||||||
{
|
{
|
||||||
var radius = GetFastValue(options, 'radius', Math.max(this.width, this.height) / 2);
|
this.body = Bodies.rectangle(x, y, this.width, this.height, options);
|
||||||
|
|
||||||
this.body = Bodies.circle(x, y, radius, options);
|
this.body.gameObject = this;
|
||||||
|
|
||||||
|
if (GetFastValue(options, 'addToWorld', true))
|
||||||
|
{
|
||||||
|
world.add(this.body);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.body = Bodies.rectangle(x, y, this.width, this.height, options);
|
this.setBody(shape, options);
|
||||||
}
|
|
||||||
|
|
||||||
this.body.gameObject = this;
|
|
||||||
|
|
||||||
this.world = world;
|
|
||||||
|
|
||||||
if (GetFastValue(options, 'addToWorld', true))
|
|
||||||
{
|
|
||||||
world.add(this.body);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setPosition(x, y);
|
this.setPosition(x, y);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
var Bodies = require('./lib/factory/Bodies');
|
var Bodies = require('./lib/factory/Bodies');
|
||||||
var Class = require('../../utils/Class');
|
var Class = require('../../utils/Class');
|
||||||
|
var Composite = require('./lib/body/Composite');
|
||||||
var Engine = require('./lib/core/Engine');
|
var Engine = require('./lib/core/Engine');
|
||||||
var EventDispatcher = require('../../events/EventDispatcher');
|
var EventDispatcher = require('../../events/EventDispatcher');
|
||||||
var GetFastValue = require('../../utils/object/GetFastValue');
|
var GetFastValue = require('../../utils/object/GetFastValue');
|
||||||
|
@ -61,6 +62,26 @@ var World = new Class({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.isPaused = GetValue(config, 'isPaused', false);
|
||||||
|
|
||||||
|
this.drawDebug = GetValue(config, 'debug', false);
|
||||||
|
|
||||||
|
this.debugGraphic;
|
||||||
|
|
||||||
|
this.defaults = {
|
||||||
|
debugShowBody: GetValue(config, 'debugShowBody', true),
|
||||||
|
debugShowStaticBody: GetValue(config, 'debugShowStaticBody', true),
|
||||||
|
debugShowVelocity: GetValue(config, 'debugShowVelocity', true),
|
||||||
|
bodyDebugColor: GetValue(config, 'debugBodyColor', 0xff00ff),
|
||||||
|
staticBodyDebugColor: GetValue(config, 'debugBodyColor', 0x0000ff),
|
||||||
|
velocityDebugColor: GetValue(config, 'debugVelocityColor', 0x00ff00)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.drawDebug)
|
||||||
|
{
|
||||||
|
this.createDebugGraphic();
|
||||||
|
}
|
||||||
|
|
||||||
this.setEventsProxy();
|
this.setEventsProxy();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -153,7 +174,7 @@ var World = new Class({
|
||||||
x += (width / 2);
|
x += (width / 2);
|
||||||
y += (height / 2);
|
y += (height / 2);
|
||||||
|
|
||||||
this.walls[position] = this.create(x, y, width, height, { isStatic: true });
|
this.walls[position] = this.create(x, y, width, height, { isStatic: true, friction: 0, frictionStatic: 0 });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -166,6 +187,28 @@ var World = new Class({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
createDebugGraphic: function ()
|
||||||
|
{
|
||||||
|
var graphic = this.scene.sys.add.graphics({ x: 0, y: 0 });
|
||||||
|
|
||||||
|
graphic.setZ(Number.MAX_SAFE_INTEGER);
|
||||||
|
|
||||||
|
this.debugGraphic = graphic;
|
||||||
|
|
||||||
|
this.drawDebug = true;
|
||||||
|
|
||||||
|
return graphic;
|
||||||
|
},
|
||||||
|
|
||||||
|
disableGravity: function ()
|
||||||
|
{
|
||||||
|
this.localWorld.gravity.x = 0;
|
||||||
|
this.localWorld.gravity.y = 0;
|
||||||
|
this.localWorld.gravity.scale = 0;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
setGravity: function (x, y, scale)
|
setGravity: function (x, y, scale)
|
||||||
{
|
{
|
||||||
this.localWorld.gravity.x = x;
|
this.localWorld.gravity.x = x;
|
||||||
|
@ -188,10 +231,17 @@ var World = new Class({
|
||||||
return body;
|
return body;
|
||||||
},
|
},
|
||||||
|
|
||||||
// body can be single or an array
|
// object can be single or an array, and can be a body, composite or constraint
|
||||||
add: function (body)
|
add: function (object)
|
||||||
{
|
{
|
||||||
MatterWorld.add(this.localWorld, body);
|
MatterWorld.add(this.localWorld, object);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
remove: function (object, deep)
|
||||||
|
{
|
||||||
|
MatterWorld.remove(this.localWorld, object, deep);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
@ -208,6 +258,11 @@ var World = new Class({
|
||||||
|
|
||||||
update: function (time, delta)
|
update: function (time, delta)
|
||||||
{
|
{
|
||||||
|
if (this.isPaused)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var correction = 1;
|
var correction = 1;
|
||||||
|
|
||||||
Engine.update(this.engine, delta, correction);
|
Engine.update(this.engine, delta, correction);
|
||||||
|
@ -215,7 +270,51 @@ var World = new Class({
|
||||||
|
|
||||||
postUpdate: function ()
|
postUpdate: function ()
|
||||||
{
|
{
|
||||||
// NOOP
|
if (this.drawDebug)
|
||||||
|
{
|
||||||
|
var graphics = this.debugGraphic;
|
||||||
|
var bodies = Composite.allBodies(this.localWorld);
|
||||||
|
|
||||||
|
graphics.clear();
|
||||||
|
graphics.lineStyle(1, this.defaults.bodyDebugColor);
|
||||||
|
|
||||||
|
for (var i = 0; i < bodies.length; i++)
|
||||||
|
{
|
||||||
|
body = bodies[i];
|
||||||
|
|
||||||
|
var vertices = body.vertices;
|
||||||
|
|
||||||
|
graphics.moveTo(vertices[0].x, vertices[0].y);
|
||||||
|
|
||||||
|
for (var j = 1; j < vertices.length; j++)
|
||||||
|
{
|
||||||
|
graphics.lineTo(vertices[j].x, vertices[j].y);
|
||||||
|
}
|
||||||
|
|
||||||
|
graphics.lineTo(vertices[0].x, vertices[0].y);
|
||||||
|
|
||||||
|
graphics.strokePath();
|
||||||
|
|
||||||
|
// if (body.willDrawDebug())
|
||||||
|
// {
|
||||||
|
// body.drawDebug(graphics);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
fromPath: function (path, points)
|
||||||
|
{
|
||||||
|
if (points === undefined) { points = []; }
|
||||||
|
|
||||||
|
var pathPattern = /L?\s*([\-\d\.e]+)[\s,]*([\-\d\.e]+)*/ig;
|
||||||
|
|
||||||
|
path.replace(pathPattern, function(match, x, y)
|
||||||
|
{
|
||||||
|
points.push({ x: parseFloat(x), y: parseFloat(y) });
|
||||||
|
});
|
||||||
|
|
||||||
|
return points;
|
||||||
},
|
},
|
||||||
|
|
||||||
shutdown: function ()
|
shutdown: function ()
|
||||||
|
|
|
@ -1,9 +1,19 @@
|
||||||
var Friction = {
|
var Friction = {
|
||||||
|
|
||||||
setFriction: function (value)
|
setFriction: function (value, air, static)
|
||||||
{
|
{
|
||||||
this.body.friction = value;
|
this.body.friction = value;
|
||||||
|
|
||||||
|
if (air !== undefined)
|
||||||
|
{
|
||||||
|
this.body.frictionAir = air;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (static !== undefined)
|
||||||
|
{
|
||||||
|
this.body.frictionStatic = static;
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
110
v3/src/physics/matter-js/components/SetBody.js
Normal file
110
v3/src/physics/matter-js/components/SetBody.js
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
var Bodies = require('../lib/factory/Bodies');
|
||||||
|
var Body = require('../lib/body/Body');
|
||||||
|
var GetFastValue = require('../../../utils/object/GetFastValue');
|
||||||
|
|
||||||
|
var SetBody = {
|
||||||
|
|
||||||
|
// Calling any of these methods resets previous properties you may have set on the body, including plugins, mass, etc
|
||||||
|
|
||||||
|
setRectangle: function (width, height, options)
|
||||||
|
{
|
||||||
|
return this.setBody({ type: 'rectangle', width: width, height: height }, options);
|
||||||
|
},
|
||||||
|
|
||||||
|
setCircle: function (radius, options)
|
||||||
|
{
|
||||||
|
return this.setBody({ type: 'circle', radius: radius }, options);
|
||||||
|
},
|
||||||
|
|
||||||
|
setPolygon: function (radius, sides, options)
|
||||||
|
{
|
||||||
|
return this.setBody({ type: 'polygon', sides: sides, radius: radius }, options);
|
||||||
|
},
|
||||||
|
|
||||||
|
setTrapezoid: function (width, height, slope, options)
|
||||||
|
{
|
||||||
|
return this.setBody({ type: 'trapezoid', width: width, height: height, slope: slope }, options);
|
||||||
|
},
|
||||||
|
|
||||||
|
setBody: function (config, options)
|
||||||
|
{
|
||||||
|
// Existing body? Remove it.
|
||||||
|
if (this.body)
|
||||||
|
{
|
||||||
|
this.world.remove(this.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config)
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Allow them to do: shape: 'circle' instead of shape: { type: 'circle' }
|
||||||
|
if (typeof config === 'string')
|
||||||
|
{
|
||||||
|
// Using defaults
|
||||||
|
config = { type: config };
|
||||||
|
}
|
||||||
|
|
||||||
|
var shapeType = GetFastValue(config, 'type', 'rectangle');
|
||||||
|
var bodyX = GetFastValue(config, 'x', this._tempVec2.x);
|
||||||
|
var bodyY = GetFastValue(config, 'y', this._tempVec2.y);
|
||||||
|
var bodyWidth = GetFastValue(config, 'width', this.width);
|
||||||
|
var bodyHeight = GetFastValue(config, 'height', this.height);
|
||||||
|
|
||||||
|
switch (shapeType)
|
||||||
|
{
|
||||||
|
case 'rectangle':
|
||||||
|
this.body = Bodies.rectangle(bodyX, bodyY, bodyWidth, bodyHeight, options);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'circle':
|
||||||
|
var radius = GetFastValue(config, 'radius', Math.max(bodyWidth, bodyHeight) / 2);
|
||||||
|
var maxSides = GetFastValue(config, 'maxSides', 25);
|
||||||
|
this.body = Bodies.circle(bodyX, bodyY, radius, options, maxSides);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'trapezoid':
|
||||||
|
var slope = GetFastValue(config, 'slope', 0.5);
|
||||||
|
this.body = Bodies.trapezoid(bodyX, bodyY, bodyWidth, bodyHeight, slope, options);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'polygon':
|
||||||
|
var sides = GetFastValue(config, 'sides', 5);
|
||||||
|
var pradius = GetFastValue(config, 'radius', Math.max(bodyWidth, bodyHeight) / 2);
|
||||||
|
this.body = Bodies.polygon(bodyX, bodyY, sides, pradius, options);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'fromVertices':
|
||||||
|
case 'fromVerts':
|
||||||
|
var verts = GetFastValue(config, 'verts', []);
|
||||||
|
|
||||||
|
if (this.body)
|
||||||
|
{
|
||||||
|
Body.setVertices(this.body, verts);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var flagInternal = GetFastValue(config, 'flagInternal', false);
|
||||||
|
var removeCollinear = GetFastValue(config, 'removeCollinear', 0.01);
|
||||||
|
var minimumArea = GetFastValue(config, 'minimumArea', 10);
|
||||||
|
this.body = Bodies.fromVertices(bodyX, bodyY, verts, options, flagInternal, removeCollinear, minimumArea);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.body.gameObject = this;
|
||||||
|
|
||||||
|
if (GetFastValue(config, 'addToWorld', true))
|
||||||
|
{
|
||||||
|
this.world.add(this.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = SetBody;
|
|
@ -10,6 +10,7 @@ module.exports = {
|
||||||
Mass: require('./Mass'),
|
Mass: require('./Mass'),
|
||||||
Static: require('./Static'),
|
Static: require('./Static'),
|
||||||
Sensor: require('./Sensor'),
|
Sensor: require('./Sensor'),
|
||||||
|
SetBody: require('./SetBody'),
|
||||||
Sleep: require('./Sleep'),
|
Sleep: require('./Sleep'),
|
||||||
Transform: require('./Transform'),
|
Transform: require('./Transform'),
|
||||||
Velocity: require('./Velocity')
|
Velocity: require('./Velocity')
|
||||||
|
|
|
@ -40,6 +40,7 @@ var Axes = require('../geometry/Axes');
|
||||||
id: Common.nextId(),
|
id: Common.nextId(),
|
||||||
type: 'body',
|
type: 'body',
|
||||||
label: 'Body',
|
label: 'Body',
|
||||||
|
gameObject: null,
|
||||||
parts: [],
|
parts: [],
|
||||||
plugin: {},
|
plugin: {},
|
||||||
angle: 0,
|
angle: 0,
|
||||||
|
@ -292,19 +293,23 @@ var Axes = require('../geometry/Axes');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the mass of the body. Inverse mass and density are automatically updated to reflect the change.
|
* Sets the mass of the body. Inverse mass, density and inertia are automatically updated to reflect the change.
|
||||||
* @method setMass
|
* @method setMass
|
||||||
* @param {body} body
|
* @param {body} body
|
||||||
* @param {number} mass
|
* @param {number} mass
|
||||||
*/
|
*/
|
||||||
Body.setMass = function(body, mass) {
|
Body.setMass = function(body, mass) {
|
||||||
|
var moment = body.inertia / (body.mass / 6);
|
||||||
|
body.inertia = moment * (mass / 6);
|
||||||
|
body.inverseInertia = 1 / body.inertia;
|
||||||
|
|
||||||
body.mass = mass;
|
body.mass = mass;
|
||||||
body.inverseMass = 1 / body.mass;
|
body.inverseMass = 1 / body.mass;
|
||||||
body.density = body.mass / body.area;
|
body.density = body.mass / body.area;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the density of the body. Mass is automatically updated to reflect the change.
|
* Sets the density of the body. Mass and inertia are automatically updated to reflect the change.
|
||||||
* @method setDensity
|
* @method setDensity
|
||||||
* @param {body} body
|
* @param {body} body
|
||||||
* @param {number} density
|
* @param {number} density
|
||||||
|
@ -538,11 +543,17 @@ var Axes = require('../geometry/Axes');
|
||||||
* @param {vector} [point]
|
* @param {vector} [point]
|
||||||
*/
|
*/
|
||||||
Body.scale = function(body, scaleX, scaleY, point) {
|
Body.scale = function(body, scaleX, scaleY, point) {
|
||||||
|
point = point || body.position;
|
||||||
|
|
||||||
for (var i = 0; i < body.parts.length; i++) {
|
for (var i = 0; i < body.parts.length; i++) {
|
||||||
var part = body.parts[i];
|
var part = body.parts[i];
|
||||||
|
|
||||||
|
// scale position
|
||||||
|
part.position.x = point.x + (part.position.x - point.x) * scaleX;
|
||||||
|
part.position.y = point.y + (part.position.y - point.y) * scaleY;
|
||||||
|
|
||||||
// scale vertices
|
// scale vertices
|
||||||
Vertices.scale(part.vertices, scaleX, scaleY, body.position);
|
Vertices.scale(part.vertices, scaleX, scaleY, point);
|
||||||
|
|
||||||
// update properties
|
// update properties
|
||||||
part.axes = Axes.fromVertices(part.vertices);
|
part.axes = Axes.fromVertices(part.vertices);
|
||||||
|
@ -671,16 +682,16 @@ var Axes = require('../geometry/Axes');
|
||||||
|
|
||||||
// sum the properties of all compound parts of the parent body
|
// sum the properties of all compound parts of the parent body
|
||||||
for (var i = body.parts.length === 1 ? 0 : 1; i < body.parts.length; i++) {
|
for (var i = body.parts.length === 1 ? 0 : 1; i < body.parts.length; i++) {
|
||||||
var part = body.parts[i];
|
var part = body.parts[i],
|
||||||
|
mass = part.mass !== Infinity ? part.mass : 1;
|
||||||
|
|
||||||
properties.mass += part.mass;
|
properties.mass += part.mass;
|
||||||
properties.area += part.area;
|
properties.area += part.area;
|
||||||
properties.inertia += part.inertia;
|
properties.inertia += part.inertia;
|
||||||
properties.centre = Vector.add(properties.centre,
|
properties.centre = Vector.add(properties.centre, Vector.mult(part.position, mass));
|
||||||
Vector.mult(part.position, part.mass !== Infinity ? part.mass : 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
properties.centre = Vector.div(properties.centre,
|
properties.centre = Vector.div(properties.centre, properties.mass);
|
||||||
properties.mass !== Infinity ? properties.mass : body.parts.length);
|
|
||||||
|
|
||||||
return properties;
|
return properties;
|
||||||
};
|
};
|
||||||
|
|
|
@ -275,7 +275,12 @@ var Common = require('../core/Common');
|
||||||
* @param {number} qualityMax
|
* @param {number} qualityMax
|
||||||
*/
|
*/
|
||||||
Vertices.chamfer = function(vertices, radius, quality, qualityMin, qualityMax) {
|
Vertices.chamfer = function(vertices, radius, quality, qualityMin, qualityMax) {
|
||||||
radius = radius || [8];
|
|
||||||
|
if (typeof radius === 'number') {
|
||||||
|
radius = [radius];
|
||||||
|
} else {
|
||||||
|
radius = radius || [8];
|
||||||
|
}
|
||||||
|
|
||||||
if (!radius.length)
|
if (!radius.length)
|
||||||
radius = [radius];
|
radius = [radius];
|
||||||
|
|
|
@ -10,7 +10,7 @@ var GetFastValue = function (source, key, defaultValue)
|
||||||
{
|
{
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
else if (source.hasOwnProperty(key))
|
else if (source.hasOwnProperty(key) && source[key] !== undefined)
|
||||||
{
|
{
|
||||||
return source[key];
|
return source[key];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue