#28 tiled 数据解析与渲染
This commit is contained in:
@@ -1,15 +1,17 @@
|
||||
module es {
|
||||
export class TiledMapRenderer extends RenderableComponent{
|
||||
export class TiledMapRenderer extends RenderableComponent {
|
||||
public tiledMap: TmxMap;
|
||||
public physicsLayer: number = 1 << 0;
|
||||
/**
|
||||
* 如果空,所有层将被渲染
|
||||
*/
|
||||
public layerIndicesToRender: number[];
|
||||
public get width(){
|
||||
|
||||
public get width() {
|
||||
return this.tiledMap.width * this.tiledMap.tileWidth;
|
||||
}
|
||||
public get height(){
|
||||
|
||||
public get height() {
|
||||
return this.tiledMap.height * this.tiledMap.tileHeight;
|
||||
}
|
||||
|
||||
@@ -17,13 +19,14 @@ module es {
|
||||
public _shouldCreateColliders: boolean;
|
||||
public _colliders: Collider[];
|
||||
|
||||
constructor(tiledMap: TmxMap, collisionLayerName: string = null, shouldCreateColliders: boolean = true){
|
||||
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.get(collisionLayerName);
|
||||
if (collisionLayerName) {
|
||||
this.collisionLayer = tiledMap.tileLayers[collisionLayerName];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +34,7 @@ module es {
|
||||
* 将此组件设置为只渲染单层
|
||||
* @param layerName
|
||||
*/
|
||||
public setLayerToRender(layerName: string){
|
||||
public setLayerToRender(layerName: string) {
|
||||
this.layerIndicesToRender = [];
|
||||
this.layerIndicesToRender[0] = this.getLayerIndex(layerName);
|
||||
}
|
||||
@@ -40,18 +43,18 @@ module es {
|
||||
* 设置该组件应该按名称呈现哪些层。如果你知道索引,你可以直接设置layerIndicesToRender
|
||||
* @param layerNames
|
||||
*/
|
||||
public setLayersToRender(...layerNames: string[]){
|
||||
public setLayersToRender(...layerNames: string[]) {
|
||||
this.layerIndicesToRender = [];
|
||||
for (let i = 0; i < layerNames.length; i ++)
|
||||
for (let i = 0; i < layerNames.length; i++)
|
||||
this.layerIndicesToRender[i] = this.getLayerIndex(layerNames[i]);
|
||||
}
|
||||
|
||||
private getLayerIndex(layerName: string){
|
||||
private getLayerIndex(layerName: string) {
|
||||
let index = 0;
|
||||
let layerType = this.tiledMap.getLayer(layerName);
|
||||
for (let layer in this.tiledMap.layers){
|
||||
for (let layer in this.tiledMap.layers) {
|
||||
if (this.tiledMap.layers.hasOwnProperty(layer) &&
|
||||
this.tiledMap.layers.get(layer) == layerType){
|
||||
this.tiledMap.layers[layer] == layerType) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
@@ -64,14 +67,14 @@ module es {
|
||||
return this.tiledMap.worldToTilePositionY(yPos);
|
||||
}
|
||||
|
||||
public getColumnAtWorldPosition(xPos: number): number{
|
||||
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){
|
||||
if (this._shouldCreateColliders && comp == transform.Component.position) {
|
||||
this.removeColliders();
|
||||
this.addColliders();
|
||||
}
|
||||
@@ -90,19 +93,19 @@ module es {
|
||||
}
|
||||
|
||||
public render(camera: es.Camera) {
|
||||
if (!this.layerIndicesToRender){
|
||||
TiledRendering.renderMap(this.tiledMap, Vector2.add(this.entity.transform.position, this._localOffset),
|
||||
if (!this.layerIndicesToRender) {
|
||||
TiledRendering.renderMap(this.tiledMap, this.displayObject as egret.DisplayObjectContainer, Vector2.add(this.entity.transform.position, this._localOffset),
|
||||
this.transform.scale, this.renderLayer);
|
||||
}else{
|
||||
for (let i = 0; i < this.tiledMap.layers.size; i ++){
|
||||
if (this.tiledMap.layers.get(i.toString()).visible && this.layerIndicesToRender.contains(i))
|
||||
TiledRendering.renderLayer(this.tiledMap.layers.get(i.toString()), Vector2.add(this.entity.transform.position, this._localOffset),
|
||||
} else {
|
||||
for (let i = 0; i < this.tiledMap.layers.length; i++) {
|
||||
if (this.tiledMap.layers[i].visible && this.layerIndicesToRender.contains(i))
|
||||
TiledRendering.renderLayer(this.tiledMap.layers[i] as TmxLayer, this.displayObject as egret.DisplayObjectContainer, Vector2.add(this.entity.transform.position, this._localOffset),
|
||||
this.transform.scale, this.renderLayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public addColliders(){
|
||||
public addColliders() {
|
||||
if (!this.collisionLayer || !this._shouldCreateColliders)
|
||||
return;
|
||||
|
||||
@@ -111,7 +114,7 @@ module es {
|
||||
|
||||
// 为我们收到的矩形创建碰撞器
|
||||
this._colliders = [];
|
||||
for (let i = 0; i < collisionRects.length; i ++){
|
||||
for (let i = 0; i < collisionRects.length; i++) {
|
||||
let collider = new BoxCollider().createBoxRect(collisionRects[i].x + this._localOffset.x,
|
||||
collisionRects[i].y + this._localOffset.y, collisionRects[i].width, collisionRects[i].height);
|
||||
collider.physicsLayer = this.physicsLayer;
|
||||
@@ -122,11 +125,11 @@ module es {
|
||||
}
|
||||
}
|
||||
|
||||
public removeColliders(){
|
||||
public removeColliders() {
|
||||
if (this._colliders == null)
|
||||
return;
|
||||
|
||||
for (let collider of this._colliders){
|
||||
for (let collider of this._colliders) {
|
||||
Physics.removeCollider(collider);
|
||||
}
|
||||
this._colliders = null;
|
||||
|
||||
@@ -7,6 +7,10 @@ module es {
|
||||
* 核心发射器。只发出核心级别的事件
|
||||
*/
|
||||
public static emitter: Emitter<CoreEvents>;
|
||||
/**
|
||||
* 是否启用调试渲染
|
||||
*/
|
||||
public static debugRenderEndabled = false;
|
||||
/**
|
||||
* 全局访问图形设备
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,124 +1,134 @@
|
||||
class Base64Utils {
|
||||
private static _keyNum = "0123456789+/";
|
||||
private static _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
private static _keyAll = Base64Utils._keyNum + Base64Utils._keyStr;
|
||||
/**
|
||||
* 加密
|
||||
* @param input
|
||||
*/
|
||||
public static encode = function (input) {
|
||||
let output = "";
|
||||
let chr1, chr2, chr3, enc1, enc2, enc3, enc4;
|
||||
let i = 0;
|
||||
input = this._utf8_encode(input);
|
||||
while (i < input.length) {
|
||||
chr1 = input.charCodeAt(i++);
|
||||
chr2 = input.charCodeAt(i++);
|
||||
chr3 = input.charCodeAt(i++);
|
||||
enc1 = chr1 >> 2;
|
||||
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
||||
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
||||
enc4 = chr3 & 63;
|
||||
if (isNaN(chr2)) {
|
||||
enc3 = enc4 = 64;
|
||||
} else if (isNaN(chr3)) {
|
||||
enc4 = 64;
|
||||
}
|
||||
output = output +
|
||||
this._keyAll.charAt(enc1) + this._keyAll.charAt(enc2) +
|
||||
this._keyAll.charAt(enc3) + this._keyAll.charAt(enc4);
|
||||
}
|
||||
return this._keyStr.charAt(Math.floor((Math.random() * this._keyStr.length))) + output;
|
||||
};
|
||||
module es{
|
||||
export class Base64Utils {
|
||||
private static _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
/**
|
||||
* 解码
|
||||
* @param input
|
||||
* @param isNotStr
|
||||
*/
|
||||
public static decode(input, isNotStr: boolean = true) {
|
||||
let output = "";
|
||||
let chr1, chr2, chr3;
|
||||
let enc1, enc2, enc3, enc4;
|
||||
let i = 0;
|
||||
input = this.getConfKey(input);
|
||||
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
||||
while (i < input.length) {
|
||||
enc1 = this._keyAll.indexOf(input.charAt(i++));
|
||||
enc2 = this._keyAll.indexOf(input.charAt(i++));
|
||||
enc3 = this._keyAll.indexOf(input.charAt(i++));
|
||||
enc4 = this._keyAll.indexOf(input.charAt(i++));
|
||||
chr1 = (enc1 << 2) | (enc2 >> 4);
|
||||
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
||||
chr3 = ((enc3 & 3) << 6) | enc4;
|
||||
output = output + String.fromCharCode(chr1);
|
||||
if (enc3 != 64) {
|
||||
if (chr2 == 0) {
|
||||
if (isNotStr) output = output + String.fromCharCode(chr2);
|
||||
} else {
|
||||
output = output + String.fromCharCode(chr2);
|
||||
}
|
||||
}
|
||||
|
||||
if (enc4 != 64) {
|
||||
if (chr3 == 0) {
|
||||
if (isNotStr) output = output + String.fromCharCode(chr3);
|
||||
} else {
|
||||
output = output + String.fromCharCode(chr3);
|
||||
/**
|
||||
* 判断是否原生支持Base64位解析
|
||||
*/
|
||||
static get nativeBase64() {
|
||||
return (typeof (window.atob) === "function");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 解码
|
||||
* @param input
|
||||
*/
|
||||
static decode(input:string): string {
|
||||
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
||||
|
||||
if (this.nativeBase64) {
|
||||
return window.atob(input);
|
||||
} else {
|
||||
var output: any = [], chr1: number, chr2: number, chr3: number, enc1: number, enc2: number, enc3: number, enc4: number, i: number = 0;
|
||||
|
||||
while (i < input.length) {
|
||||
enc1 = this._keyStr.indexOf(input.charAt(i++));
|
||||
enc2 = this._keyStr.indexOf(input.charAt(i++));
|
||||
enc3 = this._keyStr.indexOf(input.charAt(i++));
|
||||
enc4 = this._keyStr.indexOf(input.charAt(i++));
|
||||
|
||||
chr1 = (enc1 << 2) | (enc2 >> 4);
|
||||
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
||||
chr3 = ((enc3 & 3) << 6) | enc4;
|
||||
|
||||
output.push(String.fromCharCode(chr1));
|
||||
|
||||
if (enc3 !== 64) {
|
||||
output.push(String.fromCharCode(chr2));
|
||||
}
|
||||
if (enc4 !== 64) {
|
||||
output.push(String.fromCharCode(chr3));
|
||||
}
|
||||
}
|
||||
|
||||
output = output.join("");
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 编码
|
||||
* @param input
|
||||
*/
|
||||
static encode(input:string): string {
|
||||
input = input.replace(/\r\n/g, "\n");
|
||||
if (this.nativeBase64) {
|
||||
window.btoa(input);
|
||||
} else {
|
||||
var output: any = [], chr1: number, chr2: number, chr3: number, enc1: number, enc2: number, enc3: number, enc4: number, i: number = 0;
|
||||
while (i < input.length) {
|
||||
chr1 = input.charCodeAt(i++);
|
||||
chr2 = input.charCodeAt(i++);
|
||||
chr3 = input.charCodeAt(i++);
|
||||
|
||||
enc1 = chr1 >> 2;
|
||||
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
||||
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
||||
enc4 = chr3 & 63;
|
||||
|
||||
if (isNaN(chr2)) {
|
||||
enc3 = enc4 = 64;
|
||||
} else if (isNaN(chr3)) {
|
||||
enc4 = 64;
|
||||
}
|
||||
|
||||
output.push(this._keyStr.charAt(enc1));
|
||||
output.push(this._keyStr.charAt(enc2));
|
||||
output.push(this._keyStr.charAt(enc3));
|
||||
output.push(this._keyStr.charAt(enc4));
|
||||
}
|
||||
|
||||
output = output.join("");
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 解析Base64格式数据
|
||||
* @param input
|
||||
* @param bytes
|
||||
*/
|
||||
static decodeBase64AsArray(input: string, bytes: number): Uint32Array {
|
||||
bytes = bytes || 1;
|
||||
|
||||
var dec = Base64Utils.decode(input), i, j, len;
|
||||
var ar: Uint32Array = new Uint32Array(dec.length / bytes);
|
||||
|
||||
for (i = 0, len = dec.length / bytes; i < len; i++) {
|
||||
ar[i] = 0;
|
||||
for (j = bytes - 1; j >= 0; --j) {
|
||||
ar[i] += dec.charCodeAt((i * bytes) + j) << (j << 3);
|
||||
}
|
||||
}
|
||||
return ar;
|
||||
}
|
||||
output = this._utf8_decode(output);
|
||||
return output;
|
||||
}
|
||||
|
||||
private static _utf8_encode(string) {
|
||||
string = string.replace(/\r\n/g, "\n");
|
||||
let utftext = "";
|
||||
for (let n = 0; n < string.length; n++) {
|
||||
let c = string.charCodeAt(n);
|
||||
if (c < 128) {
|
||||
utftext += String.fromCharCode(c);
|
||||
} else if ((c > 127) && (c < 2048)) {
|
||||
utftext += String.fromCharCode((c >> 6) | 192);
|
||||
utftext += String.fromCharCode((c & 63) | 128);
|
||||
} else {
|
||||
utftext += String.fromCharCode((c >> 12) | 224);
|
||||
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
||||
utftext += String.fromCharCode((c & 63) | 128);
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂时不支持
|
||||
* @param data
|
||||
* @param decoded
|
||||
* @param compression
|
||||
* @private
|
||||
*/
|
||||
static decompress(data: string, decoded: any, compression: string): any {
|
||||
throw new Error("GZIP/ZLIB compressed TMX Tile Map not supported!");
|
||||
}
|
||||
return utftext;
|
||||
}
|
||||
|
||||
private static _utf8_decode(utftext) {
|
||||
let string = "";
|
||||
let i = 0;
|
||||
let c = 0;
|
||||
let c1 = 0;
|
||||
let c2 = 0;
|
||||
let c3 = 0;
|
||||
while (i < utftext.length) {
|
||||
c = utftext.charCodeAt(i);
|
||||
if (c < 128) {
|
||||
string += String.fromCharCode(c);
|
||||
i++;
|
||||
} else if ((c > 191) && (c < 224)) {
|
||||
c2 = utftext.charCodeAt(i + 1);
|
||||
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
|
||||
i += 2;
|
||||
} else {
|
||||
c2 = utftext.charCodeAt(i + 1);
|
||||
c3 = utftext.charCodeAt(i + 2);
|
||||
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
|
||||
i += 3;
|
||||
/**
|
||||
* 解析csv数据
|
||||
* @param input
|
||||
*/
|
||||
static decodeCSV(input: string): Array<number> {
|
||||
var entries: Array<any> = input.replace("\n", "").trim().split(",");
|
||||
|
||||
var result:Array<number> = [];
|
||||
for (var i:number = 0; i < entries.length; i++) {
|
||||
result.push(+entries[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
private static getConfKey(key): string {
|
||||
return key.slice(1, key.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,29 @@ module es {
|
||||
this.drawLineAngle(shape, start, MathHelper.angleBetweenVectors(start, end), Vector2.distance(start, end), color, thickness);
|
||||
}
|
||||
|
||||
public static drawCircle(shape: egret.Shape, position: Vector2, radius: number, color: number){
|
||||
shape.graphics.beginFill(color);
|
||||
shape.graphics.drawCircle(position.x, position.y, radius);
|
||||
shape.graphics.endFill();
|
||||
}
|
||||
|
||||
public static drawPoints(shape: egret.Shape, position: Vector2, points: Vector2[], color: number,
|
||||
closePoly: boolean = true, thickness: number = 1){
|
||||
if (points.length < 2)
|
||||
return;
|
||||
|
||||
for (let i = 1; i < points.length; i ++)
|
||||
this.drawLine(shape, Vector2.add(position, points[i - 1]), Vector2.add(position, points[i]), color, thickness);
|
||||
|
||||
if (closePoly)
|
||||
this.drawLine(shape, Vector2.add(position, points[points.length - 1]), Vector2.add(position, points[0]), color, thickness);
|
||||
}
|
||||
|
||||
public static drawString(textField: egret.TextField, text: string, position: Vector2, color: number, rotation: number,
|
||||
origin: Vector2, scale: number){
|
||||
|
||||
}
|
||||
|
||||
public static drawLineAngle(shape: egret.Shape, start: Vector2, radians: number, length: number, color: number, thickness = 1) {
|
||||
shape.graphics.beginFill(color);
|
||||
shape.graphics.drawRect(start.x, start.y, 1, 1);
|
||||
|
||||
Reference in New Issue
Block a user