diff --git a/v3/src/gameobjects/tilemap/components/Copy.js b/v3/src/gameobjects/tilemap/components/Copy.js index c29ea1d93..fe390a16e 100644 --- a/v3/src/gameobjects/tilemap/components/Copy.js +++ b/v3/src/gameobjects/tilemap/components/Copy.js @@ -3,8 +3,8 @@ var CalculateFacesWithin = require('./CalculateFacesWithin'); /** * 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 - * faces in the destination region. + * coordinates) within the layer. This copies all tile properties & recalculates collision + * information in the destination region. * * @param {number} srcTileX - [description] * @param {number} srcTileY - [description] @@ -16,7 +16,6 @@ var CalculateFacesWithin = require('./CalculateFacesWithin'); * @param {boolean} [recalculateFaces=true] - [description] * @param {LayerData} layer - [description] */ - var Copy = function (srcTileX, srcTileY, width, height, destTileX, destTileY, recalculateFaces, layer) { if (srcTileX < 0) { srcTileX = 0; } diff --git a/v3/src/gameobjects/tilemap/components/CullTiles.js b/v3/src/gameobjects/tilemap/components/CullTiles.js index 4246ce3aa..fa9e9cf8d 100644 --- a/v3/src/gameobjects/tilemap/components/CullTiles.js +++ b/v3/src/gameobjects/tilemap/components/CullTiles.js @@ -3,7 +3,7 @@ * internally. * * @param {LayerData} layer - [description] - * @param {Camera} camera - [description] + * @param {Camera} [camera=main camera] - [description] * @param {array} [outputArray] - [description] * @returns {array} */ diff --git a/v3/src/gameobjects/tilemap/components/Fill.js b/v3/src/gameobjects/tilemap/components/Fill.js index 7e4b390de..7828a8ac8 100644 --- a/v3/src/gameobjects/tilemap/components/Fill.js +++ b/v3/src/gameobjects/tilemap/components/Fill.js @@ -4,13 +4,13 @@ var CalculateFacesWithin = require('./CalculateFacesWithin'); /** * 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. - * Interesting tile faces in the region will be recalculated. + * Collision information in the region will be recalculated. * * @param {number} index - [description] - * @param {number} tileX - [description] - * @param {number} tileY - [description] - * @param {number} width - [description] - * @param {number} height - [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 {boolean} [recalculateFaces=true] - [description] * @param {LayerData} layer - [description] */ diff --git a/v3/src/gameobjects/tilemap/components/FindByIndex.js b/v3/src/gameobjects/tilemap/components/FindByIndex.js index 75fcc526c..9f5ba29ff 100644 --- a/v3/src/gameobjects/tilemap/components/FindByIndex.js +++ b/v3/src/gameobjects/tilemap/components/FindByIndex.js @@ -12,7 +12,6 @@ * @param {LayerData} layer - [description] * @return {Tile|null} The first (or n skipped) tile with the matching index. */ - var FindByIndex = function (findIndex, skip, reverse, layer) { if (skip === undefined) { skip = 0; } diff --git a/v3/src/gameobjects/tilemap/components/ForEachTile.js b/v3/src/gameobjects/tilemap/components/ForEachTile.js index c5b38d3e1..ea08eb30b 100644 --- a/v3/src/gameobjects/tilemap/components/ForEachTile.js +++ b/v3/src/gameobjects/tilemap/components/ForEachTile.js @@ -1,26 +1,25 @@ var GetTilesWithin = require('./GetTilesWithin'); /** -* For each tile in the given rectangular area (in tile coordinates) of the layer, run the given -* callback. -* -* @param {number} callback - The callback. Each tile in the given area will be passed to this -* callback as the first and only parameter. -* @param {number} context - The context under which the callback should be run. -* @param {number} [tileX=0] -* @param {number} [tileY=0] -* @param {number} [width=max width based on tileX] - [description] -* @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] -*/ - + * For each tile in the given rectangular area (in tile coordinates) of the layer, run the given + * callback. + * + * @param {number} callback - The callback. Each tile in the given area will be passed to this + * callback as the first and only parameter. + * @param {number} context - The context under which the callback should be run. + * @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 {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] + */ var ForEachTile = function (callback, context, tileX, tileY, width, height, filteringOptions, layer) { var tiles = GetTilesWithin(tileX, tileY, width, height, filteringOptions, layer); diff --git a/v3/src/gameobjects/tilemap/components/GetTileAt.js b/v3/src/gameobjects/tilemap/components/GetTileAt.js index 9392ee179..09721d21b 100644 --- a/v3/src/gameobjects/tilemap/components/GetTileAt.js +++ b/v3/src/gameobjects/tilemap/components/GetTileAt.js @@ -1,5 +1,16 @@ 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) { if (nonNull === undefined) { nonNull = false; } diff --git a/v3/src/gameobjects/tilemap/components/GetTileAtWorldXY.js b/v3/src/gameobjects/tilemap/components/GetTileAtWorldXY.js index e201159a0..5683646b8 100644 --- a/v3/src/gameobjects/tilemap/components/GetTileAtWorldXY.js +++ b/v3/src/gameobjects/tilemap/components/GetTileAtWorldXY.js @@ -2,6 +2,18 @@ var GetTileAt = require('./GetTileAt'); var WorldToTileX = require('./WorldToTileX'); 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 tileX = WorldToTileX(worldX, true, camera, layer); diff --git a/v3/src/gameobjects/tilemap/components/GetTilesWithin.js b/v3/src/gameobjects/tilemap/components/GetTilesWithin.js index 7f4266c68..5cdad790b 100644 --- a/v3/src/gameobjects/tilemap/components/GetTilesWithin.js +++ b/v3/src/gameobjects/tilemap/components/GetTilesWithin.js @@ -2,14 +2,23 @@ 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. -// Options: -// { -// isNotEmpty: false, -// isColliding: false, -// hasInterestingFace: false -// } +/** + * Gets the tiles in the given rectangular area (in tile coordinates) of the layer. + * + * @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 {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) { if (tileX === undefined) { tileX = 0; } diff --git a/v3/src/gameobjects/tilemap/components/GetTilesWithinShape.js b/v3/src/gameobjects/tilemap/components/GetTilesWithinShape.js index abe016c8a..18e2c4d9a 100644 --- a/v3/src/gameobjects/tilemap/components/GetTilesWithinShape.js +++ b/v3/src/gameobjects/tilemap/components/GetTilesWithinShape.js @@ -13,9 +13,25 @@ var TriangleToRectangle = function (triangle, rect) 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 // 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) { if (shape === undefined) { return []; } diff --git a/v3/src/gameobjects/tilemap/components/GetTilesWithinWorldXY.js b/v3/src/gameobjects/tilemap/components/GetTilesWithinWorldXY.js index 614611749..ad9b67a18 100644 --- a/v3/src/gameobjects/tilemap/components/GetTilesWithinWorldXY.js +++ b/v3/src/gameobjects/tilemap/components/GetTilesWithinWorldXY.js @@ -2,6 +2,24 @@ var GetTilesWithin = require('./GetTilesWithin'); var WorldToTileX = require('./WorldToTileX'); 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) { // Top left corner of the rect, rounded down to include partial tiles diff --git a/v3/src/gameobjects/tilemap/components/HasTileAt.js b/v3/src/gameobjects/tilemap/components/HasTileAt.js index 85d600559..998b1dbbe 100644 --- a/v3/src/gameobjects/tilemap/components/HasTileAt.js +++ b/v3/src/gameobjects/tilemap/components/HasTileAt.js @@ -1,5 +1,14 @@ 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) { if (IsInLayerBounds(tileX, tileY, layer)) diff --git a/v3/src/gameobjects/tilemap/components/HasTileAtWorldXY.js b/v3/src/gameobjects/tilemap/components/HasTileAtWorldXY.js index a03e49bc4..111efc48c 100644 --- a/v3/src/gameobjects/tilemap/components/HasTileAtWorldXY.js +++ b/v3/src/gameobjects/tilemap/components/HasTileAtWorldXY.js @@ -2,6 +2,16 @@ var HasTileAt = require('./HasTileAt'); var WorldToTileX = require('./WorldToTileX'); 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 tileX = WorldToTileX(worldX, true, camera, layer); diff --git a/v3/src/gameobjects/tilemap/components/IsInLayerBounds.js b/v3/src/gameobjects/tilemap/components/IsInLayerBounds.js index 0f0ed9444..5ba52b3f6 100644 --- a/v3/src/gameobjects/tilemap/components/IsInLayerBounds.js +++ b/v3/src/gameobjects/tilemap/components/IsInLayerBounds.js @@ -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) { return (tileX >= 0 && tileX < layer.width && tileY >= 0 && tileY < layer.height); diff --git a/v3/src/gameobjects/tilemap/components/PutTileAt.js b/v3/src/gameobjects/tilemap/components/PutTileAt.js index 2b5261b38..f1a7e2116 100644 --- a/v3/src/gameobjects/tilemap/components/PutTileAt.js +++ b/v3/src/gameobjects/tilemap/components/PutTileAt.js @@ -2,8 +2,19 @@ var Tile = require('../Tile'); var IsInLayerBounds = require('./IsInLayerBounds'); 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) { 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); } - else - { - layer.data[tileY][tileX].copy(tile); - } + layer.data[tileY][tileX].copy(tile); } else { diff --git a/v3/src/gameobjects/tilemap/components/PutTileAtWorldXY.js b/v3/src/gameobjects/tilemap/components/PutTileAtWorldXY.js index 91b90cc06..c1d84c59e 100644 --- a/v3/src/gameobjects/tilemap/components/PutTileAtWorldXY.js +++ b/v3/src/gameobjects/tilemap/components/PutTileAtWorldXY.js @@ -2,6 +2,20 @@ var PutTileAt = require('./PutTileAt'); var WorldToTileX = require('./WorldToTileX'); 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 tileX = WorldToTileX(worldX, true, camera, layer); diff --git a/v3/src/gameobjects/tilemap/components/Randomize.js b/v3/src/gameobjects/tilemap/components/Randomize.js index 3cf2ba131..bd99558e7 100644 --- a/v3/src/gameobjects/tilemap/components/Randomize.js +++ b/v3/src/gameobjects/tilemap/components/Randomize.js @@ -1,7 +1,20 @@ var GetTilesWithin = require('./GetTilesWithin'); 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 i; diff --git a/v3/src/gameobjects/tilemap/components/RecalculateFacesAt.js b/v3/src/gameobjects/tilemap/components/RecalculateFacesAt.js index 3edd57d1d..92e9e8985 100644 --- a/v3/src/gameobjects/tilemap/components/RecalculateFacesAt.js +++ b/v3/src/gameobjects/tilemap/components/RecalculateFacesAt.js @@ -1,8 +1,14 @@ 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 -// 951. +/** + * Calculates interesting faces at the given tile coordinates of the specified layer. Interesting + * 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 tile = GetTileAt(tileX, tileY, true, layer); diff --git a/v3/src/gameobjects/tilemap/components/RemoveTileAt.js b/v3/src/gameobjects/tilemap/components/RemoveTileAt.js index d9538a93c..bfd043c5e 100644 --- a/v3/src/gameobjects/tilemap/components/RemoveTileAt.js +++ b/v3/src/gameobjects/tilemap/components/RemoveTileAt.js @@ -2,7 +2,19 @@ var Tile = require('../Tile'); var IsInLayerBounds = require('./IsInLayerBounds'); 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) { if (replaceWithNull === undefined) { replaceWithNull = false; } diff --git a/v3/src/gameobjects/tilemap/components/RemoveTileAtWorldXY.js b/v3/src/gameobjects/tilemap/components/RemoveTileAtWorldXY.js index 53092e4e6..a5285b232 100644 --- a/v3/src/gameobjects/tilemap/components/RemoveTileAtWorldXY.js +++ b/v3/src/gameobjects/tilemap/components/RemoveTileAtWorldXY.js @@ -2,6 +2,20 @@ var RemoveTileAt = require('./RemoveTileAt'); var WorldToTileX = require('./WorldToTileX'); 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 tileX = WorldToTileX(worldX, true, camera, layer); diff --git a/v3/src/gameobjects/tilemap/components/ReplaceByIndex.js b/v3/src/gameobjects/tilemap/components/ReplaceByIndex.js index 58a502c47..f4844811b 100644 --- a/v3/src/gameobjects/tilemap/components/ReplaceByIndex.js +++ b/v3/src/gameobjects/tilemap/components/ReplaceByIndex.js @@ -1,6 +1,18 @@ 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 tiles = GetTilesWithin(tileX, tileY, width, height, null, layer); diff --git a/v3/src/gameobjects/tilemap/components/SetCollision.js b/v3/src/gameobjects/tilemap/components/SetCollision.js index 6b6b258a1..fb5e9a510 100644 --- a/v3/src/gameobjects/tilemap/components/SetCollision.js +++ b/v3/src/gameobjects/tilemap/components/SetCollision.js @@ -2,6 +2,18 @@ var SetTileCollision = require('./SetTileCollision'); var CalculateFacesWithin = require('./CalculateFacesWithin'); 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) { if (collides === undefined) { collides = true; } diff --git a/v3/src/gameobjects/tilemap/components/SetCollisionBetween.js b/v3/src/gameobjects/tilemap/components/SetCollisionBetween.js index 67fa57ca3..58c731592 100644 --- a/v3/src/gameobjects/tilemap/components/SetCollisionBetween.js +++ b/v3/src/gameobjects/tilemap/components/SetCollisionBetween.js @@ -2,6 +2,20 @@ var SetTileCollision = require('./SetTileCollision'); var CalculateFacesWithin = require('./CalculateFacesWithin'); 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) { if (collides === undefined) { collides = true; } diff --git a/v3/src/gameobjects/tilemap/components/SetCollisionByExclusion.js b/v3/src/gameobjects/tilemap/components/SetCollisionByExclusion.js index 38fac088d..e93f02252 100644 --- a/v3/src/gameobjects/tilemap/components/SetCollisionByExclusion.js +++ b/v3/src/gameobjects/tilemap/components/SetCollisionByExclusion.js @@ -2,13 +2,25 @@ var SetTileCollision = require('./SetTileCollision'); var CalculateFacesWithin = require('./CalculateFacesWithin'); 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) { if (collides === undefined) { collides = true; } if (recalculateFaces === undefined) { recalculateFaces = true; } 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 tx = 0; tx < layer.width; tx++) diff --git a/v3/src/gameobjects/tilemap/components/SetLayerCollisionIndex.js b/v3/src/gameobjects/tilemap/components/SetLayerCollisionIndex.js index af2fc6385..d180c4d80 100644 --- a/v3/src/gameobjects/tilemap/components/SetLayerCollisionIndex.js +++ b/v3/src/gameobjects/tilemap/components/SetLayerCollisionIndex.js @@ -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 loc = layer.collideIndexes.indexOf(tileIndex); diff --git a/v3/src/gameobjects/tilemap/components/SetTileCollision.js b/v3/src/gameobjects/tilemap/components/SetTileCollision.js index 215caae59..d513b8837 100644 --- a/v3/src/gameobjects/tilemap/components/SetTileCollision.js +++ b/v3/src/gameobjects/tilemap/components/SetTileCollision.js @@ -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) { if (collides) diff --git a/v3/src/gameobjects/tilemap/components/Shuffle.js b/v3/src/gameobjects/tilemap/components/Shuffle.js index 6d2dc42a7..4dc39a258 100644 --- a/v3/src/gameobjects/tilemap/components/Shuffle.js +++ b/v3/src/gameobjects/tilemap/components/Shuffle.js @@ -1,7 +1,18 @@ var GetTilesWithin = require('./GetTilesWithin'); 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 tiles = GetTilesWithin(tileX, tileY, width, height, null, layer); diff --git a/v3/src/gameobjects/tilemap/components/SwapByIndex.js b/v3/src/gameobjects/tilemap/components/SwapByIndex.js index 8c9d02589..f63cf388d 100644 --- a/v3/src/gameobjects/tilemap/components/SwapByIndex.js +++ b/v3/src/gameobjects/tilemap/components/SwapByIndex.js @@ -1,6 +1,18 @@ 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 tiles = GetTilesWithin(tileX, tileY, width, height, null, layer); diff --git a/v3/src/gameobjects/tilemap/components/TileToWorldX.js b/v3/src/gameobjects/tilemap/components/TileToWorldX.js index 6710dd21e..ec73dd770 100644 --- a/v3/src/gameobjects/tilemap/components/TileToWorldX.js +++ b/v3/src/gameobjects/tilemap/components/TileToWorldX.js @@ -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 tileWidth = layer.tileWidth; diff --git a/v3/src/gameobjects/tilemap/components/TileToWorldY.js b/v3/src/gameobjects/tilemap/components/TileToWorldY.js index ddb3d443c..351b3ddd1 100644 --- a/v3/src/gameobjects/tilemap/components/TileToWorldY.js +++ b/v3/src/gameobjects/tilemap/components/TileToWorldY.js @@ -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 tileHeight = layer.tileHeight; diff --git a/v3/src/gameobjects/tilemap/components/WorldToTileX.js b/v3/src/gameobjects/tilemap/components/WorldToTileX.js index 6805b64d1..b248b81ce 100644 --- a/v3/src/gameobjects/tilemap/components/WorldToTileX.js +++ b/v3/src/gameobjects/tilemap/components/WorldToTileX.js @@ -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) { if (snapToFloor === undefined) { snapToFloor = true; } diff --git a/v3/src/gameobjects/tilemap/components/WorldToTileXY.js b/v3/src/gameobjects/tilemap/components/WorldToTileXY.js index d40a137b2..c64ac542e 100644 --- a/v3/src/gameobjects/tilemap/components/WorldToTileXY.js +++ b/v3/src/gameobjects/tilemap/components/WorldToTileXY.js @@ -2,6 +2,20 @@ var WorldToTileX = require('./WorldToTileX'); var WorldToTileY = require('./WorldToTileY'); 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) { if (point === undefined) { point = new Vector2(0, 0); } diff --git a/v3/src/gameobjects/tilemap/components/WorldToTileY.js b/v3/src/gameobjects/tilemap/components/WorldToTileY.js index 9f649920e..bab14494e 100644 --- a/v3/src/gameobjects/tilemap/components/WorldToTileY.js +++ b/v3/src/gameobjects/tilemap/components/WorldToTileY.js @@ -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) { if (snapToFloor === undefined) { snapToFloor = true; } diff --git a/v3/src/gameobjects/tilemap/mapdata/LayerData.js b/v3/src/gameobjects/tilemap/mapdata/LayerData.js index a013c2869..3d3958e2d 100644 --- a/v3/src/gameobjects/tilemap/mapdata/LayerData.js +++ b/v3/src/gameobjects/tilemap/mapdata/LayerData.js @@ -5,7 +5,17 @@ var LayerData = new Class({ 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 = {}; } diff --git a/v3/src/gameobjects/tilemap/mapdata/MapData.js b/v3/src/gameobjects/tilemap/mapdata/MapData.js index 8497d5d95..6526460ac 100644 --- a/v3/src/gameobjects/tilemap/mapdata/MapData.js +++ b/v3/src/gameobjects/tilemap/mapdata/MapData.js @@ -5,6 +5,16 @@ var MapData = new Class({ 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) { if (config === undefined) { config = {}; } diff --git a/v3/src/gameobjects/tilemap/parsers/Parse.js b/v3/src/gameobjects/tilemap/parsers/Parse.js index 562171a2a..42c85f414 100644 --- a/v3/src/gameobjects/tilemap/parsers/Parse.js +++ b/v3/src/gameobjects/tilemap/parsers/Parse.js @@ -4,20 +4,34 @@ var ParseCSV = require('./ParseCSV'); var ParseTiledJSON = require('./parsetiledjson/'); 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; switch(mapFormat) { case (Formats.TILEMAP_2D_ARRAY): - newMap = Parse2DArray(key, mapData, tileWidth, tileHeight, insertNull); + newMap = Parse2DArray(name, data, tileWidth, tileHeight, insertNull); break; case (Formats.TILEMAP_CSV): - newMap = ParseCSV(key, mapData, tileWidth, tileHeight, insertNull); + newMap = ParseCSV(name, data, tileWidth, tileHeight, insertNull); break; case (Formats.TILEMAP_TILED_JSON): - newMap = ParseTiledJSON(key, mapData, insertNull); + newMap = ParseTiledJSON(name, data, insertNull); break; default: console.warn('Unrecognized tilemap data format: ' + mapFormat); diff --git a/v3/src/physics/matter-js/MatterImage.js b/v3/src/physics/matter-js/MatterImage.js index a8707e353..9f0f56019 100644 --- a/v3/src/physics/matter-js/MatterImage.js +++ b/v3/src/physics/matter-js/MatterImage.js @@ -18,6 +18,7 @@ var MatterImage = new Class({ Components.Gravity, Components.Mass, Components.Sensor, + Components.SetBody, Components.Sleep, Components.Static, Components.Transform, @@ -35,28 +36,26 @@ var MatterImage = new Class({ this.setSizeToFrame(); 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 { - this.body = Bodies.rectangle(x, y, this.width, this.height, options); - } - - this.body.gameObject = this; - - this.world = world; - - if (GetFastValue(options, 'addToWorld', true)) - { - world.add(this.body); + this.setBody(shape, options); } this.setPosition(x, y); diff --git a/v3/src/physics/matter-js/MatterSprite.js b/v3/src/physics/matter-js/MatterSprite.js index 4fc06e32c..45265b195 100644 --- a/v3/src/physics/matter-js/MatterSprite.js +++ b/v3/src/physics/matter-js/MatterSprite.js @@ -19,6 +19,7 @@ var MatterSprite = new Class({ Components.Gravity, Components.Mass, Components.Sensor, + Components.SetBody, Components.Sleep, Components.Static, Components.Transform, @@ -38,28 +39,26 @@ var MatterSprite = new Class({ this.setSizeToFrame(); 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 { - this.body = Bodies.rectangle(x, y, this.width, this.height, options); - } - - this.body.gameObject = this; - - this.world = world; - - if (GetFastValue(options, 'addToWorld', true)) - { - world.add(this.body); + this.setBody(shape, options); } this.setPosition(x, y); diff --git a/v3/src/physics/matter-js/World.js b/v3/src/physics/matter-js/World.js index 422795dde..6a8d5a990 100644 --- a/v3/src/physics/matter-js/World.js +++ b/v3/src/physics/matter-js/World.js @@ -2,6 +2,7 @@ var Bodies = require('./lib/factory/Bodies'); var Class = require('../../utils/Class'); +var Composite = require('./lib/body/Composite'); var Engine = require('./lib/core/Engine'); var EventDispatcher = require('../../events/EventDispatcher'); 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(); }, @@ -153,7 +174,7 @@ var World = new Class({ x += (width / 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 { @@ -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) { this.localWorld.gravity.x = x; @@ -188,10 +231,17 @@ var World = new Class({ return body; }, - // body can be single or an array - add: function (body) + // object can be single or an array, and can be a body, composite or constraint + 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; }, @@ -208,6 +258,11 @@ var World = new Class({ update: function (time, delta) { + if (this.isPaused) + { + return; + } + var correction = 1; Engine.update(this.engine, delta, correction); @@ -215,7 +270,51 @@ var World = new Class({ 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 () diff --git a/v3/src/physics/matter-js/components/Friction.js b/v3/src/physics/matter-js/components/Friction.js index 2204ddd25..f8347a11d 100644 --- a/v3/src/physics/matter-js/components/Friction.js +++ b/v3/src/physics/matter-js/components/Friction.js @@ -1,9 +1,19 @@ var Friction = { - setFriction: function (value) + setFriction: function (value, air, static) { this.body.friction = value; + if (air !== undefined) + { + this.body.frictionAir = air; + } + + if (static !== undefined) + { + this.body.frictionStatic = static; + } + return this; }, diff --git a/v3/src/physics/matter-js/components/SetBody.js b/v3/src/physics/matter-js/components/SetBody.js new file mode 100644 index 000000000..a2da8aa1e --- /dev/null +++ b/v3/src/physics/matter-js/components/SetBody.js @@ -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; diff --git a/v3/src/physics/matter-js/components/index.js b/v3/src/physics/matter-js/components/index.js index 85058553f..dcb5673fe 100644 --- a/v3/src/physics/matter-js/components/index.js +++ b/v3/src/physics/matter-js/components/index.js @@ -10,6 +10,7 @@ module.exports = { Mass: require('./Mass'), Static: require('./Static'), Sensor: require('./Sensor'), + SetBody: require('./SetBody'), Sleep: require('./Sleep'), Transform: require('./Transform'), Velocity: require('./Velocity') diff --git a/v3/src/physics/matter-js/lib/body/Body.js b/v3/src/physics/matter-js/lib/body/Body.js index 3f36c9522..21362eb03 100644 --- a/v3/src/physics/matter-js/lib/body/Body.js +++ b/v3/src/physics/matter-js/lib/body/Body.js @@ -40,6 +40,7 @@ var Axes = require('../geometry/Axes'); id: Common.nextId(), type: 'body', label: 'Body', + gameObject: null, parts: [], plugin: {}, 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 * @param {body} body * @param {number} 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.inverseMass = 1 / body.mass; 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 * @param {body} body * @param {number} density @@ -538,11 +543,17 @@ var Axes = require('../geometry/Axes'); * @param {vector} [point] */ Body.scale = function(body, scaleX, scaleY, point) { + point = point || body.position; + for (var i = 0; i < body.parts.length; 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 - Vertices.scale(part.vertices, scaleX, scaleY, body.position); + Vertices.scale(part.vertices, scaleX, scaleY, point); // update properties 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 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.area += part.area; properties.inertia += part.inertia; - properties.centre = Vector.add(properties.centre, - Vector.mult(part.position, part.mass !== Infinity ? part.mass : 1)); + properties.centre = Vector.add(properties.centre, Vector.mult(part.position, mass)); } - properties.centre = Vector.div(properties.centre, - properties.mass !== Infinity ? properties.mass : body.parts.length); + properties.centre = Vector.div(properties.centre, properties.mass); return properties; }; diff --git a/v3/src/physics/matter-js/lib/geometry/Vertices.js b/v3/src/physics/matter-js/lib/geometry/Vertices.js index 5869cbec1..8489a14f5 100644 --- a/v3/src/physics/matter-js/lib/geometry/Vertices.js +++ b/v3/src/physics/matter-js/lib/geometry/Vertices.js @@ -275,7 +275,12 @@ var Common = require('../core/Common'); * @param {number} 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) radius = [radius]; diff --git a/v3/src/utils/object/GetFastValue.js b/v3/src/utils/object/GetFastValue.js index 61b5c3996..8f44f7e3f 100644 --- a/v3/src/utils/object/GetFastValue.js +++ b/v3/src/utils/object/GetFastValue.js @@ -10,7 +10,7 @@ var GetFastValue = function (source, key, defaultValue) { return defaultValue; } - else if (source.hasOwnProperty(key)) + else if (source.hasOwnProperty(key) && source[key] !== undefined) { return source[key]; }