2020-08-12 12:16:35 +08:00
|
|
|
|
module es {
|
|
|
|
|
|
export class TmxLayer implements ITmxLayer {
|
|
|
|
|
|
public map: TmxMap;
|
|
|
|
|
|
public name: string;
|
|
|
|
|
|
public opacity: number;
|
|
|
|
|
|
public offsetX: number;
|
|
|
|
|
|
public offsetY: number;
|
|
|
|
|
|
public properties: Map<string, string>;
|
|
|
|
|
|
public visible: boolean;
|
|
|
|
|
|
public get offset(): Vector2 {
|
|
|
|
|
|
return new Vector2(this.offsetX, this.offsetY);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 这一层tile的宽度。对于固定大小的地图,始终与地图宽度相同。
|
|
|
|
|
|
*/
|
|
|
|
|
|
public width: number;
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 这一层的tile高度。对于固定大小的地图,始终与地图高度相同。
|
|
|
|
|
|
*/
|
|
|
|
|
|
public height: number;
|
|
|
|
|
|
public tiles: TmxLayerTile[];
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 回带有gid的TmxLayerTile。这是一个慢查询,所以要缓存它
|
|
|
|
|
|
* @param gid
|
|
|
|
|
|
*/
|
|
|
|
|
|
public getTileWithGid(gid: number){
|
|
|
|
|
|
for (let i = 0; i < this.tiles.length; i ++){
|
|
|
|
|
|
if (this.tiles[i] && this.tiles[i].gid == gid)
|
|
|
|
|
|
return this.tiles[i];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
2020-08-12 18:08:12 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取x/y坐标处的TmxLayerTile。注意,这些是平铺坐标而不是世界坐标!
|
|
|
|
|
|
* @param x
|
|
|
|
|
|
* @param y
|
|
|
|
|
|
*/
|
|
|
|
|
|
public getTile(x: number, y: number): TmxLayerTile {
|
|
|
|
|
|
return this.tiles[x + y * this.width];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 返回平铺空间中的矩形列表,其中任何非空平铺组合为边界区域
|
|
|
|
|
|
*/
|
|
|
|
|
|
public getCollisionRectangles(): Rectangle[] {
|
|
|
|
|
|
let checkedIndexes = [];
|
|
|
|
|
|
let rectangles = [];
|
|
|
|
|
|
let startCol = -1;
|
|
|
|
|
|
let index = -1;
|
|
|
|
|
|
|
|
|
|
|
|
for (let y = 0; y < this.map.height; y ++){
|
|
|
|
|
|
for (let x = 0; x< this.map.width; x ++){
|
|
|
|
|
|
index = y * this.map.width + x;
|
|
|
|
|
|
let tile = this.getTile(x, y);
|
|
|
|
|
|
if (tile && !checkedIndexes[index]){
|
|
|
|
|
|
if (startCol < 0)
|
|
|
|
|
|
startCol = x;
|
|
|
|
|
|
checkedIndexes[index] = true;
|
|
|
|
|
|
}else if(tile || checkedIndexes[index]){
|
|
|
|
|
|
if (startCol >= 0){
|
|
|
|
|
|
rectangles.push(this.findBoundsRect(startCol, x, y, checkedIndexes));
|
|
|
|
|
|
startCol = -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (startCol >= 0){
|
|
|
|
|
|
rectangles.push(this.findBoundsRect(startCol, this.map.width, y, checkedIndexes));
|
|
|
|
|
|
startCol = -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return rectangles;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 在startX和endX之间的tile周围找到最大的边界矩形,从startY开始,尽可能向下
|
|
|
|
|
|
* @param startX
|
|
|
|
|
|
* @param endX
|
|
|
|
|
|
* @param startY
|
|
|
|
|
|
* @param checkedIndexes
|
|
|
|
|
|
*/
|
|
|
|
|
|
public findBoundsRect(startX: number, endX: number, startY: number, checkedIndexes?: boolean[]){
|
|
|
|
|
|
let index = -1;
|
|
|
|
|
|
for (let y = startY + 1; y < this.map.height; y ++){
|
|
|
|
|
|
for (let x = startX; x < endX; x ++){
|
|
|
|
|
|
index = y * this.map.width + x;
|
|
|
|
|
|
let tile = this.getTile(x, y);
|
|
|
|
|
|
if (tile || checkedIndexes[index]){
|
|
|
|
|
|
// 再次将我们到目前为止在这一行中访问过的所有内容设置为false,因为它不会包含在矩形中,应该再次进行检查
|
|
|
|
|
|
for (let _x = startX; _x < x; _x++){
|
|
|
|
|
|
index = y * this.map.width + _x;
|
|
|
|
|
|
checkedIndexes[index] = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return new Rectangle(startX * this.map.tileWidth, startY * this.map.tileHeight,
|
|
|
|
|
|
(endX - startX) * this.map.tileWidth, (y - startY) * this.map.tileHeight);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
checkedIndexes[index] = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return new Rectangle(startX * this.map.tileWidth, startY * this.map.tileHeight,
|
|
|
|
|
|
(endX - startX) * this.map.tileWidth, (this.map.height - startY) * this.map.tileHeight);
|
|
|
|
|
|
}
|
2020-08-12 12:16:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export class TmxLayerTile {
|
|
|
|
|
|
public static readonly FLIPPED_HORIZONTALLY_FLAG = 0x80000000;
|
|
|
|
|
|
public static readonly FLIPPED_VERTICALLY_FLAG = 0x40000000;
|
|
|
|
|
|
public static readonly FLIPPED_DIAGONALLY_FLAG = 0x20000000;
|
|
|
|
|
|
|
|
|
|
|
|
public tileset: TmxTileset;
|
|
|
|
|
|
public gid: number;
|
|
|
|
|
|
public x: number;
|
|
|
|
|
|
public y: number;
|
|
|
|
|
|
public get position(): Vector2{
|
|
|
|
|
|
return new Vector2(this.x, this.y);
|
|
|
|
|
|
}
|
|
|
|
|
|
public horizontalFlip: boolean;
|
|
|
|
|
|
public verticalFlip: boolean;
|
|
|
|
|
|
public diagonalFlip: boolean;
|
|
|
|
|
|
public _tilesetTileIndex?: number;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取此TmxLayerTile(如果存在)的TmxTilesetTile
|
|
|
|
|
|
* TmxTilesetTile只存在于动态的tiles和带有附加属性的tiles中。
|
|
|
|
|
|
*/
|
|
|
|
|
|
public get tilesetTile(): TmxTilesetTile {
|
|
|
|
|
|
if (this._tilesetTileIndex == undefined){
|
|
|
|
|
|
this._tilesetTileIndex = -1;
|
|
|
|
|
|
if (this.tileset.firstGid <= this.gid){
|
|
|
|
|
|
let tilesetTile = this.tileset.tiles.get(this.gid - this.tileset.firstGid);
|
|
|
|
|
|
if (tilesetTile){
|
|
|
|
|
|
this._tilesetTileIndex = this.gid - this.tileset.firstGid;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (this._tilesetTileIndex < 0)
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
|
|
return this.tileset.tiles.get(this._tilesetTileIndex);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
constructor(map: TmxMap, id: number, x: number, y: number){
|
|
|
|
|
|
this.x = x;
|
|
|
|
|
|
this.y = y;
|
|
|
|
|
|
let rawGid = id;
|
|
|
|
|
|
|
|
|
|
|
|
// 扫描平铺反转位标志
|
|
|
|
|
|
let flip: boolean;
|
|
|
|
|
|
flip = (rawGid & TmxLayerTile.FLIPPED_HORIZONTALLY_FLAG) != 0;
|
|
|
|
|
|
this.horizontalFlip = flip;
|
|
|
|
|
|
|
|
|
|
|
|
flip = (rawGid & TmxLayerTile.FLIPPED_VERTICALLY_FLAG) != 0;
|
|
|
|
|
|
this.verticalFlip = flip;
|
|
|
|
|
|
|
|
|
|
|
|
flip = (rawGid & TmxLayerTile.FLIPPED_DIAGONALLY_FLAG) != 0;
|
|
|
|
|
|
this.diagonalFlip = flip;
|
|
|
|
|
|
|
|
|
|
|
|
// 零位标志
|
|
|
|
|
|
rawGid &= ~(TmxLayerTile.FLIPPED_HORIZONTALLY_FLAG | TmxLayerTile.FLIPPED_VERTICALLY_FLAG | TmxLayerTile.FLIPPED_DIAGONALLY_FLAG);
|
|
|
|
|
|
|
|
|
|
|
|
// 将GID保存
|
|
|
|
|
|
this.gid = rawGid;
|
|
|
|
|
|
this.tileset = map.getTilesetForTileGid(this.gid);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|