This commit is contained in:
yhh
2020-11-20 16:30:09 +08:00
parent 7eab688d9c
commit 0fd6a24f5a
605 changed files with 1944 additions and 184497 deletions

View File

@@ -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;
}
}
}

View File

@@ -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;
// }
// }
// }

View File

@@ -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[];
}
}

View File

@@ -1,9 +0,0 @@
module es {
export interface ITmxLayer {
offsetX: number;
offsetY: number;
opacity: number;
visible: boolean;
properties: Map<string, string>;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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>;
/**
* 当我们有一个图像tilesettile可以是任何大小所以我们记录的最大大小来剔除
*/
public maxTileWidth: number;
/**
* 当我们有一个图像tilesettile可以是任何大小所以我们记录的最大大小来剔除
*/
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
}
}

View File

@@ -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
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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];
}
}
}
}
}

View File

@@ -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>;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}