移除tiled依赖,改为可选 https://github.com/esengine/egret-framework-tiled
This commit is contained in:
@@ -1,146 +0,0 @@
|
||||
module es {
|
||||
export class TiledMapRenderer extends RenderableComponent {
|
||||
public tiledMap: TmxMap;
|
||||
public physicsLayer: Ref<number> = new Ref(1 << 0);
|
||||
/**
|
||||
* 如果空,所有层将被渲染
|
||||
*/
|
||||
public layerIndicesToRender: number[];
|
||||
private toContainer: boolean = false;
|
||||
|
||||
public get width() {
|
||||
return this.tiledMap.width * this.tiledMap.tileWidth;
|
||||
}
|
||||
|
||||
public get height() {
|
||||
return this.tiledMap.height * this.tiledMap.tileHeight;
|
||||
}
|
||||
|
||||
public collisionLayer: TmxLayer;
|
||||
public _shouldCreateColliders: boolean;
|
||||
public _colliders: Collider[];
|
||||
|
||||
constructor(tiledMap: TmxMap, collisionLayerName: string = null, shouldCreateColliders: boolean = true) {
|
||||
super();
|
||||
this.tiledMap = tiledMap;
|
||||
this._shouldCreateColliders = shouldCreateColliders;
|
||||
this.displayObject = new egret.DisplayObjectContainer();
|
||||
|
||||
if (collisionLayerName) {
|
||||
this.collisionLayer = tiledMap.tileLayers.find(layer => layer.name == collisionLayerName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将此组件设置为只渲染单层
|
||||
* @param layerName
|
||||
*/
|
||||
public setLayerToRender(layerName: string) {
|
||||
this.layerIndicesToRender = [];
|
||||
this.layerIndicesToRender[0] = this.getLayerIndex(layerName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置该组件应该按名称呈现哪些层。如果你知道索引,你可以直接设置layerIndicesToRender
|
||||
* @param layerNames
|
||||
*/
|
||||
public setLayersToRender(...layerNames: string[]) {
|
||||
this.layerIndicesToRender = [];
|
||||
for (let i = 0; i < layerNames.length; i++)
|
||||
this.layerIndicesToRender[i] = this.getLayerIndex(layerNames[i]);
|
||||
}
|
||||
|
||||
private getLayerIndex(layerName: string) {
|
||||
let index = 0;
|
||||
let layerType = this.tiledMap.getLayer(layerName);
|
||||
for (let layer in this.tiledMap.layers) {
|
||||
if (this.tiledMap.layers.hasOwnProperty(layer) &&
|
||||
this.tiledMap.layers[layer] == layerType) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public getRowAtWorldPosition(yPos: number): number {
|
||||
yPos -= this.entity.transform.position.y + this._localOffset.y;
|
||||
return this.tiledMap.worldToTilePositionY(yPos);
|
||||
}
|
||||
|
||||
public getColumnAtWorldPosition(xPos: number): number {
|
||||
xPos -= this.entity.transform.position.x + this._localOffset.x;
|
||||
return this.tiledMap.worldToTilePositionX(xPos);
|
||||
}
|
||||
|
||||
public onEntityTransformChanged(comp: transform.Component) {
|
||||
// 这里我们只处理位置变化。平铺地图不能缩放
|
||||
if (this._shouldCreateColliders && comp == transform.Component.position) {
|
||||
this.removeColliders();
|
||||
this.addColliders();
|
||||
}
|
||||
}
|
||||
|
||||
public onAddedToEntity() {
|
||||
this.addColliders();
|
||||
}
|
||||
|
||||
public onRemovedFromEntity() {
|
||||
this.removeColliders();
|
||||
}
|
||||
|
||||
public update() {
|
||||
this.tiledMap.update();
|
||||
}
|
||||
|
||||
public render(camera: es.Camera) {
|
||||
this.sync(camera);
|
||||
|
||||
if (!this.layerIndicesToRender) {
|
||||
TiledRendering.renderMap(this.tiledMap, !this.toContainer ? this.displayObject as egret.DisplayObjectContainer : null, Vector2.add(this.entity.transform.position, this._localOffset),
|
||||
this.transform.scale, this.renderLayer);
|
||||
} else {
|
||||
for (let i = 0; i < this.tiledMap.layers.length; i++) {
|
||||
if (this.tiledMap.layers[i].visible && this.layerIndicesToRender.contains(i))
|
||||
TiledRendering.renderLayerRenderCamera(this.tiledMap.layers[i] as TmxLayer, !this.toContainer ? this.displayObject as egret.DisplayObjectContainer : null, Vector2.add(this.entity.transform.position, this._localOffset),
|
||||
this.transform.scale, this.renderLayer, camera.bounds);
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.toContainer){
|
||||
this.displayObject.cacheAsBitmap = true;
|
||||
this.toContainer = true;
|
||||
}
|
||||
}
|
||||
|
||||
public addColliders() {
|
||||
if (!this.collisionLayer || !this._shouldCreateColliders)
|
||||
return;
|
||||
|
||||
// 获取冲突层及其冲突的矩形
|
||||
let collisionRects = this.collisionLayer.getCollisionRectangles();
|
||||
|
||||
// 为我们收到的矩形创建碰撞器
|
||||
this._colliders = [];
|
||||
for (let i = 0; i < collisionRects.length; i++) {
|
||||
let collider = new BoxCollider(collisionRects[i].x + this._localOffset.x,
|
||||
collisionRects[i].y + this._localOffset.y, collisionRects[i].width, collisionRects[i].height);
|
||||
collider.physicsLayer = this.physicsLayer;
|
||||
collider.entity = this.entity;
|
||||
this._colliders[i] = collider;
|
||||
|
||||
Physics.addCollider(collider);
|
||||
}
|
||||
}
|
||||
|
||||
public removeColliders() {
|
||||
if (this._colliders == null)
|
||||
return;
|
||||
|
||||
for (let collider of this._colliders) {
|
||||
Physics.removeCollider(collider);
|
||||
}
|
||||
this._colliders = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
// module es {
|
||||
// /**
|
||||
// * 用来存放来自移动调用的所有冲突信息
|
||||
// */
|
||||
// export class CollisionState {
|
||||
// public right: boolean;
|
||||
// public left: boolean;
|
||||
// public above: boolean;
|
||||
// public below: boolean;
|
||||
// public becameGroundedThisFrame: boolean;
|
||||
// public wasGroundedLastFrame: boolean;
|
||||
// public isGroundedOnOnewayPlatform: boolean;
|
||||
// public slopAngle: number;
|
||||
|
||||
// public get hasCollision(): boolean {
|
||||
// return this.below || this.right || this.left || this.above;
|
||||
// }
|
||||
|
||||
// public _movementRemainderX: SubpixelNumber;
|
||||
// public _movementRemainderY: SubpixelNumber;
|
||||
|
||||
// public reset() {
|
||||
// this.becameGroundedThisFrame = this.isGroundedOnOnewayPlatform = this.right = this.left = this.above = this.below = false;
|
||||
// this.slopAngle = 0;
|
||||
// }
|
||||
|
||||
// public toString() {
|
||||
// return `[CollisionState] r: ${this.right}, l: ${this.left}, a: ${this.above}, b: ${this.below}, angle: ${this.slopAngle}, wasGroundedLastFrame: ${this.wasGroundedLastFrame}, becameGroundedThisFrame: ${this.becameGroundedThisFrame}`;
|
||||
// }
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * TiledMapMover是在基于重力的平铺地图中移动对象的助手。
|
||||
// * 它要求它所在的实体有一个BoxCollider。BoxCollider将与colliderHorizontal/VerticalInset用于所有碰撞检测。
|
||||
// *
|
||||
// * 一种方法是通过将你的Transform向下移动1个像素并调用CollisionState.clearLastGroundTile来跳过平台。
|
||||
// */
|
||||
// export class TiledMapMover extends Component {
|
||||
// /**
|
||||
// * 在垂直移动时,BoxCollider将根据水平面上的嵌入缩小
|
||||
// */
|
||||
// public colliderHorizontalInset = 2;
|
||||
|
||||
// /**
|
||||
// * 垂直平面上的嵌入,在水平移动时,BoxCollider将根据该嵌入缩小
|
||||
// */
|
||||
// public colliderVerticalInset = 6;
|
||||
|
||||
// /**
|
||||
// * 临时存储
|
||||
// */
|
||||
// public _boxColliderBounds: Rectangle;
|
||||
|
||||
// constructor() {
|
||||
// super();
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * 测试碰撞,然后移动实体
|
||||
// * @param motion
|
||||
// * @param boxColliderBounds
|
||||
// * @param collisionState
|
||||
// */
|
||||
// public testCollisions(motion: Vector2, boxColliderBounds: Rectangle, collisionState: CollisionState) {
|
||||
// this._boxColliderBounds = boxColliderBounds;
|
||||
|
||||
// // 保存我们当前的接地状态,我们将用于wasGroundedLastFrame和becameGroundedThisFrame
|
||||
// collisionState.wasGroundedLastFrame = collisionState.below;
|
||||
|
||||
// // 重置碰撞状态
|
||||
// collisionState.reset();
|
||||
|
||||
// // 获取圆角值用于我们的实际检测
|
||||
// let motionX = motion.x;
|
||||
// let motionY = motion.y;
|
||||
|
||||
// // 首先,检查水平方向中的移动
|
||||
// if (motionX != 0){
|
||||
// let direction = motionX > 0 ? Edge.right : Edge.left;
|
||||
// let sweptBounds = this.collisionRectForSide(direction, motionX);
|
||||
|
||||
// let collisionResponse: number = 0;
|
||||
// if (this.testMapCollision(sweptBounds, direction, collisionState, collisionResponse)){
|
||||
// motion.x = collisionResponse - RectangleExt.getSide(boxColliderBounds, direction);
|
||||
// collisionState.left = direction == Edge.left;
|
||||
// collisionState.right = direction == Edge.right;
|
||||
// collisionState._movementRemainderX.reset();
|
||||
// }else{
|
||||
// collisionState.left = false;
|
||||
// collisionState.right = false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// public testMapCollision(collisionRect: Rectangle, direction: Edge, collisionState: CollisionState, collisionResponse: number){
|
||||
// let side = EdgeExt.oppositeEdge(direction);
|
||||
// let perpindicularPosition = EdgeExt.isVertical(side) ? collisionRect.center.x : collisionRect.center.y;
|
||||
// let leadingPosition = RectangleExt.getSide(collisionRect, direction);
|
||||
// let shouldTestSlopes = EdgeExt.isVertical(side);
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * 获取展开以考虑运动的给定边的碰撞矩形
|
||||
// * @param side
|
||||
// * @param motion
|
||||
// */
|
||||
// public collisionRectForSide(side: Edge, motion: number){
|
||||
// let bounds: Rectangle;
|
||||
|
||||
// // 对于水平碰撞检查,我们只使用一个条块作为边界。Vertical得到矩形的一半,就可以正确地向上推,
|
||||
// // 当相交的斜率,忽略以进行水平移动。
|
||||
// if (EdgeExt.isHorizontal(side)){
|
||||
// bounds = RectangleExt.getRectEdgePortion(this._boxColliderBounds, side);
|
||||
// }else {
|
||||
// bounds = RectangleExt.getHalfRect(this._boxColliderBounds, side);
|
||||
// }
|
||||
|
||||
// // 我们水平收缩用于垂直移动,垂直收缩用于水平移动
|
||||
// if (EdgeExt.isVertical(side)){
|
||||
// RectangleExt.contract(bounds, this.colliderHorizontalInset, 0);
|
||||
// }else {
|
||||
// RectangleExt.contract(bounds, 0, this.colliderVerticalInset);
|
||||
// }
|
||||
|
||||
// // 最后在移动方向上扩展边
|
||||
// RectangleExt.expandSide(bounds, side, motion);
|
||||
|
||||
// return bounds;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -1,16 +0,0 @@
|
||||
module es {
|
||||
export class TmxGroup implements ITmxLayer{
|
||||
public map: TmxMap;
|
||||
public offsetX: number;
|
||||
public offsetY: number;
|
||||
public opacity: number;
|
||||
public properties: Map<string, string>;
|
||||
public visible: boolean;
|
||||
public name: string;
|
||||
public layers: ITmxLayer[];
|
||||
public tileLayers: TmxLayer[];
|
||||
public objectGroups: TmxObjectGroup[];
|
||||
public imageLayers: TmxImageLayer[];
|
||||
public groups: TmxGroup[];
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
module es {
|
||||
export interface ITmxLayer {
|
||||
offsetX: number;
|
||||
offsetY: number;
|
||||
opacity: number;
|
||||
visible: boolean;
|
||||
properties: Map<string, string>;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
module es {
|
||||
export class TmxImageLayer implements ITmxLayer {
|
||||
public map: TmxMap;
|
||||
public name: string;
|
||||
public offsetX: number;
|
||||
public offsetY: number;
|
||||
public opacity: number;
|
||||
public properties: Map<string, string>;
|
||||
public visible: boolean;
|
||||
|
||||
public width?: number;
|
||||
public height?: number;
|
||||
public image: TmxImage;
|
||||
}
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
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: boolean[] = new Array(this.tiles.length);
|
||||
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] == true){
|
||||
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){
|
||||
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);
|
||||
|
||||
// 将GID保存
|
||||
this.gid = Math.floor(rawGid);
|
||||
this.tileset = map.getTilesetForTileGid(this.gid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
///<reference path="./TiledCore.ts" />
|
||||
module es {
|
||||
export class TmxMap extends TmxDocument {
|
||||
public version: string;
|
||||
public tiledVersion: string;
|
||||
public width: number;
|
||||
public height: number;
|
||||
public get worldWidth(){
|
||||
return this.width * this.tileWidth;
|
||||
}
|
||||
public get worldHeight(){
|
||||
return this.height * this.tileHeight;
|
||||
}
|
||||
|
||||
public tileWidth: number;
|
||||
public tileHeight: number;
|
||||
public hexSideLength?: number;
|
||||
public orientation: OrientationType;
|
||||
public staggerAxis: StaggerAxisType;
|
||||
public staggerIndex: StaggerIndexType;
|
||||
public renderOrder: RenderOrderType;
|
||||
public backgroundColor: number;
|
||||
public nextObjectID?: number;
|
||||
|
||||
/**
|
||||
* 包含所有的ITmxLayers,不管它们的具体类型是什么。
|
||||
* 注意,TmxGroup中的层将不在此列表中。TmxGroup管理自己的层列表。
|
||||
*/
|
||||
public layers: ITmxLayer[];
|
||||
public tilesets: TmxTileset[];
|
||||
public tileLayers: TmxLayer[];
|
||||
public objectGroups: TmxObjectGroup[];
|
||||
public imageLayers: TmxImageLayer[];
|
||||
public groups: TmxGroup[];
|
||||
public properties: Map<string, string>;
|
||||
|
||||
/**
|
||||
* 当我们有一个图像tileset,tile可以是任何大小,所以我们记录的最大大小来剔除
|
||||
*/
|
||||
public maxTileWidth: number;
|
||||
|
||||
/**
|
||||
* 当我们有一个图像tileset,tile可以是任何大小,所以我们记录的最大大小来剔除
|
||||
*/
|
||||
public maxTileHeight: number;
|
||||
|
||||
/**
|
||||
* 此地图是否具有需要非默认平铺大小的特殊剔除
|
||||
*/
|
||||
public get requiresLargeTileCulling(): boolean {
|
||||
return this.maxTileHeight > this.tileHeight || this.maxTileWidth > this.tileWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取给定tileId的tile tileset
|
||||
* @param gid
|
||||
*/
|
||||
public getTilesetForTileGid(gid: number): TmxTileset {
|
||||
if (gid == 0)
|
||||
return null;
|
||||
|
||||
for (let i = this.tilesets.length - 1; i >= 0; i --){
|
||||
if (this.tilesets[i].firstGid <= gid)
|
||||
return this.tilesets[i];
|
||||
}
|
||||
|
||||
console.error(`tile gid${gid}未在任何tileset中找到`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换从世界平铺位置获取tilemap边界
|
||||
* @param x
|
||||
* @param clampToTilemapBounds
|
||||
*/
|
||||
public worldToTilePositionX(x: number, clampToTilemapBounds = true){
|
||||
let tileX = Math.floor(x / this.tileWidth);
|
||||
if (!clampToTilemapBounds)
|
||||
return tileX;
|
||||
return MathHelper.clamp(tileX, 0, this.width - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换从世界平铺位置获取tilemap边界
|
||||
* @param y
|
||||
* @param clampToTilemapBounds
|
||||
*/
|
||||
public worldToTilePositionY(y: number, clampToTilemapBounds = true){
|
||||
let tileY = Math.floor(y / this.tileHeight);
|
||||
if (!clampToTilemapBounds)
|
||||
return tileY;
|
||||
return MathHelper.clamp(tileY, 0, this.height - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按名称获取平铺层
|
||||
* @param name
|
||||
*/
|
||||
public getLayer(name: string): ITmxLayer {
|
||||
return this.layers[name];
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新他们的动画tile
|
||||
*/
|
||||
public update(){
|
||||
this.tilesets.forEach(tileset => {tileset.update();});
|
||||
}
|
||||
|
||||
public _isDisposed;
|
||||
public dispose(disposing: boolean = true){
|
||||
if (!this._isDisposed){
|
||||
if (disposing){
|
||||
this.tilesets.forEach(tileset => {if (tileset.image) tileset.image.dispose()});
|
||||
this.imageLayers.forEach(layer => {if (layer.image) layer.image.dispose();});
|
||||
}
|
||||
|
||||
this._isDisposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export enum OrientationType {
|
||||
unknown,
|
||||
orthogonal,
|
||||
isometric,
|
||||
staggered,
|
||||
hexagonal
|
||||
}
|
||||
|
||||
export enum StaggerAxisType {
|
||||
x,
|
||||
y
|
||||
}
|
||||
|
||||
export enum StaggerIndexType {
|
||||
odd,
|
||||
even
|
||||
}
|
||||
|
||||
export enum RenderOrderType {
|
||||
rightDown,
|
||||
rightUp,
|
||||
leftDown,
|
||||
leftUp
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
module es {
|
||||
export class TmxObjectGroup implements ITmxLayer {
|
||||
public map: TmxMap;
|
||||
public name: string;
|
||||
public opacity: number;
|
||||
public visible: boolean;
|
||||
public offsetX: number;
|
||||
public offsetY: number;
|
||||
public color: number;
|
||||
public drawOrder: DrawOrderType;
|
||||
public objects: TmxObject[];
|
||||
public properties: Map<string, string>;
|
||||
}
|
||||
|
||||
export class TmxObject implements ITmxElement {
|
||||
public id: number;
|
||||
public name: string;
|
||||
public shape: egret.Shape;
|
||||
public textField: egret.TextField;
|
||||
public objectType: TmxObjectType;
|
||||
public type: string;
|
||||
public x: number;
|
||||
public y: number;
|
||||
public width: number;
|
||||
public height: number;
|
||||
public rotation: number;
|
||||
public tile: TmxLayerTile;
|
||||
public visible: boolean;
|
||||
public text: TmxText;
|
||||
public points: Vector2[];
|
||||
public properties: Map<string, string>;
|
||||
|
||||
constructor(){
|
||||
this.shape = new egret.Shape();
|
||||
this.textField = new egret.TextField();
|
||||
}
|
||||
}
|
||||
|
||||
export class TmxText {
|
||||
public fontFamily: string;
|
||||
public pixelSize: number;
|
||||
public wrap: boolean;
|
||||
public color: number;
|
||||
public bold: boolean;
|
||||
public italic: boolean;
|
||||
public underline: boolean;
|
||||
public strikeout: boolean;
|
||||
public kerning: boolean;
|
||||
public alignment: TmxAlignment;
|
||||
public value: string;
|
||||
}
|
||||
|
||||
export class TmxAlignment {
|
||||
public horizontal: TmxHorizontalAlignment;
|
||||
public vertical: TmxVerticalAlignment;
|
||||
}
|
||||
|
||||
export enum TmxObjectType {
|
||||
basic,
|
||||
point,
|
||||
tile,
|
||||
ellipse,
|
||||
polygon,
|
||||
polyline,
|
||||
text
|
||||
}
|
||||
|
||||
export enum DrawOrderType {
|
||||
unkownOrder = -1,
|
||||
TopDown,
|
||||
IndexOrder
|
||||
}
|
||||
|
||||
export enum TmxHorizontalAlignment {
|
||||
left,
|
||||
center,
|
||||
right,
|
||||
justify
|
||||
}
|
||||
|
||||
export enum TmxVerticalAlignment {
|
||||
top,
|
||||
center,
|
||||
bottom
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
module es {
|
||||
export class TmxDocument {
|
||||
public tmxDirectory: string;
|
||||
constructor(){
|
||||
this.tmxDirectory = "resource/assets/";
|
||||
}
|
||||
}
|
||||
|
||||
export interface ITmxElement {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export class TmxImage {
|
||||
public texture: egret.Bitmap;
|
||||
public bitmap: egret.SpriteSheet;
|
||||
public source: string;
|
||||
public format: string;
|
||||
public data: any;
|
||||
public trans: number;
|
||||
public width: number;
|
||||
public height: number;
|
||||
|
||||
public dispose(){
|
||||
if (this.bitmap){
|
||||
this.bitmap.dispose();
|
||||
this.bitmap = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,544 +0,0 @@
|
||||
module es {
|
||||
|
||||
|
||||
export class TiledMapLoader {
|
||||
public static loadTmxMap(map: TmxMap, filePath: string) {
|
||||
let xMap = RES.getRes(filePath);
|
||||
return this.loadTmxMapData(map, xMap, RES.getResourceInfo(filePath));
|
||||
}
|
||||
|
||||
public static async loadTmxMapData(map: TmxMap, xMap: any, info: any) {
|
||||
map.version = xMap["version"];
|
||||
map.tiledVersion = xMap["tiledversion"];
|
||||
map.width = xMap["width"];
|
||||
map.height = xMap["height"];
|
||||
map.tileWidth = xMap["tilewidth"];
|
||||
map.tileHeight = xMap["tileheight"];
|
||||
map.hexSideLength = xMap["hexsidelength"];
|
||||
|
||||
map.orientation = this.parseOrientationType(xMap["orientation"]);
|
||||
map.staggerAxis = this.parseStaggerAxisType(xMap["staggeraxis"]);
|
||||
map.staggerIndex = this.parseStaggerIndexType(xMap["staggerindex"]);
|
||||
map.renderOrder = this.parseRenderOrderType(xMap["renderorder"]);
|
||||
|
||||
map.nextObjectID = xMap["nextobjectid"];
|
||||
map.backgroundColor = TmxUtils.color16ToUnit(xMap["color"]);
|
||||
|
||||
map.properties = this.parsePropertyDict(xMap["properties"]);
|
||||
|
||||
// 我们保持记录的最大瓷砖大小的情况下,图像tileset随机大小
|
||||
map.maxTileWidth = map.tileWidth;
|
||||
map.maxTileHeight = map.tileHeight;
|
||||
map.tmxDirectory = info.root + info.url.replace(".", "_").replace(info.name, "");
|
||||
|
||||
map.tilesets = [];
|
||||
for (let e of xMap["tilesets"]) {
|
||||
let tileset = await this.parseTmxTileset(map, e);
|
||||
map.tilesets.push(tileset);
|
||||
|
||||
this.updateMaxTileSizes(tileset);
|
||||
}
|
||||
|
||||
map.layers = [];
|
||||
map.tileLayers = [];
|
||||
map.objectGroups = [];
|
||||
map.imageLayers = [];
|
||||
map.groups = [];
|
||||
|
||||
this.parseLayers(map, xMap, map, map.width, map.height, map.tmxDirectory);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析xEle中的所有层,将它们放入容器中
|
||||
* @param container
|
||||
* @param xEle
|
||||
* @param map
|
||||
* @param width
|
||||
* @param height
|
||||
* @param tmxDirectory
|
||||
*/
|
||||
public static async parseLayers(container: any, xEle: any, map: TmxMap, width: number, height: number, tmxDirectory: string) {
|
||||
for (let e of ObjectUtils.elements(xEle).where(x => {
|
||||
return x.type == "tilelayer" || x.type == "objectgroup" || x.type == "imagelayer" || x.type == "group"
|
||||
})) {
|
||||
let layer: ITmxLayer;
|
||||
switch (e.type) {
|
||||
case "tilelayer":
|
||||
let tileLayer = this.loadTmxLayer(new TmxLayer(), map, e, width, height);
|
||||
layer = tileLayer;
|
||||
|
||||
if (container instanceof TmxMap || container instanceof TmxGroup)
|
||||
container.tileLayers.push(tileLayer);
|
||||
break;
|
||||
case "objectgroup":
|
||||
let objectgroup = this.loadTmxObjectGroup(new TmxObjectGroup(), map, e);
|
||||
layer = objectgroup;
|
||||
|
||||
if (container instanceof TmxMap || container instanceof TmxGroup)
|
||||
container.objectGroups.push(objectgroup);
|
||||
break;
|
||||
case "imagelayer":
|
||||
let imagelayer = await this.loadTmxImageLayer(new TmxImageLayer(), map, e, tmxDirectory);
|
||||
layer = imagelayer;
|
||||
|
||||
if (container instanceof TmxMap || container instanceof TmxGroup)
|
||||
container.imageLayers.push(imagelayer);
|
||||
break;
|
||||
case "group":
|
||||
let newGroup = await this.loadTmxGroup(new TmxGroup(), map, e, width, height, tmxDirectory);
|
||||
layer = newGroup;
|
||||
|
||||
if (container instanceof TmxMap || container instanceof TmxGroup)
|
||||
container.groups.push(newGroup);
|
||||
break;
|
||||
default:
|
||||
throw new Error("无效的操作");
|
||||
}
|
||||
|
||||
if (container instanceof TmxMap || container instanceof TmxGroup)
|
||||
container.layers.push(layer);
|
||||
}
|
||||
}
|
||||
|
||||
public static async loadTmxGroup(group: TmxGroup, map: TmxMap, xGroup: any, width: number, height: number, tmxDirectory: string) {
|
||||
group.map = map;
|
||||
group.name = xGroup["name"] != undefined ? xGroup["name"] : "";
|
||||
group.opacity = xGroup["opacity"] != undefined ? xGroup["opacity"] : 1;
|
||||
group.visible = xGroup["visible"] != undefined ? xGroup["visible"] : true;
|
||||
group.offsetX = xGroup["offsetx"] != undefined ? xGroup["offsetx"] : 0;
|
||||
group.offsetY = xGroup["offsety"] != undefined ? xGroup["offsety"] : 0;
|
||||
group.properties = this.parsePropertyDict(xGroup["properties"]);
|
||||
group.layers = [];
|
||||
group.tileLayers = [];
|
||||
group.objectGroups = [];
|
||||
group.imageLayers = [];
|
||||
group.groups = [];
|
||||
|
||||
await this.parseLayers(group, xGroup, map, width, height, tmxDirectory);
|
||||
return group;
|
||||
}
|
||||
|
||||
public static async loadTmxImageLayer(layer: TmxImageLayer, map: TmxMap, xImageLayer: any, tmxDirectory: string) {
|
||||
layer.map = map;
|
||||
layer.name = xImageLayer["name"];
|
||||
layer.width = xImageLayer["width"];
|
||||
layer.height = xImageLayer["height"];
|
||||
layer.visible = xImageLayer["visible"] != undefined ? xImageLayer["visible"] : true;
|
||||
layer.opacity = xImageLayer["opacity"] != undefined ? xImageLayer["opacity"] : 1;
|
||||
layer.offsetX = xImageLayer["offsetx"] != undefined ? xImageLayer["offsetx"] : 0;
|
||||
layer.offsetY = xImageLayer["offsety"] != undefined ? xImageLayer["offsety"] : 0;
|
||||
|
||||
let xImage = xImageLayer["image"];
|
||||
if (xImage) {
|
||||
layer.image = await this.loadTmxImage(new TmxImage(), xImage, tmxDirectory);
|
||||
}
|
||||
layer.properties = this.parsePropertyDict(xImageLayer["properties"]);
|
||||
return layer;
|
||||
}
|
||||
|
||||
public static loadTmxLayer(layer: TmxLayer, map: TmxMap, xLayer: any, width: number, height: number) {
|
||||
layer.map = map;
|
||||
layer.name = xLayer["name"];
|
||||
layer.opacity = xLayer["opacity"] != undefined ? xLayer["opacity"] : 1;
|
||||
layer.visible = xLayer["visible"] != undefined ? xLayer["visible"] : true;
|
||||
layer.offsetX = xLayer["offsetx"] != undefined ? xLayer["offsetx"] : 0;
|
||||
layer.offsetY = xLayer["offsety"] != undefined ? xLayer["offsety"] : 0;
|
||||
// TODO: 传入的宽度/高度是否与TMX层?
|
||||
layer.width = xLayer["width"];
|
||||
layer.height = xLayer["height"];
|
||||
|
||||
let xData = xLayer["data"];
|
||||
let encoding = xData["encoding"] != undefined ? xData["encoding"] : "csv";
|
||||
|
||||
layer.tiles = new Array<TmxLayerTile>(width * height);
|
||||
if (encoding == "base64") {
|
||||
let br = TmxUtils.decode(xData.toString(), encoding, xData["compression"]);
|
||||
let index = 0;
|
||||
for (let j = 0; j < height; j++) {
|
||||
for (let i = 0; i < width; i++) {
|
||||
let gid = br[index];
|
||||
layer.tiles[index++] = gid != 0 ? new TmxLayerTile(map, gid, i, j) : null;
|
||||
}
|
||||
}
|
||||
} else if (encoding == "csv") {
|
||||
// let csvData = TmxUtils.decode(xData.toString(), encoding, xData["compression"]);
|
||||
let k = 0;
|
||||
for (let s of xData) {
|
||||
let gid = s;
|
||||
let x = k % width;
|
||||
let y = k / width;
|
||||
|
||||
layer.tiles[k++] = gid != 0 ? new TmxLayerTile(map, gid, x, y) : null;
|
||||
}
|
||||
} else if (!encoding) {
|
||||
let k = 0;
|
||||
for (let e of xData["tile"]) {
|
||||
let gid = e["gid"] != undefined ? e["gid"] : 0;
|
||||
let x = k % width;
|
||||
let y = k / width;
|
||||
|
||||
layer.tiles[k++] = gid != 0 ? new TmxLayerTile(map, gid, x, y) : null;
|
||||
}
|
||||
} else {
|
||||
throw new Error("TmxLayer:未知编码");
|
||||
}
|
||||
|
||||
layer.properties = TiledMapLoader.parsePropertyDict(xLayer["properties"]);
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
private static updateMaxTileSizes(tileset: TmxTileset) {
|
||||
// 必须迭代字典,因为tile.gid可以是任意顺序的的任何数字
|
||||
tileset.tiles.forEach(tile => {
|
||||
if (tile.image) {
|
||||
if (tile.image.width > tileset.map.maxTileWidth)
|
||||
tileset.map.maxTileWidth = tile.image.width;
|
||||
if (tile.image.height > tileset.map.maxTileHeight)
|
||||
tileset.map.maxTileHeight = tile.image.height;
|
||||
}
|
||||
});
|
||||
|
||||
tileset.tileRegions.forEach(region => {
|
||||
let width = region.width;
|
||||
let height = region.height;
|
||||
if (width > tileset.map.maxTileWidth) tileset.map.maxTileWidth = width;
|
||||
if (width > tileset.map.maxTileHeight) tileset.map.maxTileHeight = height;
|
||||
});
|
||||
}
|
||||
|
||||
public static parseOrientationType(type: string) {
|
||||
if (type == "unknown")
|
||||
return OrientationType.unknown;
|
||||
if (type == "orthogonal")
|
||||
return OrientationType.orthogonal;
|
||||
if (type == "isometric")
|
||||
return OrientationType.isometric;
|
||||
if (type == "staggered")
|
||||
return OrientationType.staggered;
|
||||
if (type == "hexagonal")
|
||||
return OrientationType.hexagonal;
|
||||
|
||||
return OrientationType.unknown;
|
||||
}
|
||||
|
||||
public static parseStaggerAxisType(type: string) {
|
||||
if (type == "y")
|
||||
return StaggerAxisType.y;
|
||||
return StaggerAxisType.x;
|
||||
}
|
||||
|
||||
public static parseStaggerIndexType(type: string) {
|
||||
if (type == "even")
|
||||
return StaggerIndexType.even;
|
||||
return StaggerIndexType.odd;
|
||||
}
|
||||
|
||||
public static parseRenderOrderType(type: string) {
|
||||
if (type == "right-up")
|
||||
return RenderOrderType.rightUp;
|
||||
if (type == "left-down")
|
||||
return RenderOrderType.leftDown;
|
||||
if (type == "left-up")
|
||||
return RenderOrderType.leftUp;
|
||||
return RenderOrderType.rightDown;
|
||||
}
|
||||
|
||||
public static parsePropertyDict(prop) {
|
||||
if (!prop)
|
||||
return null;
|
||||
|
||||
let dict = new Map<string, string>();
|
||||
for (let p of prop) {
|
||||
let pname = p["name"];
|
||||
let valueAttr = p["value"];
|
||||
|
||||
if (p["type"] == "color")
|
||||
dict.set(pname, TmxUtils.color16ToUnit(valueAttr).toString());
|
||||
else
|
||||
dict.set(pname, valueAttr);
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
|
||||
public static async parseTmxTileset(map: TmxMap, xTileset: any) {
|
||||
// firstgid总是在TMX中,而不是在TSX中
|
||||
let xFirstGid = xTileset["firstgid"];
|
||||
let firstGid = xFirstGid;
|
||||
let source = xTileset["source"];
|
||||
|
||||
// 如果是嵌入式TmxTileset,即不是外部的,source将为null
|
||||
if (source != undefined) {
|
||||
source = map.tmxDirectory + source;
|
||||
// 其他所有内容都在TSX文件中
|
||||
let xDocTileset = await RES.getResByUrl(source).catch(err => {
|
||||
throw new Error(err);
|
||||
});
|
||||
return this.loadTmxTileset(new TmxTileset(), map, xDocTileset["tileset"], firstGid);
|
||||
}
|
||||
|
||||
return this.loadTmxTileset(new TmxTileset(), map, xTileset, firstGid);
|
||||
}
|
||||
|
||||
public static async loadTmxTileset(tileset: TmxTileset, map: TmxMap, xTileset: any,
|
||||
firstGid: number) {
|
||||
tileset.map = map;
|
||||
tileset.firstGid = firstGid;
|
||||
|
||||
tileset.name = xTileset["name"];
|
||||
tileset.tileWidth = xTileset["tilewidth"];
|
||||
tileset.tileHeight = xTileset["tileheight"];
|
||||
tileset.spacing = xTileset["spacing"] != undefined ? xTileset["spacing"] : 0;
|
||||
tileset.margin = xTileset["margin"] != undefined ? xTileset["margin"] : 0;
|
||||
tileset.columns = xTileset["columns"];
|
||||
tileset.tileCount = xTileset["tilecount"];
|
||||
tileset.tileOffset = this.parseTmxTileOffset(xTileset["tileoffset"]);
|
||||
|
||||
let xImage = xTileset["image"];
|
||||
if (xImage)
|
||||
await this.loadTmxImage(new TmxImage(), xTileset, map.tmxDirectory).then(image => {
|
||||
tileset.image = image;
|
||||
}).catch(err => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
tileset.terrains = [];
|
||||
if (xTileset["terrains"])
|
||||
for (let e of xTileset["terrains"])
|
||||
tileset.terrains.push(this.parseTmxTerrain(e));
|
||||
|
||||
tileset.tiles = new Map<number, TmxTilesetTile>();
|
||||
for (let t in xTileset["tiles"]){
|
||||
if (xTileset["tiles"].hasOwnProperty(t)){
|
||||
let xTile = xTileset["tiles"][t];
|
||||
let tile = await this.loadTmxTilesetTile(new TmxTilesetTile(), tileset, xTile, tileset.terrains, map.tmxDirectory);
|
||||
tileset.tiles.set(tile.id == undefined ? Number(t) + 1 : tile.id, tile);
|
||||
}
|
||||
}
|
||||
|
||||
tileset.properties = this.parsePropertyDict(xTileset["properties"]);
|
||||
|
||||
// 缓存我们的源矩形为每个瓷砖,所以我们不必每次我们渲染计算他们。
|
||||
// 如果我们有一个image,这是一个普通的tileset,否则它是一个image tileset
|
||||
tileset.tileRegions = new Map<number, Rectangle>();
|
||||
if (tileset.image) {
|
||||
let id = firstGid;
|
||||
for (let y = tileset.margin; y < tileset.image.height - tileset.margin; y += tileset.tileHeight + tileset.spacing) {
|
||||
let column = 0;
|
||||
for (let x = tileset.margin; x < tileset.image.width - tileset.margin; x += tileset.tileWidth + tileset.spacing) {
|
||||
tileset.tileRegions.set(id++, new Rectangle(x, y, tileset.tileWidth, tileset.tileHeight));
|
||||
|
||||
if (++column >= tileset.columns)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tileset.tiles.forEach((tile, key) => {
|
||||
tileset.tileRegions.set(key, new Rectangle(0, 0, tile.image.width, tile.image.height));
|
||||
});
|
||||
}
|
||||
|
||||
return tileset;
|
||||
}
|
||||
|
||||
public static async loadTmxTilesetTile(tile: TmxTilesetTile, tileset: TmxTileset, xTile: any, terrains: TmxTerrain[], tmxDirectory: string) {
|
||||
tile.tileset = tileset;
|
||||
tile.id = xTile["id"];
|
||||
|
||||
let strTerrain = xTile["terrain"];
|
||||
if (strTerrain){
|
||||
tile.terrainEdges = new Array(4);
|
||||
let index = 0;
|
||||
for (let v of strTerrain){
|
||||
let edge: TmxTerrain = terrains[v];
|
||||
tile.terrainEdges[index ++] = edge;
|
||||
}
|
||||
}
|
||||
tile.probability = xTile["probability"] != undefined ? xTile["probability"] : 1;
|
||||
tile.type = xTile["type"];
|
||||
let xImage = xTile["image"];
|
||||
if (xImage) {
|
||||
tile.image = await this.loadTmxImage(new TmxImage(), xImage, tmxDirectory);
|
||||
}
|
||||
|
||||
tile.objectGroups = [];
|
||||
if (xTile["objectgroup"])
|
||||
for (let e of xTile["objectgroup"])
|
||||
tile.objectGroups.push(this.loadTmxObjectGroup(new TmxObjectGroup(), tileset.map, e));
|
||||
|
||||
tile.animationFrames = [];
|
||||
if (xTile["animation"]) {
|
||||
for (let e of xTile["animation"]["frame"])
|
||||
tile.animationFrames.push(this.loadTmxAnimationFrame(new TmxAnimationFrame(), e));
|
||||
}
|
||||
|
||||
tile.properties = this.parsePropertyDict(xTile["properties"]);
|
||||
if (tile.properties)
|
||||
tile.processProperties();
|
||||
return tile;
|
||||
}
|
||||
|
||||
public static loadTmxAnimationFrame(frame: TmxAnimationFrame, xFrame: any) {
|
||||
frame.gid = xFrame["tileid"];
|
||||
frame.duration = xFrame["duration"] / 1000;
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
public static loadTmxObjectGroup(group: TmxObjectGroup, map: TmxMap, xObjectGroup: any) {
|
||||
group.map = map;
|
||||
group.name = xObjectGroup["name"] != undefined ? xObjectGroup["name"] : "";
|
||||
group.color = TmxUtils.color16ToUnit(xObjectGroup["color"]);
|
||||
group.opacity = xObjectGroup["opacity"] != undefined ? xObjectGroup["opacity"] : 1;
|
||||
group.visible = xObjectGroup["visible"] != undefined ? xObjectGroup["visible"] : true;
|
||||
group.offsetX = xObjectGroup["offsetx"] != undefined ? xObjectGroup["offsetx"] : 0;
|
||||
group.offsetY = xObjectGroup["offsety"] != undefined ? xObjectGroup["offsety"] : 0;
|
||||
|
||||
let drawOrderDict = new Map<string, DrawOrderType>();
|
||||
drawOrderDict.set("unknown", DrawOrderType.unkownOrder);
|
||||
drawOrderDict.set("topdown", DrawOrderType.IndexOrder);
|
||||
drawOrderDict.set("index", DrawOrderType.TopDown);
|
||||
|
||||
let drawOrderValue = xObjectGroup["draworder"];
|
||||
if (drawOrderValue)
|
||||
group.drawOrder = drawOrderDict.get(drawOrderValue);
|
||||
|
||||
group.objects = [];
|
||||
for (let e of xObjectGroup["objects"])
|
||||
group.objects.push(this.loadTmxObject(new TmxObject(), map, e));
|
||||
group.properties = this.parsePropertyDict(xObjectGroup["properties"]);
|
||||
return group;
|
||||
}
|
||||
|
||||
public static loadTmxObject(obj: TmxObject, map: TmxMap, xObject: any) {
|
||||
obj.id = xObject["id"] != undefined ? xObject["id"] : 0;
|
||||
obj.name = xObject["name"] != undefined ? xObject["name"] : "";
|
||||
obj.x = xObject["x"];
|
||||
obj.y = xObject["y"];
|
||||
obj.width = xObject["width"] != undefined ? xObject["width"] : 0;
|
||||
obj.height = xObject["height"] != undefined ? xObject["height"] : 0;
|
||||
obj.type = xObject["type"] != undefined ? xObject["type"] : "";
|
||||
obj.visible = xObject["visible"] != undefined ? xObject["visible"] : true;
|
||||
obj.rotation = xObject["rotation"] != undefined ? xObject["rotation"] : 0;
|
||||
|
||||
// 评估对象类型并分配适当的内容
|
||||
let xGid = xObject["gid"];
|
||||
let xEllipse = xObject["ellipse"];
|
||||
let xPolygon = xObject["polygon"];
|
||||
let xPolyline = xObject["polyline"];
|
||||
let xText = xObject["text"];
|
||||
let xPoint = xObject["point"];
|
||||
|
||||
if (xGid) {
|
||||
obj.tile = new TmxLayerTile(map, xGid, Math.round(obj.x), Math.round(obj.y));
|
||||
obj.objectType = TmxObjectType.tile;
|
||||
} else if (xEllipse) {
|
||||
obj.objectType = TmxObjectType.ellipse;
|
||||
} else if (xPolygon) {
|
||||
obj.points = this.parsePoints(xPolygon);
|
||||
obj.objectType = TmxObjectType.polygon;
|
||||
} else if (xPolyline) {
|
||||
obj.points = this.parsePoints(xPolyline);
|
||||
obj.objectType = TmxObjectType.polyline;
|
||||
} else if (xText) {
|
||||
obj.text = this.loadTmxText(new TmxText(), xText);
|
||||
obj.objectType = TmxObjectType.text;
|
||||
} else if (xPoint) {
|
||||
obj.objectType = TmxObjectType.point;
|
||||
} else {
|
||||
obj.objectType = TmxObjectType.basic;
|
||||
}
|
||||
|
||||
obj.properties = this.parsePropertyDict(xObject["properties"]);
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static loadTmxText(text: TmxText, xText: any) {
|
||||
text.fontFamily = xText["fontfamily"] != undefined ? xText["fontfamily"] : "sans-serif";
|
||||
text.pixelSize = xText["pixelsize"] != undefined ? xText["pixelsize"] : 16;
|
||||
text.wrap = xText["wrap"] != undefined ? xText["wrap"] : false;
|
||||
text.color = TmxUtils.color16ToUnit(xText["color"]);
|
||||
text.bold = xText["bold"] ? xText["bold"] : false;
|
||||
text.italic = xText["italic"] ? xText["italic"] : false;
|
||||
text.underline = xText["underline"] ? xText["underline"] : false;
|
||||
text.strikeout = xText["strikeout"] ? xText["strikeout"] : false;
|
||||
text.kerning = xText["kerning"] ? xText["kerning"] : true;
|
||||
text.alignment = this.loadTmxAlignment(new TmxAlignment(), xText);
|
||||
text.value = xText;
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
public static loadTmxAlignment(alignment: TmxAlignment, xText: any) {
|
||||
function firstLetterToUpperCase(str: string) {
|
||||
if (!str || str == "")
|
||||
return str;
|
||||
return str[0].toString().toUpperCase() + str.substr(1);
|
||||
}
|
||||
|
||||
let xHorizontal = xText["halign"] != undefined ? xText["halign"] : "left";
|
||||
alignment.horizontal = TmxHorizontalAlignment[firstLetterToUpperCase(xHorizontal)];
|
||||
|
||||
let xVertical = xText["valign"] != undefined ? xText["valign"] : "top";
|
||||
alignment.vertical = TmxVerticalAlignment[firstLetterToUpperCase((xVertical))];
|
||||
|
||||
return alignment;
|
||||
}
|
||||
|
||||
public static parsePoints(xPoints: any) {
|
||||
let points = [];
|
||||
|
||||
let index = 0;
|
||||
for (let s of xPoints)
|
||||
points[index++] = this.parsePoint(s);
|
||||
return points;
|
||||
}
|
||||
|
||||
public static parsePoint(pt: {x: number, y: number}) {
|
||||
return new Vector2(pt.x, pt.y);
|
||||
}
|
||||
|
||||
public static parseTmxTerrain(xTerrain: any) {
|
||||
let terrain = new TmxTerrain();
|
||||
terrain.name = xTerrain["name"];
|
||||
terrain.tile = xTerrain["tile"];
|
||||
terrain.properties = this.parsePropertyDict(xTerrain["properties"]);
|
||||
|
||||
return terrain;
|
||||
}
|
||||
|
||||
public static parseTmxTileOffset(xTileOffset: any) {
|
||||
let tmxTileOffset = new TmxTileOffset();
|
||||
if (!xTileOffset) {
|
||||
tmxTileOffset.x = 0;
|
||||
tmxTileOffset.y = 0;
|
||||
return tmxTileOffset;
|
||||
}
|
||||
|
||||
tmxTileOffset.x = xTileOffset["x"];
|
||||
tmxTileOffset.y = xTileOffset["y"];
|
||||
return tmxTileOffset;
|
||||
}
|
||||
|
||||
public static async loadTmxImage(image: TmxImage, xImage: any, tmxDirectory: string) {
|
||||
let xSource = xImage["image"];
|
||||
if (xSource != undefined) {
|
||||
image.source = tmxDirectory + xSource;
|
||||
} else {
|
||||
image.source = tmxDirectory + xImage;
|
||||
}
|
||||
let texture: egret.Texture = await RES.getResByUrl(image.source, null, this, RES.ResourceItem.TYPE_IMAGE).catch(err => {
|
||||
throw new Error(err);
|
||||
});
|
||||
image.bitmap = new egret.SpriteSheet(texture);
|
||||
|
||||
image.trans = TmxUtils.color16ToUnit(xImage["trans"]);
|
||||
image.width = xImage["imagewidth"] != undefined ? xImage["imagewidth"] : texture.textureWidth;
|
||||
image.height = xImage["imageheight"] != undefined ? xImage["imageheight"] : texture.textureHeight;
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,411 +0,0 @@
|
||||
module es {
|
||||
import Bitmap = egret.Bitmap;
|
||||
|
||||
|
||||
export class TiledRendering {
|
||||
public static renderMap(map: TmxMap, container: egret.DisplayObjectContainer, position: Vector2, scale: Vector2, layerDepth: number) {
|
||||
map.layers.forEach(layer => {
|
||||
if (layer instanceof TmxLayer && layer.visible) {
|
||||
this.renderLayer(layer, container, position, scale, layerDepth);
|
||||
} else if (layer instanceof TmxImageLayer && layer.visible) {
|
||||
this.renderImageLayer(layer, container, position, scale, layerDepth);
|
||||
} else if (layer instanceof TmxGroup && layer.visible) {
|
||||
this.renderGroup(layer, container, position, scale, layerDepth);
|
||||
} else if (layer instanceof TmxObjectGroup && layer.visible) {
|
||||
this.renderObjectGroup(layer, container, position, scale, layerDepth);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static renderLayer(layer: TmxLayer, container: egret.DisplayObjectContainer, position: Vector2, scale: Vector2, layerDepth: number) {
|
||||
if (!layer.visible)
|
||||
return;
|
||||
|
||||
let tileWidth = layer.map.tileWidth * scale.x;
|
||||
let tileHeight = layer.map.tileHeight * scale.y;
|
||||
|
||||
let color = DrawUtils.getColorMatrix(0xFFFFFF);
|
||||
for (let i = 0; i < layer.tiles.length; i++) {
|
||||
let tile = layer.tiles[i];
|
||||
if (!tile)
|
||||
continue;
|
||||
|
||||
this.renderTile(tile, container, position, scale, tileWidth, tileHeight, color, layerDepth);
|
||||
}
|
||||
}
|
||||
|
||||
public static renderLayerRenderCamera(layer: ITmxLayer, container: egret.DisplayObjectContainer, position: Vector2, scale: Vector2, layerDepth: number, camerClipBounds: Rectangle){
|
||||
if (layer instanceof TmxLayer && layer.visible) {
|
||||
this.renderLayerCamera(layer, container, position, scale, layerDepth, camerClipBounds);
|
||||
} else if (layer instanceof TmxImageLayer && layer.visible) {
|
||||
this.renderImageLayer(layer, container, position, scale, layerDepth);
|
||||
} else if (layer instanceof TmxGroup && layer.visible) {
|
||||
this.renderGroup(layer, container, position, scale, layerDepth);
|
||||
} else if (layer instanceof TmxObjectGroup && layer.visible) {
|
||||
this.renderObjectGroup(layer, container, position, scale, layerDepth);
|
||||
}
|
||||
}
|
||||
|
||||
public static renderLayerCamera(layer: TmxLayer, container: egret.DisplayObjectContainer, position: Vector2, scale: Vector2, layerDepth: number, camerClipBounds: Rectangle){
|
||||
if (!layer.visible)
|
||||
return;
|
||||
|
||||
position = position.add(layer.offset);
|
||||
|
||||
camerClipBounds.location = camerClipBounds.location.subtract(position);
|
||||
|
||||
let tileWidth = layer.map.tileWidth * scale.x;
|
||||
let tileHeight = layer.map.tileHeight * scale.y;
|
||||
|
||||
let minX, minY, maxX, maxY = 0;
|
||||
if (layer.map.requiresLargeTileCulling){
|
||||
minX = layer.map.worldToTilePositionX(camerClipBounds.left - (layer.map.maxTileWidth * scale.x - tileWidth));
|
||||
minY = layer.map.worldToTilePositionY(camerClipBounds.top - (layer.map.maxTileHeight * scale.y - tileHeight));
|
||||
maxX = layer.map.worldToTilePositionX(camerClipBounds.right + (layer.map.maxTileWidth * scale.x - tileWidth));
|
||||
maxY = layer.map.worldToTilePositionY(camerClipBounds.bottom + (layer.map.maxTileHeight * scale.y - tileHeight));
|
||||
}else{
|
||||
minX = layer.map.worldToTilePositionX(camerClipBounds.left);
|
||||
minY = layer.map.worldToTilePositionY(camerClipBounds.top);
|
||||
maxX = layer.map.worldToTilePositionX(camerClipBounds.right);
|
||||
maxY = layer.map.worldToTilePositionY(camerClipBounds.bottom);
|
||||
}
|
||||
|
||||
let color = DrawUtils.getColorMatrix(0xFFFFFF);
|
||||
|
||||
for (let y = minY; y <= maxY; y ++){
|
||||
for (let x = minX; x <= maxX; x ++){
|
||||
let tile = layer.getTile(x, y);
|
||||
if (tile)
|
||||
this.renderTile(tile, container, position, scale, tileWidth, tileHeight, color, layerDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static renderImageLayer(layer: TmxImageLayer, container: egret.DisplayObjectContainer, position: Vector2, scale: Vector2, layerDepth: number) {
|
||||
if (!layer.visible)
|
||||
return;
|
||||
|
||||
let color = DrawUtils.getColorMatrix(0xFFFFFF);
|
||||
let pos = Vector2.add(position, new Vector2(layer.offsetX, layer.offsetY).multiply(scale));
|
||||
if (!layer.image.texture.parent)
|
||||
container.addChild(layer.image.texture);
|
||||
layer.image.texture.x = pos.x;
|
||||
layer.image.texture.y = pos.y;
|
||||
layer.image.texture.scaleX = scale.x;
|
||||
layer.image.texture.scaleY = scale.y;
|
||||
layer.image.texture.filters = [color];
|
||||
}
|
||||
|
||||
public static renderObjectGroup(objGroup: TmxObjectGroup, container: egret.DisplayObjectContainer, position: Vector2, scale: Vector2, layerDepth: number) {
|
||||
if (!objGroup.visible)
|
||||
return;
|
||||
|
||||
function debugRender(obj: TmxObject, pos: Vector2){
|
||||
if (!container)
|
||||
return;
|
||||
|
||||
if (!Core.debugRenderEndabled)
|
||||
return;
|
||||
|
||||
if (!obj.textField.parent && obj.name){
|
||||
obj.textField.text = obj.name;
|
||||
obj.textField.size = 12;
|
||||
obj.textField.fontFamily = "sans-serif";
|
||||
if (obj.shape){
|
||||
obj.textField.x = pos.x + (obj.shape.getBounds().width - obj.textField.width) / 2 + obj.shape.getBounds().x;
|
||||
obj.textField.y = pos.y - obj.textField.height - 5 + obj.shape.getBounds().y;
|
||||
}else{
|
||||
obj.textField.x = pos.x + (obj.width - obj.textField.width) / 2;
|
||||
obj.textField.y = pos.y - obj.textField.height - 5;
|
||||
}
|
||||
obj.textField.background = true;
|
||||
obj.textField.backgroundColor = 0xa0a0a4;
|
||||
obj.textField.textColor = 0xffffff;
|
||||
container.addChild(obj.textField);
|
||||
}
|
||||
}
|
||||
|
||||
for (let object in objGroup.objects) {
|
||||
let obj = objGroup.objects[object];
|
||||
if (!obj.visible)
|
||||
continue;
|
||||
|
||||
// 如果我们不调试渲染,我们只渲染平铺块和文本类型
|
||||
if (!Core.debugRenderEndabled) {
|
||||
if (obj.objectType != TmxObjectType.tile && obj.objectType != TmxObjectType.text)
|
||||
continue;
|
||||
}
|
||||
|
||||
let pos = Vector2.add(position, new Vector2(obj.x, obj.y).multiply(scale));
|
||||
switch (obj.objectType) {
|
||||
case TmxObjectType.basic:
|
||||
if (!obj.shape.parent){
|
||||
obj.shape.x = obj.x;
|
||||
obj.shape.y = obj.y;
|
||||
container.addChild(obj.shape);
|
||||
|
||||
obj.shape.graphics.clear();
|
||||
obj.shape.graphics.lineStyle(1, 0xa0a0a4);
|
||||
obj.shape.graphics.beginFill(0x979798, 0.5);
|
||||
obj.shape.graphics.drawRect(0, 0, obj.width * scale.x, obj.height * scale.y);
|
||||
obj.shape.graphics.endFill();
|
||||
debugRender(obj, pos);
|
||||
}
|
||||
break;
|
||||
case TmxObjectType.point:
|
||||
let size = objGroup.map.tileWidth * 0.5;
|
||||
pos.x -= size * 0.5;
|
||||
pos.y -= size * 0.5;
|
||||
if (!obj.shape.parent){
|
||||
obj.shape.x = pos.x;
|
||||
obj.shape.y = pos.y;
|
||||
container.addChild(obj.shape);
|
||||
|
||||
obj.shape.graphics.clear();
|
||||
obj.shape.graphics.lineStyle(1, 0xa0a0a4);
|
||||
obj.shape.graphics.beginFill(0x979798, 0.5);
|
||||
obj.shape.graphics.drawCircle(0, 0, 1);
|
||||
obj.shape.graphics.endFill();
|
||||
debugRender(obj, pos);
|
||||
}
|
||||
break;
|
||||
case TmxObjectType.tile:
|
||||
this.renderTilesetTile(objGroup, obj, container, pos, scale, debugRender);
|
||||
break;
|
||||
case TmxObjectType.ellipse:
|
||||
pos = new Vector2(obj.x + obj.width * 0.5, obj.y + obj.height * 0.5).multiply(scale);
|
||||
if (!obj.shape.parent){
|
||||
obj.shape.x = pos.x;
|
||||
obj.shape.y = pos.y;
|
||||
container.addChild(obj.shape);
|
||||
|
||||
obj.shape.graphics.clear();
|
||||
obj.shape.graphics.lineStyle(1, 0xa0a0a4);
|
||||
obj.shape.graphics.beginFill(0x979798, 0.5);
|
||||
obj.shape.graphics.drawCircle(0, 0, obj.width * 0.5);
|
||||
obj.shape.graphics.endFill();
|
||||
debugRender(obj, pos);
|
||||
}
|
||||
break;
|
||||
case TmxObjectType.polygon:
|
||||
case TmxObjectType.polyline:
|
||||
let points: Vector2[] = [];
|
||||
for (let i = 0; i < obj.points.length; i++)
|
||||
points[i] = Vector2.multiply(obj.points[i], scale);
|
||||
|
||||
if (!obj.shape.parent && points.length > 0){
|
||||
obj.shape.x = pos.x;
|
||||
obj.shape.y = pos.y;
|
||||
container.addChild(obj.shape);
|
||||
|
||||
obj.shape.graphics.clear();
|
||||
obj.shape.graphics.lineStyle(1, 0xa0a0a4);
|
||||
for (let i = 0; i < points.length; i ++){
|
||||
if (i == 0){
|
||||
obj.shape.graphics.moveTo(points[i].x, points[i].y);
|
||||
}else{
|
||||
obj.shape.graphics.lineTo(points[i].x, points[i].y);
|
||||
}
|
||||
}
|
||||
obj.shape.graphics.endFill();
|
||||
debugRender(obj, pos);
|
||||
}
|
||||
break;
|
||||
case TmxObjectType.text:
|
||||
if (!obj.textField.parent){
|
||||
obj.textField.x = pos.x;
|
||||
obj.textField.y = pos.y;
|
||||
container.addChild(obj.textField);
|
||||
|
||||
obj.textField.text = obj.text.value;
|
||||
obj.textField.textColor = obj.text.color;
|
||||
obj.textField.bold = obj.text.bold != undefined ? obj.text.bold : false;
|
||||
obj.textField.italic = obj.text.italic != undefined ? obj.text.italic : false;
|
||||
obj.textField.size = obj.text.pixelSize;
|
||||
obj.textField.fontFamily = obj.text.fontFamily;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static renderTilesetTile(objGroup: es.TmxObjectGroup, obj, container: egret.DisplayObjectContainer, pos, scale: es.Vector2, debugRender) {
|
||||
let tileset = objGroup.map.getTilesetForTileGid(obj.tile.gid);
|
||||
let sourceRect = tileset.tileRegions.get(obj.tile.gid);
|
||||
|
||||
if (container) {
|
||||
if (tileset.image) {
|
||||
if (obj.tile.horizontalFlip && obj.tile.verticalFlip) {
|
||||
pos.x += tileset.tileHeight + (sourceRect.height * scale.y - tileset.tileHeight);
|
||||
pos.y -= (sourceRect.width * scale.x - tileset.tileWidth);
|
||||
} else if (obj.tile.horizontalFlip) {
|
||||
pos.x += tileset.tileWidth + (sourceRect.height * scale.y - tileset.tileHeight);
|
||||
} else if (obj.tile.verticalFlip) {
|
||||
pos.y += (tileset.tileWidth - sourceRect.width * scale.x);
|
||||
} else {
|
||||
pos.y += (tileset.tileHeight - sourceRect.height * scale.y);
|
||||
}
|
||||
let texture: egret.Texture = tileset.image.bitmap.getTexture(`${obj.tile.gid}`);
|
||||
if (!texture) {
|
||||
texture = tileset.image.bitmap.createTexture(`${obj.tile.gid}`, sourceRect.x, sourceRect.y, sourceRect.width, sourceRect.height);
|
||||
}
|
||||
|
||||
tileset.image.texture = new Bitmap(texture);
|
||||
container.addChild(tileset.image.texture);
|
||||
|
||||
tileset.image.texture.x = pos.x;
|
||||
tileset.image.texture.y = pos.y;
|
||||
if (obj.tile.verticalFlip && obj.tile.horizontalFlip) {
|
||||
tileset.image.texture.scaleX = -1;
|
||||
tileset.image.texture.scaleY = -1;
|
||||
} else if (obj.tile.verticalFlip) {
|
||||
tileset.image.texture.scaleX = scale.x;
|
||||
tileset.image.texture.scaleY = -1;
|
||||
} else if (obj.tile.horizontalFlip) {
|
||||
tileset.image.texture.scaleX = -1;
|
||||
tileset.image.texture.scaleY = scale.y;
|
||||
} else {
|
||||
tileset.image.texture.scaleX = scale.x;
|
||||
tileset.image.texture.scaleY = scale.y;
|
||||
}
|
||||
tileset.image.texture.anchorOffsetX = 0;
|
||||
tileset.image.texture.anchorOffsetY = 0;
|
||||
debugRender(obj, pos);
|
||||
} else {
|
||||
let tilesetTile = tileset.tiles.get(obj.tile.gid);
|
||||
let texture: egret.Texture = tilesetTile.image.bitmap.getTexture(`${obj.tile.gid}`);
|
||||
if (!texture) {
|
||||
texture = tilesetTile.image.bitmap.createTexture(`${obj.tile.gid}`, sourceRect.x, sourceRect.y, sourceRect.width, sourceRect.height);
|
||||
}
|
||||
|
||||
pos.y -= obj.height;
|
||||
tilesetTile.image.texture = new Bitmap(texture);
|
||||
container.addChild(tilesetTile.image.texture);
|
||||
|
||||
tilesetTile.image.texture.width = obj.width;
|
||||
tilesetTile.image.texture.height = obj.height;
|
||||
tilesetTile.image.texture.x = pos.x;
|
||||
tilesetTile.image.texture.y = pos.y;
|
||||
if (obj.tile.verticalFlip && obj.tile.horizontalFlip) {
|
||||
tilesetTile.image.texture.scaleX = -1;
|
||||
tilesetTile.image.texture.scaleY = -1;
|
||||
} else if (obj.tile.verticalFlip) {
|
||||
tilesetTile.image.texture.scaleX = scale.x;
|
||||
tilesetTile.image.texture.scaleY = -1;
|
||||
} else if (obj.tile.horizontalFlip) {
|
||||
tilesetTile.image.texture.scaleX = -1;
|
||||
tilesetTile.image.texture.scaleY = scale.y;
|
||||
} else {
|
||||
tilesetTile.image.texture.scaleX = scale.x;
|
||||
tilesetTile.image.texture.scaleY = scale.y;
|
||||
}
|
||||
tilesetTile.image.texture.anchorOffsetX = 0;
|
||||
tilesetTile.image.texture.anchorOffsetY = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static renderGroup(group: TmxGroup, container: egret.DisplayObjectContainer, position: Vector2, scale: Vector2, layerDepth: number) {
|
||||
if (!group.visible)
|
||||
return;
|
||||
|
||||
group.layers.forEach(layer => {
|
||||
if (layer instanceof TmxGroup) {
|
||||
this.renderGroup(layer, container, position, scale, layerDepth);
|
||||
}
|
||||
|
||||
if (layer instanceof TmxObjectGroup) {
|
||||
this.renderObjectGroup(layer, container, position, scale, layerDepth);
|
||||
}
|
||||
|
||||
if (layer instanceof TmxLayer) {
|
||||
this.renderLayer(layer, container, position, scale, layerDepth);
|
||||
}
|
||||
|
||||
if (layer instanceof TmxImageLayer) {
|
||||
this.renderImageLayer(layer, container, position, scale, layerDepth);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static renderTile(tile: TmxLayerTile, container: egret.DisplayObjectContainer, position: Vector2, scale: Vector2, tileWidth: number, tileHeight: number, color: egret.ColorMatrixFilter, layerDepth: number) {
|
||||
let gid = tile.gid;
|
||||
|
||||
// 动画tiles(以及来自图像tile的tiles)将位于Tileset本身内,位于单独的TmxTilesetTile对象中,不要与我们在此循环中处理的TmxLayerTiles混淆
|
||||
let tilesetTile = tile.tilesetTile;
|
||||
if (tilesetTile && tilesetTile.animationFrames.length > 0)
|
||||
gid = tilesetTile.currentAnimationFrameGid;
|
||||
|
||||
let sourceRect = tile.tileset.tileRegions.get(gid);
|
||||
|
||||
// 对于y位置,我们需要考虑瓦片是否大于瓦片的高度和移位。
|
||||
// tiled使用左下角的坐标系统,而egret则使用左上角的坐标系统
|
||||
let tx = Math.floor(tile.x) * tileWidth;
|
||||
let ty = Math.floor(tile.y) * tileHeight;
|
||||
let rotation = 0;
|
||||
|
||||
if (tile.horizontalFlip && tile.verticalFlip) {
|
||||
tx += tileHeight + (sourceRect.height * scale.y - tileHeight);
|
||||
ty -= (sourceRect.width * scale.x - tileWidth);
|
||||
} else if (tile.horizontalFlip) {
|
||||
tx += tileWidth + (sourceRect.height * scale.y - tileHeight);
|
||||
} else if (tile.verticalFlip) {
|
||||
ty += (tileWidth - sourceRect.width * scale.x);
|
||||
} else {
|
||||
ty += (tileHeight - sourceRect.height * scale.y);
|
||||
}
|
||||
|
||||
let pos = new Vector2(tx, ty).add(position);
|
||||
|
||||
if (tile.tileset.image) {
|
||||
if (container){
|
||||
let texture: egret.Texture = tile.tileset.image.bitmap.getTexture(`${gid}`);
|
||||
if (!texture) {
|
||||
texture = tile.tileset.image.bitmap.createTexture(`${gid}`, sourceRect.x, sourceRect.y, sourceRect.width, sourceRect.height);
|
||||
}
|
||||
|
||||
tile.tileset.image.texture = new Bitmap(texture);
|
||||
container.addChild(tile.tileset.image.texture);
|
||||
|
||||
if (tile.tileset.image.texture.x != pos.x) tile.tileset.image.texture.x = pos.x;
|
||||
if (tile.tileset.image.texture.y != pos.y) tile.tileset.image.texture.y = pos.y;
|
||||
if (tile.verticalFlip && tile.horizontalFlip){
|
||||
tile.tileset.image.texture.scaleX = -1;
|
||||
tile.tileset.image.texture.scaleY = -1;
|
||||
}else if (tile.verticalFlip){
|
||||
tile.tileset.image.texture.scaleX = scale.x;
|
||||
tile.tileset.image.texture.scaleY = -1;
|
||||
}else if(tile.horizontalFlip){
|
||||
tile.tileset.image.texture.scaleX = -1;
|
||||
tile.tileset.image.texture.scaleY = scale.y;
|
||||
}else{
|
||||
tile.tileset.image.texture.scaleX = scale.x;
|
||||
tile.tileset.image.texture.scaleY = scale.y;
|
||||
}
|
||||
if (tile.tileset.image.texture.rotation != rotation) tile.tileset.image.texture.rotation = rotation;
|
||||
if (tile.tileset.image.texture.anchorOffsetX != 0) tile.tileset.image.texture.anchorOffsetX = 0;
|
||||
if (tile.tileset.image.texture.anchorOffsetY != 0) tile.tileset.image.texture.anchorOffsetY = 0;
|
||||
}
|
||||
// tile.tileset.image.texture.filters = [color];
|
||||
} else {
|
||||
if (tilesetTile.image.texture) {
|
||||
if (!tilesetTile.image.bitmap.getTexture(gid.toString())) {
|
||||
tilesetTile.image.texture = new Bitmap(tilesetTile.image.bitmap.createTexture(gid.toString(), sourceRect.x, sourceRect.y, sourceRect.width, sourceRect.height));
|
||||
container.addChild(tilesetTile.image.texture);
|
||||
}
|
||||
tilesetTile.image.texture.x = pos.x;
|
||||
tilesetTile.image.texture.y = pos.y;
|
||||
tilesetTile.image.texture.scaleX = scale.x;
|
||||
tilesetTile.image.texture.scaleY = scale.y;
|
||||
tilesetTile.image.texture.rotation = rotation;
|
||||
tilesetTile.image.texture.anchorOffsetX = 0;
|
||||
tilesetTile.image.texture.anchorOffsetY = 0;
|
||||
tilesetTile.image.texture.filters = [color];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
module es {
|
||||
export class TmxTileset extends TmxDocument implements ITmxElement {
|
||||
public map: TmxMap;
|
||||
public firstGid: number;
|
||||
public name;
|
||||
public tileWidth: number;
|
||||
public tileHeight: number;
|
||||
public spacing: number;
|
||||
public margin: number;
|
||||
public columns?: number;
|
||||
public tileCount?: number;
|
||||
public tiles: Map<number, TmxTilesetTile>;
|
||||
public tileOffset: TmxTileOffset;
|
||||
public properties: Map<string, string>;
|
||||
public image: TmxImage;
|
||||
public terrains: TmxTerrain[];
|
||||
/**
|
||||
* 为每个块缓存源矩形
|
||||
*/
|
||||
public tileRegions: Map<number, Rectangle>;
|
||||
|
||||
public update(){
|
||||
this.tiles.forEach(value => {
|
||||
value.updateAnimatedTiles();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class TmxTileOffset {
|
||||
public x: number;
|
||||
public y: number;
|
||||
}
|
||||
|
||||
export class TmxTerrain implements ITmxElement {
|
||||
public name;
|
||||
public tile: number;
|
||||
public properties: Map<string, string>;
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
module es {
|
||||
export class TmxTilesetTile {
|
||||
public tileset: TmxTileset;
|
||||
public id: number;
|
||||
public terrainEdges: TmxTerrain[];
|
||||
public probability: number;
|
||||
public type: string;
|
||||
public properties: Map<string, string>;
|
||||
public image: TmxImage;
|
||||
public objectGroups: TmxObjectGroup[];
|
||||
public animationFrames: TmxAnimationFrame[];
|
||||
|
||||
// TODO: 为什么动画瓷砖需要添加firstGid
|
||||
public get currentAnimationFrameGid(){
|
||||
return this.animationFrames[this._animationCurrentFrame].gid + this.tileset.firstGid;
|
||||
}
|
||||
public _animationElapsedTime: number;
|
||||
public _animationCurrentFrame: number;
|
||||
/**
|
||||
* 返回“engine:isDestructable”属性的值(如果属性字典中存在)
|
||||
*/
|
||||
public isDestructable: boolean;
|
||||
/**
|
||||
* 返回“engine:isSlope”属性的值(如果存在于属性字典中)
|
||||
*/
|
||||
public isSlope: boolean;
|
||||
/**
|
||||
* 返回“engine:isOneWayPlatform”属性的值(如果存在于属性字典中)
|
||||
*/
|
||||
public isOneWayPlatform: boolean;
|
||||
/**
|
||||
* 返回“engine:slopeTopLeft”属性的值(如果存在于属性字典中)
|
||||
*/
|
||||
public slopeTopLeft: number;
|
||||
/**
|
||||
* 如果属性字典中存在“engine:slopeTopRight”属性,则返回该属性的值
|
||||
*/
|
||||
public slopeTopRight: number;
|
||||
|
||||
public processProperties(){
|
||||
let value: string;
|
||||
value = this.properties.get("engine.isDestructable");
|
||||
if (value)
|
||||
this.isDestructable = Boolean(value);
|
||||
|
||||
value = this.properties.get("engine:isSlope");
|
||||
if (value)
|
||||
this.isSlope = Boolean(value);
|
||||
|
||||
value = this.properties.get("engine:isOneWayPlatform");
|
||||
if (value)
|
||||
this.isOneWayPlatform = Boolean(value);
|
||||
|
||||
value = this.properties.get("engine:slopeTopLeft");
|
||||
if (value)
|
||||
this.slopeTopLeft = Number(value);
|
||||
|
||||
value = this.properties.get("engine:slopeTopRight");
|
||||
if (value)
|
||||
this.slopeTopRight = Number(value);
|
||||
}
|
||||
|
||||
public updateAnimatedTiles(){
|
||||
if (this.animationFrames.length == 0)
|
||||
return;
|
||||
|
||||
this._animationElapsedTime += Time.deltaTime;
|
||||
if (this._animationElapsedTime > this.animationFrames[this._animationCurrentFrame].duration){
|
||||
this._animationCurrentFrame = MathHelper.incrementWithWrap(this._animationCurrentFrame, this.animationFrames.length);
|
||||
this._animationElapsedTime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class TmxAnimationFrame {
|
||||
public gid: number;
|
||||
public duration: number;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
module es {
|
||||
export class TmxUtils {
|
||||
/**
|
||||
* 解码
|
||||
* @param data 数据
|
||||
* @param encoding 编码方式 目前暂时只支持XML、base64(无压缩)、csv解析
|
||||
* @param compression 压缩方式
|
||||
* @returns 返回解析后的数据列表
|
||||
*
|
||||
* @version Egret 3.0.3
|
||||
*/
|
||||
static decode(data: any, encoding: any, compression: string): Array<number> {
|
||||
compression = compression || "none";
|
||||
encoding = encoding || "none";
|
||||
switch (encoding) {
|
||||
case "base64":
|
||||
var decoded = Base64Utils.decodeBase64AsArray(data, 4);
|
||||
return (compression === "none") ? decoded : Base64Utils.decompress(data, decoded, compression);
|
||||
|
||||
case "csv":
|
||||
return Base64Utils.decodeCSV(data);
|
||||
|
||||
case "none":
|
||||
var datas: Array<number> = [];
|
||||
for (var i: number = 0; i < data.length; i++) {
|
||||
datas[i] = +data[i].gid;
|
||||
}
|
||||
return datas;
|
||||
|
||||
default:
|
||||
throw new Error("未定义的编码:" + encoding);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将带"#"号的颜色字符串转换为16进制的颜色,例如:可将"#ff0000"转换为"0xff0000"
|
||||
* @param $color 要转换的颜色字符串
|
||||
* @returns 返回16进制的颜色值
|
||||
* @version Egret 3.0.3
|
||||
*/
|
||||
static color16ToUnit($color:string): number {
|
||||
if (!$color)
|
||||
return 0xFFFFFF;
|
||||
var colorStr: string = "0x" + $color.slice(1);
|
||||
return parseInt(colorStr, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user