UNPKG

phaser

Version:

A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.

458 lines (411 loc) 16.7 kB
/** * @author Richard Davey <rich@phaser.io> * @copyright 2013-2026 Phaser Studio Inc. * @license {@link https://opensource.org/licenses/MIT|MIT License} */ var DefaultTilemapLayerNodes = require('../renderer/webgl/renderNodes/defaults/DefaultTilemapLayerNodes'); var Class = require('../utils/Class'); var TilemapComponents = require('./components'); var TilemapLayerRender = require('./TilemapLayerRender'); var TilemapLayerBase = require('./TilemapLayerBase'); var TintModes = require('../renderer/TintModes'); /** * @classdesc * A TilemapLayer is a Game Object responsible for rendering a single layer of tile data from a * Tilemap. It works in combination with one or more Tileset objects, which provide the actual * tile imagery. You would typically create a TilemapLayer via `Tilemap.createLayer`, rather than * instantiating it directly. * * Each layer corresponds to a LayerData entry within the Tilemap, and supports all four map * orientations: Orthogonal, Isometric, Hexagonal, and Staggered. The layer handles its own * camera culling, only sending visible tiles to the renderer each frame, which keeps performance * efficient even for large maps. * * TilemapLayers support physics via both Arcade Physics and Matter.js, and can have tints, * alpha, and other standard Game Object properties applied to them. * * A TilemapLayer can be placed inside a Container, but its physics * will work as though it was placed directly in the world. * This is rarely what you want. * * @class TilemapLayer * @extends Phaser.Tilemaps.TilemapLayerBase * @memberof Phaser.Tilemaps * @constructor * @since 3.50.0 * * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. * @param {Phaser.Tilemaps.Tilemap} tilemap - The Tilemap this layer is a part of. * @param {number} layerIndex - The index of the LayerData associated with this layer. * @param {(string|string[]|Phaser.Tilemaps.Tileset|Phaser.Tilemaps.Tileset[])} tileset - The tileset, or an array of tilesets, used to render this layer. Can be a string or a Tileset object. * @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. */ var TilemapLayer = new Class({ Extends: TilemapLayerBase, Mixins: [ TilemapLayerRender ], initialize: function TilemapLayer (scene, tilemap, layerIndex, tileset, x, y) { TilemapLayerBase.call(this, 'TilemapLayer', scene, tilemap, layerIndex, x, y); /** * An array of `Tileset` objects associated with this layer. * * @name Phaser.Tilemaps.TilemapLayer#tileset * @type {Phaser.Tilemaps.Tileset[]} * @since 3.50.0 */ this.tileset = []; /** * The total number of tiles drawn by the renderer in the last frame. * * @name Phaser.Tilemaps.TilemapLayer#tilesDrawn * @type {number} * @readonly * @since 3.50.0 */ this.tilesDrawn = 0; /** * The total number of tiles in this layer. Updated every frame. * * @name Phaser.Tilemaps.TilemapLayer#tilesTotal * @type {number} * @readonly * @since 3.50.0 */ this.tilesTotal = this.layer.width * this.layer.height; /** * Used internally during rendering. This holds the tiles that are visible within the Camera. * * @name Phaser.Tilemaps.TilemapLayer#culledTiles * @type {Phaser.Tilemaps.Tile[]} * @since 3.50.0 */ this.culledTiles = []; /** * You can control if the camera should cull tiles on this layer before rendering them or not. * * By default the camera will try to cull the tiles in this layer, to avoid over-drawing to the renderer. * * However, there are some instances when you may wish to disable this, and toggling this flag allows * you to do so. Also see `setSkipCull` for a chainable method that does the same thing. * * @name Phaser.Tilemaps.TilemapLayer#skipCull * @type {boolean} * @since 3.50.0 */ this.skipCull = false; /** * The amount of extra tiles to add into the cull rectangle when calculating its horizontal size. * * See the method `setCullPadding` for more details. * * @name Phaser.Tilemaps.TilemapLayer#cullPaddingX * @type {number} * @default 1 * @since 3.50.0 */ this.cullPaddingX = 1; /** * The amount of extra tiles to add into the cull rectangle when calculating its vertical size. * * See the method `setCullPadding` for more details. * * @name Phaser.Tilemaps.TilemapLayer#cullPaddingY * @type {number} * @default 1 * @since 3.50.0 */ this.cullPaddingY = 1; /** * The callback that is invoked when the tiles are culled. * * It will call a different function based on the map orientation: * * Orthogonal (the default) is `TilemapComponents.CullTiles` * Isometric is `TilemapComponents.IsometricCullTiles` * Hexagonal is `TilemapComponents.HexagonalCullTiles` * Staggered is `TilemapComponents.StaggeredCullTiles` * * However, you can override this to call any function you like. * * It will be sent 4 arguments: * * 1. The Phaser.Tilemaps.LayerData object for this Layer * 2. The Camera that is culling the layer. You can check its `dirty` property to see if it has changed since the last cull. * 3. A reference to the `culledTiles` array, which should be used to store the tiles you want rendered. * 4. The Render Order constant. * * See the `TilemapComponents.CullTiles` source code for details on implementing your own culling system. * * @name Phaser.Tilemaps.TilemapLayer#cullCallback * @type {function} * @since 3.50.0 */ this.cullCallback = TilemapComponents.GetCullTilesFunction(this.layer.orientation); /** * The rendering (draw) order of the tiles in this layer. * * The default is 0 which is 'right-down', meaning it will draw the tiles starting from the top-left, * drawing to the right and then moving down to the next row. * * The draw orders are: * * 0 = right-down * 1 = left-down * 2 = right-up * 3 = left-up * * This can be changed via the `setRenderOrder` method. * * @name Phaser.Tilemaps.TilemapLayer#_renderOrder * @type {number} * @default 0 * @private * @since 3.50.0 */ this._renderOrder = 0; this.setTilesets(tileset); this.initRenderNodes(this._defaultRenderNodesMap); }, /** * The default render nodes for this Game Object. * * @name Phaser.Tilemaps.TilemapLayer#_defaultRenderNodesMap * @type {Map<string, string>} * @private * @webglOnly * @readonly * @since 4.0.0 */ _defaultRenderNodesMap: { get: function () { return DefaultTilemapLayerNodes; } }, /** * Populates the internal `tileset` array with the Tileset references this Layer requires for rendering. * * @method Phaser.Tilemaps.TilemapLayer#setTilesets * @private * @since 3.50.0 * * @param {(string|string[]|Phaser.Tilemaps.Tileset|Phaser.Tilemaps.Tileset[])} tileset - The tileset, or an array of tilesets, used to render this layer. Can be a string or a Tileset object. */ setTilesets: function (tilesets) { var gidMap = []; var setList = []; var map = this.tilemap; if (!Array.isArray(tilesets)) { tilesets = [ tilesets ]; } for (var i = 0; i < tilesets.length; i++) { var tileset = tilesets[i]; if (typeof tileset === 'string') { tileset = map.getTileset(tileset); } if (tileset) { setList.push(tileset); var s = tileset.firstgid; for (var t = 0; t < tileset.total; t++) { gidMap[s + t] = tileset; } } } this.gidMap = gidMap; this.tileset = setList; }, /** * Sets the rendering (draw) order of the tiles in this layer. * * The default is 'right-down', meaning it will order the tiles starting from the top-left, * drawing to the right and then moving down to the next row. * * The draw orders are: * * 0 = right-down * 1 = left-down * 2 = right-up * 3 = left-up * * Setting the render order does not change the tiles or how they are stored in the layer, * it purely impacts the order in which they are rendered. * * You can provide either an integer (0 to 3), or the string version of the order. * * @method Phaser.Tilemaps.TilemapLayer#setRenderOrder * @since 3.50.0 * * @param {(number|string)} renderOrder - The render (draw) order value. Either an integer between 0 and 3, or a string: 'right-down', 'left-down', 'right-up' or 'left-up'. * * @return {this} This Tilemap Layer object. */ setRenderOrder: function (renderOrder) { var orders = [ 'right-down', 'left-down', 'right-up', 'left-up' ]; if (typeof renderOrder === 'string') { renderOrder = orders.indexOf(renderOrder); } if (renderOrder >= 0 && renderOrder < 4) { this._renderOrder = renderOrder; } return this; }, /** * Returns the tiles in the given layer that are within the camera's viewport. * This is used internally during rendering. * * @method Phaser.Tilemaps.TilemapLayer#cull * @since 3.50.0 * * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to run the cull check against. * * @return {Phaser.Tilemaps.Tile[]} An array of Tile objects to render. */ cull: function (camera) { return this.cullCallback(this.layer, camera, this.culledTiles, this._renderOrder); }, /** * You can control if the Cameras should cull tiles before rendering them or not. * * By default the camera will try to cull the tiles in this layer, to avoid over-drawing to the renderer. * * However, there are some instances when you may wish to disable this. * * @method Phaser.Tilemaps.TilemapLayer#setSkipCull * @since 3.50.0 * * @param {boolean} [value=true] - Set to `true` to stop culling tiles. Set to `false` to enable culling again. * * @return {this} This Tilemap Layer object. */ setSkipCull: function (value) { if (value === undefined) { value = true; } this.skipCull = value; return this; }, /** * When a Camera culls the tiles in this layer it does so using its view into the world, building up a * rectangle inside which the tiles must exist or they will be culled. Sometimes you may need to expand the size * of this 'cull rectangle', especially if you plan on rotating the Camera viewing the layer. Do so * by providing the padding values. The values given are in tiles, not pixels. So if the tile width was 32px * and you set `paddingX` to be 4, it would add 32px x 4 to the cull rectangle (adjusted for scale) * * @method Phaser.Tilemaps.TilemapLayer#setCullPadding * @since 3.50.0 * * @param {number} [paddingX=1] - The amount of extra horizontal tiles to add to the cull check padding. * @param {number} [paddingY=1] - The amount of extra vertical tiles to add to the cull check padding. * * @return {this} This Tilemap Layer object. */ setCullPadding: function (paddingX, paddingY) { if (paddingX === undefined) { paddingX = 1; } if (paddingY === undefined) { paddingY = 1; } this.cullPaddingX = paddingX; this.cullPaddingY = paddingY; return this; }, /** * Sets an additive tint on each Tile within the given area. * * The tint works by taking the pixel color values from the tileset texture, and then * multiplying it by the color value of the tint. * * If no area values are given then all tiles will be tinted to the given color. * * To remove a tint call this method with either no parameters, or by passing white `0xffffff` as the tint color. * * If a tile already has a tint set then calling this method will override that. * * @method Phaser.Tilemaps.TilemapLayer#setTint * @webglOnly * @since 3.60.0 * * @param {number} [tint=0xffffff] - The tint color being applied to each tile within the region. Given as a hex value, i.e. `0xff0000` for red. Set to white (`0xffffff`) to reset the tint. * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area to search. * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area to search. * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. * @param {Phaser.Types.Tilemaps.FilteringOptions} [filteringOptions] - Optional filters to apply when getting the tiles. * * @return {this} This Tilemap Layer object. */ setTint: function (tint, tileX, tileY, width, height, filteringOptions) { if (tint === undefined) { tint = 0xffffff; } var tintTile = function (tile) { tile.tint = tint; }; return this.forEachTile(tintTile, this, tileX, tileY, width, height, filteringOptions); }, /** * Sets the tint mode to use when applying the tint to the texture. * * Available modes are: * * - Phaser.TintModes.MULTIPLY (default) * - Phaser.TintModes.FILL * - Phaser.TintModes.ADD * - Phaser.TintModes.SCREEN * - Phaser.TintModes.OVERLAY * - Phaser.TintModes.HARD_LIGHT * * Call this method with no parameters to reset the tint mode to the default. * * If a tile already has a tint mode set then calling this method will override that. * * @method Phaser.Tilemaps.TilemapLayer#setTintMode * @webglOnly * @since 4.0.0 * * @param {Phaser.TintModes} [tintMode=Phaser.TintModes.MULTIPLY] - The tint mode to use. * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area to search. * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area to search. * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. * @param {Phaser.Types.Tilemaps.FilteringOptions} [filteringOptions] - Optional filters to apply when getting the tiles. * * @return {this} This Tilemap Layer object. */ setTintMode: function (tintMode, tileX, tileY, width, height, filteringOptions) { if (tintMode === undefined) { tintMode = TintModes.MULTIPLY; } var tintTile = function (tile) { tile.tintMode = tintMode; }; return this.forEachTile(tintTile, this, tileX, tileY, width, height, filteringOptions); }, /** * Destroys this TilemapLayer, clearing the culled tiles array and removing the cull callback. * Also removes the layer from its parent Tilemap if `removeFromTilemap` is set to `true`. * * @method Phaser.Tilemaps.TilemapLayer#destroy * @since 3.50.0 * * @param {boolean} [removeFromTilemap=true] - Remove this layer from the parent Tilemap before destroying it. */ destroy: function (removeFromTilemap) { this.culledTiles.length = 0; this.cullCallback = null; TilemapLayerBase.prototype.destroy.call(this, removeFromTilemap); } }); module.exports = TilemapLayer;