#28 tiled 数据解析与渲染
This commit is contained in:
@@ -7,10 +7,10 @@ module es {
|
||||
public properties: Map<string, string>;
|
||||
public visible: boolean;
|
||||
public name: string;
|
||||
public layers: TmxList<any>;
|
||||
public tileLayers: TmxList<TmxLayer>;
|
||||
public objectGroups: TmxList<TmxObjectGroup>;
|
||||
public imageLayers: TmxList<TmxImageLayer>;
|
||||
public groups: TmxList<TmxGroup>;
|
||||
public layers: ITmxLayer[];
|
||||
public tileLayers: TmxLayer[];
|
||||
public objectGroups: TmxObjectGroup[];
|
||||
public imageLayers: TmxImageLayer[];
|
||||
public groups: TmxGroup[];
|
||||
}
|
||||
}
|
||||
@@ -26,12 +26,12 @@ module es {
|
||||
* 包含所有的ITmxLayers,不管它们的具体类型是什么。
|
||||
* 注意,TmxGroup中的层将不在此列表中。TmxGroup管理自己的层列表。
|
||||
*/
|
||||
public layers: TmxList<any>;
|
||||
public tilesets: TmxList<TmxTileset>;
|
||||
public tileLayers: TmxList<TmxLayer>;
|
||||
public objectGroups: TmxList<TmxObjectGroup>;
|
||||
public imageLayers: TmxList<TmxImageLayer>;
|
||||
public groups: TmxList<TmxGroup>;
|
||||
public layers: ITmxLayer[];
|
||||
public tilesets: TmxTileset[];
|
||||
public tileLayers: TmxLayer[];
|
||||
public objectGroups: TmxLayer[];
|
||||
public imageLayers: TmxImageLayer[];
|
||||
public groups: TmxGroup[];
|
||||
public properties: Map<string, string>;
|
||||
|
||||
/**
|
||||
@@ -59,9 +59,9 @@ module es {
|
||||
if (gid == 0)
|
||||
return null;
|
||||
|
||||
for (let i = this.tilesets.size - 1; i >= 0; i --){
|
||||
if (this.tilesets.get(i.toString()).firstGid <= gid)
|
||||
return this.tilesets.get(i.toString());
|
||||
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中找到`);
|
||||
@@ -96,7 +96,7 @@ module es {
|
||||
* @param name
|
||||
*/
|
||||
public getLayer(name: string): ITmxLayer {
|
||||
return this.layers.get(name);
|
||||
return this.layers[name];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,13 +8,15 @@ module es {
|
||||
public offsetY: number;
|
||||
public color: number;
|
||||
public drawOrder: DrawOrderType;
|
||||
public objects: TmxList<TmxObject>;
|
||||
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;
|
||||
@@ -27,6 +29,11 @@ module es {
|
||||
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 {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
module es {
|
||||
export class TmxDocument {
|
||||
public TmxDirectory: string;
|
||||
public tmxDirectory: string;
|
||||
constructor(){
|
||||
this.TmxDirectory = "";
|
||||
this.tmxDirectory = "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,37 +10,40 @@ module es {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export class TmxList<T extends ITmxElement> extends Map<string, T>{
|
||||
public _nameCount: Map<string, number> = new Map<string, number>();
|
||||
|
||||
public add(t: T){
|
||||
let tName = t.name;
|
||||
|
||||
// 通过附加数字重命名重复的条目
|
||||
if (this.has(tName))
|
||||
this._nameCount.set(tName, this._nameCount.get(tName) + 1);
|
||||
else
|
||||
this._nameCount.set(tName, 0);
|
||||
}
|
||||
|
||||
protected getKeyForItem(item: T): string {
|
||||
let name = item.name;
|
||||
let count = this._nameCount.get(name);
|
||||
|
||||
let dupes = 0;
|
||||
|
||||
// 对于重复的键,附加一个计数器。对于病理情况,插入下划线以确保唯一性
|
||||
while (this.has(name)){
|
||||
name = name + Enumerable.repeat("_", dupes).toString() + count.toString();
|
||||
dupes ++;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
}
|
||||
// export class TmxList<T extends ITmxElement> extends Map<string, T>{
|
||||
// public _nameCount: Map<string, number> = new Map<string, number>();
|
||||
//
|
||||
// public add(t: T){
|
||||
// let tName = t.name;
|
||||
//
|
||||
// // 通过附加数字重命名重复的条目
|
||||
// if (this.has(tName))
|
||||
// this._nameCount.set(tName, this._nameCount.get(tName) + 1);
|
||||
// else
|
||||
// this._nameCount.set(tName, 0);
|
||||
// }
|
||||
//
|
||||
// protected getKeyForItem(item: T): string {
|
||||
// let name = item.name;
|
||||
// let count = this._nameCount.get(name);
|
||||
//
|
||||
// let dupes = 0;
|
||||
//
|
||||
// // 对于重复的键,附加一个计数器。对于病理情况,插入下划线以确保唯一性
|
||||
// while (this.has(name)){
|
||||
// name = name + Enumerable.repeat("_", dupes).toString() + count.toString();
|
||||
// dupes ++;
|
||||
// }
|
||||
//
|
||||
// return name;
|
||||
// }
|
||||
// }
|
||||
|
||||
export class TmxImage {
|
||||
public texture: egret.Texture;
|
||||
public bitmap: egret.Bitmap;
|
||||
public get texture(): egret.Texture{
|
||||
return this.bitmap.texture;
|
||||
}
|
||||
public source: string;
|
||||
public format: string;
|
||||
public data: any;
|
||||
@@ -49,9 +52,9 @@ module es {
|
||||
public height: number;
|
||||
|
||||
public dispose(){
|
||||
if (this.texture){
|
||||
if (this.bitmap){
|
||||
this.texture.dispose();
|
||||
this.texture = null;
|
||||
this.bitmap = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
406
source/src/Tiled/TiledMapLoader.ts
Normal file
406
source/src/Tiled/TiledMapLoader.ts
Normal file
@@ -0,0 +1,406 @@
|
||||
module es {
|
||||
import Bitmap = egret.Bitmap;
|
||||
|
||||
export class TiledMapLoader {
|
||||
public static loadTmxMap(map: TmxMap, filePath: string){
|
||||
let xMap = RES.getRes(filePath);
|
||||
return this.loadTmxMapData(map, xMap);
|
||||
}
|
||||
|
||||
public static async loadTmxMapData(map: TmxMap, xMap: 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.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 parseLayers(container: any, xEle: any, map: TmxMap, width: number, height: number, tmxDirectory: string){
|
||||
|
||||
}
|
||||
|
||||
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["property"]){
|
||||
let pname = p["name"];
|
||||
let valueAttr = p["value"];
|
||||
let pval = valueAttr ? valueAttr : p;
|
||||
|
||||
dict.set(pname, pval);
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
|
||||
public static async parseTmxTileset(map: TmxMap, xTileset: any){
|
||||
// firstgid总是在TMX中,而不是在TSX中
|
||||
let xFirstGid = xTileset["firstgid"];
|
||||
let firstGid = xFirstGid;
|
||||
let source = xTileset["image"];
|
||||
|
||||
// 如果是嵌入式TmxTileset,即不是外部的,source将为null
|
||||
if (!source){
|
||||
source = "resource/assets/" + source;
|
||||
// 其他所有内容都在TSX文件中
|
||||
let xDocTileset = await RES.getResByUrl(source, null, this, RES.ResourceItem.TYPE_IMAGE);
|
||||
let tileset = this.loadTmxTileset(new TmxTileset(), map, xDocTileset["tileset"], firstGid);
|
||||
|
||||
return tileset;
|
||||
}
|
||||
|
||||
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)
|
||||
tileset.image = await this.loadTmxImage(new TmxImage(), xTileset);
|
||||
|
||||
let xTerrainType = xTileset["terraintypes"];
|
||||
if (xTerrainType){
|
||||
tileset.terrains = [];
|
||||
for (let e of xTerrainType["terrains"])
|
||||
tileset.terrains.push(this.parseTmxTerrain(e));
|
||||
}
|
||||
|
||||
tileset.tiles = new Map<number, TmxTilesetTile>();
|
||||
for (let xTile of xTileset["tiles"]){
|
||||
let tile = await this.loadTmxTilesetTile(new TmxTilesetTile(), tileset, xTile, tileset.terrains);
|
||||
tileset.tiles[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 => {
|
||||
tileset.tileRegions.set(firstGid + tile.id, new Rectangle(0, 0, tile.image.width, tile.image.height));
|
||||
});
|
||||
}
|
||||
|
||||
return tileset;
|
||||
}
|
||||
|
||||
public static async loadTmxTilesetTile(tile: TmxTilesetTile, tileset: TmxTileset, xTile: any, terrains: TmxTerrain[]){
|
||||
tile.tileset = tileset;
|
||||
tile.id = xTile["id"];
|
||||
|
||||
tile.terrainEdges = xTile["terrain"];
|
||||
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);
|
||||
}
|
||||
|
||||
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[drawOrderValue];
|
||||
|
||||
group.objects = [];
|
||||
for (let e of xObjectGroup["object"])
|
||||
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 pointString: string = xPoints["points"];
|
||||
let pointStringPair = pointString.split(' ');
|
||||
let points = [];
|
||||
|
||||
let index = 0;
|
||||
for (let s of pointStringPair)
|
||||
points[index ++] = this.parsePoint(s);
|
||||
return points;
|
||||
}
|
||||
|
||||
public static parsePoint(s: string){
|
||||
let pt = s.split(',');
|
||||
let x = Number(pt[0]);
|
||||
let y = Number(pt[1]);
|
||||
return new Vector2(x, 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){
|
||||
let xSource = xImage["image"];
|
||||
if (xSource) {
|
||||
image.source = "resource/assets/" + xSource;
|
||||
image.bitmap = new Bitmap(await RES.getResByUrl(image.source, null, this, RES.ResourceItem.TYPE_IMAGE));
|
||||
}else {
|
||||
image.format = xImage["format"];
|
||||
let xData = xImage["data"];
|
||||
image.data = TmxUtils.decode(xData, xData["encoding"], xData["compression"]);
|
||||
}
|
||||
|
||||
image.trans = TmxUtils.color16ToUnit(xImage["trans"]);
|
||||
image.width = xImage["width"] != undefined ? xImage["width"] : 0;
|
||||
image.height = xImage["height"] != undefined ? xImage["height"] : 0;
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,119 +1,154 @@
|
||||
module es {
|
||||
export class TiledRendering {
|
||||
public static renderMap(map: TmxMap, position: Vector2, scale: Vector2, layerDepth: number) {
|
||||
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, position, scale, layerDepth);
|
||||
this.renderLayer(layer, container, position, scale, layerDepth);
|
||||
} else if (layer instanceof TmxImageLayer && layer.visible) {
|
||||
this.renderImageLayer(layer, position, scale, layerDepth);
|
||||
this.renderImageLayer(layer, container, position, scale, layerDepth);
|
||||
} else if (layer instanceof TmxGroup && layer.visible) {
|
||||
this.renderGroup(layer, position, scale, layerDepth);
|
||||
this.renderGroup(layer, container, position, scale, layerDepth);
|
||||
} else if (layer instanceof TmxObjectGroup && layer.visible) {
|
||||
this.renderObjectGroup(layer, position, scale, layerDepth);
|
||||
this.renderObjectGroup(layer, container, position, scale, layerDepth);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static renderLayer(layer: TmxLayer, position: Vector2, scale: Vector2, layerDepth: number) {
|
||||
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 = new Color(0, 0, 0, layer.opacity * 255);
|
||||
for (let i = 0; i < layer.tiles.length; i ++){
|
||||
let color = DrawUtils.getColorMatrix(0x000000);
|
||||
for (let i = 0; i < layer.tiles.length; i++) {
|
||||
let tile = layer.tiles[i];
|
||||
if (!tile)
|
||||
continue;
|
||||
|
||||
this.renderTile(tile, position, scale, tileWidth, tileHeight, color, layerDepth);
|
||||
this.renderTile(tile, container, position, scale, tileWidth, tileHeight, color, layerDepth);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static renderImageLayer(layer: TmxImageLayer, position: Vector2, scale: Vector2, layerDepth: number) {
|
||||
public static renderImageLayer(layer: TmxImageLayer, container: egret.DisplayObjectContainer, position: Vector2, scale: Vector2, layerDepth: number) {
|
||||
if (!layer.visible)
|
||||
return;
|
||||
|
||||
let color = new Color(0, 0, 0, layer.opacity * 255);
|
||||
let color = DrawUtils.getColorMatrix(0x000000);
|
||||
let pos = Vector2.add(position, new Vector2(layer.offsetX, layer.offsetY).multiply(scale));
|
||||
// TODO: draw
|
||||
if (!layer.image.bitmap.parent)
|
||||
container.addChild(layer.image.bitmap);
|
||||
layer.image.bitmap.x = pos.x;
|
||||
layer.image.bitmap.y = pos.y;
|
||||
layer.image.bitmap.scaleX = scale.x;
|
||||
layer.image.bitmap.scaleY = scale.y;
|
||||
layer.image.bitmap.filters = [color];
|
||||
}
|
||||
|
||||
public static renderObjectGroup(objGroup: TmxObjectGroup, position: Vector2, scale: Vector2, layerDepth: number) {
|
||||
public static renderObjectGroup(objGroup: TmxObjectGroup, container: egret.DisplayObjectContainer, position: Vector2, scale: Vector2, layerDepth: number) {
|
||||
if (!objGroup.visible)
|
||||
return;
|
||||
|
||||
for (let object in objGroup.objects) {
|
||||
let obj = objGroup.objects.get(object);
|
||||
let obj = objGroup.objects[object];
|
||||
if (!obj.visible)
|
||||
continue;
|
||||
|
||||
// TODO: debug draw
|
||||
// 如果我们不调试渲染,我们只渲染平铺块和文本类型
|
||||
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:
|
||||
// TODO: draw
|
||||
if (!obj.shape.parent)
|
||||
container.addChild(obj.shape);
|
||||
|
||||
let rect = new Rectangle(pos.x, pos.y, obj.width * scale.x, obj.height * scale.y);
|
||||
DrawUtils.drawHollowRect(obj.shape, rect, objGroup.color);
|
||||
break;
|
||||
case TmxObjectType.point:
|
||||
let size = objGroup.map.tileWidth * 0.5;
|
||||
pos.x -= size * 0.5;
|
||||
pos.y -= size * 0.5;
|
||||
// TODO: draw
|
||||
if (!obj.shape.parent)
|
||||
container.addChild(obj.shape);
|
||||
|
||||
DrawUtils.drawPixel(obj.shape, pos, objGroup.color, size);
|
||||
break;
|
||||
case TmxObjectType.tile:
|
||||
let tileset = objGroup.map.getTilesetForTileGid(obj.tile.gid);
|
||||
let sourceRect = tileset.tileRegions[obj.tile.gid];
|
||||
pos.y -= obj.tile.tilesetTile.image.height;
|
||||
// TODO: draw
|
||||
|
||||
if (!obj.tile.tilesetTile.image.bitmap)
|
||||
container.addChild(obj.tile.tilesetTile.image.bitmap);
|
||||
obj.tile.tilesetTile.image.bitmap.x = pos.x;
|
||||
obj.tile.tilesetTile.image.bitmap.y = pos.y;
|
||||
obj.tile.tilesetTile.image.bitmap.filters = [];
|
||||
obj.tile.tilesetTile.image.bitmap.rotation = 0;
|
||||
obj.tile.tilesetTile.image.bitmap.scaleX = scale.x;
|
||||
obj.tile.tilesetTile.image.bitmap.scaleY = scale.y;
|
||||
break;
|
||||
case TmxObjectType.ellipse:
|
||||
pos = new Vector2(obj.x + obj.width * 0.5, obj.y + obj.height * 0.5).multiply(scale);
|
||||
// TODO: draw
|
||||
if (!obj.shape.parent)
|
||||
container.addChild(obj.shape);
|
||||
DrawUtils.drawCircle(obj.shape, pos, obj.width * 0.5, objGroup.color);
|
||||
break;
|
||||
case TmxObjectType.polygon:
|
||||
case TmxObjectType.polyline:
|
||||
let points = [];
|
||||
for (let i = 0; i < obj.points.length; i++)
|
||||
points[i] = Vector2.multiply(obj.points[i], scale);
|
||||
// TODO: draw
|
||||
DrawUtils.drawPoints(obj.shape, pos, points, objGroup.color, obj.objectType == TmxObjectType.polygon);
|
||||
break;
|
||||
case TmxObjectType.text:
|
||||
// TODO: draw
|
||||
if (!obj.textField.parent)
|
||||
container.addChild(obj.textField);
|
||||
DrawUtils.drawString(obj.textField, obj.text.value, pos, obj.text.color, MathHelper.toRadians(obj.rotation),
|
||||
Vector2.zero, 1);
|
||||
break;
|
||||
default:
|
||||
// TODO: debug draw
|
||||
if (Core.debugRenderEndabled){
|
||||
if (!obj.textField.parent)
|
||||
container.addChild(obj.textField);
|
||||
DrawUtils.drawString(obj.textField, `${obj.name}(${obj.type})`, Vector2.subtract(pos, new Vector2(0, 15)), 0xffffff, 0, Vector2.zero, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static renderGroup(group: TmxGroup, position: Vector2, scale: Vector2, layerDepth: number) {
|
||||
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, position, scale, layerDepth);
|
||||
this.renderGroup(layer, container, position, scale, layerDepth);
|
||||
}
|
||||
|
||||
if (layer instanceof TmxObjectGroup) {
|
||||
this.renderObjectGroup(layer, position, scale,layerDepth);
|
||||
this.renderObjectGroup(layer, container, position, scale, layerDepth);
|
||||
}
|
||||
|
||||
if (layer instanceof TmxLayer){
|
||||
this.renderLayer(layer, position, scale, layerDepth);
|
||||
if (layer instanceof TmxLayer) {
|
||||
this.renderLayer(layer, container, position, scale, layerDepth);
|
||||
}
|
||||
|
||||
if (layer instanceof TmxImageLayer){
|
||||
this.renderImageLayer(layer, position, scale, layerDepth);
|
||||
if (layer instanceof TmxImageLayer) {
|
||||
this.renderImageLayer(layer, container, position, scale, layerDepth);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static renderTile(tile: TmxLayerTile, position: Vector2, scale: Vector2, tileWidth: number, tileHeight: number, color: Color, layerDepth: number) {
|
||||
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混淆
|
||||
@@ -153,9 +188,23 @@ module es {
|
||||
|
||||
let pos = new Vector2(tx, ty).add(position);
|
||||
if (tile.tileset.image) {
|
||||
// TODO: draw
|
||||
if (!tile.tilesetTile.image.bitmap.parent)
|
||||
container.addChild(tile.tilesetTile.image.bitmap);
|
||||
tile.tilesetTile.image.bitmap.x = pos.x;
|
||||
tile.tilesetTile.image.bitmap.y = pos.y;
|
||||
tile.tilesetTile.image.bitmap.scaleX = scale.x;
|
||||
tile.tilesetTile.image.bitmap.scaleY = scale.y;
|
||||
tile.tilesetTile.image.bitmap.rotation = rotation;
|
||||
tile.tilesetTile.image.bitmap.filters = [color];
|
||||
} else {
|
||||
// TODO: draw
|
||||
if (!tilesetTile.image.bitmap)
|
||||
container.addChild(tilesetTile.image.bitmap);
|
||||
tilesetTile.image.bitmap.x = pos.x;
|
||||
tilesetTile.image.bitmap.y = pos.y;
|
||||
tilesetTile.image.bitmap.scaleX = scale.x;
|
||||
tilesetTile.image.bitmap.scaleY = scale.y;
|
||||
tilesetTile.image.bitmap.rotation = rotation;
|
||||
tilesetTile.image.bitmap.filters = [color];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ module es {
|
||||
public tileOffset: TmxTileOffset;
|
||||
public properties: Map<string, string>;
|
||||
public image: TmxImage;
|
||||
public terrains: TmxList<TmxTerrain>;
|
||||
public terrains: TmxTerrain[];
|
||||
/**
|
||||
* 为每个块缓存源矩形
|
||||
*/
|
||||
|
||||
@@ -7,7 +7,7 @@ module es {
|
||||
public type: string;
|
||||
public properties: Map<string, string>;
|
||||
public image: TmxImage;
|
||||
public objectGroups: TmxList<TmxObjectGroup>;
|
||||
public objectGroups: TmxObjectGroup[];
|
||||
public animationFrames: TmxAnimationFrame[];
|
||||
|
||||
// TODO: 为什么动画瓷砖需要添加firstGid
|
||||
|
||||
50
source/src/Tiled/TmxUtils.ts
Normal file
50
source/src/Tiled/TmxUtils.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
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";
|
||||
var text:string=data.children[0].text;
|
||||
switch (encoding) {
|
||||
case "base64":
|
||||
var decoded = Base64Utils.decodeBase64AsArray(text, 4);
|
||||
return (compression === "none") ? decoded : Base64Utils.decompress(text, decoded, compression);
|
||||
|
||||
case "csv":
|
||||
return Base64Utils.decodeCSV(text);
|
||||
|
||||
case "none":
|
||||
var datas: Array<number> = [];
|
||||
for (var i: number = 0; i < data.children.length; i++) {
|
||||
datas[i] = +data.children[i].attributes.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 0x000000;
|
||||
var colorStr: string = "0x" + $color.slice(1);
|
||||
return parseInt(colorStr, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user