2018-02-07 17:10:01 +00:00
|
|
|
var Class = require('../utils/Class');
|
2017-11-10 21:56:14 +00:00
|
|
|
|
2018-02-07 15:27:21 +00:00
|
|
|
/**
|
|
|
|
* @classdesc
|
|
|
|
* 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.
|
|
|
|
*/
|
2017-11-10 21:56:14 +00:00
|
|
|
var Tileset = new Class({
|
|
|
|
|
|
|
|
initialize:
|
|
|
|
|
2017-11-29 20:39:30 +00:00
|
|
|
function Tileset (name, firstgid, tileWidth, tileHeight, tileMargin, tileSpacing, tileProperties, tileData)
|
2017-11-10 21:56:14 +00:00
|
|
|
{
|
|
|
|
if (tileWidth === undefined || tileWidth <= 0) { tileWidth = 32; }
|
|
|
|
if (tileHeight === undefined || tileHeight <= 0) { tileHeight = 32; }
|
|
|
|
if (tileMargin === undefined) { tileMargin = 0; }
|
|
|
|
if (tileSpacing === undefined) { tileSpacing = 0; }
|
2017-11-29 20:39:30 +00:00
|
|
|
if (tileProperties === undefined) { tileProperties = {}; }
|
2017-11-24 14:23:22 +00:00
|
|
|
if (tileData === undefined) { tileData = {}; }
|
2017-11-10 21:56:14 +00:00
|
|
|
|
2017-11-29 20:39:30 +00:00
|
|
|
/**
|
|
|
|
* The name of the Tileset.
|
|
|
|
* @property {string} name
|
|
|
|
*/
|
2017-11-10 21:56:14 +00:00
|
|
|
this.name = name;
|
2017-11-29 20:39:30 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The starting index of the first tile index this Tileset contains.
|
|
|
|
* @property {integer} firstgid
|
|
|
|
*/
|
2017-11-10 21:56:14 +00:00
|
|
|
this.firstgid = firstgid;
|
2017-11-29 20:39:30 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The width of each tile (in pixels). Use setTileSize to change.
|
|
|
|
* @property {integer} tileWidth
|
|
|
|
* @readonly
|
|
|
|
*/
|
2017-11-10 21:56:14 +00:00
|
|
|
this.tileWidth = tileWidth;
|
2017-11-29 20:39:30 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The height of each tile (in pixels). Use setTileSize to change.
|
|
|
|
* @property {integer} tileHeight
|
|
|
|
* @readonly
|
|
|
|
*/
|
2017-11-10 21:56:14 +00:00
|
|
|
this.tileHeight = tileHeight;
|
2017-11-29 20:39:30 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The margin around the tiles in the sheet (in pixels). Use `setSpacing` to change.
|
|
|
|
* @property {integer} tileMargin
|
|
|
|
* @readonly
|
|
|
|
*/
|
2017-11-10 21:56:14 +00:00
|
|
|
this.tileMargin = tileMargin;
|
2017-11-29 20:39:30 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The spacing between each the tile in the sheet (in pixels). Use `setSpacing` to change.
|
|
|
|
* @property {integer} tileSpacing
|
|
|
|
* @readonly
|
|
|
|
*/
|
2017-11-10 21:56:14 +00:00
|
|
|
this.tileSpacing = tileSpacing;
|
2017-11-29 20:39:30 +00:00
|
|
|
|
|
|
|
/**
|
2018-01-23 13:55:43 +00:00
|
|
|
* Tileset-specific properties per tile that are typically defined in the Tiled editor in the
|
|
|
|
* Tileset editor.
|
2017-11-29 20:39:30 +00:00
|
|
|
* @property {object} tileProperties
|
|
|
|
*/
|
|
|
|
this.tileProperties = tileProperties;
|
|
|
|
|
|
|
|
/**
|
2018-01-23 13:55:43 +00:00
|
|
|
* Tileset-specific data per tile that are typically defined in the Tiled editor, e.g. within
|
2018-01-23 14:38:25 +00:00
|
|
|
* the Tileset collision editor. This is where collision objects and terrain are stored.
|
2017-11-29 20:39:30 +00:00
|
|
|
* @property {object} tileData
|
|
|
|
*/
|
2017-11-24 14:23:22 +00:00
|
|
|
this.tileData = tileData;
|
2017-11-29 20:39:30 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The cached image that contains the individual tiles. Use setImage to set.
|
|
|
|
* @property {Texture|null} image
|
|
|
|
* @readonly
|
|
|
|
*/
|
2017-11-10 21:56:14 +00:00
|
|
|
this.image = null;
|
2017-11-29 20:39:30 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The number of tile rows in the the tileset.
|
|
|
|
* @property {integer} rows
|
|
|
|
* @readonly
|
|
|
|
*/
|
2017-11-10 21:56:14 +00:00
|
|
|
this.rows = 0;
|
2017-11-29 20:39:30 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The number of tile columns in the tileset.
|
|
|
|
* @property {integer} columns
|
|
|
|
* @readonly
|
|
|
|
*/
|
2017-11-10 21:56:14 +00:00
|
|
|
this.columns = 0;
|
2017-11-29 20:39:30 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The total number of tiles in the tileset.
|
|
|
|
* @property {integer} total
|
|
|
|
* @readonly
|
|
|
|
*/
|
2017-11-10 21:56:14 +00:00
|
|
|
this.total = 0;
|
2017-11-29 20:39:30 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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}.
|
2017-11-29 21:07:56 +00:00
|
|
|
* @property {object[]} texCoordinates
|
2017-11-29 20:39:30 +00:00
|
|
|
* @readonly
|
|
|
|
*/
|
2017-11-10 21:56:14 +00:00
|
|
|
this.texCoordinates = [];
|
|
|
|
},
|
|
|
|
|
2017-11-29 20:39:30 +00:00
|
|
|
/**
|
|
|
|
* Get a tile's properties that are stored in the Tileset. Returns null if tile index is not
|
2018-01-23 13:55:43 +00:00
|
|
|
* contained in this Tileset. This is typically defined in Tiled under the Tileset editor.
|
2017-11-29 20:39:30 +00:00
|
|
|
*
|
|
|
|
* @param {integer} tileIndex - The unique id of the tile across all tilesets in the map.
|
|
|
|
* @returns {object|undefined|null}
|
|
|
|
*/
|
2018-01-23 13:54:03 +00:00
|
|
|
getTileProperties: function (tileIndex)
|
2017-11-24 14:23:22 +00:00
|
|
|
{
|
|
|
|
if (!this.containsTileIndex(tileIndex)) { return null; }
|
2017-11-29 20:39:30 +00:00
|
|
|
return this.tileProperties[tileIndex - this.firstgid];
|
2017-11-24 14:23:22 +00:00
|
|
|
},
|
|
|
|
|
2017-11-29 20:39:30 +00:00
|
|
|
/**
|
2018-01-23 13:55:43 +00:00
|
|
|
* Get a tile's data that is stored in the Tileset. Returns null if tile index is not contained
|
|
|
|
* in this Tileset. This is typically defined in Tiled and will contain both Tileset collision
|
|
|
|
* info and terrain mapping.
|
2017-11-29 20:39:30 +00:00
|
|
|
*
|
|
|
|
* @param {integer} tileIndex - The unique id of the tile across all tilesets in the map.
|
|
|
|
* @returns {object|undefined|null}
|
|
|
|
*/
|
2017-11-24 14:23:22 +00:00
|
|
|
getTileData: function (tileIndex)
|
|
|
|
{
|
|
|
|
if (!this.containsTileIndex(tileIndex)) { return null; }
|
|
|
|
return this.tileData[tileIndex - this.firstgid];
|
|
|
|
},
|
|
|
|
|
2017-12-02 00:57:27 +00:00
|
|
|
/**
|
2018-01-23 13:55:43 +00:00
|
|
|
* Get a tile's collision group that is stored in the Tileset. Returns null if tile index is not
|
|
|
|
* contained in this Tileset. This is typically defined within Tiled's tileset collision editor.
|
2017-12-02 00:57:27 +00:00
|
|
|
*
|
|
|
|
* @param {integer} tileIndex - The unique id of the tile across all tilesets in the map.
|
|
|
|
* @returns {object|null}
|
|
|
|
*/
|
|
|
|
getTileCollisionGroup: function (tileIndex)
|
|
|
|
{
|
|
|
|
var data = this.getTileData(tileIndex);
|
|
|
|
return (data && data.objectgroup) ? data.objectgroup : null;
|
|
|
|
},
|
|
|
|
|
|
|
|
|
2017-11-29 20:39:30 +00:00
|
|
|
/**
|
|
|
|
* 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}
|
|
|
|
*/
|
2017-11-10 21:56:14 +00:00
|
|
|
containsTileIndex: function (tileIndex)
|
|
|
|
{
|
|
|
|
return (
|
|
|
|
tileIndex >= this.firstgid &&
|
|
|
|
tileIndex < (this.firstgid + this.total)
|
|
|
|
);
|
|
|
|
},
|
|
|
|
|
2017-11-29 20:39:30 +00:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
2017-11-10 21:56:14 +00:00
|
|
|
getTileTextureCoordinates: function (tileIndex)
|
|
|
|
{
|
|
|
|
if (!this.containsTileIndex(tileIndex)) { return null; }
|
|
|
|
return this.texCoordinates[tileIndex - this.firstgid];
|
|
|
|
},
|
|
|
|
|
2017-11-29 20:39:30 +00:00
|
|
|
/**
|
|
|
|
* 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}
|
|
|
|
*/
|
2017-11-18 21:40:27 +00:00
|
|
|
setTileSize: function (tileWidth, tileHeight)
|
|
|
|
{
|
|
|
|
if (tileWidth !== undefined) { this.tileWidth = tileWidth; }
|
|
|
|
if (tileHeight !== undefined) { this.tileHeight = tileHeight; }
|
|
|
|
|
|
|
|
if (this.image)
|
|
|
|
{
|
|
|
|
this.updateTileData(this.image.source[0].width, this.image.source[0].height);
|
|
|
|
}
|
2017-11-29 20:39:30 +00:00
|
|
|
|
|
|
|
return this;
|
2017-11-18 21:40:27 +00:00
|
|
|
},
|
|
|
|
|
2017-11-29 20:39:30 +00:00
|
|
|
/**
|
|
|
|
* 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}
|
|
|
|
*/
|
2017-11-16 21:25:45 +00:00
|
|
|
setSpacing: function (margin, spacing)
|
|
|
|
{
|
2017-11-18 21:40:27 +00:00
|
|
|
if (margin !== undefined) { this.tileMargin = margin; }
|
|
|
|
if (spacing !== undefined) { this.tileSpacing = spacing; }
|
2017-11-16 21:25:45 +00:00
|
|
|
|
|
|
|
if (this.image)
|
|
|
|
{
|
|
|
|
this.updateTileData(this.image.source[0].width, this.image.source[0].height);
|
|
|
|
}
|
2017-11-29 20:39:30 +00:00
|
|
|
|
|
|
|
return this;
|
2017-11-16 21:25:45 +00:00
|
|
|
},
|
|
|
|
|
2017-11-29 20:39:30 +00:00
|
|
|
/**
|
|
|
|
* 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}
|
|
|
|
*/
|
2017-11-10 21:56:14 +00:00
|
|
|
updateTileData: function (imageWidth, imageHeight)
|
|
|
|
{
|
|
|
|
var rowCount = (imageHeight - this.tileMargin * 2 + this.tileSpacing) / (this.tileHeight + this.tileSpacing);
|
|
|
|
var colCount = (imageWidth - this.tileMargin * 2 + this.tileSpacing) / (this.tileWidth + this.tileSpacing);
|
|
|
|
|
|
|
|
if (rowCount % 1 !== 0 || colCount % 1 !== 0)
|
|
|
|
{
|
|
|
|
console.warn('Tileset ' + this.name + ' image tile area is not an even multiple of tile size');
|
|
|
|
}
|
|
|
|
|
2017-11-29 20:39:30 +00:00
|
|
|
// 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.
|
2017-11-10 21:56:14 +00:00
|
|
|
rowCount = Math.floor(rowCount);
|
|
|
|
colCount = Math.floor(colCount);
|
|
|
|
|
|
|
|
this.rows = rowCount;
|
|
|
|
this.columns = colCount;
|
|
|
|
|
|
|
|
// In Tiled, "empty" spaces in a tileset count as tiles and hence count towards the gid
|
|
|
|
this.total = rowCount * colCount;
|
|
|
|
|
|
|
|
this.texCoordinates.length = 0;
|
|
|
|
|
|
|
|
var tx = this.tileMargin;
|
|
|
|
var ty = this.tileMargin;
|
|
|
|
|
|
|
|
for (var y = 0; y < this.rows; y++)
|
|
|
|
{
|
|
|
|
for (var x = 0; x < this.columns; x++)
|
|
|
|
{
|
|
|
|
this.texCoordinates.push({ x: tx, y: ty });
|
|
|
|
tx += this.tileWidth + this.tileSpacing;
|
|
|
|
}
|
|
|
|
|
|
|
|
tx = this.tileMargin;
|
|
|
|
ty += this.tileHeight + this.tileSpacing;
|
|
|
|
}
|
2017-11-29 20:39:30 +00:00
|
|
|
|
|
|
|
return this;
|
2017-11-10 21:56:14 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
module.exports = Tileset;
|