tiled 基本数据
This commit is contained in:
131
source/src/ECS/Components/TiledMapMover.ts
Normal file
131
source/src/ECS/Components/TiledMapMover.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,5 +76,18 @@ module es {
|
||||
public static angleBetweenVectors(from: Vector2, to: Vector2) {
|
||||
return Math.atan2(to.y - from.y, to.x - from.x);
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加t并确保它总是大于或等于0并且小于长度
|
||||
* @param t
|
||||
* @param length
|
||||
*/
|
||||
public static incrementWithWrap(t: number, length: number){
|
||||
t ++;
|
||||
if (t == length)
|
||||
return 0;
|
||||
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
16
source/src/Tiled/Group.ts
Normal file
16
source/src/Tiled/Group.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
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: TmxList<any>;
|
||||
public tileLayers: TmxList<TmxLayer>;
|
||||
public objectGroups: TmxList<TmxObjectGroup>;
|
||||
public imageLayers: TmxList<TmxImageLayer>;
|
||||
public groups: TmxList<TmxGroup>;
|
||||
}
|
||||
}
|
||||
9
source/src/Tiled/ITmxLayer.ts
Normal file
9
source/src/Tiled/ITmxLayer.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
module es {
|
||||
export interface ITmxLayer {
|
||||
offsetX: number;
|
||||
offsetY: number;
|
||||
opacity: number;
|
||||
visible: boolean;
|
||||
properties: Map<string, string>;
|
||||
}
|
||||
}
|
||||
15
source/src/Tiled/ImageLayer.ts
Normal file
15
source/src/Tiled/ImageLayer.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
100
source/src/Tiled/Layer.ts
Normal file
100
source/src/Tiled/Layer.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
export class TmxLayerTile {
|
||||
public static readonly FLIPPED_HORIZONTALLY_FLAG = 0x80000000;
|
||||
public static readonly FLIPPED_VERTICALLY_FLAG = 0x40000000;
|
||||
public static readonly FLIPPED_DIAGONALLY_FLAG = 0x20000000;
|
||||
|
||||
public tileset: TmxTileset;
|
||||
public gid: number;
|
||||
public x: number;
|
||||
public y: number;
|
||||
public get position(): Vector2{
|
||||
return new Vector2(this.x, this.y);
|
||||
}
|
||||
public horizontalFlip: boolean;
|
||||
public verticalFlip: boolean;
|
||||
public diagonalFlip: boolean;
|
||||
public _tilesetTileIndex?: number;
|
||||
|
||||
/**
|
||||
* 获取此TmxLayerTile(如果存在)的TmxTilesetTile
|
||||
* TmxTilesetTile只存在于动态的tiles和带有附加属性的tiles中。
|
||||
*/
|
||||
public get tilesetTile(): TmxTilesetTile {
|
||||
if (this._tilesetTileIndex == undefined){
|
||||
this._tilesetTileIndex = -1;
|
||||
if (this.tileset.firstGid <= this.gid){
|
||||
let tilesetTile = this.tileset.tiles.get(this.gid - this.tileset.firstGid);
|
||||
if (tilesetTile){
|
||||
this._tilesetTileIndex = this.gid - this.tileset.firstGid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this._tilesetTileIndex < 0)
|
||||
return null;
|
||||
|
||||
return this.tileset.tiles.get(this._tilesetTileIndex);
|
||||
}
|
||||
|
||||
constructor(map: TmxMap, id: number, x: number, y: number){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
let rawGid = id;
|
||||
|
||||
// 扫描平铺反转位标志
|
||||
let flip: boolean;
|
||||
flip = (rawGid & TmxLayerTile.FLIPPED_HORIZONTALLY_FLAG) != 0;
|
||||
this.horizontalFlip = flip;
|
||||
|
||||
flip = (rawGid & TmxLayerTile.FLIPPED_VERTICALLY_FLAG) != 0;
|
||||
this.verticalFlip = flip;
|
||||
|
||||
flip = (rawGid & TmxLayerTile.FLIPPED_DIAGONALLY_FLAG) != 0;
|
||||
this.diagonalFlip = flip;
|
||||
|
||||
// 零位标志
|
||||
rawGid &= ~(TmxLayerTile.FLIPPED_HORIZONTALLY_FLAG | TmxLayerTile.FLIPPED_VERTICALLY_FLAG | TmxLayerTile.FLIPPED_DIAGONALLY_FLAG);
|
||||
|
||||
// 将GID保存
|
||||
this.gid = rawGid;
|
||||
this.tileset = map.getTilesetForTileGid(this.gid);
|
||||
}
|
||||
}
|
||||
}
|
||||
114
source/src/Tiled/Map.ts
Normal file
114
source/src/Tiled/Map.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
///<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: TmxList<any>;
|
||||
public tilesets: TmxList<TmxTileset>;
|
||||
public tileLayers: TmxList<TmxLayer>;
|
||||
public objectGroups: TmxList<TmxObjectGroup>;
|
||||
public imageLayers: TmxList<TmxImageLayer>;
|
||||
public groups: TmxList<TmxGroup>;
|
||||
public properties: Map<string, string>;
|
||||
|
||||
/**
|
||||
* 当我们有一个图像tileset,tile可以是任何大小,所以我们记录的最大大小来剔除
|
||||
*/
|
||||
public maxTileWidth: number;
|
||||
|
||||
/**
|
||||
* 当我们有一个图像tileset,tile可以是任何大小,所以我们记录的最大大小来剔除
|
||||
*/
|
||||
public maxTileHeight: number;
|
||||
|
||||
/**
|
||||
* 此地图是否具有需要非默认平铺大小的特殊剔除
|
||||
*/
|
||||
public get requiresLargeTileCulling(): boolean {
|
||||
return this.maxTileHeight > this.tileHeight || this.maxTileWidth > this.tileWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取给定tileId的tile tileset
|
||||
* @param gid
|
||||
*/
|
||||
public getTilesetForTileGid(gid: number): TmxTileset {
|
||||
if (gid == 0)
|
||||
return null;
|
||||
|
||||
for (let i = this.tilesets.size - 1; i >= 0; i --){
|
||||
if (this.tilesets.get(i.toString()).firstGid <= gid)
|
||||
return this.tilesets.get(i.toString());
|
||||
}
|
||||
|
||||
console.error(`tile gid${gid}未在任何tileset中找到`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新他们的动画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
|
||||
}
|
||||
}
|
||||
77
source/src/Tiled/ObjectGroup.ts
Normal file
77
source/src/Tiled/ObjectGroup.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
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: TmxList<TmxObject>;
|
||||
public properties: Map<string, string>;
|
||||
}
|
||||
|
||||
export class TmxObject implements ITmxElement {
|
||||
public id: number;
|
||||
public name: string;
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
58
source/src/Tiled/TiledCore.ts
Normal file
58
source/src/Tiled/TiledCore.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
module es {
|
||||
export class TmxDocument {
|
||||
public TmxDirectory: string;
|
||||
constructor(){
|
||||
this.TmxDirectory = "";
|
||||
}
|
||||
}
|
||||
|
||||
export interface ITmxElement {
|
||||
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 TmxImage {
|
||||
public texture: egret.Texture;
|
||||
public source: string;
|
||||
public format: string;
|
||||
public data: any;
|
||||
public trans: number;
|
||||
public width: number;
|
||||
public height: number;
|
||||
|
||||
public dispose(){
|
||||
if (this.texture){
|
||||
this.texture.dispose();
|
||||
this.texture = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
39
source/src/Tiled/Tileset.ts
Normal file
39
source/src/Tiled/Tileset.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
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: TmxList<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>;
|
||||
}
|
||||
}
|
||||
79
source/src/Tiled/TilesetTile.ts
Normal file
79
source/src/Tiled/TilesetTile.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
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: TmxList<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;
|
||||
}
|
||||
}
|
||||
32
source/src/Utils/EdgeExt.ts
Normal file
32
source/src/Utils/EdgeExt.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
module es {
|
||||
export class EdgeExt {
|
||||
public static oppositeEdge(self: Edge) {
|
||||
switch (self) {
|
||||
case Edge.bottom:
|
||||
return Edge.top;
|
||||
case Edge.top:
|
||||
return Edge.bottom;
|
||||
case Edge.left:
|
||||
return Edge.right;
|
||||
case Edge.right:
|
||||
return Edge.left;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果边是右或左,则返回true
|
||||
* @param self
|
||||
*/
|
||||
public static isHorizontal(self: Edge): boolean{
|
||||
return self == Edge.right || self == Edge.left;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果边是顶部或底部,则返回true
|
||||
* @param self
|
||||
*/
|
||||
public static isVertical(self: Edge): boolean {
|
||||
return self == Edge.top || self == Edge.bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
8
source/src/Utils/Enum.ts
Normal file
8
source/src/Utils/Enum.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
module es {
|
||||
export enum Edge {
|
||||
top,
|
||||
bottom,
|
||||
left,
|
||||
right
|
||||
}
|
||||
}
|
||||
16
source/src/Utils/Enumerable.ts
Normal file
16
source/src/Utils/Enumerable.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
module es {
|
||||
export class Enumerable {
|
||||
/**
|
||||
* 生成包含一个重复值的序列
|
||||
* @param element 要重复的值
|
||||
* @param count 在生成的序列中重复该值的次数
|
||||
*/
|
||||
public static repeat<T>(element: T, count: number){
|
||||
let result = [];
|
||||
while (count--) {
|
||||
result.push(element)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,23 @@
|
||||
module es {
|
||||
export class RectangleExt {
|
||||
/**
|
||||
* 获取指定边的位置
|
||||
* @param rect
|
||||
* @param edge
|
||||
*/
|
||||
public static getSide(rect: Rectangle, edge: Edge) {
|
||||
switch (edge) {
|
||||
case Edge.top:
|
||||
return rect.top;
|
||||
case Edge.bottom:
|
||||
return rect.bottom;
|
||||
case es.Edge.left:
|
||||
return rect.left;
|
||||
case Edge.right:
|
||||
return rect.right;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算两个矩形的并集。结果将是一个包含其他两个的矩形。
|
||||
* @param first
|
||||
@@ -15,5 +33,65 @@ module es {
|
||||
result.height = Math.max(first.bottom, result.bottom) - result.y;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static getHalfRect(rect: Rectangle, edge: Edge) {
|
||||
switch (edge) {
|
||||
case Edge.top:
|
||||
return new Rectangle(rect.x, rect.y, rect.width, rect.height / 2);
|
||||
case Edge.bottom:
|
||||
return new Rectangle(rect.x, rect.y + rect.height / 2, rect.width, rect.height / 2);
|
||||
case Edge.left:
|
||||
return new Rectangle(rect.x, rect.y, rect.width / 2, rect.height);
|
||||
case Edge.right:
|
||||
return new Rectangle(rect.x + rect.width / 2, rect.y, rect.width / 2, rect.height);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取矩形的一部分,其宽度/高度的大小位于矩形的边缘,但仍然包含在其中。
|
||||
* @param rect
|
||||
* @param edge
|
||||
* @param size
|
||||
*/
|
||||
public static getRectEdgePortion(rect: Rectangle, edge: Edge, size: number = 1) {
|
||||
switch (edge) {
|
||||
case es.Edge.top:
|
||||
return new Rectangle(rect.x, rect.y, rect.width, size);
|
||||
case Edge.bottom:
|
||||
return new Rectangle(rect.x, rect.y + rect.height - size, rect.width, size);
|
||||
case Edge.left:
|
||||
return new Rectangle(rect.x, rect.y, size, rect.height);
|
||||
case Edge.right:
|
||||
return new Rectangle(rect.x + rect.width - size, rect.y, size, rect.height);
|
||||
}
|
||||
}
|
||||
|
||||
public static expandSide(rect: Rectangle, edge: Edge, amount: number) {
|
||||
amount = Math.abs(amount);
|
||||
|
||||
switch (edge) {
|
||||
case Edge.top:
|
||||
rect.y -= amount;
|
||||
rect.height += amount;
|
||||
break;
|
||||
case es.Edge.bottom:
|
||||
rect.height += amount;
|
||||
break;
|
||||
case Edge.left:
|
||||
rect.x -= amount;
|
||||
rect.width += amount;
|
||||
break;
|
||||
case Edge.right:
|
||||
rect.width += amount;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static contract(rect: Rectangle, horizontalAmount, verticalAmount) {
|
||||
rect.x += horizontalAmount;
|
||||
rect.y += verticalAmount;
|
||||
rect.width -= horizontalAmount * 2;
|
||||
rect.height -= verticalAmount * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
27
source/src/Utils/SubpixelNumber.ts
Normal file
27
source/src/Utils/SubpixelNumber.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
module es {
|
||||
/**
|
||||
* 管理数值的简单助手类。它存储值,直到累计的总数大于1。一旦超过1,该值将在调用update时添加到amount中。
|
||||
*/
|
||||
export class SubpixelNumber {
|
||||
public remainder: number;
|
||||
|
||||
/**
|
||||
* 以amount递增余数,将值截断为int,存储新的余数并将amount设置为当前值。
|
||||
* @param amount
|
||||
*/
|
||||
public update(amount: number){
|
||||
this.remainder += amount;
|
||||
let motion = Math.trunc(this.remainder);
|
||||
this.remainder -= motion;
|
||||
return motion;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将余数重置为0。当一个物体与一个不可移动的物体碰撞时有用。
|
||||
* 在这种情况下,您将希望将亚像素余数归零,因为它是空的和无效的碰撞。
|
||||
*/
|
||||
public reset(){
|
||||
this.remainder = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user