diff --git a/v3/src/camera/2d/Camera.js b/v3/src/camera/2d/Camera.js index 0f1e7894c..0ad8f13e1 100644 --- a/v3/src/camera/2d/Camera.js +++ b/v3/src/camera/2d/Camera.js @@ -65,7 +65,6 @@ var Camera = new Class({ this._id = 0; }, - cameraToWorld: require('./inc/CameraToWorld'), centerToBounds: require('./inc/CenterToBounds'), centerToSize: require('./inc/CenterToSize'), cull: require('./inc/Cull'), @@ -74,6 +73,7 @@ var Camera = new Class({ destroy: require('./inc/Destroy'), fade: require('./inc/Fade'), flash: require('./inc/Flash'), + getWorldPoint: require('./inc/GetWorldPoint'), ignore: require('./inc/Ignore'), preRender: require('./inc/PreRender'), removeBounds: require('./inc/RemoveBounds'), @@ -93,8 +93,7 @@ var Camera = new Class({ startFollow: require('./inc/StartFollow'), stopFollow: require('./inc/StopFollow'), toJSON: require('./inc/ToJSON'), - update: require('./inc/Update'), - worldToCamera: require('./inc/WorldToCamera') + update: require('./inc/Update') }); diff --git a/v3/src/camera/2d/inc/CameraToWorld.js b/v3/src/camera/2d/inc/GetWorldPoint.js similarity index 65% rename from v3/src/camera/2d/inc/CameraToWorld.js rename to v3/src/camera/2d/inc/GetWorldPoint.js index f4577bf5d..c869ee482 100644 --- a/v3/src/camera/2d/inc/CameraToWorld.js +++ b/v3/src/camera/2d/inc/GetWorldPoint.js @@ -1,4 +1,6 @@ -var CameraToWorld = function (pointIn, pointOut) +var Vector2 = require('../../../math/Vector2'); + +var GetWorldPoint = function (screenPoint, output) { var cameraMatrix = this.matrix.matrix; var mva = cameraMatrix[0]; @@ -13,7 +15,7 @@ var CameraToWorld = function (pointIn, pointOut) if (!determinant) { - return pointIn; + return screenPoint; } determinant = 1 / determinant; @@ -29,19 +31,19 @@ var CameraToWorld = function (pointIn, pointOut) var zoom = this.zoom; var scrollX = this.scrollX; var scrollY = this.scrollY; - var x = pointIn.x + ((scrollX * c - scrollY * s) * zoom); - var y = pointIn.y + ((scrollX * s + scrollY * c) * zoom); + var x = screenPoint.x + ((scrollX * c - scrollY * s) * zoom); + var y = screenPoint.y + ((scrollX * s + scrollY * c) * zoom); - if (!pointOut) + if (!output) { - pointOut = { x: 0, y: 0 }; + output = new Vector2(); } /* Apply transform to point */ - pointOut.x = (x * ima + y * imc + ime); - pointOut.y = (x * imb + y * imd + imf); + output.x = (x * ima + y * imc + ime); + output.y = (x * imb + y * imd + imf); - return pointOut; + return output; }; -module.exports = CameraToWorld; +module.exports = GetWorldPoint; diff --git a/v3/src/camera/2d/inc/WorldToCamera.js b/v3/src/camera/2d/inc/WorldToCamera.js deleted file mode 100644 index c57df3873..000000000 --- a/v3/src/camera/2d/inc/WorldToCamera.js +++ /dev/null @@ -1,65 +0,0 @@ -var TransformMatrix = require('../../../gameobjects/components/TransformMatrix'); -var matrix0 = new TransformMatrix(1, 0, 0, 1, 0, 0); -var matrix1 = new TransformMatrix(1, 0, 0, 1, 0, 0); -var WorldToCamera = function (pointIn, pointOut) -{ - if (!pointOut) - { - pointOut = { x: pointIn.x, y: pointIn.y }; - } - - var cameraMatrix = this.matrix.matrix; - var mva = cameraMatrix[0]; - var mvb = cameraMatrix[1]; - var mvc = cameraMatrix[2]; - var mvd = cameraMatrix[3]; - var mve = cameraMatrix[4]; - var mvf = cameraMatrix[5]; - - /* First Invert Matrix */ - var determinant = (mva * mvd) - (mvb * mvc); - - if (!determinant) - { - return pointIn; - } - - determinant = 1 / determinant; - - var ima = mvd * determinant; - var imb = -mvb * determinant; - var imc = -mvc * determinant; - var imd = mva * determinant; - var ime = (mvc * mvf - mvd * mve) * determinant; - var imf = (mvb * mve - mva * mvf) * determinant; - - matrix0.matrix[0] = ima; - matrix0.matrix[1] = imb; - matrix0.matrix[2] = imc; - matrix0.matrix[3] = imd; - matrix0.matrix[4] = ime; - matrix0.matrix[5] = imf; - - //var c = Math.cos(this.rotation); - //var s = Math.sin(this.rotation); - var zoom = this.zoom; - var scrollX = this.scrollX; - var scrollY = this.scrollY; - var x = pointIn.x;// + scrollX * zoom; - var y = pointIn.y;// + scrollY * zoom; - - //var x = pointIn.x - ((scrollX * c - scrollY * s) * zoom); - //var y = pointIn.y - ((scrollX * s + scrollY * c) * zoom); - - matrix1.applyITRS(scrollX, scrollY, 0.0, zoom, zoom); - //matrix1.invert(); - //matrix0.invert(); - - matrix0.multiply(matrix1); - - pointOut = matrix0.transformPoint(x, y, pointOut); - - return pointOut; -}; - -module.exports = WorldToCamera; diff --git a/v3/src/gameobjects/GameObject.js b/v3/src/gameobjects/GameObject.js index 8316ccbeb..a7152c6d1 100644 --- a/v3/src/gameobjects/GameObject.js +++ b/v3/src/gameobjects/GameObject.js @@ -244,6 +244,11 @@ var GameObject = new Class({ */ destroy: function () { + if (this.preDestroy) + { + this.preDestroy(); + } + this.scene.sys.displayList.remove(this); this.scene.sys.updateList.remove(this); diff --git a/v3/src/gameobjects/text/TextStyle.js b/v3/src/gameobjects/text/TextStyle.js index e660577dd..1b9810fe9 100644 --- a/v3/src/gameobjects/text/TextStyle.js +++ b/v3/src/gameobjects/text/TextStyle.js @@ -90,11 +90,6 @@ var TextStyle = new Class({ syncFont: function (canvas, context) { - if (this.rtl) - { - canvas.dir = 'rtl'; - } - context.font = this.font; context.textBaseline = 'alphabetic'; diff --git a/v3/src/gameobjects/text/static/Text.js b/v3/src/gameobjects/text/static/Text.js index 00fd3f62b..7b579c62e 100644 --- a/v3/src/gameobjects/text/static/Text.js +++ b/v3/src/gameobjects/text/static/Text.js @@ -1,11 +1,12 @@ - -var Class = require('../../../utils/Class'); -var GameObject = require('../../GameObject'); -var Components = require('../../components'); +var AddToDOM = require('../../../dom/AddToDOM'); var CanvasPool = require('../../../display/canvas/CanvasPool'); +var Class = require('../../../utils/Class'); +var Components = require('../../components'); +var GameObject = require('../../GameObject'); +var GetTextSize = require('../GetTextSize'); +var RemoveFromDOM = require('../../../dom/RemoveFromDOM'); var TextRender = require('./TextRender'); var TextStyle = require('../TextStyle'); -var GetTextSize = require('../GetTextSize'); var Text = new Class({ @@ -32,10 +33,6 @@ var Text = new Class({ { if (x === undefined) { x = 0; } if (y === undefined) { y = 0; } - if (text === undefined) { text = ''; } - - // Cast to string whatever our value may be (numeric, etc) - text = text.toString(); GameObject.call(this, scene, 'Text'); @@ -64,7 +61,8 @@ var Text = new Class({ */ this.splitRegExp = /(?:\r\n|\r|\n)/; - this.text = (Array.isArray(text)) ? text.join('\n') : text; + // This is populated in this.setText + this.text = ''; this.resolution = 1; @@ -81,10 +79,9 @@ var Text = new Class({ this.canvasTexture = null; this.dirty = false; - if (text !== '') - { - this.updateText(); - } + this.initRTL(); + + this.setText(text); var _this = this; @@ -95,6 +92,32 @@ var Text = new Class({ }); }, + initRTL: function () + { + if (!this.style.rtl) + { + return; + } + + // Here is where the crazy starts. + // + // Due to browser implementation issues, you cannot fillText BiDi text to a canvas + // that is not part of the DOM. It just completely ignores the direction property. + + this.canvas.dir = 'rtl'; + + // Experimental atm, but one day ... + this.context.direction = 'rtl'; + + // Add it to the DOM, but hidden within the parent canvas. + this.canvas.style.display = 'none'; + + AddToDOM(this.canvas, this.scene.sys.canvas); + + // And finally we set the x origin + this.originX = 1; + }, + setText: function (value) { if (Array.isArray(value)) @@ -255,13 +278,20 @@ var Text = new Class({ linePositionY += (textSize.lineSpacing * i); } - if (style.align === 'right') + if (style.rtl) { - linePositionX += textSize.width - textSize.lineWidths[i]; + linePositionX = w - linePositionX; } - else if (style.align === 'center') + else { - linePositionX += (textSize.width - textSize.lineWidths[i]) / 2; + if (style.align === 'right') + { + linePositionX += textSize.width - textSize.lineWidths[i]; + } + else if (style.align === 'center') + { + linePositionX += (textSize.width - textSize.lineWidths[i]) / 2; + } } if (this.autoRound) @@ -315,7 +345,18 @@ var Text = new Class({ out.data = data; return out; + }, + + preDestroy: function () + { + if (this.style.rtl) + { + RemoveFromDOM(this.canvas); + } + + CanvasPool.remove(this.canvas); } + }); module.exports = Text; diff --git a/v3/src/gameobjects/tilemap/ImageCollection.js b/v3/src/gameobjects/tilemap/ImageCollection.js index c16e0f7f9..d341cc0e1 100644 --- a/v3/src/gameobjects/tilemap/ImageCollection.js +++ b/v3/src/gameobjects/tilemap/ImageCollection.js @@ -1,3 +1,5 @@ +// Note: direct port from v2 + /** * An Image Collection is a special tileset containing mulitple images, with no slicing into each image. * diff --git a/v3/src/gameobjects/tilemap/ParseToTilemap.js b/v3/src/gameobjects/tilemap/ParseToTilemap.js index 32e90707e..d41d5e6a8 100644 --- a/v3/src/gameobjects/tilemap/ParseToTilemap.js +++ b/v3/src/gameobjects/tilemap/ParseToTilemap.js @@ -11,12 +11,12 @@ var Tilemap = require('./Tilemap'); * * @param {Scene} scene - [description] * @param {string} [key] - The key in the Phaser cache that corresponds to the loaded tilemap data. - * @param {number} [tileWidth=32] - The width of a tile in pixels. - * @param {number} [tileHeight=32] - The height of a tile in pixels. - * @param {number} [width=10] - The width of the map in tiles. - * @param {number} [height=10] - The height of the map in tiles. - * @param {array} [data] - Instead of loading from the cache, you can also load directly from a 2D - * array of tile indexes. + * @param {integer} [tileWidth=32] - The width of a tile in pixels. + * @param {integer} [tileHeight=32] - The height of a tile in pixels. + * @param {integer} [width=10] - The width of the map in tiles. + * @param {integer} [height=10] - The height of the map in tiles. + * @param {integer[][]} [data] - Instead of loading from the cache, you can also load directly from + * a 2D array of tile indexes. * @param {boolean} [insertNull=false] - Controls how empty tiles, tiles with an index of -1, in the * map data are handled. If `true`, empty locations will get a value of `null`. If `false`, empty * location will get a Tile object with an index of -1. If you've a large sparsely populated map and diff --git a/v3/src/gameobjects/tilemap/Tile.js b/v3/src/gameobjects/tilemap/Tile.js index 1e825f6c4..e4427dc5b 100644 --- a/v3/src/gameobjects/tilemap/Tile.js +++ b/v3/src/gameobjects/tilemap/Tile.js @@ -11,35 +11,197 @@ var Tile = new Class({ initialize: - function Tile (layer, index, x, y, width, height) + /** + * A Tile is a representation of a single tile within the Tilemap. This is a lightweight data + * representation, so it's position information is stored without factoring in scroll, layer + * scale or layer position. + * + * @class Tile + * @constructor + * + * @param {LayerData} layer - The LayerData object in the Tilemap that this tile belongs to. + * @param {integer} index - The unique index of this tile within the map. + * @param {integer} x - The x coordinate of this tile in tile coordinates. + * @param {integer} y - The y coordinate of this tile in tile coordinates. + * @param {integer} width - Width of the tile in pixels. + * @param {integer} height - Height of the tile in pixels. + * @param {integer} baseWidth - The base width a tile in the map (in pixels). Tiled maps support + * multiple tileset sizes within one map, but they are still placed at intervals of the base + * tile width. + * @param {integer} baseHeight - The base height of the tile in pixels (in pixels). Tiled maps + * support multiple tileset sizes within one map, but they are still placed at intervals of the + * base tile height. + */ + function Tile (layer, index, x, y, width, height, baseWidth, baseHeight) { + /** + * The LayerData in the Tilemap data that this tile belongs to. + * @property {LayerData} layer + */ this.layer = layer; - this.index = index; - this.x = x; - this.y = y; - this.worldX = x * width; - this.worldY = y * height; - this.width = width; - this.height = height; - this.properties = {}; - this.rotation = 0; - this.collideLeft = false; - this.collideRight = false; - this.collideUp = false; - this.collideDown = false; - this.faceLeft = false; - this.faceRight = false; - this.faceTop = false; - this.faceBottom = false; - this.collisionCallback = null; - this.collisionCallbackContext = this; - this.scanned = false; - // Note: tint is currently a single color value instead of the 4 corner tint component - this.tint = 0xFFFFFF; + /** + * The index of this tile within the map data corresponding to the tileset, or -1 if this + * represents a blank tile. + * @property {integer} index + */ + this.index = index; + + /** + * The x map coordinate of this tile in tile units. + * @property {integer} x + */ + this.x = x; + + /** + * The y map coordinate of this tile in tile units. + * @property {integer} y + */ + this.y = y; + + /** + * The width of the tile in pixels. + * @property {integer} width + */ + this.width = width; + + /** + * The height of the tile in pixels. + * @property {integer} height + */ + this.height = height; + + /** + * The map's base width of a tile in pixels. Tiled maps support multiple tileset sizes + * within one map, but they are still placed at intervals of the base tile size. + * @property {integer} baseWidth + */ + this.baseWidth = (baseWidth !== undefined) ? baseWidth : width; + + /** + * The map's base height of a tile in pixels. Tiled maps support multiple tileset sizes + * within one map, but they are still placed at intervals of the base tile size. + * @property {integer} baseHeight + */ + this.baseHeight = (baseHeight !== undefined) ? baseHeight : height; + + /** + * The world x coordinate of the top left of this tile in pixels. This does not factor in + * camera scroll, layer scale or layer position. + * @property {number} x + */ + this.worldX = 0; + + /** + * The world y coordinate of the top left of this tile in pixels. This does not factor in + * camera scroll, layer scale or layer position. + * @property {number} y + */ + this.worldY = 0; + + this.updateWorldXY(); + + /** + * Tile specific properties. These usually come from Tiled. + * @property {object} properties + */ + this.properties = {}; + + /** + * The rotation angle of this tile. + * @property {number} rotation + */ + this.rotation = 0; + + /** + * Whether the tile should collide with any object on the left side. + * @property {boolean} collideLeft + */ + this.collideLeft = false; + + /** + * Whether the tile should collide with any object on the right side. + * @property {boolean} collideRight + */ + this.collideRight = false; + + /** + * Whether the tile should collide with any object on the top side. + * @property {boolean} collideUp + */ + this.collideUp = false; + + /** + * Whether the tile should collide with any object on the bottom side. + * @property {boolean} collideDown + */ + this.collideDown = false; + + /** + * Whether the tile's left edge is interesting for collisions. + * @property {boolean} faceLeft + */ + this.faceLeft = false; + + /** + * Whether the tile's right edge is interesting for collisions. + * @property {boolean} faceRight + */ + this.faceRight = false; + + /** + * Whether the tile's top edge is interesting for collisions. + * @property {boolean} faceTop + */ + this.faceTop = false; + + /** + * Whether the tile's bottom edge is interesting for collisions. + * @property {boolean} faceBottom + */ + this.faceBottom = false; + + /** + * Tile collision callback. + * @property {function} collisionCallback + */ + this.collisionCallback = null; + + /** + * The context in which the collision callback will be called. + * @property {object} collisionCallbackContext + */ + this.collisionCallbackContext = this; + + /** + * The tint to apply to this tile. Note: tint is currently a single color value instead of + * the 4 corner tint component on other GameObjects. + * @property {number} Tint + * @default + */ + this.tint = 0xffffff; }, - // Copy everything except position & interesting faces + /** + * Check if the given x and y world coordinates are within this Tile. This does not factor in + * camera scroll, layer scale or layer position. + * + * @param {number} x - The x coordinate to test. + * @param {number} y - The y coordinate to test. + * @return {boolean} True if the coordinates are within this Tile, otherwise false. + */ + containsPoint: function (x, y) + { + return !(x < this.worldX || y < this.worldY || x > this.right || y > this.bottom); + }, + + /** + * Copies the tile data & properties from the given tile to this tile. This copies everything + * except for position and interesting faces. + * + * @param {Tile} tile - The tile to copy from. + * @returns {this} + */ copy: function (tile) { this.index = tile.index; @@ -59,12 +221,9 @@ var Tile = new Class({ return this; }, - // Does not factor in scroll offset or tilemap layer position - containsPoint: function (x, y) - { - return !(x < this.worldX || y < this.worldY || x > this.right || y > this.bottom); - }, - + /** + * Clean up memory. + */ destroy: function () { this.collisionCallback = undefined; @@ -72,12 +231,33 @@ var Tile = new Class({ this.properties = undefined; }, - // Does not factor in scroll offset or tilemap layer position + /** + * Check for intersection with this tile. This does not factor in camera scroll, layer scale or + * layer position. + * + * @param {number} x - The x axis in pixels. + * @param {number} y - The y axis in pixels. + * @param {number} right - The right point. + * @param {number} bottom - The bottom point. + * @return {boolean} + */ intersects: function (x, y, right, bottom) { - return !(right <= this.worldX || bottom <= this.worldY || x >= this.right || y >= this.bottom); + return !( + right <= this.worldX || bottom <= this.worldY || + x >= this.right || y >= this.bottom + ); }, + /** + * Checks if the tile is interesting. + * + * @param {boolean} collides - If true, will consider the tile interesting if it collides on any + * side. + * @param {boolean} faces - If true, will consider the tile interesting if it has an interesting + * face. + * @returns {boolean} True if the Tile is interesting, otherwise false. + */ isInteresting: function (collides, faces) { if (collides && faces) { return (this.canCollide || this.hasInterestingFace); } @@ -86,6 +266,11 @@ var Tile = new Class({ return false; }, + /** + * Reset collision status flags. + * + * @returns {this} + */ resetCollision: function () { this.collideLeft = false; @@ -97,8 +282,19 @@ var Tile = new Class({ this.faceBottom = false; this.faceLeft = false; this.faceRight = false; + + return this; }, + /** + * Sets the collision flags for each side of this tile and updates the interesting faces list. + * + * @param {boolean} left - Indicating collide with any object on the left. + * @param {boolean} right - Indicating collide with any object on the right. + * @param {boolean} up - Indicating collide with any object on the top. + * @param {boolean} down - Indicating collide with any object on the bottom. + * @returns {this} + */ setCollision: function (left, right, up, down) { if (right === undefined) { right = left; } @@ -114,11 +310,22 @@ var Tile = new Class({ this.faceRight = right; this.faceTop = up; this.faceBottom = down; + + return this; }, + /** + * Set a callback to be called when this tile is hit by an object. The callback must true for + * collision processing to take place. + * + * @param {function} callback - Callback function. + * @param {object} context - Callback will be called within this context. + * @returns {this} + */ setCollisionCallback: function (callback, context) { - if (callback === null) { + if (callback === null) + { this.collisionCallback = undefined; this.collisionCallbackContext = undefined; } @@ -127,17 +334,52 @@ var Tile = new Class({ this.collisionCallback = callback; this.collisionCallbackContext = context; } + + return this; }, - setSize: function (tileWidth, tileHeight) + /** + * Sets the size of the tile and updates its worldX and worldY. + * + * @param {integer} tileWidth - The width of the tile in pixels. + * @param {integer} tileHeight - The height of the tile in pixels. + * @param {integer} baseWidth - The base width a tile in the map (in pixels). + * @param {integer} baseHeight - The base height of the tile in pixels (in pixels). + * @returns {this} + */ + setSize: function (tileWidth, tileHeight, baseWidth, baseHeight) { - this.worldX = this.x * tileWidth; - this.worldY = this.y * tileHeight; - this.width = tileWidth; - this.height = tileHeight; + if (tileWidth !== undefined) { this.width = tileWidth; } + if (tileHeight !== undefined) { this.height = tileHeight; } + if (baseWidth !== undefined) { this.baseWidth = baseWidth; } + if (baseHeight !== undefined) { this.baseHeight = baseHeight; } + + this.updateWorldXY(); + + return this; }, - // True if this tile can collide on any of its faces or has a collision callback set. + /** + * Used internally. Updates the tile's world XY position based on the current tile size. + * + * @returns {this} + */ + updateWorldXY: function () + { + // Tiled places tiles on a grid of baseWidth x baseHeight. The origin for a tile is the + // bottom left, while the Phaser renderer assumes the origin is the top left. The y + // coordinate needs to be adjusted by the difference. + this.worldX = this.x * this.baseWidth; + this.worldY = this.y * this.baseHeight - (this.height - this.baseHeight); + + return this; + }, + + /** + * True if this tile can collide on any of its faces or has a collision callback set. + * @property {boolean} canCollide + * @readonly + */ canCollide: { get: function () { @@ -145,7 +387,11 @@ var Tile = new Class({ } }, - // True if this tile can collide on any of its faces. + /** + * True if this tile can collide on any of its faces. + * @property {boolean} canCollide + * @readonly + */ collides: { get: function () { @@ -153,7 +399,11 @@ var Tile = new Class({ } }, - // True if this tile has any interesting faces + /** + * True if this tile has any interesting faces. + * @property {boolean} canCollide + * @readonly + */ hasInterestingFace: { get: function () { @@ -161,6 +411,12 @@ var Tile = new Class({ } }, + /** + * The world position of the left side of the tile. This does not factor in camera scroll, layer + * scale or layer position. + * @property {integer} left + * @readonly + */ left: { get: function () { @@ -168,6 +424,12 @@ var Tile = new Class({ } }, + /** + * The world position of the right side of the tile. This does not factor in camera scroll, + * layer scale or layer position. + * @property {integer} right + * @readonly + */ right: { get: function () { @@ -175,6 +437,12 @@ var Tile = new Class({ } }, + /** + * The world position of the top side of the tile. This does not factor in camera scroll, + * layer scale or layer position. + * @property {integer} top + * @readonly + */ top: { get: function () { @@ -182,6 +450,12 @@ var Tile = new Class({ } }, + /** + * The world position of the bottom side of the tile. This does not factor in camera scroll, + * layer scale or layer position. + * @property {integer} bottom + * @readonly + */ bottom: { get: function () { @@ -189,6 +463,12 @@ var Tile = new Class({ } }, + /** + * The x world position of the center of the tile. This does not factor in camera scroll, layer + * scale or layer position. + * @property {integer} centerX + * @readonly + */ centerX: { get: function () { @@ -196,6 +476,12 @@ var Tile = new Class({ } }, + /** + * The y world position of the center of the tile. This does not factor in camera scroll, layer + * scale or layer position. + * @property {integer} centerY + * @readonly + */ centerY: { get: function () { diff --git a/v3/src/gameobjects/tilemap/Tilemap.js b/v3/src/gameobjects/tilemap/Tilemap.js index 0b845f8f5..05d49a464 100644 --- a/v3/src/gameobjects/tilemap/Tilemap.js +++ b/v3/src/gameobjects/tilemap/Tilemap.js @@ -14,32 +14,161 @@ var Tilemap = new Class({ initialize: + /** + * A Tilemap is a container for Tilemap data. This isn't a display object, rather, it holds data + * about the map and allows you to add tilesets and tilemap layers to it. A map can have one or + * more tilemap layers (StaticTilemapLayer or DynamicTilemapLayer), which are the display + * objects that actually render tiles. + * + * The Tilemap data be parsed from a Tiled JSON file, a CSV file or a 2D array. Tiled is a free + * software package specifically for creating tile maps, and is available from: + * http://www.mapeditor.org + * + * A Tilemap has handy methods for getting & manipulating the tiles within a layer. You can only + * use the methods that change tiles (e.g. removeTileAt) on a DynamicTilemapLayer. + * + * Note that all Tilemaps use a base tile size to calculate dimensions from, but that a + * StaticTilemapLayer or DynamicTilemapLayer may have its own unique tile size that overrides + * it. + * + * @class Tilemap + * @constructor + * + * @param {Scene} scene - [description] + * @param {MapData} mapData - A MapData instance containing Tilemap data. + */ function Tilemap (scene, mapData) { + /** + * @property {Scene} Scene + */ this.scene = scene; - this.tilesets = []; + /** + * The base width of a tile in pixels. Note that individual layers may have a different tile + * width. + * @property {integer} tileWidth + */ this.tileWidth = mapData.tileWidth; + + /** + * The base height of a tile in pixels. Note that individual layers may have a different + * tile height. + * @property {integer} tileHeight + */ this.tileHeight = mapData.tileHeight; + /** + * The width of the map (in tiles). + * @property {number} width + */ this.width = mapData.width; + + /** + * The height of the map (in tiles). + * @property {number} width + */ this.height = mapData.height; + + /** + * The orientation of the map data (as specified in Tiled), usually 'orthogonal'. + * @property {string} orientation + */ this.orientation = mapData.orientation; + + /** + * @property {number} format - The format of the map data. + */ this.format = mapData.format; + + /** + * The version of the map data (as specified in Tiled, usually 1). + * @property {number} version + */ this.version = mapData.version; + + /** + * Map specific properties as specified in Tiled. + * @property {object} properties + */ this.properties = mapData.properties; + + /** + * The width of the map in pixels based on width * tileWidth. + * @property {number} widthInPixels + */ this.widthInPixels = mapData.widthInPixels; + + /** + * The height of the map in pixels based on height * tileHeight. + * @property {number} heightInPixels + */ this.heightInPixels = mapData.heightInPixels; + + /** + * @property {ImageCollection[]} imagecollections + */ this.imageCollections = mapData.imageCollections; + + /** + * An array of Tiled Image Layers. + * @property {array} images + */ this.images = mapData.images; - this.collision = mapData.collision; + + /** + * An array of collision data. Specifically, any polyline objects defined in object layers. + * @property {array} collision + */ + this.collision = mapData.collision; // Note: this probably isn't useful anymore + + /** + * @property {LayerData[]} layers - An array of Tilemap layer data. + */ this.layers = mapData.layers; + + /** + * An array of Tilesets used in the map. + * @property {Tileset[]} tilesets + */ this.tilesets = mapData.tilesets; - this.tiles = mapData.tiles; + + /** + * An array of Tiled Object Layers. + * @property {array} objects + */ this.objects = mapData.objects; + + /** + * The index of the currently selected LayerData object. + * @property {integer} currentLayerIndex + */ this.currentLayerIndex = 0; }, + /** + * Adds an image to the map to be used as a tileset. A single map may use multiple tilesets. + * Note that the tileset name can be found in the JSON file exported from Tiled, or in the Tiled + * editor. + * + * @param {string} tilesetName - The name of the tileset as specified in the map data. + * @param {string} [key] - The key of the Phaser.Cache image used for this tileset. If + * `undefined` or `null` it will look for an image with a key matching the tileset parameter. + * @param {integer} [tileWidth] - The width of the tile (in pixels) in the Tileset Image. If not + * given it will default to the map's tileWidth value, or the tileWidth specified in the Tiled + * JSON file. + * @param {integer} [tileHeight] - The height of the tiles (in pixels) in the Tileset Image. If + * not given it will default to the map's tileHeight value, or the tileHeight specified in the + * Tiled JSON file. + * @param {integer} [tileMargin] - The margin around the tiles in the sheet (in pixels). If not + * specified, it will default to 0 or the value specified in the Tiled JSON file. + * @param {integer} [tileSpacing] - The spacing between each the tile in the sheet (in pixels). + * If not specified, it will default to 0 or the value specified in the Tiled JSON file. + * @param {integer} [gid=0] - If adding multiple tilesets to a blank map, specify the starting + * GID this set will use here. + * @return {Tileset|null} Returns the Tileset object that was created or updated, or null if it + * failed. + */ addTilesetImage: function (tilesetName, key, tileWidth, tileHeight, tileMargin, tileSpacing, gid) { if (tilesetName === undefined) { return null; } @@ -75,13 +204,77 @@ var Tilemap = new Class({ if (tileSpacing === undefined) { tileSpacing = 0; } if (gid === undefined) { gid = 0; } - var tileset = new Tileset(tilesetName, gid, tileWidth, tileHeight, tileMargin, tileSpacing, {}); + var tileset = new Tileset(tilesetName, gid, tileWidth, tileHeight, tileMargin, tileSpacing); tileset.setImage(texture); this.tilesets.push(tileset); return tileset; }, - // Creates & selects + /** + * Turns the StaticTilemapLayer associated with the given layer into a DynamicTilemapLayer. If + * no layer specified, the map's current layer is used. This is useful if you want to manipulate + * a map at the start of a scene, but then make it non-manipulable and optimize it for speed. + * + * @param {string|integer|DynamicTilemapLayer} [layer] - The name of the layer from Tiled, the + * index of the layer in the map, or a StaticTilemapLayer. + * @return {StaticTilemapLayer|null} Returns the new layer that was created, or null if it + * failed. + */ + convertLayerToStatic: function (layer) + { + layer = this.getLayer(layer); + if (layer === null) { return null; } + + var dynamicLayer = layer.tilemapLayer; + + if (!dynamicLayer || !(dynamicLayer instanceof DynamicTilemapLayer)) + { + return null; + } + + var staticLayer = new StaticTilemapLayer(dynamicLayer.scene, dynamicLayer.map, + dynamicLayer.layerIndex, dynamicLayer.tileset, dynamicLayer.x, dynamicLayer.y); + this.scene.sys.displayList.add(staticLayer); + + dynamicLayer.destroy(); + + return staticLayer; + }, + + /** + * See component documentation. If no layer specified, the map's current layer is used. This + * cannot be applied to StaticTilemapLayers. + * + * @return {this|null} Returns this, or null if the layer given was invalid. + */ + copy: function (srcTileX, srcTileY, width, height, destTileX, destTileY, recalculateFaces, layer) + { + layer = this.getLayer(layer); + if (this._isStaticCall(layer, 'copy')) { return this; } + if (layer !== null) + { + TilemapComponents.Copy(srcTileX, srcTileY, width, height, destTileX, destTileY, + recalculateFaces, layer); + } + return this; + }, + + /** + * Creates a new and empty DynamicTilemapLayer. The currently selected layer in the map is set + * to this new layer. + * + * @param {string} name - The name of this layer. Must be unique within the map. + * @param {Tileset} tileset - The tileset the new layer will use. + * @param {integer} width - The width of the layer in tiles. If not specified, it will default + * to the map's width. + * @param {integer} height - The height of the layer in tiles. If not specified, it will default + * to the map's height. + * @param {integer} tileWidth - The width of the tiles the layer uses for calculations. If not + * specified, it will default to the map's tileWidth. + * @param {integer} tileHeight - The height of the tiles the layer uses for calculations. If not + * specified, it will default to the map's tileHeight. + * @return {DynamicTilemapLayer|null} Returns the new layer was created, or null if it failed. + */ createBlankDynamicLayer: function (name, tileset, x, y, width, height, tileWidth, tileHeight) { if (tileWidth === undefined) { tileWidth = tileset.tileWidth; } @@ -127,6 +320,65 @@ var Tilemap = new Class({ return dynamicLayer; }, + /** + * Creates a new DynamicTilemapLayer that renders the LayerData associated with the given + * `layerID`. The currently selected layer in the map is set to this new layer. + * + * The `layerID` is important. If you've created your map in Tiled then you can get this by + * looking in Tiled and looking at the layer name. Or you can open the JSON file it exports and + * look at the layers[].name value. Either way it must match. + * + * Unlike a static layer, a dynamic layer can be modified. See DynamicTilemapLayer for more + * information. + * + * @param {integer|string} layerID - The layer array index value, or if a string is given, the + * layer name from Tiled. + * @param {Tileset} tileset - The tileset the new layer will use. + * @param {number} x - The x position to place the layer in the world. If not specified, it will + * default to the layer offset from Tiled or 0. + * @param {number} y - The y position to place the layer in the world. If not specified, it will + * default to the layer offset from Tiled or 0. + * @return {DynamicTilemapLayer|null} Returns the new layer was created, or null if it failed. + */ + createDynamicLayer: function (layerID, tileset, x, y) + { + var index = this.getLayerIndex(layerID); + + if (index === null) + { + console.warn('Cannot create tilemap layer, invalid layer ID given: ' + layerID); + return null; + } + + var layerData = this.layers[index]; + + // Check for an associated static or dynamic tilemap layer + if (layerData.tilemapLayer) + { + console.warn('Cannot create dynamic tilemap layer since a static or dynamic tilemap layer exists for layer ID:' + layerID); + return null; + } + + this.currentLayerIndex = index; + + // Make sure that all the LayerData & the tiles have the correct tile size. They usually + // are, but wouldn't match if you try to load a 2x or 4x res tileset when the map was made + // with a 1x res tileset. + if (layerData.tileWidth !== tileset.tileWidth || layerData.tileHeight !== tileset.tileHeight) + { + this.setLayerTileSize(tileset.tileWidth, tileset.tileHeight, index); + } + + // Default the x/y position to match Tiled layer offset, if it exists. + if (x === undefined && this.layers[index].x) { x = this.layers[index].x; } + if (y === undefined && this.layers[index].y) { y = this.layers[index].y; } + + var layer = new DynamicTilemapLayer(this.scene, this, index, tileset, x, y); + this.scene.sys.displayList.add(layer); + + return layer; + }, + /** * Creates a Sprite for every object matching the given gid in the map data. All properties from * the map data objectgroup are copied into the `spriteConfig`, so you can use this as an easy @@ -134,13 +386,13 @@ var Tilemap = new Class({ * property of alpha: 0.5 in the map editor will duplicate that when the Sprite is created. * * @param {string} name - The name of the object layer (from Tiled) to create Sprites from. - * @param {number} id - Either the id (object), gid (tile object) or name (object or tile - * object) from Tiled. Ids are unique in Tiled, but a gid is shared by all tile objects with the - * same graphic. The same name can be used on multiple objects. + * @param {integer|string} id - Either the id (object), gid (tile object) or name (object or + * tile object) from Tiled. Ids are unique in Tiled, but a gid is shared by all tile objects + * with the same graphic. The same name can be used on multiple objects. * @param {object} spriteConfig - The config object to pass into the Sprite creator (i.e. * scene.make.sprite). * @param {Scene} [scene=the scene the map is within] - The Scene to create the Sprites within. - * @return {array} An array of the Sprites that were created. + * @return {Sprite[]} An array of the Sprites that were created. */ createFromObjects: function (name, id, spriteConfig, scene) { @@ -212,7 +464,38 @@ var Tilemap = new Class({ return sprites; }, - // Creates & selects, uses layer offset if x,y undefined + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {Sprite[]|null} Returns an array of Tiles, or null if the layer given was invalid. + */ + createFromTiles: function (indexes, replacements, spriteConfig, scene, camera, layer) + { + layer = this.getLayer(layer); + if (layer === null) { return null; } + return TilemapComponents.CreateFromTiles(indexes, replacements, spriteConfig, scene, camera, layer); + }, + + /** + * Creates a new StaticTilemapLayer that renders the LayerData associated with the given + * `layerID`. The currently selected layer in the map is set to this new layer. + * + * The `layerID` is important. If you've created your map in Tiled then you can get this by + * looking in Tiled and looking at the layer name. Or you can open the JSON file it exports and + * look at the layers[].name value. Either way it must match. + * + * It's important to remember that a static layer cannot be modified. See StaticTilemapLayer for + * more information. + * + * @param {integer|string} layerID - The layer array index value, or if a string is given, the + * layer name from Tiled. + * @param {Tileset} tileset - The tileset the new layer will use. + * @param {number} x - The x position to place the layer in the world. If not specified, it will + * default to the layer offset from Tiled or 0. + * @param {number} y - The y position to place the layer in the world. If not specified, it will + * default to the layer offset from Tiled or 0. + * @return {StaticTilemapLayer|null} Returns the new layer was created, or null if it failed. + */ createStaticLayer: function (layerID, tileset, x, y) { var index = this.getLayerIndex(layerID); @@ -252,94 +535,24 @@ var Tilemap = new Class({ return layer; }, - // Creates & selects, uses layer offset if x,y undefined - createDynamicLayer: function (layerID, tileset, x, y) - { - var index = this.getLayerIndex(layerID); - - if (index === null) - { - console.warn('Cannot create tilemap layer, invalid layer ID given: ' + layerID); - return null; - } - - var layerData = this.layers[index]; - - // Check for an associated static or dynamic tilemap layer - if (layerData.tilemapLayer) - { - console.warn('Cannot create dynamic tilemap layer since a static or dynamic tilemap layer exists for layer ID:' + layerID); - return null; - } - - this.currentLayerIndex = index; - - // Make sure that all the LayerData & the tiles have the correct tile size. They usually - // are, but wouldn't match if you try to load a 2x or 4x res tileset when the map was made - // with a 1x res tileset. - if (layerData.tileWidth !== tileset.tileWidth || layerData.tileHeight !== tileset.tileHeight) - { - this.setLayerTileSize(tileset.tileWidth, tileset.tileHeight, index); - } - - // Default the x/y position to match Tiled layer offset, if it exists. - if (x === undefined && this.layers[index].x) { x = this.layers[index].x; } - if (y === undefined && this.layers[index].y) { y = this.layers[index].y; } - - var layer = new DynamicTilemapLayer(this.scene, this, index, tileset, x, y); - this.scene.sys.displayList.add(layer); - - return layer; - }, - - convertLayerToStatic: function (layer) - { - layer = this.getLayer(layer); - if (layer === null) { return null; } - - var dynamicLayer = layer.tilemapLayer; - - if (!dynamicLayer || !(dynamicLayer instanceof DynamicTilemapLayer)) - { - return null; - } - - var staticLayer = new StaticTilemapLayer(dynamicLayer.scene, dynamicLayer.map, - dynamicLayer.layerIndex, dynamicLayer.tileset, dynamicLayer.x, dynamicLayer.y); - this.scene.sys.displayList.add(staticLayer); - - dynamicLayer.destroy(); - - return staticLayer; - }, - - copy: function (srcTileX, srcTileY, width, height, destTileX, destTileY, recalculateFaces, layer) - { - layer = this.getLayer(layer); - if (this._isStaticCall(layer, 'copy')) { return this; } - if (layer !== null) - { - TilemapComponents.Copy(srcTileX, srcTileY, width, height, destTileX, destTileY, recalculateFaces, layer); - } - return this; - }, - - createFromTiles: function (indexes, replacements, spriteConfig, scene, camera, layer) - { - layer = this.getLayer(layer); - if (layer === null) { return null; } - return TilemapComponents.CreateFromTiles(indexes, replacements, spriteConfig, scene, camera, layer); - }, - + /** + * Removes all layer data from this Tilemap and nulls the scene reference. This will destroy any + * StaticTilemapLayers or DynamicTilemapLayers that have been linked to LayerData. + */ destroy: function () { - this.layers.length = 0; + this.removeAllLayers(); this.tilesets.length = 0; - this.tiles.length = 0; this.objects.length = 0; this.scene = undefined; }, + /** + * See component documentation. If no layer specified, the map's current layer is used. This + * cannot be applied to StaticTilemapLayers. + * + * @return {this|null} Returns this, or null if the layer given was invalid. + */ fill: function (index, tileX, tileY, width, height, recalculateFaces, layer) { layer = this.getLayer(layer); @@ -351,6 +564,11 @@ var Tilemap = new Class({ return this; }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {Tile[]|null} Returns an array of Tiles, or null if the layer given was invalid. + */ filterTiles: function (callback, context, tileX, tileY, width, height, filteringOptions, layer) { layer = this.getLayer(layer); @@ -358,6 +576,11 @@ var Tilemap = new Class({ return TilemapComponents.FilterTiles(callback, context, tileX, tileY, width, height, filteringOptions, layer); }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {Tile|null} Returns a Tiles, or null if the layer given was invalid. + */ findByIndex: function (findIndex, skip, reverse, layer) { layer = this.getLayer(layer); @@ -365,6 +588,11 @@ var Tilemap = new Class({ return TilemapComponents.FindByIndex(findIndex, skip, reverse, layer); }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {this|null} Returns this, or null if the layer given was invalid. + */ forEachTile: function (callback, context, tileX, tileY, width, height, filteringOptions, layer) { layer = this.getLayer(layer); @@ -375,11 +603,26 @@ var Tilemap = new Class({ return this; }, + /** + * Gets the image layer index based on its name. + * + * @method Phaser.Tilemap#getImageIndex + * @param {string} name - The name of the image to get. + * @return {integer} The index of the image in this tilemap, or null if not found. + */ getImageIndex: function (name) { return this.getIndex(this.images, name); }, + /** + * Internally used. Returns the index of the object in one of the Tilemap's arrays whose name + * property matches the given `name`. + * + * @param {array} location - The Tilemap array to search. + * @param {string} name - The name of the array element to get. + * @return {number} The index of the element in the array, or null if not found. + */ getIndex: function (location, name) { for (var i = 0; i < location.length; i++) @@ -392,12 +635,30 @@ var Tilemap = new Class({ return null; }, + /** + * Gets the LayerData from this.layers that is associated with `layer`, or null if an invalid + * `layer` is given. + * + * @param {string|integer|DynamicTilemapLayer|StaticTilemapLayer} [layer] - The name of the + * layer from Tiled, the index of the layer in the map, a DynamicTilemapLayer or a + * StaticTilemapLayer. If not given will default to the map's current layer index. + * @return {LayerData} The corresponding LayerData within this.layers. + */ getLayer: function (layer) { var index = this.getLayerIndex(layer); return index !== null ? this.layers[index] : null; }, + /** + * Gets the LayerData index of the given `layer` within this.layers, or null if an invalid + * `layer` is given. + * + * @param {string|integer|DynamicTilemapLayer|StaticTilemapLayer} [layer] - The name of the + * layer from Tiled, the index of the layer in the map, a DynamicTilemapLayer or a + * StaticTilemapLayer. If not given will default to the map's current layer index. + * @return {integer} The LayerData index within this.layers. + */ getLayerIndex: function (layer) { if (layer === undefined) @@ -422,11 +683,23 @@ var Tilemap = new Class({ } }, + /** + * Gets the index of the LayerData within this.layers that has the given `name`, or null if an + * invalid `name` is given. + * + * @param {string} name - The name of the layer to get. + * @return {integer} The LayerData index within this.layers. + */ getLayerIndexByName: function (name) { return this.getIndex(this.layers, name); }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {Tile|null} Returns a Tile, or null if the layer given was invalid. + */ getTileAt: function (tileX, tileY, nonNull, layer) { layer = this.getLayer(layer); @@ -434,6 +707,11 @@ var Tilemap = new Class({ return TilemapComponents.GetTileAt(tileX, tileY, nonNull, layer); }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {Tile|null} Returns a Tile, or null if the layer given was invalid. + */ getTileAtWorldXY: function (worldX, worldY, nonNull, camera, layer) { layer = this.getLayer(layer); @@ -441,6 +719,11 @@ var Tilemap = new Class({ return TilemapComponents.GetTileAtWorldXY(worldX, worldY, nonNull, camera, layer); }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {Tile[]|null} Returns an array of Tiles, or null if the layer given was invalid. + */ getTilesWithin: function (tileX, tileY, width, height, filteringOptions, layer) { layer = this.getLayer(layer); @@ -448,6 +731,11 @@ var Tilemap = new Class({ return TilemapComponents.GetTilesWithin(tileX, tileY, width, height, filteringOptions, layer); }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {Tile[]|null} Returns an array of Tiles, or null if the layer given was invalid. + */ getTilesWithinShape: function (shape, filteringOptions, camera, layer) { layer = this.getLayer(layer); @@ -455,6 +743,11 @@ var Tilemap = new Class({ return TilemapComponents.GetTilesWithinShape(shape, filteringOptions, camera, layer); }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {Tile[]|null} Returns an array of Tiles, or null if the layer given was invalid. + */ getTilesWithinWorldXY: function (worldX, worldY, width, height, filteringOptions, camera, layer) { layer = this.getLayer(layer); @@ -462,11 +755,23 @@ var Tilemap = new Class({ return TilemapComponents.GetTilesWithinWorldXY(worldX, worldY, width, height, filteringOptions, camera, layer); }, + /** + * Gets the index of the Tileset within this.tilesets that has the given `name`, or null if an + * invalid `name` is given. + * + * @param {string} name - The name of the Tileset to get. + * @return {integer} The Tileset index within this.tilesets. + */ getTilesetIndex: function (name) { return this.getIndex(this.tilesets, name); }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {boolean|null} Returns a boolean, or null if the layer given was invalid. + */ hasTileAt: function (tileX, tileY, layer) { layer = this.getLayer(layer); @@ -474,6 +779,11 @@ var Tilemap = new Class({ return TilemapComponents.HasTileAt(tileX, tileY, layer); }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {boolean|null} Returns a boolean, or null if the layer given was invalid. + */ hasTileAtWorldXY: function (worldX, worldY, camera, layer) { layer = this.getLayer(layer); @@ -481,6 +791,11 @@ var Tilemap = new Class({ return TilemapComponents.HasTileAtWorldXY(worldX, worldY, camera, layer); }, + /** + * The LayerData object that is currently selected in the map. You can set this property using + * any type supported by setLayer. + * @property {LayerData} layer + */ layer: { get: function () { @@ -493,6 +808,12 @@ var Tilemap = new Class({ } }, + /** + * See component documentation. If no layer specified, the map's current layer is used. This + * cannot be applied to StaticTilemapLayers. + * + * @return {Tile|null} Returns a Tile, or null if the layer given was invalid. + */ putTileAt: function (tile, tileX, tileY, recalculateFaces, layer) { layer = this.getLayer(layer); @@ -501,6 +822,12 @@ var Tilemap = new Class({ return TilemapComponents.PutTileAt(tile, tileX, tileY, recalculateFaces, layer); }, + /** + * See component documentation. If no layer specified, the map's current layer is used. This + * cannot be applied to StaticTilemapLayers. + * + * @return {Tile|null} Returns a Tile, or null if the layer given was invalid. + */ putTileAtWorldXY: function (tile, worldX, worldY, recalculateFaces, camera, layer) { layer = this.getLayer(layer); @@ -509,6 +836,29 @@ var Tilemap = new Class({ return TilemapComponents.PutTileAtWorldXY(tile, worldX, worldY, recalculateFaces, camera, layer); }, + /** + * See component documentation. If no layer specified, the map's current layer is used. This + * cannot be applied to StaticTilemapLayers. + * + * @return {this|null} Returns this, or null if the layer given was invalid. + */ + putTilesAt: function (tilesArray, tileX, tileY, recalculateFaces, layer) + { + layer = this.getLayer(layer); + if (this._isStaticCall(layer, 'putTilesAt')) { return this; } + if (layer !== null) + { + TilemapComponents.PutTilesAt(tilesArray, tileX, tileY, recalculateFaces, layer); + } + return this; + }, + + /** + * See component documentation. If no layer specified, the map's current layer is used. This + * cannot be applied to StaticTilemapLayers. + * + * @return {this|null} Returns this, or null if the layer given was invalid. + */ randomize: function (tileX, tileY, width, height, indexes, layer) { layer = this.getLayer(layer); @@ -520,6 +870,11 @@ var Tilemap = new Class({ return this; }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {this|null} Returns this, or null if the layer given was invalid. + */ calculateFacesWithin: function (tileX, tileY, width, height, layer) { layer = this.getLayer(layer); @@ -528,13 +883,33 @@ var Tilemap = new Class({ return this; }, + /** + * Removes all layers from this Tilemap and destroys any associated StaticTilemapLayers or + * DynamicTilemapLayers. + * + * @return {this} + */ removeAllLayers: function () { + // Destroy any StaticTilemapLayers or DynamicTilemapLayers that are stored in LayerData + for (var i = 0; i < this.layers.length; i++) + { + if (this.layers[i].tilemapLayer) + { + this.layers[i].tilemapLayer.destroy(); + } + } this.layers.length = 0; this.currentLayerIndex = 0; return this; }, + /** + * See component documentation. If no layer specified, the map's current layer is used. This + * cannot be applied to StaticTilemapLayers. + * + * @return {Tile|null} Returns a Tile, or null if the layer given was invalid. + */ removeTileAt: function (tileX, tileY, replaceWithNull, recalculateFaces, layer) { layer = this.getLayer(layer); @@ -543,6 +918,12 @@ var Tilemap = new Class({ return TilemapComponents.RemoveTileAt(tileX, tileY, replaceWithNull, recalculateFaces, layer); }, + /** + * See component documentation. If no layer specified, the map's current layer is used. This + * cannot be applied to StaticTilemapLayers. + * + * @return {Tile|null} Returns a Tile, or null if the layer given was invalid. + */ removeTileAtWorldXY: function (worldX, worldY, replaceWithNull, recalculateFaces, camera, layer) { layer = this.getLayer(layer); @@ -551,6 +932,11 @@ var Tilemap = new Class({ return TilemapComponents.RemoveTileAtWorldXY(worldX, worldY, replaceWithNull, recalculateFaces, camera, layer); }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {this|null} Returns this, or null if the layer given was invalid. + */ renderDebug: function (graphics, styleConfig, layer) { layer = this.getLayer(layer); @@ -559,6 +945,12 @@ var Tilemap = new Class({ return this; }, + /** + * See component documentation. If no layer specified, the map's current layer is used. This + * cannot be applied to StaticTilemapLayers. + * + * @return {this|null} Returns this, or null if the layer given was invalid. + */ replaceByIndex: function (findIndex, newIndex, tileX, tileY, width, height, layer) { layer = this.getLayer(layer); @@ -570,6 +962,11 @@ var Tilemap = new Class({ return this; }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {this|null} Returns this, or null if the layer given was invalid. + */ setCollision: function (indexes, collides, recalculateFaces, layer) { layer = this.getLayer(layer); @@ -578,6 +975,11 @@ var Tilemap = new Class({ return this; }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {this|null} Returns this, or null if the layer given was invalid. + */ setCollisionBetween: function (start, stop, collides, recalculateFaces, layer) { layer = this.getLayer(layer); @@ -586,6 +988,11 @@ var Tilemap = new Class({ return this; }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {this|null} Returns this, or null if the layer given was invalid. + */ setCollisionByExclusion: function (indexes, collides, recalculateFaces, layer) { layer = this.getLayer(layer); @@ -594,6 +1001,11 @@ var Tilemap = new Class({ return this; }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {this|null} Returns this, or null if the layer given was invalid. + */ setTileIndexCallback: function (indexes, callback, callbackContext, layer) { layer = this.getLayer(layer); @@ -602,6 +1014,11 @@ var Tilemap = new Class({ return this; }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {this|null} Returns this, or null if the layer given was invalid. + */ setTileLocationCallback: function (tileX, tileY, width, height, callback, callbackContext, layer) { layer = this.getLayer(layer); @@ -610,6 +1027,14 @@ var Tilemap = new Class({ return this; }, + /** + * Sets the current layer to the LayerData associated with `layer`. + * + * @param {string|integer|DynamicTilemapLayer|StaticTilemapLayer} [layer] - The name of the + * layer from Tiled, the index of the layer in the map, a DynamicTilemapLayer or a + * StaticTilemapLayer. If not given will default to the map's current layer index. + * @return {this} + */ setLayer: function (layer) { var index = this.getLayerIndex(layer); @@ -620,15 +1045,56 @@ var Tilemap = new Class({ return this; }, + /** + * Sets the base tile size for the map. Note: this does not necessarily match the tileWidth and + * tileHeight for all layers. This also updates the base size on all tiles across all layers. + * + * @param {integer} tileWidth - The width of the tiles the map uses for calculations. + * @param {integer} tileHeight - The height of the tiles the map uses for calculations. + * @return {this} + */ setBaseTileSize: function (tileWidth, tileHeight) { this.tileWidth = tileWidth; this.tileHeight = tileHeight; this.widthInPixels = this.width * tileWidth; this.heightInPixels = this.height * tileHeight; + + // Update the base tile size on all tiles + for (var i = 0; i < this.layers.length; i++) + { + var mapData = this.layers[i].data; + var mapWidth = this.layers[i].width; + var mapHeight = this.layers[i].height; + + for (var row = 0; row < mapHeight; ++row) + { + for (var col = 0; col < mapWidth; ++col) + { + var tile = mapData[row][col]; + if (tile !== null) + { + tile.setSize(undefined, undefined, tileWidth, tileHeight); + } + } + } + } + + return this; }, - // Sets the tile size for a given layer + /** + * Sets the tile size for a specific `layer`. Note: this does not necessarily match the map's + * tileWidth and tileHeight for all layers. This will set the tile size for the layer and any + * tiles the layer has. + * + * @param {integer} tileWidth - The width of the tiles (in pixels) in the layer. + * @param {integer} tileHeight - The height of the tiles (in pixels) in the layer. + * @param {string|integer|DynamicTilemapLayer|StaticTilemapLayer} [layer] - The name of the + * layer from Tiled, the index of the layer in the map, a DynamicTilemapLayer or a + * StaticTilemapLayer. If not given will default to the map's current layer index. + * @return {this} + */ setLayerTileSize: function (tileWidth, tileHeight, layer) { layer = this.getLayer(layer); @@ -653,6 +1119,12 @@ var Tilemap = new Class({ return this; }, + /** + * See component documentation. If no layer specified, the map's current layer is used. This + * cannot be applied to StaticTilemapLayers. + * + * @return {this|null} Returns this, or null if the layer given was invalid. + */ shuffle: function (tileX, tileY, width, height, layer) { layer = this.getLayer(layer); @@ -664,6 +1136,12 @@ var Tilemap = new Class({ return this; }, + /** + * See component documentation. If no layer specified, the map's current layer is used. This + * cannot be applied to StaticTilemapLayers. + * + * @return {this|null} Returns this, or null if the layer given was invalid. + */ swapByIndex: function (indexA, indexB, tileX, tileY, width, height, layer) { layer = this.getLayer(layer); @@ -675,6 +1153,11 @@ var Tilemap = new Class({ return this; }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {number|null} Returns this, or null if the layer given was invalid. + */ worldToTileX: function (worldX, snapToFloor, camera, layer) { layer = this.getLayer(layer); @@ -682,6 +1165,11 @@ var Tilemap = new Class({ return TilemapComponents.WorldToTileX(worldX, snapToFloor, camera, layer); }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {number|null} Returns this, or null if the layer given was invalid. + */ worldToTileY: function (worldY, snapToFloor, camera, layer) { layer = this.getLayer(layer); @@ -689,6 +1177,11 @@ var Tilemap = new Class({ return TilemapComponents.WorldToTileY(worldY, snapToFloor, camera, layer); }, + /** + * See component documentation. If no layer specified, the map's current layer is used. + * + * @return {Vector|null} Returns this, or null if the layer given was invalid. + */ worldToTileXY: function (worldX, worldY, snapToFloor, point, camera, layer) { layer = this.getLayer(layer); @@ -696,6 +1189,12 @@ var Tilemap = new Class({ return TilemapComponents.WorldToTileXY(worldX, worldY, snapToFloor, point, camera, layer); }, + /** + * Used internally to check if a layer is static and prints out a warning. + * + * @private + * @return {boolean} + */ _isStaticCall: function (layer, functionName) { if (layer.tilemapLayer instanceof StaticTilemapLayer) diff --git a/v3/src/gameobjects/tilemap/TilemapCreator.js b/v3/src/gameobjects/tilemap/TilemapCreator.js index de17581d0..851d56543 100644 --- a/v3/src/gameobjects/tilemap/TilemapCreator.js +++ b/v3/src/gameobjects/tilemap/TilemapCreator.js @@ -4,20 +4,20 @@ var ParseToTilemap = require('./ParseToTilemap'); // When registering a factory function 'this' refers to the GameObjectCreator context. /** - * Creates a Tilemap from the given key or data, or creates a blank Tilemap if no key/data - * provided. When loading from CSV or a 2D array, you should specify the tileWidth & tileHeight. When - * parsing from a map from Tiled, the tileWidth, tileHeight, width & height will be pulled from the - * map data. For an empty map, you should specify tileWidth, tileHeight, width & height. + * Creates a Tilemap from the given key or data, or creates a blank Tilemap if no key/data provided. + * When loading from CSV or a 2D array, you should specify the tileWidth & tileHeight. When parsing + * from a map from Tiled, the tileWidth, tileHeight, width & height will be pulled from the map + * data. For an empty map, you should specify tileWidth, tileHeight, width & height. * * @param {object} [config] - The config options for the Tilemap. * @param {string} [config.key] - The key in the Phaser cache that corresponds to the loaded tilemap * data. - * @param {array} [config.data] - Instead of loading from the cache, you can also load directly from - * a 2D array of tile indexes. - * @param {number} [config.tileWidth=32] - The width of a tile in pixels. - * @param {number} [config.tileHeight=32] - The height of a tile in pixels. - * @param {number} [config.width=10] - The width of the map in tiles. - * @param {number} [config.height=10] - The height of the map in tiles. + * @param {integer[][]} [config.data] - Instead of loading from the cache, you can also load + * directly from a 2D array of tile indexes. + * @param {integer} [config.tileWidth=32] - The width of a tile in pixels. + * @param {integer} [config.tileHeight=32] - The height of a tile in pixels. + * @param {integer} [config.width=10] - The width of the map in tiles. + * @param {integer} [config.height=10] - The height of the map in tiles. * @param {boolean} [config.insertNull=false] - Controls how empty tiles, tiles with an index of -1, * in the map data are handled. If `true`, empty locations will get a value of `null`. If `false`, * empty location will get a Tile object with an index of -1. If you've a large sparsely populated diff --git a/v3/src/gameobjects/tilemap/TilemapFactory.js b/v3/src/gameobjects/tilemap/TilemapFactory.js index 6c4e482f7..463aad167 100644 --- a/v3/src/gameobjects/tilemap/TilemapFactory.js +++ b/v3/src/gameobjects/tilemap/TilemapFactory.js @@ -16,16 +16,16 @@ var ParseToTilemap = require('./ParseToTilemap'); * data. For an empty map, you should specify tileWidth, tileHeight, width & height. * * @param {string} [key] - The key in the Phaser cache that corresponds to the loaded tilemap data. - * @param {number} [tileWidth=32] - The width of a tile in pixels. Pass in `null` to leave as the + * @param {integer} [tileWidth=32] - The width of a tile in pixels. Pass in `null` to leave as the * default. - * @param {number} [tileHeight=32] - The height of a tile in pixels. Pass in `null` to leave as the + * @param {integer} [tileHeight=32] - The height of a tile in pixels. Pass in `null` to leave as the * default. - * @param {number} [width=10] - The width of the map in tiles. Pass in `null` to leave as the + * @param {integer} [width=10] - The width of the map in tiles. Pass in `null` to leave as the * default. - * @param {number} [height=10] - The height of the map in tiles. Pass in `null` to leave as the + * @param {integer} [height=10] - The height of the map in tiles. Pass in `null` to leave as the * default. - * @param {array} [data] - Instead of loading from the cache, you can also load directly from a 2D - * array of tile indexes. Pass in `null` for no data. + * @param {integer[][]} [data] - Instead of loading from the cache, you can also load directly from + * a 2D array of tile indexes. Pass in `null` for no data. * @param {boolean} [insertNull=false] - Controls how empty tiles, tiles with an index of -1, in the * map data are handled. If `true`, empty locations will get a value of `null`. If `false`, empty * location will get a Tile object with an index of -1. If you've a large sparsely populated map and diff --git a/v3/src/gameobjects/tilemap/Tileset.js b/v3/src/gameobjects/tilemap/Tileset.js index 803d0a453..e702215cb 100644 --- a/v3/src/gameobjects/tilemap/Tileset.js +++ b/v3/src/gameobjects/tilemap/Tileset.js @@ -4,48 +4,155 @@ var Tileset = new Class({ initialize: - function Tileset (name, firstgid, tileWidth, tileHeight, tileMargin, tileSpacing, properties, tileData) + /** + * A Tileset is a combination of an image containing the tiles and a container for data about + * each tile. + * + * @class Tileset + * @constructor + * + * @param {string} name - The name of the tileset in the map data. + * @param {integer} firstgid - The first tile index this tileset contains. + * @param {integer} [tileWidth=32] - Width of each tile (in pixels). + * @param {integer} [tileHeight=32] - Height of each tile (in pixels). + * @param {integer} [tileMargin=0] - The margin around all tiles in the sheet (in pixels). + * @param {integer} [tileSpacing=0] - The spacing between each tile in the sheet (in pixels). + * @param {object} [tileProperties={}] - Custom properties defined per tile in the Tileset. + * These typically are custom properties created in Tiled when editing a tileset. + * @param {object} [tileData={}] - Data stored per tile. These typically are created in Tiled + * when editing a tileset, e.g. from Tiled's tile collision editor or terrain editor. + */ + function Tileset (name, firstgid, tileWidth, tileHeight, tileMargin, tileSpacing, tileProperties, tileData) { if (tileWidth === undefined || tileWidth <= 0) { tileWidth = 32; } if (tileHeight === undefined || tileHeight <= 0) { tileHeight = 32; } if (tileMargin === undefined) { tileMargin = 0; } if (tileSpacing === undefined) { tileSpacing = 0; } - if (properties === undefined) { properties = {}; } + if (tileProperties === undefined) { tileProperties = {}; } if (tileData === undefined) { tileData = {}; } + /** + * The name of the Tileset. + * @property {string} name + */ this.name = name; + + /** + * The starting index of the first tile index this Tileset contains. + * @property {integer} firstgid + */ this.firstgid = firstgid; + + /** + * The width of each tile (in pixels). Use setTileSize to change. + * @property {integer} tileWidth + * @readonly + */ this.tileWidth = tileWidth; + + /** + * The height of each tile (in pixels). Use setTileSize to change. + * @property {integer} tileHeight + * @readonly + */ this.tileHeight = tileHeight; + + /** + * The margin around the tiles in the sheet (in pixels). Use `setSpacing` to change. + * @property {integer} tileMargin + * @readonly + */ this.tileMargin = tileMargin; + + /** + * The spacing between each the tile in the sheet (in pixels). Use `setSpacing` to change. + * @property {integer} tileSpacing + * @readonly + */ this.tileSpacing = tileSpacing; - this.properties = properties; + + /** + * Tileset-specific properties per tile that are typically defined in the Tiled editor. + * @property {object} tileProperties + */ + this.tileProperties = tileProperties; + + /** + * Tileset-specific data per tile that are typically defined in the Tiled editor. This is + * where collision objects and terrain are stored. + * @property {object} tileData + */ this.tileData = tileData; + + /** + * The cached image that contains the individual tiles. Use setImage to set. + * @property {Texture|null} image + * @readonly + */ this.image = null; + + /** + * The number of tile rows in the the tileset. + * @property {integer} rows + * @readonly + */ this.rows = 0; + + /** + * The number of tile columns in the tileset. + * @property {integer} columns + * @readonly + */ this.columns = 0; + + /** + * The total number of tiles in the tileset. + * @property {integer} total + * @readonly + */ this.total = 0; + + /** + * The look-up table to specific tile image texture coordinates (UV in pixels). Each element + * contains the coordinates for a tile in an object of the form {x, y}. + * @property {object[]} texCoordinates + * @readonly + */ this.texCoordinates = []; }, + /** + * Get a tile's properties that are stored in the Tileset. Returns null if tile index is not + * contained in this Tileset. + * + * @param {integer} tileIndex - The unique id of the tile across all tilesets in the map. + * @returns {object|undefined|null} + */ getTileProperty: function (tileIndex) { if (!this.containsTileIndex(tileIndex)) { return null; } - return this.properties[tileIndex - this.firstgid]; + return this.tileProperties[tileIndex - this.firstgid]; }, + /** + * Get a tile's data that is stored in the Tileset. Returns null if tile index is not + * contained in this Tileset. + * + * @param {integer} tileIndex - The unique id of the tile across all tilesets in the map. + * @returns {object|undefined|null} + */ getTileData: function (tileIndex) { if (!this.containsTileIndex(tileIndex)) { return null; } return this.tileData[tileIndex - this.firstgid]; }, - setImage: function (texture) - { - this.image = texture; - this.updateTileData(this.image.source[0].width, this.image.source[0].height); - }, - + /** + * Returns true if and only if this Tileset contains the given tile index. + * + * @param {integer} tileIndex - The unique id of the tile across all tilesets in the map. + * @returns {boolean} + */ containsTileIndex: function (tileIndex) { return ( @@ -54,12 +161,40 @@ var Tileset = new Class({ ); }, + /** + * Returns the texture coordinates (UV in pixels) in the Tileset image for the given tile index. + * Returns null if tile index is not contained in this Tileset. + * + * @param {integer} tileIndex - The unique id of the tile across all tilesets in the map. + * @returns {object|null} Object in the form { x, y } representing the top-left UV coordinate + * within the Tileset image. + */ getTileTextureCoordinates: function (tileIndex) { if (!this.containsTileIndex(tileIndex)) { return null; } return this.texCoordinates[tileIndex - this.firstgid]; }, + /** + * Sets the image associated with this Tileset and updates the tile data (rows, columns, etc.). + * + * @param {Texture} texture - The image that contains the tiles. + * @returns {this} + */ + setImage: function (texture) + { + this.image = texture; + this.updateTileData(this.image.source[0].width, this.image.source[0].height); + return this; + }, + + /** + * Sets the tile width & height and updates the tile data (rows, columns, etc.). + * + * @param {integer} [tileWidth] - The width of a tile in pixels. + * @param {integer} [tileHeight] - The height of a tile in pixels. + * @returns {this} + */ setTileSize: function (tileWidth, tileHeight) { if (tileWidth !== undefined) { this.tileWidth = tileWidth; } @@ -69,8 +204,17 @@ var Tileset = new Class({ { this.updateTileData(this.image.source[0].width, this.image.source[0].height); } + + return this; }, + /** + * Sets the tile margin & spacing and updates the tile data (rows, columns, etc.). + * + * @param {integer} [margin] - The margin around the tiles in the sheet (in pixels). + * @param {integer} [spacing] - The spacing between the tiles in the sheet (in pixels). + * @returns {this} + */ setSpacing: function (margin, spacing) { if (margin !== undefined) { this.tileMargin = margin; } @@ -80,8 +224,17 @@ var Tileset = new Class({ { this.updateTileData(this.image.source[0].width, this.image.source[0].height); } + + return this; }, + /** + * Updates tile texture coordinates and tileset data. + * + * @param {integer} imageWidth - The (expected) width of the image to slice. + * @param {integer} imageHeight - The (expected) height of the image to slice. + * @returns {this} + */ updateTileData: function (imageWidth, imageHeight) { var rowCount = (imageHeight - this.tileMargin * 2 + this.tileSpacing) / (this.tileHeight + this.tileSpacing); @@ -92,8 +245,8 @@ var Tileset = new Class({ console.warn('Tileset ' + this.name + ' image tile area is not an even multiple of tile size'); } - // In Tiled a tileset image that is not an even multiple of the tile dimensions - // is truncated - hence the floor when calculating the rows/columns. + // In Tiled a tileset image that is not an even multiple of the tile dimensions is truncated + // - hence the floor when calculating the rows/columns. rowCount = Math.floor(rowCount); colCount = Math.floor(colCount); @@ -119,6 +272,8 @@ var Tileset = new Class({ tx = this.tileMargin; ty += this.tileHeight + this.tileSpacing; } + + return this; } }); diff --git a/v3/src/gameobjects/tilemap/components/CalculateFacesWithin.js b/v3/src/gameobjects/tilemap/components/CalculateFacesWithin.js index eaffcd16f..2a6499be2 100644 --- a/v3/src/gameobjects/tilemap/components/CalculateFacesWithin.js +++ b/v3/src/gameobjects/tilemap/components/CalculateFacesWithin.js @@ -6,10 +6,10 @@ var GetTilesWithin = require('./GetTilesWithin'); * layer. Interesting faces are used internally for optimizing collisions against tiles. This method * is mostly used internally. * - * @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 {integer} [tileX=0] - [description] + * @param {integer} [tileY=0] - [description] + * @param {integer} [width=max width based on tileX] - [description] + * @param {integer} [height=max height based on tileY] - [description] * @param {LayerData} layer - [description] */ var CalculateFacesWithin = function (tileX, tileY, width, height, layer) diff --git a/v3/src/gameobjects/tilemap/components/Copy.js b/v3/src/gameobjects/tilemap/components/Copy.js index fe390a16e..ab21c063e 100644 --- a/v3/src/gameobjects/tilemap/components/Copy.js +++ b/v3/src/gameobjects/tilemap/components/Copy.js @@ -6,13 +6,13 @@ var CalculateFacesWithin = require('./CalculateFacesWithin'); * coordinates) within the layer. This copies all tile properties & recalculates collision * information in the destination region. * - * @param {number} srcTileX - [description] - * @param {number} srcTileY - [description] - * @param {number} width - [description] - * @param {number} height - [description] - * @param {number} destTileX - [description] - * @param {number} destTileY - [description] - * @param {number} destTileY - [description] + * @param {integer} srcTileX - [description] + * @param {integer} srcTileY - [description] + * @param {integer} width - [description] + * @param {integer} height - [description] + * @param {integer} destTileX - [description] + * @param {integer} destTileY - [description] + * @param {integer} destTileY - [description] * @param {boolean} [recalculateFaces=true] - [description] * @param {LayerData} layer - [description] */ diff --git a/v3/src/gameobjects/tilemap/components/CreateFromTiles.js b/v3/src/gameobjects/tilemap/components/CreateFromTiles.js index e4737318c..ec358e03c 100644 --- a/v3/src/gameobjects/tilemap/components/CreateFromTiles.js +++ b/v3/src/gameobjects/tilemap/components/CreateFromTiles.js @@ -9,8 +9,8 @@ var ReplaceByIndex = require('./ReplaceByIndex'); * created. This is useful if you want to lay down special tiles in a level that are converted to * Sprites, but want to replace the tile itself with a floor tile or similar once converted. * - * @param {number|array} indexes - The tile index, or array of indexes, to create Sprites from. - * @param {number|array} replacements - The tile index, or array of indexes, to change a converted + * @param {integer|array} indexes - The tile index, or array of indexes, to create Sprites from. + * @param {integer|array} replacements - The tile index, or array of indexes, to change a converted * tile to. Set to `null` to leave the tiles unchanged. If an array is given, it is assumed to be a * one-to-one mapping with the indexes array. * @param {object} spriteConfig - The config object to pass into the Sprite creator (i.e. @@ -18,7 +18,7 @@ var ReplaceByIndex = require('./ReplaceByIndex'); * @param {Scene} [scene=scene the map is within] - The Scene to create the Sprites within. * @param {Camera} [camera=main camera] - The Camera to use when determining the world XY * @param {LayerData} layer - [description] - * @return {array} An array of the Sprites that were created. + * @return {Sprite[]} An array of the Sprites that were created. */ var CreateFromTiles = function (indexes, replacements, spriteConfig, scene, camera, layer) { diff --git a/v3/src/gameobjects/tilemap/components/CullTiles.js b/v3/src/gameobjects/tilemap/components/CullTiles.js index fa9e9cf8d..38c2ef4bb 100644 --- a/v3/src/gameobjects/tilemap/components/CullTiles.js +++ b/v3/src/gameobjects/tilemap/components/CullTiles.js @@ -5,7 +5,7 @@ * @param {LayerData} layer - [description] * @param {Camera} [camera=main camera] - [description] * @param {array} [outputArray] - [description] - * @returns {array} + * @returns {Tile[]} */ var CullTiles = function (layer, camera, outputArray) { diff --git a/v3/src/gameobjects/tilemap/components/Fill.js b/v3/src/gameobjects/tilemap/components/Fill.js index 7828a8ac8..6da21bbfe 100644 --- a/v3/src/gameobjects/tilemap/components/Fill.js +++ b/v3/src/gameobjects/tilemap/components/Fill.js @@ -6,11 +6,11 @@ var CalculateFacesWithin = require('./CalculateFacesWithin'); * specified index. Tiles will be set to collide if the given index is a colliding index. * Collision information in the region will be recalculated. * - * @param {number} index - [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 {integer} index - [description] + * @param {integer} [tileX=0] - [description] + * @param {integer} [tileY=0] - [description] + * @param {integer} [width=max width based on tileX] - [description] + * @param {integer} [height=max height based on tileY] - [description] * @param {boolean} [recalculateFaces=true] - [description] * @param {LayerData} layer - [description] */ diff --git a/v3/src/gameobjects/tilemap/components/FilterTiles.js b/v3/src/gameobjects/tilemap/components/FilterTiles.js index e64986917..e4fd9e2bd 100644 --- a/v3/src/gameobjects/tilemap/components/FilterTiles.js +++ b/v3/src/gameobjects/tilemap/components/FilterTiles.js @@ -5,14 +5,14 @@ var GetTilesWithin = require('./GetTilesWithin'); * filter callback function. Any tiles that pass the filter test (i.e. where the callback returns * true) will returned as a new array. Similar to Array.prototype.Filter in vanilla JS. * - * @param {number} callback - The callback. Each tile in the given area will be passed to this + * @param {function} callback - The callback. Each tile in the given area will be passed to this * callback as the first and only parameter. The callback should return true for tiles that pass the * filter. - * @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} [context] - The context under which the callback should be run. + * @param {integer} [tileX=0] - [description] + * @param {integer} [tileY=0] - [description] + * @param {integer} [width=max width based on tileX] - [description] + * @param {integer} [height=max height based on tileY] - [description] * @param {object} [filteringOptions] - Optional filters to apply when getting the tiles. * @param {boolean} [filteringOptions.isNotEmpty=false] - If true, only return tiles that don't have * -1 for an index. @@ -21,7 +21,7 @@ var GetTilesWithin = require('./GetTilesWithin'); * @param {boolean} [filteringOptions.hasInterestingFace=false] - If true, only return tiles that * have at least one interesting face. * @param {LayerData} layer - [description] - * @returns {array} The filtered array of Tiles. + * @returns {Tile[]} The filtered array of Tiles. */ var FilterTiles = function (callback, context, tileX, tileY, width, height, filteringOptions, layer) { diff --git a/v3/src/gameobjects/tilemap/components/FindByIndex.js b/v3/src/gameobjects/tilemap/components/FindByIndex.js index 9f5ba29ff..88e1787bb 100644 --- a/v3/src/gameobjects/tilemap/components/FindByIndex.js +++ b/v3/src/gameobjects/tilemap/components/FindByIndex.js @@ -5,9 +5,9 @@ * If the reverse boolean is true, it scans starting from the bottom-right corner traveling up to * the top-left. * - * @param {number} index - The tile index value to search for. - * @param {number} [skip=0] - The number of times to skip a matching tile before returning. - * @param {number} [reverse=false] - If true it will scan the layer in reverse, starting at the + * @param {integer} index - The tile index value to search for. + * @param {integer} [skip=0] - The number of times to skip a matching tile before returning. + * @param {boolean} [reverse=false] - If true it will scan the layer in reverse, starting at the * bottom-right. Otherwise it scans from the top-left. * @param {LayerData} layer - [description] * @return {Tile|null} The first (or n skipped) tile with the matching index. diff --git a/v3/src/gameobjects/tilemap/components/ForEachTile.js b/v3/src/gameobjects/tilemap/components/ForEachTile.js index f6750d77f..478f27318 100644 --- a/v3/src/gameobjects/tilemap/components/ForEachTile.js +++ b/v3/src/gameobjects/tilemap/components/ForEachTile.js @@ -4,13 +4,13 @@ var GetTilesWithin = require('./GetTilesWithin'); * For each tile in the given rectangular area (in tile coordinates) of the layer, run the given * callback. Similar to Array.prototype.forEach in vanilla JS. * - * @param {number} callback - The callback. Each tile in the given area will be passed to this + * @param {function} 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} [context] - The context under which the callback should be run. + * @param {integer} [tileX=0] - [description] + * @param {integer} [tileY=0] - [description] + * @param {integer} [width=max width based on tileX] - [description] + * @param {integer} [height=max height based on tileY] - [description] * @param {object} [filteringOptions] - Optional filters to apply when getting the tiles. * @param {boolean} [filteringOptions.isNotEmpty=false] - If true, only return tiles that don't have * -1 for an index. diff --git a/v3/src/gameobjects/tilemap/components/GetTileAt.js b/v3/src/gameobjects/tilemap/components/GetTileAt.js index 09721d21b..4bd634fed 100644 --- a/v3/src/gameobjects/tilemap/components/GetTileAt.js +++ b/v3/src/gameobjects/tilemap/components/GetTileAt.js @@ -3,8 +3,8 @@ 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 {integer} tileX - X position to get the tile from (given in tile units, not pixels). + * @param {integer} 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] diff --git a/v3/src/gameobjects/tilemap/components/GetTilesWithin.js b/v3/src/gameobjects/tilemap/components/GetTilesWithin.js index 16597fac6..2f3d33b85 100644 --- a/v3/src/gameobjects/tilemap/components/GetTilesWithin.js +++ b/v3/src/gameobjects/tilemap/components/GetTilesWithin.js @@ -3,10 +3,10 @@ var GetFastValue = require('../../../utils/object/GetFastValue'); /** * 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 {integer} [tileX=0] - [description] + * @param {integer} [tileY=0] - [description] + * @param {integer} [width=max width based on tileX] - [description] + * @param {integer} [height=max height based on tileY] - [description] * @param {object} [filteringOptions] - Optional filters to apply when getting the tiles. * @param {boolean} [filteringOptions.isNotEmpty=false] - If true, only return tiles that don't have * -1 for an index. @@ -15,7 +15,7 @@ var GetFastValue = require('../../../utils/object/GetFastValue'); * @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. + * @return {Tile[]} Array of Tile objects. */ var GetTilesWithin = function (tileX, tileY, width, height, filteringOptions, layer) { diff --git a/v3/src/gameobjects/tilemap/components/GetTilesWithinShape.js b/v3/src/gameobjects/tilemap/components/GetTilesWithinShape.js index 18e2c4d9a..b11ff0121 100644 --- a/v3/src/gameobjects/tilemap/components/GetTilesWithinShape.js +++ b/v3/src/gameobjects/tilemap/components/GetTilesWithinShape.js @@ -30,7 +30,7 @@ var TriangleToRectangle = function (triangle, rect) * have at least one interesting face. * @param {Camera} [camera=main camera] - [description] * @param {LayerData} layer - [description] - * @return {array} Array of Tile objects. + * @return {Tile[]} Array of Tile objects. */ var GetTilesWithinShape = function (shape, filteringOptions, camera, layer) { diff --git a/v3/src/gameobjects/tilemap/components/GetTilesWithinWorldXY.js b/v3/src/gameobjects/tilemap/components/GetTilesWithinWorldXY.js index ad9b67a18..94d028153 100644 --- a/v3/src/gameobjects/tilemap/components/GetTilesWithinWorldXY.js +++ b/v3/src/gameobjects/tilemap/components/GetTilesWithinWorldXY.js @@ -18,7 +18,7 @@ var WorldToTileY = require('./WorldToTileY'); * have at least one interesting face. * @param {Camera} [camera=main camera] - [description] * @param {LayerData} layer - [description] - * @return {array} Array of Tile objects. + * @return {Tile[]} Array of Tile objects. */ var GetTilesWithinWorldXY = function (worldX, worldY, width, height, filteringOptions, camera, layer) { diff --git a/v3/src/gameobjects/tilemap/components/HasTileAt.js b/v3/src/gameobjects/tilemap/components/HasTileAt.js index 998b1dbbe..7500b0c28 100644 --- a/v3/src/gameobjects/tilemap/components/HasTileAt.js +++ b/v3/src/gameobjects/tilemap/components/HasTileAt.js @@ -4,8 +4,8 @@ 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 {integer} tileX - [description] + * @param {integer} tileY - [description] * @param {LayerData} layer - [description] * @return {boolean} */ diff --git a/v3/src/gameobjects/tilemap/components/IsInLayerBounds.js b/v3/src/gameobjects/tilemap/components/IsInLayerBounds.js index 5ba52b3f6..c85f9d6a6 100644 --- a/v3/src/gameobjects/tilemap/components/IsInLayerBounds.js +++ b/v3/src/gameobjects/tilemap/components/IsInLayerBounds.js @@ -1,8 +1,8 @@ /** * Checks if the given tile coordinates are within the bounds of the layer. * - * @param {number} tileX - [description] - * @param {number} tileY - [description] + * @param {integer} tileX - [description] + * @param {integer} tileY - [description] * @param {LayerData} layer - [description] * @return {boolean} */ diff --git a/v3/src/gameobjects/tilemap/components/PutTileAt.js b/v3/src/gameobjects/tilemap/components/PutTileAt.js index f1a7e2116..8530303f3 100644 --- a/v3/src/gameobjects/tilemap/components/PutTileAt.js +++ b/v3/src/gameobjects/tilemap/components/PutTileAt.js @@ -8,9 +8,9 @@ var RecalculateFacesAt = require('./RecalculateFacesAt'); * 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 {integer|Tile} tile - The index of this tile to set or a Tile object. + * @param {integer} tileX - [description] + * @param {integer} tileY - [description] * @param {boolean} [recalculateFaces=true] - [description] * @param {LayerData} layer - [description] * @return {Tile} The Tile object that was created or added to this map. diff --git a/v3/src/gameobjects/tilemap/components/PutTileAtWorldXY.js b/v3/src/gameobjects/tilemap/components/PutTileAtWorldXY.js index c1d84c59e..f7bd19711 100644 --- a/v3/src/gameobjects/tilemap/components/PutTileAtWorldXY.js +++ b/v3/src/gameobjects/tilemap/components/PutTileAtWorldXY.js @@ -8,9 +8,9 @@ var WorldToTileY = require('./WorldToTileY'); * 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 {integer|Tile} tile - The index of this tile to set or a Tile object. + * @param {integer} worldX - [description] + * @param {integer} worldY - [description] * @param {boolean} [recalculateFaces=true] - [description] * @param {Camera} [camera=main camera] - [description] * @param {LayerData} layer - [description] diff --git a/v3/src/gameobjects/tilemap/components/PutTilesAt.js b/v3/src/gameobjects/tilemap/components/PutTilesAt.js new file mode 100644 index 000000000..0ad5fcebc --- /dev/null +++ b/v3/src/gameobjects/tilemap/components/PutTilesAt.js @@ -0,0 +1,49 @@ +var CalculateFacesWithin = require('./CalculateFacesWithin'); +var PutTileAt = require('./PutTileAt'); + +/** + * Puts an array of tiles or a 2D array of tiles at the given tile coordinates in the specified + * layer. The array can be composed of either tile indexes or Tile objects. 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 + * within the region tiles were changed. + * + * @param {integer[]|integer[][]|Tile[]|Tile[][]} tile - A row (array) or grid (2D array) of Tiles + * or tile indexes to place. + * @param {integer} tileX - [description] + * @param {integer} tileY - [description] + * @param {boolean} [recalculateFaces=true] - [description] + * @param {LayerData} layer - [description] + */ +var PutTilesAt = function (tilesArray, tileX, tileY, recalculateFaces, layer) +{ + if (!Array.isArray(tilesArray)) { return null; } + if (recalculateFaces === undefined) { recalculateFaces = true; } + + // Force the input array to be a 2D array + if (!Array.isArray(tilesArray[0])) + { + tilesArray = [ tilesArray ]; + } + + var height = tilesArray.length; + var width = tilesArray[0].length; + + for (var ty = 0; ty < height; ty++) + { + for (var tx = 0; tx < width; tx++) + { + var tile = tilesArray[ty][tx]; + PutTileAt(tile, tileX + tx, tileY + ty, false, layer); + } + } + + if (recalculateFaces) + { + // Recalculate the faces within the destination area and neighboring tiles + CalculateFacesWithin(tileX - 1, tileY - 1, width + 2, height + 2, layer); + } +}; + +module.exports = PutTilesAt; + diff --git a/v3/src/gameobjects/tilemap/components/Randomize.js b/v3/src/gameobjects/tilemap/components/Randomize.js index af8ada9e3..c5e9f99e4 100644 --- a/v3/src/gameobjects/tilemap/components/Randomize.js +++ b/v3/src/gameobjects/tilemap/components/Randomize.js @@ -8,11 +8,11 @@ var GetRandomElement = require('../../../utils/array/GetRandomElement'); * indexes found within the region (excluding -1) will be used for randomly assigning new tile * indexes. 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} [indexes] - An array of indexes to randomly draw from during randomization. + * @param {integer} [tileX=0] - [description] + * @param {integer} [tileY=0] - [description] + * @param {integer} [width=max width based on tileX] - [description] + * @param {integer} [height=max height based on tileY] - [description] + * @param {integer[]} [indexes] - An array of indexes to randomly draw from during randomization. * @param {LayerData} layer - [description] */ var Randomize = function (tileX, tileY, width, height, indexes, layer) diff --git a/v3/src/gameobjects/tilemap/components/RecalculateFacesAt.js b/v3/src/gameobjects/tilemap/components/RecalculateFacesAt.js index 92e9e8985..fbbda04f9 100644 --- a/v3/src/gameobjects/tilemap/components/RecalculateFacesAt.js +++ b/v3/src/gameobjects/tilemap/components/RecalculateFacesAt.js @@ -5,8 +5,8 @@ var GetTileAt = require('./GetTileAt'); * 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 {integer} tileX - [description] + * @param {integer} tileY - [description] * @param {LayerData} layer - [description] */ var RecalculateFacesAt = function (tileX, tileY, layer) diff --git a/v3/src/gameobjects/tilemap/components/RemoveTileAt.js b/v3/src/gameobjects/tilemap/components/RemoveTileAt.js index bfd043c5e..bf6c1653f 100644 --- a/v3/src/gameobjects/tilemap/components/RemoveTileAt.js +++ b/v3/src/gameobjects/tilemap/components/RemoveTileAt.js @@ -6,9 +6,9 @@ var RecalculateFacesAt = require('./RecalculateFacesAt'); * 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 {integer|Tile} tile - The index of this tile to set or a Tile object. + * @param {integer} tileX - [description] + * @param {integer} 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] diff --git a/v3/src/gameobjects/tilemap/components/RemoveTileAtWorldXY.js b/v3/src/gameobjects/tilemap/components/RemoveTileAtWorldXY.js index a5285b232..85c0962ef 100644 --- a/v3/src/gameobjects/tilemap/components/RemoveTileAtWorldXY.js +++ b/v3/src/gameobjects/tilemap/components/RemoveTileAtWorldXY.js @@ -6,7 +6,7 @@ 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 {integer|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 diff --git a/v3/src/gameobjects/tilemap/components/ReplaceByIndex.js b/v3/src/gameobjects/tilemap/components/ReplaceByIndex.js index f4844811b..290ff3bd2 100644 --- a/v3/src/gameobjects/tilemap/components/ReplaceByIndex.js +++ b/v3/src/gameobjects/tilemap/components/ReplaceByIndex.js @@ -5,12 +5,12 @@ var GetTilesWithin = require('./GetTilesWithin'); * `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 {integer} findIndex - [description] + * @param {integer} newIndex - [description] + * @param {integer} [tileX=0] - [description] + * @param {integer} [tileY=0] - [description] + * @param {integer} [width=max width based on tileX] - [description] + * @param {integer} [height=max height based on tileY] - [description] * @param {LayerData} layer - [description] */ var ReplaceByIndex = function (findIndex, newIndex, tileX, tileY, width, height, layer) diff --git a/v3/src/gameobjects/tilemap/components/SetCollision.js b/v3/src/gameobjects/tilemap/components/SetCollision.js index fb5e9a510..8e95a0006 100644 --- a/v3/src/gameobjects/tilemap/components/SetCollision.js +++ b/v3/src/gameobjects/tilemap/components/SetCollision.js @@ -7,7 +7,7 @@ var SetLayerCollisionIndex = require('./SetLayerCollisionIndex'); * 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 {integer|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 diff --git a/v3/src/gameobjects/tilemap/components/SetCollisionBetween.js b/v3/src/gameobjects/tilemap/components/SetCollisionBetween.js index 58c731592..e0e9f510e 100644 --- a/v3/src/gameobjects/tilemap/components/SetCollisionBetween.js +++ b/v3/src/gameobjects/tilemap/components/SetCollisionBetween.js @@ -8,8 +8,8 @@ var SetLayerCollisionIndex = require('./SetLayerCollisionIndex'); * 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 {integer} start - The first index of the tile to be set for collision. + * @param {integer} 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 diff --git a/v3/src/gameobjects/tilemap/components/SetCollisionByExclusion.js b/v3/src/gameobjects/tilemap/components/SetCollisionByExclusion.js index e93f02252..067d0e7a3 100644 --- a/v3/src/gameobjects/tilemap/components/SetCollisionByExclusion.js +++ b/v3/src/gameobjects/tilemap/components/SetCollisionByExclusion.js @@ -7,7 +7,7 @@ var SetLayerCollisionIndex = require('./SetLayerCollisionIndex'); * 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 {integer[]} 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 diff --git a/v3/src/gameobjects/tilemap/components/SetLayerCollisionIndex.js b/v3/src/gameobjects/tilemap/components/SetLayerCollisionIndex.js index d180c4d80..92c988e5e 100644 --- a/v3/src/gameobjects/tilemap/components/SetLayerCollisionIndex.js +++ b/v3/src/gameobjects/tilemap/components/SetLayerCollisionIndex.js @@ -2,7 +2,7 @@ * 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 {integer} tileIndex - [description] * @param {boolean} [collides=true] - [description] * @param {LayerData} layer - [description] */ diff --git a/v3/src/gameobjects/tilemap/components/SetTileIndexCallback.js b/v3/src/gameobjects/tilemap/components/SetTileIndexCallback.js index 4b5fa3e6c..c054fecde 100644 --- a/v3/src/gameobjects/tilemap/components/SetTileIndexCallback.js +++ b/v3/src/gameobjects/tilemap/components/SetTileIndexCallback.js @@ -4,7 +4,7 @@ * will be replaced. Set the callback to null to remove it. If you want to set a callback for a tile * at a specific location on the map then see setTileLocationCallback. * - * @param {number|array} indexes - Either a single tile index, or an array of tile indexes to have a + * @param {integer|array} indexes - Either a single tile index, or an array of tile indexes to have a * collision callback set for. * @param {function} callback - The callback that will be invoked when the tile is collided with. * @param {object} callbackContext - The context under which the callback is called. diff --git a/v3/src/gameobjects/tilemap/components/SetTileLocationCallback.js b/v3/src/gameobjects/tilemap/components/SetTileLocationCallback.js index e537c0310..efe5ca809 100644 --- a/v3/src/gameobjects/tilemap/components/SetTileLocationCallback.js +++ b/v3/src/gameobjects/tilemap/components/SetTileLocationCallback.js @@ -5,10 +5,10 @@ var GetTilesWithin = require('./GetTilesWithin'); * If a callback is already set for the tile index it will be replaced. Set the callback to null to * remove it. * - * @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 {integer} [tileX=0] - [description] + * @param {integer} [tileY=0] - [description] + * @param {integer} [width=max width based on tileX] - [description] + * @param {integer} [height=max height based on tileY] - [description] * @param {function} callback - The callback that will be invoked when the tile is collided with. * @param {object} callbackContext - The context under which the callback is called. * @param {LayerData} layer - [description] diff --git a/v3/src/gameobjects/tilemap/components/Shuffle.js b/v3/src/gameobjects/tilemap/components/Shuffle.js index 76039b94f..fa492c6cb 100644 --- a/v3/src/gameobjects/tilemap/components/Shuffle.js +++ b/v3/src/gameobjects/tilemap/components/Shuffle.js @@ -7,10 +7,10 @@ var ShuffleArray = require('../../../utils/array/Shuffle'); * 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 {integer} [tileX=0] - [description] + * @param {integer} [tileY=0] - [description] + * @param {integer} [width=max width based on tileX] - [description] + * @param {integer} [height=max height based on tileY] - [description] * @param {LayerData} layer - [description] */ var Shuffle = function (tileX, tileY, width, height, layer) diff --git a/v3/src/gameobjects/tilemap/components/SwapByIndex.js b/v3/src/gameobjects/tilemap/components/SwapByIndex.js index f63cf388d..b5184d9b8 100644 --- a/v3/src/gameobjects/tilemap/components/SwapByIndex.js +++ b/v3/src/gameobjects/tilemap/components/SwapByIndex.js @@ -5,12 +5,12 @@ var GetTilesWithin = require('./GetTilesWithin'); * `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 {integer} tileA - First tile index. + * @param {integer} tileB - Second tile index. + * @param {integer} [tileX=0] - [description] + * @param {integer} [tileY=0] - [description] + * @param {integer} [width=max width based on tileX] - [description] + * @param {integer} [height=max height based on tileY] - [description] * @param {LayerData} layer - [description] */ var SwapByIndex = function (indexA, indexB, tileX, tileY, width, height, layer) diff --git a/v3/src/gameobjects/tilemap/components/TileToWorldX.js b/v3/src/gameobjects/tilemap/components/TileToWorldX.js index ec73dd770..6776e1a40 100644 --- a/v3/src/gameobjects/tilemap/components/TileToWorldX.js +++ b/v3/src/gameobjects/tilemap/components/TileToWorldX.js @@ -2,7 +2,7 @@ * 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 {integer} tileX - [description] * @param {Camera} [camera=main camera] - [description] * @param {LayerData} layer - [description] * @returns {number} diff --git a/v3/src/gameobjects/tilemap/components/TileToWorldY.js b/v3/src/gameobjects/tilemap/components/TileToWorldY.js index 351b3ddd1..d0a318e5c 100644 --- a/v3/src/gameobjects/tilemap/components/TileToWorldY.js +++ b/v3/src/gameobjects/tilemap/components/TileToWorldY.js @@ -2,7 +2,7 @@ * 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 {integer} tileY - [description] * @param {Camera} [camera=main camera] - [description] * @param {LayerData} layer - [description] * @returns {number} diff --git a/v3/src/gameobjects/tilemap/components/index.js b/v3/src/gameobjects/tilemap/components/index.js index 56e8b2e50..b1a4133b4 100644 --- a/v3/src/gameobjects/tilemap/components/index.js +++ b/v3/src/gameobjects/tilemap/components/index.js @@ -17,6 +17,7 @@ module.exports = { IsInLayerBounds: require('./IsInLayerBounds'), PutTileAt: require('./PutTileAt'), PutTileAtWorldXY: require('./PutTileAtWorldXY'), + PutTilesAt: require('./PutTilesAt'), Randomize: require('./Randomize'), CalculateFacesWithin: require('./CalculateFacesWithin'), RemoveTileAt: require('./RemoveTileAt'), diff --git a/v3/src/gameobjects/tilemap/dynamiclayer/DynamicTilemapLayer.js b/v3/src/gameobjects/tilemap/dynamiclayer/DynamicTilemapLayer.js index d97ca856a..8e4e26036 100644 --- a/v3/src/gameobjects/tilemap/dynamiclayer/DynamicTilemapLayer.js +++ b/v3/src/gameobjects/tilemap/dynamiclayer/DynamicTilemapLayer.js @@ -26,18 +26,60 @@ var DynamicTilemapLayer = new Class({ initialize: + /** + * A DynamicTilemapLayer is a game object that renders LayerData from a Tilemap. A + * DynamicTilemapLayer can only render tiles from a single tileset. + * + * A DynamicTilemapLayer trades some speed for being able to apply powerful effects. Unlike a + * StaticTilemapLayer, you can apply per-tile effects like tint or alpha, and you can change the + * tiles in a DynamicTilemapLayer. Use this over a StaticTilemapLayer when you need those + * features. + * + * @class DynamicTilemapLayer + * @constructor + * + * @param {Scene} scene - [description] + * @param {Tilemap} tilemap - The Tilemap this layer is a part of. + * @param {integer} layerIndex - The index of the LayerData associated with this layer. + * @param {Tileset} tileset - The tileset used to render the tiles in this layer. + * @param {number} [x=0] - The world x position where the top left of this layer will be placed. + * @param {number} [y=0] - The world y position where the top left of this layer will be placed. + */ function DynamicTilemapLayer (scene, tilemap, layerIndex, tileset, x, y) { GameObject.call(this, scene, 'DynamicTilemapLayer'); + /** + * The Tilemap that this layer is a part of. + * @property {Tilemap} map + */ this.map = tilemap; + + /** + * The index of the LayerData associated with this layer. + * @property {integer} layerIndex + */ this.layerIndex = layerIndex; + + /** + * The LayerData associated with this layer. LayerData can only be associated with one + * tilemap layer. + * @property {LayerData} layerIndex + */ this.layer = tilemap.layers[layerIndex]; + this.layer.tilemapLayer = this; // Link the LayerData with this static tilemap layer + + /** + * The Tileset associated with this layer. A tilemap layer can only render from one Tileset. + * @property {Tileset} tileset + */ this.tileset = tileset; - // Link the layer data with this dynamic tilemap layer - this.layer.tilemapLayer = this; - + /** + * Used internally with the canvas render. This holds the tiles that are visible within the + * camera. + * @property {Tileset} culledTiles + */ this.culledTiles = []; this.setTexture(tileset.image.key); @@ -49,32 +91,60 @@ var DynamicTilemapLayer = new Class({ this.skipIndexZero = false; }, + /** + * See component documentation. + * + * @return {this} + */ calculateFacesWithin: function (tileX, tileY, width, height) { TilemapComponents.CalculateFacesWithin(tileX, tileY, width, height, this.layer); return this; }, + /** + * See component documentation. + * + * @return {Sprite[]} + */ createFromTiles: function (indexes, replacements, spriteConfig, scene, camera) { return TilemapComponents.CreateFromTiles(indexes, replacements, spriteConfig, scene, camera, this.layer); }, + /** + * See component documentation. + * + * @return {Tile[]} + */ cull: function (camera) { - TilemapComponents.CullTiles(this.layer, camera, this.culledTiles); + return TilemapComponents.CullTiles(this.layer, camera, this.culledTiles); }, + /** + * See component documentation. + * + * @return {this} + */ copy: function (srcTileX, srcTileY, width, height, destTileX, destTileY, recalculateFaces) { TilemapComponents.Copy(srcTileX, srcTileY, width, height, destTileX, destTileY, recalculateFaces, this.layer); return this; }, + /** + * Destroys this DynamicTilemapLayer and removes its link to the associated LayerData. + * + * @method Phaser.TilemapLayer#destroy + */ destroy: function () { // Uninstall this layer only if it is still installed on the LayerData object - if (this.layer.tilemapLayer === this) { this.layer.tilemapLayer = undefined; } + if (this.layer.tilemapLayer === this) + { + this.layer.tilemapLayer = undefined; + } this.map = undefined; this.layer = undefined; this.tileset = undefined; @@ -82,153 +152,304 @@ var DynamicTilemapLayer = new Class({ GameObject.prototype.destroy.call(this); }, + /** + * See component documentation. + * + * @return {this} + */ fill: function (index, tileX, tileY, width, height, recalculateFaces) { TilemapComponents.Fill(index, tileX, tileY, width, height, recalculateFaces, this.layer); return this; }, + /** + * See component documentation. + * + * @return {Tile[]} + */ filterTiles: function (callback, context, tileX, tileY, width, height, filteringOptions) { return TilemapComponents.FilterTiles(callback, context, tileX, tileY, width, height, filteringOptions, this.layer); }, + /** + * See component documentation. + * + * @return {Tile} + */ findByIndex: function (findIndex, skip, reverse) { return TilemapComponents.FindByIndex(findIndex, skip, reverse, this.layer); }, + /** + * See component documentation. + * + * @return {this} + */ forEachTile: function (callback, context, tileX, tileY, width, height, filteringOptions) { TilemapComponents.ForEachTile(callback, context, tileX, tileY, width, height, filteringOptions, this.layer); return this; }, + /** + * See component documentation. + * + * @return {Tile} + */ getTileAt: function (tileX, tileY, nonNull) { return TilemapComponents.GetTileAt(tileX, tileY, nonNull, this.layer); }, + /** + * See component documentation. + * + * @return {Tile} + */ getTileAtWorldXY: function (worldX, worldY, nonNull, camera) { return TilemapComponents.GetTileAtWorldXY(worldX, worldY, nonNull, camera, this.layer); }, + /** + * See component documentation. + * + * @return {Tile[]} + */ getTilesWithin: function (tileX, tileY, width, height, filteringOptions) { return TilemapComponents.GetTilesWithin(tileX, tileY, width, height, filteringOptions, this.layer); }, + /** + * See component documentation. + * + * @return {Tile[]} + */ getTilesWithinShape: function (shape, filteringOptions, camera) { return TilemapComponents.GetTilesWithinShape(shape, filteringOptions, camera, this.layer); }, + /** + * See component documentation. + * + * @return {Tile[]} + */ getTilesWithinWorldXY: function (worldX, worldY, width, height, filteringOptions, camera) { return TilemapComponents.GetTilesWithinWorldXY(worldX, worldY, width, height, filteringOptions, camera, this.layer); }, + /** + * See component documentation. + * + * @return {boolean} + */ hasTileAt: function (tileX, tileY) { return TilemapComponents.HasTileAt(tileX, tileY, this.layer); }, + /** + * See component documentation. + * + * @return {boolean} + */ hasTileAtWorldXY: function (worldX, worldY, camera) { return TilemapComponents.HasTileAtWorldXY(worldX, worldY, camera, this.layer); }, + /** + * See component documentation. + * + * @return {Tile} + */ putTileAt: function (tile, tileX, tileY, recalculateFaces) { return TilemapComponents.PutTileAt(tile, tileX, tileY, recalculateFaces, this.layer); }, + /** + * See component documentation. + * + * @return {Tile} + */ putTileAtWorldXY: function (tile, worldX, worldY, recalculateFaces, camera) { return TilemapComponents.PutTileAtWorldXY(tile, worldX, worldY, recalculateFaces, camera, this.layer); }, + /** + * See component documentation. + * + * @return {this} + */ + putTilesAt: function (tilesArray, tileX, tileY, recalculateFaces) + { + TilemapComponents.PutTilesAt(tilesArray, tileX, tileY, recalculateFaces, this.layer); + return this; + }, + + /** + * See component documentation. + * + * @return {this} + */ randomize: function (tileX, tileY, width, height, indexes) { TilemapComponents.Randomize(tileX, tileY, width, height, indexes, this.layer); return this; }, + /** + * See component documentation. + * + * @return {Tile} + */ removeTileAt: function (tileX, tileY, replaceWithNull, recalculateFaces) { return TilemapComponents.RemoveTileAt(tileX, tileY, replaceWithNull, recalculateFaces, this.layer); }, + /** + * See component documentation. + * + * @return {Tile} + */ removeTileAtWorldXY: function (worldX, worldY, replaceWithNull, recalculateFaces, camera) { return TilemapComponents.RemoveTileAtWorldXY(worldX, worldY, replaceWithNull, recalculateFaces, camera, this.layer); }, + /** + * See component documentation. + * + * @return {this} + */ renderDebug: function (graphics, styleConfig) { TilemapComponents.RenderDebug(graphics, styleConfig, this.layer); return this; }, + /** + * See component documentation. + * + * @return {this} + */ replaceByIndex: function (findIndex, newIndex, tileX, tileY, width, height) { TilemapComponents.ReplaceByIndex(findIndex, newIndex, tileX, tileY, width, height, this.layer); return this; }, + /** + * See component documentation. + * + * @return {this} + */ setCollision: function (indexes, collides, recalculateFaces) { TilemapComponents.SetCollision(indexes, collides, recalculateFaces, this.layer); return this; }, + /** + * See component documentation. + * + * @return {this} + */ setCollisionBetween: function (start, stop, collides, recalculateFaces) { TilemapComponents.SetCollisionBetween(start, stop, collides, recalculateFaces, this.layer); return this; }, + /** + * See component documentation. + * + * @return {this} + */ setCollisionByExclusion: function (indexes, collides, recalculateFaces) { TilemapComponents.SetCollisionByExclusion(indexes, collides, recalculateFaces, this.layer); return this; }, + /** + * See component documentation. + * + * @return {this} + */ setTileIndexCallback: function (indexes, callback, callbackContext) { TilemapComponents.SetTileIndexCallback(indexes, callback, callbackContext, this.layer); return this; }, + /** + * See component documentation. + * + * @return {this} + */ setTileLocationCallback: function (tileX, tileY, width, height, callback, callbackContext) { TilemapComponents.SetTileLocationCallback(tileX, tileY, width, height, callback, callbackContext, this.layer); return this; }, + /** + * See component documentation. + * + * @return {this} + */ shuffle: function (tileX, tileY, width, height) { TilemapComponents.Shuffle(tileX, tileY, width, height, this.layer); return this; }, + /** + * See component documentation. + * + * @return {this} + */ swapByIndex: function (indexA, indexB, tileX, tileY, width, height) { TilemapComponents.SwapByIndex(indexA, indexB, tileX, tileY, width, height, this.layer); return this; }, + /** + * See component documentation. + * + * @return {number} + */ worldToTileX: function (worldX, snapToFloor, camera) { return TilemapComponents.WorldToTileX(worldX, snapToFloor, camera, this.layer); }, + /** + * See component documentation. + * + * @return {number} + */ worldToTileY: function (worldY, snapToFloor, camera) { return TilemapComponents.WorldToTileY(worldY, snapToFloor, camera, this.layer); }, + /** + * See component documentation. + * + * @return {Vector} + */ worldToTileXY: function (worldX, worldY, snapToFloor, point, camera) { return TilemapComponents.WorldToTileXY(worldX, worldY, snapToFloor, point, camera, this.layer); diff --git a/v3/src/gameobjects/tilemap/parsers/Parse.js b/v3/src/gameobjects/tilemap/parsers/Parse.js index 8b5fa2317..00161bba2 100644 --- a/v3/src/gameobjects/tilemap/parsers/Parse.js +++ b/v3/src/gameobjects/tilemap/parsers/Parse.js @@ -11,11 +11,11 @@ var Formats = require('../Formats'); * the map data. * * @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 - The width of a tile in pixels. Required for 2D array and CSV, but + * @param {integer} mapFormat - See ../Formats.js. + * @param {integer[][]|string|object} data - 2D array, CSV string or Tiled JSON object. + * @param {integer} tileWidth - The width of a tile in pixels. Required for 2D array and CSV, but * ignored for Tiled JSON. - * @param {number} tileHeight - The height of a tile in pixels. Required for 2D array and CSV, but + * @param {integer} tileHeight - The height of a tile in pixels. Required for 2D array and CSV, but * ignored for Tiled JSON. * @param {boolean} insertNull - Controls how empty tiles, tiles with an index of -1, in the map * data are handled. If `true`, empty locations will get a value of `null`. If `false`, empty diff --git a/v3/src/gameobjects/tilemap/parsers/Parse2DArray.js b/v3/src/gameobjects/tilemap/parsers/Parse2DArray.js index 4b6e53a05..6ccf9c158 100644 --- a/v3/src/gameobjects/tilemap/parsers/Parse2DArray.js +++ b/v3/src/gameobjects/tilemap/parsers/Parse2DArray.js @@ -7,9 +7,9 @@ var Tile = require('../Tile'); * Parses a 2D array of tile indexes into a new MapData object with a single layer. * * @param {string} name - The name of the tilemap, used to set the name on the MapData. - * @param {array} data - 2D array, CSV string or Tiled JSON object. - * @param {number} tileWidth - The width of a tile in pixels. - * @param {number} tileHeight - The height of a tile in pixels. + * @param {integer[][]} data - 2D array, CSV string or Tiled JSON object. + * @param {integer} tileWidth - The width of a tile in pixels. + * @param {integer} tileHeight - The height of a tile in pixels. * @param {boolean} insertNull - Controls how empty tiles, tiles with an index of -1, in the map * data are handled. If `true`, empty locations will get a value of `null`. If `false`, empty * location will get a Tile object with an index of -1. If you've a large sparsely populated map and diff --git a/v3/src/gameobjects/tilemap/parsers/ParseCSV.js b/v3/src/gameobjects/tilemap/parsers/ParseCSV.js index 6c143250c..df049eb9e 100644 --- a/v3/src/gameobjects/tilemap/parsers/ParseCSV.js +++ b/v3/src/gameobjects/tilemap/parsers/ParseCSV.js @@ -6,8 +6,8 @@ var Parse2DArray = require('./Parse2DArray'); * * @param {string} name - The name of the tilemap, used to set the name on the MapData. * @param {string} data - CSV string of tile indexes. - * @param {number} tileWidth - The width of a tile in pixels. - * @param {number} tileHeight - The height of a tile in pixels. + * @param {integer} tileWidth - The width of a tile in pixels. + * @param {integer} tileHeight - The height of a tile in pixels. * @param {boolean} insertNull - Controls how empty tiles, tiles with an index of -1, in the map * data are handled. If `true`, empty locations will get a value of `null`. If `false`, empty * location will get a Tile object with an index of -1. If you've a large sparsely populated map and diff --git a/v3/src/gameobjects/tilemap/parsers/parsetiledjson/index.js b/v3/src/gameobjects/tilemap/parsers/parsetiledjson/index.js index 54c630a97..51dd6d4d2 100644 --- a/v3/src/gameobjects/tilemap/parsers/parsetiledjson/index.js +++ b/v3/src/gameobjects/tilemap/parsers/parsetiledjson/index.js @@ -169,7 +169,7 @@ var ParseJSONTiled = function (name, json, insertNull) if (set.image) { - var newSet = new Tileset(set.name, set.firstgid, set.tilewidth, set.tileheight, set.margin, set.spacing, set.properties); + var newSet = new Tileset(set.name, set.firstgid, set.tilewidth, set.tileheight, set.margin, set.spacing); // Properties stored per-tile in object with string indexes starting at "0" if (set.tileproperties) diff --git a/v3/src/gameobjects/tilemap/staticlayer/StaticTilemapLayer.js b/v3/src/gameobjects/tilemap/staticlayer/StaticTilemapLayer.js index 0e5508b21..bd1871e36 100644 --- a/v3/src/gameobjects/tilemap/staticlayer/StaticTilemapLayer.js +++ b/v3/src/gameobjects/tilemap/staticlayer/StaticTilemapLayer.js @@ -27,17 +27,60 @@ var StaticTilemapLayer = new Class({ initialize: + /** + * A StaticTilemapLayer is a game object that renders LayerData from a Tilemap. A + * StaticTilemapLayer can only render tiles from a single tileset. + * + * A StaticTilemapLayer is optimized for speed over flexibility. You cannot apply per-tile + * effects like tint or alpha. You cannot change the tiles in a StaticTilemapLayer. Use this + * over a DynamicTilemapLayer when you don't need either of those features. + * + * @class StaticTilemapLayer + * @constructor + * + * @param {Scene} scene - [description] + * @param {Tilemap} tilemap - The Tilemap this layer is a part of. + * @param {integer} layerIndex - The index of the LayerData associated with this layer. + * @param {Tileset} tileset - The tileset used to render the tiles in this layer. + * @param {number} [x=0] - The world x position where the top left of this layer will be placed. + * @param {number} [y=0] - The world y position where the top left of this layer will be placed. + */ function StaticTilemapLayer (scene, tilemap, layerIndex, tileset, x, y) { GameObject.call(this, scene, 'StaticTilemapLayer'); + /** + * The Tilemap that this layer is a part of. + * @property {Tilemap} map + */ this.map = tilemap; + + /** + * The index of the LayerData associated with this layer. + * @property {integer} layerIndex + */ this.layerIndex = layerIndex; + + /** + * The LayerData associated with this layer. LayerData can only be associated with one + * tilemap layer. + * @property {LayerData} layerIndex + */ this.layer = tilemap.layers[layerIndex]; + this.layer.tilemapLayer = this; // Link the LayerData with this static tilemap layer + + /** + * The Tileset associated with this layer. A tilemap layer can only render from one Tileset. + * @property {Tileset} tileset + */ this.tileset = tileset; - // Link the layer data with this static tilemap layer - this.layer.tilemapLayer = this; + /** + * Used internally with the canvas render. This holds the tiles that are visible within the + * camera. + * @property {Tileset} culledTiles + */ + this.culledTiles = []; this.vbo = null; this.gl = scene.sys.game.renderer.gl ? scene.sys.game.renderer.gl : null; @@ -47,7 +90,6 @@ var StaticTilemapLayer = new Class({ this.dirty = true; this.vertexCount = 0; - this.culledTiles = []; this.setTexture(tileset.image.key); this.setPosition(x, y); @@ -60,6 +102,9 @@ var StaticTilemapLayer = new Class({ scene.sys.game.renderer.addContextRestoredCallback(this.contextRestore.bind(this)); }, + /** + * @return {this} + */ contextRestore: function (renderer) { this.tileTexture = null; @@ -67,15 +112,19 @@ var StaticTilemapLayer = new Class({ this.vbo = null; this.gl = renderer.gl; this.tilemapRenderer = renderer.tilemapRenderer; + return this; }, + /** + * Upload the tile data to a VBO. + * + * @return {this} + */ upload: function (camera) { var tileset = this.tileset; var mapWidth = this.layer.width; var mapHeight = this.layer.height; - var tileWidth = this.layer.tileWidth; - var tileHeight = this.layer.tileHeight; var width = this.texture.source[0].width; var height = this.texture.source[0].height; var mapData = this.layer.data; @@ -119,10 +168,10 @@ var StaticTilemapLayer = new Class({ tile = mapData[row][col]; if (tile === null || (tile.index <= 0 && this.skipIndexZero)) { continue; } - var tx = col * tileWidth; - var ty = row * tileHeight; - var txw = tx + tileWidth; - var tyh = ty + tileHeight; + var tx = tile.worldX; + var ty = tile.worldY; + var txw = tx + tile.width; + var tyh = ty + tile.height; texCoords = tileset.getTileTextureCoordinates(tile.index); if (texCoords === null) { continue; } @@ -130,8 +179,8 @@ var StaticTilemapLayer = new Class({ // Inset UV coordinates by 0.5px to prevent tile bleeding var u0 = (texCoords.x + 0.5) / width; var v0 = (texCoords.y + 0.5) / height; - var u1 = (texCoords.x + tileWidth - 0.5) / width; - var v1 = (texCoords.y + tileHeight - 0.5) / height; + var u1 = (texCoords.x + tile.width - 0.5) / width; + var v1 = (texCoords.y + tile.height - 0.5) / height; var tx0 = tx; var ty0 = ty; @@ -201,131 +250,250 @@ var StaticTilemapLayer = new Class({ ] ); } + + return this; }, + /** + * See component documentation. + * + * @return {this} + */ calculateFacesWithin: function (tileX, tileY, width, height) { TilemapComponents.CalculateFacesWithin(tileX, tileY, width, height, this.layer); return this; }, + /** + * See component documentation. + * + * @return {Sprite[]} + */ createFromTiles: function (indexes, replacements, spriteConfig, scene, camera) { return TilemapComponents.CreateFromTiles(indexes, replacements, spriteConfig, scene, camera, this.layer); }, + /** + * See component documentation. + * + * @return {Tile[]} + */ cull: function (camera) { - TilemapComponents.CullTiles(this.layer, camera, this.culledTiles); + return TilemapComponents.CullTiles(this.layer, camera, this.culledTiles); }, + + /** + * Destroys this StaticTilemapLayer and removes its link to the associated LayerData. + */ destroy: function () { // Uninstall this layer only if it is still installed on the LayerData object - if (this.layer.tilemapLayer === this) { this.layer.tilemapLayer = undefined; } + if (this.layer.tilemapLayer === this) + { + this.layer.tilemapLayer = undefined; + } this.map = undefined; this.layer = undefined; this.tileset = undefined; GameObject.prototype.destroy.call(this); }, + /** + * See component documentation. + * + * @return {Tile} + */ findByIndex: function (findIndex, skip, reverse) { return TilemapComponents.FindByIndex(findIndex, skip, reverse, this.layer); }, + /** + * See component documentation. + * + * @return {Tile[]} + */ filterTiles: function (callback, context, tileX, tileY, width, height, filteringOptions) { return TilemapComponents.FilterTiles(callback, context, tileX, tileY, width, height, filteringOptions, this.layer); }, + /** + * See component documentation. + * + * @return {this} + */ forEachTile: function (callback, context, tileX, tileY, width, height, filteringOptions) { TilemapComponents.ForEachTile(callback, context, tileX, tileY, width, height, filteringOptions, this.layer); return this; }, + /** + * See component documentation. + * + * @return {Tile} + */ getTileAt: function (tileX, tileY, nonNull) { return TilemapComponents.GetTileAt(tileX, tileY, nonNull, this.layer); }, + /** + * See component documentation. + * + * @return {Tile} + */ getTileAtWorldXY: function (worldX, worldY, nonNull, camera) { return TilemapComponents.GetTileAtWorldXY(worldX, worldY, nonNull, camera, this.layer); }, + /** + * See component documentation. + * + * @return {Tile[]} + */ getTilesWithin: function (tileX, tileY, width, height, filteringOptions) { return TilemapComponents.GetTilesWithin(tileX, tileY, width, height, filteringOptions, this.layer); }, + /** + * See component documentation. + * + * @return {Tile[]} + */ getTilesWithinWorldXY: function (worldX, worldY, width, height, filteringOptions, camera) { return TilemapComponents.GetTilesWithinWorldXY(worldX, worldY, width, height, filteringOptions, camera, this.layer); }, + /** + * See component documentation. + * + * @return {Tile[]} + */ getTilesWithinShape: function (shape, filteringOptions, camera) { return TilemapComponents.GetTilesWithinShape(shape, filteringOptions, camera, this.layer); }, + /** + * See component documentation. + * + * @return {boolean} + */ hasTileAt: function (tileX, tileY) { return TilemapComponents.HasTileAt(tileX, tileY, this.layer); }, + /** + * See component documentation. + * + * @return {boolean} + */ hasTileAtWorldXY: function (worldX, worldY, camera) { return TilemapComponents.HasTileAtWorldXY(worldX, worldY, camera, this.layer); }, + /** + * See component documentation. + * + * @return {this} + */ renderDebug: function (graphics, styleConfig) { TilemapComponents.RenderDebug(graphics, styleConfig, this.layer); return this; }, + /** + * See component documentation. + * + * @return {this} + */ setCollision: function (indexes, collides, recalculateFaces) { TilemapComponents.SetCollision(indexes, collides, recalculateFaces, this.layer); return this; }, + /** + * See component documentation. + * + * @return {this} + */ setCollisionBetween: function (start, stop, collides, recalculateFaces) { TilemapComponents.SetCollisionBetween(start, stop, collides, recalculateFaces, this.layer); return this; }, + /** + * See component documentation. + * + * @return {this} + */ setCollisionByExclusion: function (indexes, collides, recalculateFaces) { TilemapComponents.SetCollisionByExclusion(indexes, collides, recalculateFaces, this.layer); return this; }, + /** + * See component documentation. + * + * @return {this} + */ setTileIndexCallback: function (indexes, callback, callbackContext) { TilemapComponents.SetTileIndexCallback(indexes, callback, callbackContext, this.layer); return this; }, + /** + * See component documentation. + * + * @return {this} + */ setTileLocationCallback: function (tileX, tileY, width, height, callback, callbackContext) { TilemapComponents.SetTileLocationCallback(tileX, tileY, width, height, callback, callbackContext, this.layer); return this; }, + /** + * See component documentation. + * + * @return {number} + */ worldToTileX: function (worldX, snapToFloor, camera) { return TilemapComponents.WorldToTileX(worldX, snapToFloor, camera, this.layer); }, + /** + * See component documentation. + * + * @return {number} + */ worldToTileY: function (worldY, snapToFloor, camera) { return TilemapComponents.WorldToTileY(worldY, snapToFloor, camera, this.layer); }, + /** + * See component documentation. + * + * @return {Vector} + */ worldToTileXY: function (worldX, worldY, snapToFloor, point, camera) { return TilemapComponents.WorldToTileXY(worldX, worldY, snapToFloor, point, camera, this.layer); diff --git a/v3/src/input/Pointer.js b/v3/src/input/Pointer.js index 1906b97c6..380a86753 100644 --- a/v3/src/input/Pointer.js +++ b/v3/src/input/Pointer.js @@ -69,9 +69,7 @@ var Pointer = new Class({ positionToCamera: function (camera, output) { - if (output === undefined) { output = { x: 0, y: 0 }; } - - return camera.screenToCamera(this.position.x, this.position.y, output); + return camera.getWorldPoint(this.position, output); }, x: { diff --git a/v3/src/input/global/inc/HitTest.js b/v3/src/input/global/inc/HitTest.js index 98bc929d4..dc4b33aa9 100644 --- a/v3/src/input/global/inc/HitTest.js +++ b/v3/src/input/global/inc/HitTest.js @@ -17,7 +17,7 @@ var HitTest = function (tempMatrix, x, y, gameObjects, camera, output) return output; } - var screenPoint = camera.cameraToWorld({ x: x, y: y }); + var screenPoint = camera.getWorldPoint({ x: x, y: y }); var culledGameObjects = camera.cull(gameObjects); for (var i = 0; i < culledGameObjects.length; i++) diff --git a/v3/src/physics/impact/World.js b/v3/src/physics/impact/World.js index d22d0bb30..5a2deb4d8 100644 --- a/v3/src/physics/impact/World.js +++ b/v3/src/physics/impact/World.js @@ -479,6 +479,11 @@ var World = new Class({ return this; }, + shutdown: function () + { + + }, + destroy: function () { this.scene = null; diff --git a/v3/src/physics/matter-js/PointerConstraint.js b/v3/src/physics/matter-js/PointerConstraint.js index 31065a7d4..c820c5dea 100644 --- a/v3/src/physics/matter-js/PointerConstraint.js +++ b/v3/src/physics/matter-js/PointerConstraint.js @@ -6,6 +6,7 @@ var Detector = require('./lib/collision/Detector'); var GetFastValue = require('../../utils/object/GetFastValue'); var Merge = require('../../utils/object/Merge'); var Sleeping = require('./lib/core/Sleeping'); +var Vector2 = require('../../math/Vector2'); var Vertices = require('./lib/geometry/Vertices'); var PointerConstraint = new Class({ @@ -53,6 +54,9 @@ var PointerConstraint = new Class({ this.active = true; + // The transformed position + this.position = new Vector2(); + this.constraint = Constraint.create(Merge(options, defaults)); this.world.events.on('BEFORE_UPDATE_EVENT', this.update, 0, this); @@ -123,15 +127,17 @@ var PointerConstraint = new Class({ } else { - var position = this.camera.worldToCamera({ x: pointer.position.x, y: pointer.position.y }); + var pos = this.position; + + this.camera.getWorldPoint(pointer.position, pos); if (constraint.bodyB) { // Pointer is down and we have bodyB, so wake it up Sleeping.set(constraint.bodyB, false); - constraint.pointA.x = position.x; - constraint.pointA.y = position.y; + constraint.pointA.x = pos.x; + constraint.pointA.y = pos.y; } else { @@ -142,10 +148,10 @@ var PointerConstraint = new Class({ { var body = bodies[i]; - if (!body.ignorePointer && Bounds.contains(body.bounds, position) && + if (!body.ignorePointer && Bounds.contains(body.bounds, pos) && Detector.canCollide(body.collisionFilter, constraint.collisionFilter)) { - if (this.getBodyPart(body, position)) + if (this.getBodyPart(body, pos)) { break; } diff --git a/v3/src/physics/matter-js/World.js b/v3/src/physics/matter-js/World.js index 5fcf29be0..2dae98799 100644 --- a/v3/src/physics/matter-js/World.js +++ b/v3/src/physics/matter-js/World.js @@ -167,7 +167,7 @@ var World = new Class({ { if (wall) { - this.localWorld.remove(wall); + MatterWorld.remove(this.localWorld, wall); } // adjust center @@ -180,7 +180,7 @@ var World = new Class({ { if (wall) { - this.localWorld.remove(wall); + MatterWorld.remove(this.localWorld, wall); } this.walls[position] = null; @@ -322,12 +322,14 @@ var World = new Class({ shutdown: function () { - + MatterWorld.clear(this.localWorld, false); + Engine.clear(this.engine); }, destroy: function () { - + // TODO + this.shutdown(); } }); diff --git a/v3/src/scene/local/Systems.js b/v3/src/scene/local/Systems.js index 6e03953a3..2f0cd1292 100644 --- a/v3/src/scene/local/Systems.js +++ b/v3/src/scene/local/Systems.js @@ -243,6 +243,8 @@ var Systems = new Class({ { // Was stopped by the GlobalSceneManager + console.log('Scene.shutdown'); + this.settings.active = false; this.settings.visible = false; @@ -250,6 +252,7 @@ var Systems = new Class({ this.updateList.shutdown(); this.time.shutdown(); this.tweens.shutdown(); + this.physicsManager.shutdown(); if (this.scene.shutdown) { @@ -257,14 +260,13 @@ var Systems = new Class({ } }, - // Game level nuke + // TODO: Game level nuke destroy: function () { - // TODO - this.add.destroy(); this.time.destroy(); this.tweens.destroy(); + this.physicsManager.destroy(); // etc if (this.scene.destroy) diff --git a/v3/src/scene/plugins/PhysicsManager.js b/v3/src/scene/plugins/PhysicsManager.js index 3dc5dfe19..635638c52 100644 --- a/v3/src/scene/plugins/PhysicsManager.js +++ b/v3/src/scene/plugins/PhysicsManager.js @@ -24,7 +24,7 @@ var PhysicsManager = new Class({ this.system; // This gets set by the physics system during boot - this.world = { update: NOOP, postUpdate: NOOP }; + this.world = { update: NOOP, postUpdate: NOOP, shutdown: NOOP, destroy: NOOP }; // This gets set by the physics system during boot this.add; @@ -70,6 +70,16 @@ var PhysicsManager = new Class({ postUpdate: function () { this.world.postUpdate(); + }, + + shutdown: function () + { + this.world.shutdown(); + }, + + destroy: function () + { + this.world.destroy(); } });