优化transform结构

新增实体列表排序
This commit is contained in:
yhh
2020-07-24 15:29:07 +08:00
parent d4c244daf5
commit 6be43fc9ac
11 changed files with 1595 additions and 378 deletions

View File

@@ -99,7 +99,7 @@ module es {
protected initialize(){
}
protected update() {
protected async update() {
this.startDebugUpdate();
// 更新我们所有的系统管理器
@@ -127,7 +127,7 @@ module es {
this._nextScene = null;
this.onSceneChanged();
this._scene.begin();
await this._scene.begin();
}
}

View File

@@ -107,6 +107,14 @@ module es {
this.transform.setPosition(value.x, value.y);
}
public get localPosition(): Vector2 {
return this.transform.localPosition;
}
public set localPosition(value: Vector2){
this.transform.setLocalPosition(value);
}
public get rotation(): number {
return this.transform.rotation;
}
@@ -115,6 +123,29 @@ module es {
this.transform.setRotation(value);
}
public get rotationDegrees(): number {
return this.transform.rotationDegrees;
}
public set rotationDegrees(value: number){
this.transform.setRotationDegrees(value);
}
public get localRotation(): number {
return this.transform.localRotation;
}
public set localRotation(value: number){
this.transform.setLocalRotation(value);
}
public get localRotationDegrees(): number {
return this.transform.localRotationDegrees;
}
public set localRotationDegrees(value: number){
this.transform.setLocalRotationDegrees(value);
}
public get scale(): Vector2 {
return this.transform.scale;
@@ -124,6 +155,26 @@ module es {
this.transform.setScale(value);
}
public get localScale(): Vector2 {
return this.transform.localScale;
}
public set localScale(value: Vector2){
this.transform.setLocalScale(value);
}
public get worldInverseTransform(): Matrix2D {
return this.transform.worldInverseTransform;
}
public get localToWorldTransform(): Matrix2D {
return this.transform.localToWorldTransform;
}
public get worldToLocalTransform(): Matrix2D {
return this.transform.worldToLocalTransform;
}
constructor(name: string) {
this.components = new ComponentList(this);
this.transform = new Transform(this);
@@ -180,8 +231,8 @@ module es {
if (this._updateOrder != updateOrder) {
this._updateOrder = updateOrder;
if (this.scene) {
// TODO: markEntityListSorted
// markTagUnsorted
this.scene.entities.markEntityListUnsorted();
this.scene.entities.markTagUnsorted(this.tag);
}
return this;
@@ -370,6 +421,13 @@ module es {
}
}
public compareTo(other: Entity): number {
let compare = this._updateOrder - other._updateOrder;
if (compare == 0)
compare = this.id - other.id;
return compare;
}
public toString(): string {
return `[Entity: name: ${this.name}, tag: ${this.tag}, enabled: ${this.enabled}, depth: ${this.updateOrder}]`;
}

View File

@@ -42,18 +42,204 @@ module es {
/**
* 变换在世界空间中的位置
*/
public position: Vector2;
public get position(): Vector2 {
this.updateTransform();
if (this._positionDirty){
if (!this.parent){
this._position = this._localPosition;
}else{
this.parent.updateTransform();
this._position = Vector2Ext.transformR(this._localPosition, this.parent._worldTransform);
}
this._positionDirty = false;
}
return this._position;
}
/**
* 变换在世界空间中的位置
* @param value
*/
public set position(value: Vector2){
this.setPosition(value.x, value.y);
}
/**
* 转换相对于父转换的位置。如果转换没有父元素则与transform.position相同
*/
public get localPosition(): Vector2 {
this.updateTransform();
return this._localPosition;
}
/**
* 转换相对于父转换的位置。如果转换没有父元素则与transform.position相同
* @param value
*/
public set localPosition(value: Vector2){
this.setLocalPosition(value);
}
/**
* 在世界空间中以弧度旋转的变换
*/
public get rotation(): number {
this.updateTransform();
return this._rotation;
}
/**
* 变换在世界空间的旋转度
*/
public rotation: number;
public get rotationDegrees(): number {
return MathHelper.toDegrees(this._rotation);
}
/**
* 变换在世界空间的旋转度
* @param value
*/
public set rotationDegrees(value: number){
this.setRotation(MathHelper.toRadians(value));
}
/**
* 变换在世界空间的旋转度
* @param value
*/
public set rotation(value: number){
this.setRotation(value);
}
/**
* 相对于父变换的旋转变换的旋转。如果转换没有父元素则与transform.rotation相同
*/
public get localRotation(): number {
this.updateTransform();
return this._localRotation;
}
/**
* 相对于父变换的旋转变换的旋转。如果转换没有父元素则与transform.rotation相同
* @param value
*/
public set localRotation(value: number){
this.setLocalRotation(value);
}
/**
* 旋转相对于父变换旋转的角度
*/
public get localRotationDegrees(): number {
return MathHelper.toDegrees(this._localRotation);
}
/**
* 旋转相对于父变换旋转的角度
* @param value
*/
public set localRotationDegrees(value: number){
this.localRotation = MathHelper.toRadians(value);
}
/**
* 变换在世界空间的缩放
*/
public scale: Vector2;
public get scale(): Vector2{
this.updateTransform();
return this._scale;
}
/**
* 变换在世界空间的缩放
* @param value
*/
public set scale(value: Vector2){
this.setScale(value);
}
/**
* 转换相对于父元素的比例。如果转换没有父元素则与transform.scale相同
*/
public get localScale(): Vector2 {
this.updateTransform();
return this._localScale;
}
/**
* 转换相对于父元素的比例。如果转换没有父元素则与transform.scale相同
* @param value
*/
public set localScale(value: Vector2){
this.setLocalScale(value);
}
public get worldInverseTransform(): Matrix2D {
this.updateTransform();
if (this._worldInverseDirty){
this._worldInverseTransform = this._worldTransform.invert();
this._worldInverseDirty = false;
}
return this._worldInverseTransform;
}
public get localToWorldTransform(): Matrix2D {
this.updateTransform();
return this._worldTransform;
}
public get worldToLocalTransform(): Matrix2D {
if (this._worldToLocalDirty){
if (!this.parent){
this._worldToLocalTransform = Matrix2D.create().identity();
}else{
this.parent.updateTransform();
this._worldToLocalTransform = this.parent._worldTransform.invert();
}
this._worldToLocalDirty = false;
}
return this._worldToLocalTransform;
}
public _parent: Transform;
public hierarchyDirty: DirtyType;
public _localDirty: boolean;
public _localPositionDirty: boolean;
public _localScaleDirty: boolean;
public _localRotationDirty: boolean;
public _positionDirty: boolean;
public _worldToLocalDirty: boolean;
public _worldInverseDirty: boolean;
/**
* 值会根据位置、旋转和比例自动重新计算
*/
public _localTransform: Matrix2D;
/**
* 值将自动从本地和父矩阵重新计算。
*/
public _worldTransform = Matrix2D.create().identity();
public _worldToLocalTransform = Matrix2D.create().identity();
public _worldInverseTransform = Matrix2D.create().identity();
public _rotationMatrix: Matrix2D;
public _translationMatrix: Matrix2D;
public _scaleMatrix: Matrix2D;
public _position: Vector2;
public _scale: Vector2;
public _rotation: number;
public _localPosition: Vector2;
public _localScale: Vector2;
public _localRotation: number;
public _children: Transform[];
constructor(entity: Entity) {
@@ -95,8 +281,49 @@ module es {
* @param y
*/
public setPosition(x: number, y: number): Transform {
this.position = new Vector2(x, y);
let position = new Vector2(x, y);
if (position == this._position)
return this;
this._position = position;
if (this.parent){
this.localPosition = Vector2Ext.transformR(this._position, this._worldToLocalTransform);
} else {
this.localPosition = position;
}
this._positionDirty = false;
return this;
}
/**
* 设置转换相对于父转换的位置。如果转换没有父元素则与transform.position相同
* @param localPosition
*/
public setLocalPosition(localPosition: Vector2): Transform {
if (localPosition == this._localPosition)
return this;
this._localPosition = localPosition;
this._localDirty = this._positionDirty = this._localPositionDirty = this._localRotationDirty = this._localScaleDirty = true;
this.setDirty(DirtyType.positionDirty);
return this;
}
/**
* 设置变换在世界空间的旋转度
* @param radians
*/
public setRotation(radians: number): Transform {
this._rotation = radians;
if (this.parent){
this.localRotation = this.parent.rotation + radians;
} else {
this.localRotation = radians;
}
return this;
}
@@ -104,20 +331,8 @@ module es {
* 设置变换在世界空间的旋转度
* @param degrees
*/
public setRotation(degrees: number): Transform {
this.rotation = degrees;
this.setDirty(DirtyType.rotationDirty);
return this;
}
/**
* 设置变换在世界空间中的缩放
* @param scale
*/
public setScale(scale: Vector2): Transform {
this.scale = scale;
this.setDirty(DirtyType.scaleDirty);
return this;
public setRotationDegrees(degrees: number): Transform {
return this.setRotation(MathHelper.toRadians(degrees));
}
/**
@@ -130,11 +345,105 @@ module es {
this.rotation = sign * Math.acos(Vector2.dot(vectorToAlignTo, Vector2.unitY));
}
/**
* 相对于父变换的旋转设置变换的旋转。如果转换没有父元素则与transform.rotation相同
* @param radians
*/
public setLocalRotation(radians: number){
this._localRotation = radians;
this._localDirty = this._positionDirty = this._localPositionDirty = this._localRotationDirty = this._localScaleDirty = true;
this.setDirty(DirtyType.rotationDirty);
return this;
}
/**
* 相对于父变换的旋转设置变换的旋转。如果转换没有父元素则与transform.rotation相同
* @param degrees
*/
public setLocalRotationDegrees(degrees: number): Transform {
return this.setLocalRotation(MathHelper.toRadians(degrees));
}
/**
* 设置变换在世界空间中的缩放
* @param scale
*/
public setScale(scale: Vector2): Transform {
this._scale = scale;
if (this.parent){
this.localScale = Vector2.divide(scale, this.parent._scale);
}else{
this.localScale = scale;
}
return this;
}
/**
* 设置转换相对于父对象的比例。如果转换没有父元素则与transform.scale相同
* @param scale
*/
public setLocalScale(scale: Vector2): Transform {
this._localScale = scale;
this._localDirty = this._positionDirty = this._localScaleDirty = true;
this.setDirty(DirtyType.scaleDirty);
return this;
}
/**
* 对精灵坐标进行四舍五入
*/
public roundPosition() {
this.position = this.position.round();
this.position = this._position.round();
}
public updateTransform(){
if (this.hierarchyDirty != DirtyType.clean){
if (this.parent)
this.parent.updateTransform();
if (this._localDirty){
if (this._localPositionDirty){
this._translationMatrix = Matrix2D.create().translate(this._localPosition.x, this._localPosition.y);
this._localPositionDirty = false;
}
if (this._localRotationDirty){
this._rotationMatrix = Matrix2D.create().rotate(this._localRotation);
this._localRotationDirty = false;
}
if (this._localScaleDirty){
this._scaleMatrix = Matrix2D.create().scale(this._localScale.x, this._localScale.y);
this._localScaleDirty = false;
}
this._localTransform = this._scaleMatrix.multiply(this._rotationMatrix);
this._localTransform = this._localTransform.multiply(this._translationMatrix);
if (!this.parent){
this._worldTransform = this._localTransform;
this._rotation = this._localRotation;
this._scale = this._localScale;
this._worldInverseDirty = true;
}
this._localDirty = false;
}
if (this.parent){
this._worldTransform = this._localTransform.multiply(this.parent._worldTransform);
this._rotation = this._localRotation + this.parent._rotation;
this._scale = Vector2.multiply(this.parent._scale, this._localScale);
this._worldInverseDirty = true;
}
this._worldToLocalDirty = true;
this._positionDirty = true;
this.hierarchyDirty = DirtyType.clean;
}
}
public setDirty(dirtyFlagType: DirtyType){
@@ -167,13 +476,22 @@ module es {
* @param transform
*/
public copyFrom(transform: Transform) {
this.position = transform.position;
this.rotation = transform.rotation;
this.scale = transform.scale;
this._position = transform.position;
this._localPosition = transform._localPosition;
this._rotation = transform._rotation;
this._localRotation = transform._localRotation;
this._scale = transform._scale;
this._localScale = transform._localScale;
this.setDirty(DirtyType.positionDirty);
this.setDirty(DirtyType.rotationDirty);
this.setDirty(DirtyType.scaleDirty);
}
public toString(): string{
return `[Transform: parent: ${this.parent}, position: ${this.position}, rotation: ${this.rotation},
scale: ${this.scale}, localPosition: ${this._localPosition}, localRotation: ${this._localRotation},
localScale: ${this._localScale}]`;
}
}
}

View File

@@ -1,12 +1,31 @@
module es {
export class EntityList{
public scene: Scene;
private _entitiesToRemove: Entity[] = [];
private _entitiesToAdded: Entity[] = [];
private _tempEntityList: Entity[] = [];
private _entities: Entity[] = [];
private _entityDict: Map<number, Entity[]> = new Map<number, Entity[]>();
private _unsortedTags: number[] = [];
/**
* 添加到场景中的实体列表
*/
public _entities: Entity[] = [];
/**
* 添加到此框架的实体列表。用于对实体进行分组,以便我们可以同时处理它们
*/
public _entitiesToAdded: Entity[] = [];
/**
* 标记要删除此框架的实体列表。用于对实体进行分组,以便我们可以同时处理它们
*/
public _entitiesToRemove: Entity[] = [];
/**
* 用于确定是否需要在此框架中对实体进行排序的标志
*/
public _isEntityListUnsorted: boolean;
/**
* 通过标签跟踪实体,便于检索
*/
public _entityDict: Map<number, Entity[]> = new Map<number, Entity[]>();
public _unsortedTags: number[] = [];
/**
* 在updateLists中用于双缓冲区以便可以在其他地方修改原始列表
*/
public _tempEntityList: Entity[] = [];
constructor(scene: Scene){
this.scene = scene;
@@ -20,12 +39,34 @@ module es {
return this._entities;
}
public markEntityListUnsorted(){
this._isEntityListUnsorted = true;
}
public markTagUnsorted(tag: number){
this._unsortedTags.push(tag);
}
/**
* 将实体添加到列表中。所有生命周期方法将在下一帧中被调用。
* @param entity
*/
public add(entity: Entity){
if (this._entitiesToAdded.indexOf(entity) == -1)
this._entitiesToAdded.push(entity);
}
/**
* 从列表中删除一个实体。所有生命周期方法将在下一帧中被调用。
* @param entity
*/
public remove(entity: Entity){
if (!this._entitiesToRemove.contains(entity)){
console.warn(`You are trying to remove an entity (${entity.name}) that you already removed`);
return;
}
// 防止在同一帧中添加或删除实体
if (this._entitiesToAdded.contains(entity)){
this._entitiesToAdded.remove(entity);
return;
@@ -35,6 +76,126 @@ module es {
this._entitiesToRemove.push(entity);
}
/**
* 从实体列表中删除所有实体
*/
public removeAllEntities(){
this._unsortedTags.length = 0;
this._entitiesToAdded.length = 0;
this._isEntityListUnsorted = false;
// 为什么我们要在这里更新列表?主要用于处理场景切换前分离的实体。
// 它们仍然在_entitiesToRemove列表中该列表将由更新列表处理。
this.updateLists();
for (let i = 0; i < this._entities.length; i ++){
this._entities[i]._isDestroyed = true;
this._entities[i].onRemovedFromScene();
this._entities[i].scene = null;
}
this._entities.length = 0;
this._entityDict.clear();
}
/**
* 检查该实体当前是否由此EntityList管理
* @param entity
*/
public contains(entity: Entity): boolean {
return this._entities.contains(entity) || this._entitiesToAdded.contains(entity);
}
public getTagList(tag: number){
let list = this._entityDict.get(tag);
if (!list){
list = [];
this._entityDict.set(tag, list);
}
return this._entityDict.get(tag);
}
public addToTagList(entity: Entity){
let list = this.getTagList(entity.tag);
if (!list.contains(entity)){
list.push(entity);
this._unsortedTags.push(entity.tag);
}
}
public removeFromTagList(entity: Entity){
let list = this._entityDict.get(entity.tag);
if (list){
list.remove(entity);
}
}
public update(){
for (let i = 0; i < this._entities.length; i++){
let entity = this._entities[i];
if (entity.enabled && (entity.updateInterval == 1 || Time.frameCount % entity.updateInterval == 0))
entity.update();
}
}
public updateLists(){
if (this._entitiesToRemove.length > 0){
let temp = this._entitiesToRemove;
this._entitiesToRemove = this._tempEntityList;
this._tempEntityList = temp;
this._tempEntityList.forEach(entity => {
this.removeFromTagList(entity);
this._entities.remove(entity);
entity.onRemovedFromScene();
entity.scene = null;
this.scene.entityProcessors.onEntityRemoved(entity);
});
this._tempEntityList.length = 0;
}
if (this._entitiesToAdded.length > 0){
let temp = this._entitiesToAdded;
this._entitiesToAdded = this._tempEntityList;
this._tempEntityList = temp;
this._tempEntityList.forEach(entity => {
if (!this._entities.contains(entity)){
this._entities.push(entity);
entity.scene = this.scene;
this.addToTagList(entity);
this.scene.entityProcessors.onEntityAdded(entity)
}
});
// 现在所有实体都被添加到场景中我们再次循环并调用onAddedToScene
this._tempEntityList.forEach(entity => entity.onAddedToScene());
this._tempEntityList.length = 0;
this._isEntityListUnsorted = true;
}
if (this._isEntityListUnsorted){
this._entities.sort();
this._isEntityListUnsorted = false;
}
if (this._unsortedTags.length > 0){
this._unsortedTags.forEach(tag => {
this._entityDict.get(tag).sort();
});
this._unsortedTags.length = 0;
}
}
/**
* 返回找到的第一个实体的名称。如果没有找到则返回null。
* @param name
*/
public findEntity(name: string){
for (let i = 0; i < this._entities.length; i ++){
if (this._entities[i].name == name)
@@ -120,94 +281,5 @@ module es {
return comps;
}
public getTagList(tag: number){
let list = this._entityDict.get(tag);
if (!list){
list = [];
this._entityDict.set(tag, list);
}
return this._entityDict.get(tag);
}
public addToTagList(entity: Entity){
let list = this.getTagList(entity.tag);
if (!list.contains(entity)){
list.push(entity);
this._unsortedTags.push(entity.tag);
}
}
public removeFromTagList(entity: Entity){
let list = this._entityDict.get(entity.tag);
if (list){
list.remove(entity);
}
}
public update(){
for (let i = 0; i < this._entities.length; i++){
let entity = this._entities[i];
if (entity.enabled)
entity.update();
}
}
public removeAllEntities(){
this._entitiesToAdded.length = 0;
this.updateLists();
for (let i = 0; i < this._entities.length; i ++){
this._entities[i]._isDestroyed = true;
this._entities[i].onRemovedFromScene();
this._entities[i].scene = null;
}
this._entities.length = 0;
this._entityDict.clear();
}
public updateLists(){
if (this._entitiesToRemove.length > 0){
let temp = this._entitiesToRemove;
this._entitiesToRemove = this._tempEntityList;
this._tempEntityList = temp;
this._tempEntityList.forEach(entity => {
this._entities.remove(entity);
entity.scene = null;
this.scene.entityProcessors.onEntityRemoved(entity);
});
this._tempEntityList.length = 0;
}
if (this._entitiesToAdded.length > 0){
let temp = this._entitiesToAdded;
this._entitiesToAdded = this._tempEntityList;
this._tempEntityList = temp;
this._tempEntityList.forEach(entity => {
if (!this._entities.contains(entity)){
this._entities.push(entity);
entity.scene = this.scene;
this.scene.entityProcessors.onEntityAdded(entity)
}
});
this._tempEntityList.forEach(entity => entity.onAddedToScene());
this._tempEntityList.length = 0;
}
if (this._unsortedTags.length > 0){
this._unsortedTags.forEach(tag => {
this._entityDict.get(tag).sort();
});
this._unsortedTags.length = 0;
}
}
}
}