175 lines
6.4 KiB
TypeScript
175 lines
6.4 KiB
TypeScript
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;
|
||
}
|
||
|
||
/**
|
||
* 获取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);
|
||
}
|
||
}
|
||
|
||
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);
|
||
}
|
||
}
|
||
} |