整理ecs框架

This commit is contained in:
yhh
2020-07-22 20:07:14 +08:00
parent 6b8569b0b5
commit 5b8f414a45
31 changed files with 1908 additions and 1239 deletions

View File

@@ -1,96 +1,137 @@
abstract class Component extends egret.DisplayObjectContainer {
public entity: Entity;
private _enabled: boolean = true;
public updateInterval: number = 1;
/** 允许用户为实体存入信息 */
public userData: any;
private _updateOrder = 0;
public get enabled(){
return this.entity ? this.entity.enabled && this._enabled : this._enabled;
}
public set enabled(value: boolean){
this.setEnabled(value);
}
public get localPosition(){
return new Vector2(this.entity.x + this.x, this.entity.y + this.y);
}
public setEnabled(isEnabled: boolean){
if (this._enabled != isEnabled){
this._enabled = isEnabled;
if (this._enabled){
this.onEnabled();
}else{
this.onDisabled();
}
}
return this;
}
/** 更新此实体上组件的顺序 */
public get updateOrder(){
return this._updateOrder;
}
/** 更新此实体上组件的顺序 */
public set updateOrder(value: number){
this.setUpdateOrder(value);
}
public setUpdateOrder(updateOrder: number){
if (this._updateOrder != updateOrder){
this._updateOrder = updateOrder;
}
return this;
}
public initialize(){
}
public onAddedToEntity(){
}
public onRemovedFromEntity(){
}
public onEnabled(){
}
public onDisabled(){
}
public debugRender(){
}
public update(){
}
module es {
/**
* 当实体的位置改变时调用。这允许组件知道它们由于父实体的移动而移动了。
* @param comp
* 执行顺序
* - onAddedToEntity
* - OnEnabled
*
* 删除执行顺序
* - onRemovedFromEntity
*/
public onEntityTransformChanged(comp: TransformComponent){
export abstract class Component {
/**
* 此组件附加的实体
*/
public entity: Entity;
}
/**
* 快速访问 this.entity.transform
*/
public get transform(): Transform {
return this.entity.transform;
}
/** 内部使用 运行时不应该调用 */
public registerComponent(){
this.entity.componentBits.set(ComponentTypeManager.getIndexFor(this), false);
this.entity.scene.entityProcessors.onComponentAdded(this.entity);
}
/**
* 如果组件和实体都已启用则为。当启用该组件时将调用该组件的生命周期方法。状态的改变会导致调用onEnabled/onDisable。
*/
public get enabled() {
return this.entity ? this.entity.enabled && this._enabled : this._enabled;
}
public deregisterComponent(){
this.entity.componentBits.set(ComponentTypeManager.getIndexFor(this));
this.entity.scene.entityProcessors.onComponentRemoved(this.entity);
/**
* 如果组件和实体都已启用则为。当启用该组件时将调用该组件的生命周期方法。状态的改变会导致调用onEnabled/onDisable。
* @param value
*/
public set enabled(value: boolean) {
this.setEnabled(value);
}
/** 更新此实体上组件的顺序 */
public get updateOrder() {
return this._updateOrder;
}
/** 更新此实体上组件的顺序 */
public set updateOrder(value: number) {
this.setUpdateOrder(value);
}
/**
* 更新该组件的时间间隔。这与实体的更新间隔无关。
*/
public updateInterval: number = 1;
private _enabled: boolean = true;
private _updateOrder = 0;
/**
* 当此组件已分配其实体,但尚未添加到实体的活动组件列表时调用。有用的东西,如物理组件,需要访问转换来修改碰撞体的属性。
*/
public initialize() {
}
/**
* 在提交所有挂起的组件更改后,将该组件添加到场景时调用。此时,设置了实体字段和实体。场景也设定好了。
*/
public onAddedToEntity() {
}
/**
* 当此组件从其实体中移除时调用。在这里做所有的清理工作。
*/
public onRemovedFromEntity() {
}
/**
* 当实体的位置改变时调用。这允许组件知道它们由于父实体的移动而移动了。
* @param comp
*/
public onEntityTransformChanged(comp: Transform.Component) {
}
/**
*
*/
public debugRender() {
}
/**
*当父实体或此组件启用时调用
*/
public onEnabled() {
}
/**
* 禁用父实体或此组件时调用
*/
public onDisabled() {
}
/**
* 当该组件启用时每帧进行调用
*/
public update() {
}
public setEnabled(isEnabled: boolean) {
if (this._enabled != isEnabled) {
this._enabled = isEnabled;
if (this._enabled) {
this.onEnabled();
} else {
this.onDisabled();
}
}
return this;
}
public setUpdateOrder(updateOrder: number) {
if (this._updateOrder != updateOrder) {
this._updateOrder = updateOrder;
}
return this;
}
/**
* 创建此组件的克隆
*/
public clone(): Component {
let component = ObjectUtils.clone<Component>(this);
component.entity = null;
return component;
}
}
}
}

View File

@@ -1,234 +1,236 @@
class Camera extends Component {
private _zoom;
private _origin: Vector2 = Vector2.zero;
module es {
export class Camera extends Component {
private _zoom;
private _origin: Vector2 = Vector2.zero;
private _minimumZoom = 0.3;
private _maximumZoom = 3;
private _minimumZoom = 0.3;
private _maximumZoom = 3;
private _position: Vector2 = Vector2.zero;
/**
* 如果相机模式为cameraWindow 则会进行缓动移动
* 该值为移动速度
*/
public followLerp = 0.1;
public deadzone: Rectangle = new Rectangle();
/** 锁定偏移量 默认中心 */
public focusOffset: Vector2 = new Vector2();
/** 是否地图锁定 如果锁定则需要设置mapSize属性 */
public mapLockEnabled: boolean = false;
/** 设置地图大小 默认从0 0左上角开始 只需要输入地图宽高 */
public mapSize: Vector2 = new Vector2();
/** 跟随的实体 设置后镜头将锁定目标为中心 */
public targetEntity: Entity;
private _worldSpaceDeadZone: Rectangle = new Rectangle();
private _desiredPositionDelta: Vector2 = new Vector2();
private _targetCollider: Collider;
/** 相机模式 */
public cameraStyle: CameraStyle = CameraStyle.lockOn;
private _position: Vector2 = Vector2.zero;
/**
* 如果相机模式为cameraWindow 则会进行缓动移动
* 该值为移动速度
*/
public followLerp = 0.1;
public deadzone: Rectangle = new Rectangle();
/** 锁定偏移量 默认中心 */
public focusOffset: Vector2 = new Vector2();
/** 是否地图锁定 如果锁定则需要设置mapSize属性 */
public mapLockEnabled: boolean = false;
/** 设置地图大小 默认从0 0左上角开始 只需要输入地图宽高 */
public mapSize: Vector2 = new Vector2();
/** 跟随的实体 设置后镜头将锁定目标为中心 */
public targetEntity: Entity;
private _worldSpaceDeadZone: Rectangle = new Rectangle();
private _desiredPositionDelta: Vector2 = new Vector2();
private _targetCollider: Collider;
/** 相机模式 */
public cameraStyle: CameraStyle = CameraStyle.lockOn;
public get zoom(){
if (this._zoom == 0)
return 1;
public get zoom(){
if (this._zoom == 0)
return 1;
if (this._zoom < 1)
return MathHelper.map(this._zoom, this._minimumZoom, 1, -1, 0);
if (this._zoom < 1)
return MathHelper.map(this._zoom, this._minimumZoom, 1, -1, 0);
return MathHelper.map(this._zoom, 1, this._maximumZoom, 0, 1);
}
public set zoom(value: number){
this.setZoom(value);
}
public get minimumZoom(){
return this._minimumZoom;
}
public set minimumZoom(value: number){
this.setMinimumZoom(value);
}
public get maximumZoom(){
return this._maximumZoom;
}
public set maximumZoom(value: number){
this.setMaximumZoom(value);
}
public get origin(){
return this._origin;
}
public set origin(value: Vector2){
if (this._origin != value){
this._origin = value;
}
}
public get position(){
return this._position;
}
public set position(value: Vector2){
this._position = value;
}
public get x(){
return this._position.x;
}
public set x(value: number){
this._position.x = value;
}
public get y(){
return this._position.y;
}
public set y(value: number){
this._position.y = value;
}
constructor() {
super();
this.width = SceneManager.stage.stageWidth;
this.height = SceneManager.stage.stageHeight;
this.setZoom(0);
}
public onSceneSizeChanged(newWidth: number, newHeight: number){
let oldOrigin = this._origin;
this.origin = new Vector2(newWidth / 2, newHeight / 2);
this.entity.position = Vector2.add(this.entity.position, Vector2.subtract(this._origin, oldOrigin));
}
public setMinimumZoom(minZoom: number): Camera{
if (this._zoom < minZoom)
this._zoom = this.minimumZoom;
this._minimumZoom = minZoom;
return this;
}
public setMaximumZoom(maxZoom: number): Camera {
if (this._zoom > maxZoom)
this._zoom = maxZoom;
this._maximumZoom = maxZoom;
return this;
}
public setZoom(zoom: number): Camera{
let newZoom = MathHelper.clamp(zoom, -1, 1);
if (newZoom == 0){
this._zoom = 1;
} else if(newZoom < 0){
this._zoom = MathHelper.map(newZoom, -1, 0, this._minimumZoom, 1);
} else {
this._zoom = MathHelper.map(newZoom, 0, 1, 1, this._maximumZoom);
return MathHelper.map(this._zoom, 1, this._maximumZoom, 0, 1);
}
SceneManager.scene.scaleX = this._zoom;
SceneManager.scene.scaleY = this._zoom;
return this;
}
public setRotation(rotation: number): Camera {
SceneManager.scene.rotation = rotation;
return this;
}
public setPosition(position: Vector2){
this.entity.position = position;
return this;
}
public follow(targetEntity: Entity, cameraStyle: CameraStyle = CameraStyle.cameraWindow){
this.targetEntity = targetEntity;
this.cameraStyle = cameraStyle;
let cameraBounds = new Rectangle(0, 0, SceneManager.stage.stageWidth, SceneManager.stage.stageHeight);
switch (this.cameraStyle){
case CameraStyle.cameraWindow:
let w = cameraBounds.width / 6;
let h = cameraBounds.height / 3;
this.deadzone = new Rectangle((cameraBounds.width - w) / 2, (cameraBounds.height - h) / 2, w, h);
break;
case CameraStyle.lockOn:
this.deadzone = new Rectangle(cameraBounds.width / 2, cameraBounds.height / 2, 10, 10);
break;
public set zoom(value: number){
this.setZoom(value);
}
}
public update(){
let cameraBounds = new Rectangle(0, 0, SceneManager.stage.stageWidth, SceneManager.stage.stageHeight);
let halfScreen = Vector2.multiply(new Vector2(cameraBounds.width, cameraBounds.height), new Vector2(0.5));
this._worldSpaceDeadZone.x = this.position.x - halfScreen.x * SceneManager.scene.scaleX + this.deadzone.x + this.focusOffset.x;
this._worldSpaceDeadZone.y = this.position.y - halfScreen.y * SceneManager.scene.scaleY + this.deadzone.y + this.focusOffset.y;
this._worldSpaceDeadZone.width = this.deadzone.width;
this._worldSpaceDeadZone.height = this.deadzone.height;
public get minimumZoom(){
return this._minimumZoom;
}
if (this.targetEntity)
this.updateFollow();
public set minimumZoom(value: number){
this.setMinimumZoom(value);
}
this.position = Vector2.lerp(this.position, Vector2.add(this.position, this._desiredPositionDelta), this.followLerp);
this.entity.roundPosition();
public get maximumZoom(){
return this._maximumZoom;
}
if (this.mapLockEnabled){
this.position = this.clampToMapSize(this.position);
public set maximumZoom(value: number){
this.setMaximumZoom(value);
}
public get origin(){
return this._origin;
}
public set origin(value: Vector2){
if (this._origin != value){
this._origin = value;
}
}
public get position(){
return this._position;
}
public set position(value: Vector2){
this._position = value;
}
public get x(){
return this._position.x;
}
public set x(value: number){
this._position.x = value;
}
public get y(){
return this._position.y;
}
public set y(value: number){
this._position.y = value;
}
constructor() {
super();
this.width = SceneManager.stage.stageWidth;
this.height = SceneManager.stage.stageHeight;
this.setZoom(0);
}
public onSceneSizeChanged(newWidth: number, newHeight: number){
let oldOrigin = this._origin;
this.origin = new Vector2(newWidth / 2, newHeight / 2);
this.entity.position = Vector2.add(this.entity.position, Vector2.subtract(this._origin, oldOrigin));
}
public setMinimumZoom(minZoom: number): Camera{
if (this._zoom < minZoom)
this._zoom = this.minimumZoom;
this._minimumZoom = minZoom;
return this;
}
public setMaximumZoom(maxZoom: number): Camera {
if (this._zoom > maxZoom)
this._zoom = maxZoom;
this._maximumZoom = maxZoom;
return this;
}
public setZoom(zoom: number): Camera{
let newZoom = MathHelper.clamp(zoom, -1, 1);
if (newZoom == 0){
this._zoom = 1;
} else if(newZoom < 0){
this._zoom = MathHelper.map(newZoom, -1, 0, this._minimumZoom, 1);
} else {
this._zoom = MathHelper.map(newZoom, 0, 1, 1, this._maximumZoom);
}
SceneManager.scene.scaleX = this._zoom;
SceneManager.scene.scaleY = this._zoom;
return this;
}
public setRotation(rotation: number): Camera {
SceneManager.scene.rotation = rotation;
return this;
}
public setPosition(position: Vector2){
this.entity.position = position;
return this;
}
public follow(targetEntity: Entity, cameraStyle: CameraStyle = CameraStyle.cameraWindow){
this.targetEntity = targetEntity;
this.cameraStyle = cameraStyle;
let cameraBounds = new Rectangle(0, 0, SceneManager.stage.stageWidth, SceneManager.stage.stageHeight);
switch (this.cameraStyle){
case CameraStyle.cameraWindow:
let w = cameraBounds.width / 6;
let h = cameraBounds.height / 3;
this.deadzone = new Rectangle((cameraBounds.width - w) / 2, (cameraBounds.height - h) / 2, w, h);
break;
case CameraStyle.lockOn:
this.deadzone = new Rectangle(cameraBounds.width / 2, cameraBounds.height / 2, 10, 10);
break;
}
}
public update(){
let cameraBounds = new Rectangle(0, 0, SceneManager.stage.stageWidth, SceneManager.stage.stageHeight);
let halfScreen = Vector2.multiply(new Vector2(cameraBounds.width, cameraBounds.height), new Vector2(0.5));
this._worldSpaceDeadZone.x = this.position.x - halfScreen.x * SceneManager.scene.scaleX + this.deadzone.x + this.focusOffset.x;
this._worldSpaceDeadZone.y = this.position.y - halfScreen.y * SceneManager.scene.scaleY + this.deadzone.y + this.focusOffset.y;
this._worldSpaceDeadZone.width = this.deadzone.width;
this._worldSpaceDeadZone.height = this.deadzone.height;
if (this.targetEntity)
this.updateFollow();
this.position = Vector2.lerp(this.position, Vector2.add(this.position, this._desiredPositionDelta), this.followLerp);
this.entity.roundPosition();
if (this.mapLockEnabled){
this.position = this.clampToMapSize(this.position);
this.entity.roundPosition();
}
}
private clampToMapSize(position: Vector2){
let cameraBounds = new Rectangle(0, 0, SceneManager.stage.stageWidth, SceneManager.stage.stageHeight);
let halfScreen = Vector2.multiply(new Vector2(cameraBounds.width, cameraBounds.height), new Vector2(0.5));
let cameraMax = new Vector2(this.mapSize.x - halfScreen.x, this.mapSize.y - halfScreen.y);
return Vector2.clamp(position, halfScreen, cameraMax);
}
private updateFollow(){
this._desiredPositionDelta.x = this._desiredPositionDelta.y = 0;
if (this.cameraStyle == CameraStyle.lockOn){
let targetX = this.targetEntity.position.x;
let targetY = this.targetEntity.position.y;
if (this._worldSpaceDeadZone.x > targetX)
this._desiredPositionDelta.x = targetX - this._worldSpaceDeadZone.x;
else if(this._worldSpaceDeadZone.x < targetX)
this._desiredPositionDelta.x = targetX - this._worldSpaceDeadZone.x;
if (this._worldSpaceDeadZone.y < targetY)
this._desiredPositionDelta.y = targetY - this._worldSpaceDeadZone.y;
else if(this._worldSpaceDeadZone.y > targetY)
this._desiredPositionDelta.y = targetY - this._worldSpaceDeadZone.y;
} else {
if (!this._targetCollider){
this._targetCollider = this.targetEntity.getComponent<Collider>(Collider);
if (!this._targetCollider)
return;
}
let targetBounds = this.targetEntity.getComponent<Collider>(Collider).bounds;
if (!this._worldSpaceDeadZone.containsRect(targetBounds)){
if (this._worldSpaceDeadZone.left > targetBounds.left)
this._desiredPositionDelta.x = targetBounds.left - this._worldSpaceDeadZone.left;
else if(this._worldSpaceDeadZone.right < targetBounds.right)
this._desiredPositionDelta.x = targetBounds.right - this._worldSpaceDeadZone.right;
if (this._worldSpaceDeadZone.bottom < targetBounds.bottom)
this._desiredPositionDelta.y = targetBounds.bottom - this._worldSpaceDeadZone.bottom;
else if(this._worldSpaceDeadZone.top > targetBounds.top)
this._desiredPositionDelta.y = targetBounds.top - this._worldSpaceDeadZone.top;
}
}
}
}
private clampToMapSize(position: Vector2){
let cameraBounds = new Rectangle(0, 0, SceneManager.stage.stageWidth, SceneManager.stage.stageHeight);
let halfScreen = Vector2.multiply(new Vector2(cameraBounds.width, cameraBounds.height), new Vector2(0.5));
let cameraMax = new Vector2(this.mapSize.x - halfScreen.x, this.mapSize.y - halfScreen.y);
return Vector2.clamp(position, halfScreen, cameraMax);
}
private updateFollow(){
this._desiredPositionDelta.x = this._desiredPositionDelta.y = 0;
if (this.cameraStyle == CameraStyle.lockOn){
let targetX = this.targetEntity.position.x;
let targetY = this.targetEntity.position.y;
if (this._worldSpaceDeadZone.x > targetX)
this._desiredPositionDelta.x = targetX - this._worldSpaceDeadZone.x;
else if(this._worldSpaceDeadZone.x < targetX)
this._desiredPositionDelta.x = targetX - this._worldSpaceDeadZone.x;
if (this._worldSpaceDeadZone.y < targetY)
this._desiredPositionDelta.y = targetY - this._worldSpaceDeadZone.y;
else if(this._worldSpaceDeadZone.y > targetY)
this._desiredPositionDelta.y = targetY - this._worldSpaceDeadZone.y;
} else {
if (!this._targetCollider){
this._targetCollider = this.targetEntity.getComponent<Collider>(Collider);
if (!this._targetCollider)
return;
}
let targetBounds = this.targetEntity.getComponent<Collider>(Collider).bounds;
if (!this._worldSpaceDeadZone.containsRect(targetBounds)){
if (this._worldSpaceDeadZone.left > targetBounds.left)
this._desiredPositionDelta.x = targetBounds.left - this._worldSpaceDeadZone.left;
else if(this._worldSpaceDeadZone.right < targetBounds.right)
this._desiredPositionDelta.x = targetBounds.right - this._worldSpaceDeadZone.right;
if (this._worldSpaceDeadZone.bottom < targetBounds.bottom)
this._desiredPositionDelta.y = targetBounds.bottom - this._worldSpaceDeadZone.bottom;
else if(this._worldSpaceDeadZone.top > targetBounds.top)
this._desiredPositionDelta.y = targetBounds.top - this._worldSpaceDeadZone.top;
}
}
export enum CameraStyle {
lockOn,
cameraWindow,
}
}
enum CameraStyle {
lockOn,
cameraWindow,
}

View File

@@ -1,6 +1,14 @@
abstract class Collider extends Component {
/** 对撞机的基本形状 */
public shape: Shape;
protected _localOffset: Vector2 = Vector2.zero;
public get localOffset(){
return this._localOffset;
}
public set localOffset(){
}
public _localOffsetLength: number;
/** 在处理冲突时physicsLayer可以用作过滤器。Flags类有帮助位掩码的方法。 */
public physicsLayer = 1 << 0;
/** 如果这个碰撞器是一个触发器,它将不会引起碰撞,但它仍然会触发事件 */
@@ -15,38 +23,32 @@ abstract class Collider extends Component {
/** 默认为所有层。 */
public collidesWithLayers = Physics.allLayers;
public _localOffsetLength: number;
/** 标记来跟踪我们的实体是否被添加到场景中 */
protected _isParentEntityAddedToScene;
protected _colliderRequiresAutoSizing;
protected _localOffset: Vector2 = new Vector2(0, 0);
/** 标记来记录我们是否注册了物理系统 */
protected _isColliderRegistered;
public get bounds(): Rectangle {
let shapeBounds = this.shape.bounds;
let colliderBuonds = new Rectangle(this.x + this.localOffset.x, this.y + this.localOffset.y, shapeBounds.width, shapeBounds.height);
let colliderBuonds = new Rectangle(this.entity.x, this.entity.y, shapeBounds.width, shapeBounds.height);
return colliderBuonds;
}
public get localOffset() {
return this._localOffset;
}
/**
* 将localOffset添加到实体。获取碰撞器的最终位置。这允许您向一个实体添加多个碰撞器并分别定位它们。
* 将localOffset添加到实体。获取碰撞器的最终位置。
* 这允许您向一个实体添加多个碰撞器并分别定位它们。
* @param offset
*/
public set localOffset(value: Vector2) {
this.setLocalOffset(value);
}
public setLocalOffset(offset: Vector2) {
if (this._localOffset != offset) {
public setLocalOffset(offset: Vector2): Collider{
if (this._localOffset != offset){
this.unregisterColliderWithPhysicsSystem();
this._localOffset = offset;
this._localOffsetLength = this._localOffset.length();
this.registerColliderWithPhysicsSystem();
}
return this;
}
/**
@@ -85,15 +87,15 @@ abstract class Collider extends Component {
*/
public collidesWith(collider: Collider, motion: Vector2) {
// 改变形状的位置,使它在移动后的位置,这样我们可以检查重叠
let oldPosition = this.shape.position;
this.shape.position = Vector2.add(this.shape.position, motion);
let oldPosition = this.entity.position;
this.entity.position = Vector2.add(this.entity.position, motion);
let result = this.shape.collidesWithShape(collider.shape);
if (result)
result.collider = collider;
// 将图形位置返回到检查前的位置
this.shape.position = oldPosition;
this.entity.position = oldPosition;
return result;
}
@@ -111,19 +113,17 @@ abstract class Collider extends Component {
// 这里我们需要大小*反尺度,因为当我们自动调整碰撞器的大小时,它需要没有缩放的渲染
let width = bounds.width / this.entity.scale.x;
let height = bounds.height / this.entity.scale.y;
// 圆碰撞器需要特别注意原点
if (this instanceof CircleCollider){
let circleCollider = this as CircleCollider;
circleCollider.radius = Math.max(width, height) * 0.5;
this.localOffset = bounds.location;
} else {
this.width = width;
this.height = height;
this.localOffset = bounds.location;
}
// 获取渲染的中心将其转移到本地坐标并使用它作为碰撞器的localOffset
this.localOffset = Vector2.subtract(bounds.center, this.entity.position);
} else {
console.warn("Collider has no shape and no RenderableComponent. Can't figure out how to size it.");
}
@@ -154,8 +154,8 @@ abstract class Collider extends Component {
public update(){
let renderable = this.entity.getComponent<RenderableComponent>(RenderableComponent);
if (renderable){
this.$setX(renderable.x + this.localOffset.x);
this.$setY(renderable.y + this.localOffset.y);
this.$setX(renderable.x);
this.$setY(renderable.y);
}
}
}

View File

@@ -16,8 +16,6 @@ class PolygonCollider extends Collider {
if (isPolygonClosed)
points.splice(points.length - 1, 1);
let center = Polygon.findPolygonCenter(points);
this.setLocalOffset(center);
Polygon.recenterPolygonVerts(points);
this.shape = new Polygon(points);
}

View File

@@ -1,17 +1,17 @@
class SpriteRenderer extends RenderableComponent{
class SpriteRenderer extends RenderableComponent {
private _sprite: Sprite;
protected bitmap: egret.Bitmap;
/** 应该由这个精灵显示的精灵 */
public get sprite(): Sprite{
public get sprite(): Sprite {
return this._sprite;
}
/** 应该由这个精灵显示的精灵 */
public set sprite(value: Sprite){
public set sprite(value: Sprite) {
this.setSprite(value);
}
public setSprite(sprite: Sprite): SpriteRenderer{
public setSprite(sprite: Sprite): SpriteRenderer {
this.removeChildren();
this._sprite = sprite;
if (this._sprite) {
@@ -24,7 +24,7 @@ class SpriteRenderer extends RenderableComponent{
return this;
}
public setColor(color: number): SpriteRenderer{
public setColor(color: number): SpriteRenderer {
let colorMatrix = [
1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
@@ -40,23 +40,27 @@ class SpriteRenderer extends RenderableComponent{
return this;
}
public isVisibleFromCamera(camera: Camera): boolean{
public isVisibleFromCamera(camera: Camera): boolean {
this.isVisible = new Rectangle(0, 0, this.stage.stageWidth, this.stage.stageHeight).intersects(this.bounds);
this.visible = this.isVisible;
return this.isVisible;
}
/** 渲染处理 在每个模块中处理各自的渲染逻辑 */
public render(camera: Camera){
this.x = -camera.position.x + camera.origin.x;
this.y = -camera.position.y + camera.origin.y;
public render(camera: Camera) {
if (this.x != -camera.position.x + camera.origin.x ||
this.y != -camera.position.y + camera.origin.y) {
this.x = -camera.position.x + camera.origin.x;
this.y = -camera.position.y + camera.origin.y;
this.entity.onEntityTransformChanged(TransformComponent.position);
}
}
public onRemovedFromEntity(){
public onRemovedFromEntity() {
if (this.parent)
this.parent.removeChild(this);
}
public reset(){
public reset() {
}
}

View File

@@ -1,237 +1,377 @@
class Entity extends egret.DisplayObjectContainer {
private static _idGenerator: number;
module es {
export class Entity {
public static _idGenerator: number;
public name: string;
public readonly id: number;
/** 当前实体所属的场景 */
public scene: Scene;
/** 当前附加到此实体的所有组件的列表 */
public readonly components: ComponentList;
private _updateOrder: number = 0;
private _enabled: boolean = true;
public _isDestoryed: boolean;
private _tag: number = 0;
/**
* 当前实体所属的场景
*/
public scene: Scene;
/**
* 实体名称。用于在场景范围内搜索实体
*/
public name: string;
/**
* 此实体的唯一标识
*/
public readonly id: number;
/**
* 封装实体的位置/旋转/缩放,并允许设置一个高层结构
*/
public readonly transform: Transform;
/**
* 当前附加到此实体的所有组件的列表
*/
public readonly components: ComponentList;
public componentBits: BitSet;
public get isDestoryed(){
return this._isDestoryed;
}
public get position(){
return new Vector2(this.x, this.y);
}
public set position(value: Vector2){
this.$setX(value.x);
this.$setY(value.y);
this.onEntityTransformChanged(TransformComponent.position);
}
public get scale(){
return new Vector2(this.scaleX, this.scaleY);
}
public set scale(value: Vector2){
this.$setScaleX(value.x);
this.$setScaleY(value.y);
this.onEntityTransformChanged(TransformComponent.scale);
}
public set rotation(value: number){
this.$setRotation(value);
this.onEntityTransformChanged(TransformComponent.rotation);
}
public get rotation(){
return this.$getRotation();
}
public get enabled(){
return this._enabled;
}
public set enabled(value: boolean){
this.setEnabled(value);
}
public setEnabled(isEnabled: boolean){
if (this._enabled != isEnabled){
this._enabled = isEnabled;
/**
* 你可以随意使用。稍后可以使用它来查询场景中具有特定标记的所有实体
*/
public get tag(): number {
return this._tag;
}
return this;
}
/**
* 你可以随意使用。稍后可以使用它来查询场景中具有特定标记的所有实体
* @param value
*/
public set tag(value: number) {
this.setTag(value);
}
public get tag(){
return this._tag;
}
/**
* 指定应该调用这个entity update方法的频率。1表示每一帧2表示每一帧以此类推
*/
public updateInterval: number = 1;
public set tag(value: number){
this.setTag(value);
}
/**
* 启用/禁用实体。当禁用碰撞器从物理系统和组件中移除时,方法将不会被调用
*/
public get enabled() {
return this._enabled;
}
public get stage(){
if (!this.scene)
return null;
return this.scene.stage;
}
/**
* 启用/禁用实体。当禁用碰撞器从物理系统和组件中移除时,方法将不会被调用
* @param value
*/
public set enabled(value: boolean) {
this.setEnabled(value);
}
constructor(name: string){
super();
this.name = name;
this.components = new ComponentList(this);
this.id = Entity._idGenerator ++;
/**
* 更新此实体的顺序。updateOrder还用于对scene.entities上的标签列表进行排序
*/
public get updateOrder() {
return this._updateOrder;
}
this.componentBits = new BitSet();
this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
}
/**
* 更新此实体的顺序。updateOrder还用于对scene.entities上的标签列表进行排序
* @param value
*/
public set updateOrder(value: number) {
this.setUpdateOrder(value);
}
private onAddToStage(){
this.onEntityTransformChanged(TransformComponent.position);
}
public _isDestroyed: boolean;
/**
* 如果调用了destroy那么在下一次处理实体之前这将一直为true
*/
public get isDestroyed() {
return this._isDestroyed;
}
public get updateOrder(){
return this._updateOrder;
}
public componentBits: BitSet;
public set updateOrder(value: number){
this.setUpdateOrder(value);
}
private _tag: number = 0;
private _enabled: boolean = true;
private _updateOrder: number = 0;
public roundPosition(){
this.position = Vector2Ext.round(this.position);
}
public get parent(): Transform {
return this.transform.parent;
}
public setUpdateOrder(updateOrder: number){
if (this._updateOrder != updateOrder){
this._updateOrder = updateOrder;
if (this.scene){
public set parent(value: Transform) {
this.transform.setParent(value);
}
public get childCount() {
return this.transform.childCount;
}
public get position(): Vector2 {
return this.transform.position;
}
public set position(value: Vector2) {
this.transform.setPosition(value.x, value.y);
}
public get rotation(): number {
return this.transform.rotation;
}
public set rotation(value: number) {
this.transform.setRotation(value);
}
public get scale(): Vector2 {
return this.transform.scale;
}
public set scale(value: Vector2) {
this.transform.setScale(value);
}
constructor(name: string) {
this.components = new ComponentList(this);
this.transform = new Transform(this);
this.name = name;
this.id = Entity._idGenerator++;
this.componentBits = new BitSet();
}
public onTransformChanged(comp: Transform.Component) {
// 通知我们的子项改变了位置
this.components.onEntityTransformChanged(comp);
}
/**
* 设置实体的标记
* @param tag
*/
public setTag(tag: number): Entity {
if (this._tag != tag) {
// 我们只有在已经有场景的情况下才会调用entityTagList。如果我们还没有场景我们会被添加到entityTagList
if (this.scene)
this.scene.entities.removeFromTagList(this);
this._tag = tag;
if (this.scene)
this.scene.entities.addToTagList(this);
}
return this;
}
}
public setTag(tag: number): Entity{
if (this._tag != tag){
if (this.scene){
this.scene.entities.removeFromTagList(this);
/**
* 设置实体的启用状态。当禁用碰撞器从物理系统和组件中移除时,方法将不会被调用
* @param isEnabled
*/
public setEnabled(isEnabled: boolean) {
if (this._enabled != isEnabled) {
this._enabled = isEnabled;
if (this._enabled)
this.components.onEntityEnabled();
else
this.components.onEntityDisabled();
}
this._tag = tag;
if (this.scene){
this.scene.entities.addToTagList(this);
return this;
}
/**
* 设置此实体的更新顺序。updateOrder还用于对scene.entities上的标签列表进行排序
* @param updateOrder
*/
public setUpdateOrder(updateOrder: number) {
if (this._updateOrder != updateOrder) {
this._updateOrder = updateOrder;
if (this.scene) {
// TODO: markEntityListSorted
// markTagUnsorted
}
return this;
}
}
return this;
}
/**
* 从场景中删除实体并销毁所有子元素
*/
public destroy() {
this._isDestroyed = true;
this.scene.entities.remove(this);
this.transform.parent = null;
public attachToScene(newScene: Scene){
this.scene = newScene;
newScene.entities.add(this);
this.components.registerAllComponents();
for (let i = 0; i < this.numChildren; i ++){
(this.getChildAt(i) as Component).entity.attachToScene(newScene);
}
}
public detachFromScene(){
this.scene.entities.remove(this);
this.components.deregisterAllComponents();
for (let i = 0; i < this.numChildren; i ++)
(this.getChildAt(i) as Component).entity.detachFromScene();
}
public addComponent<T extends Component>(component: T): T{
component.entity = this;
this.components.add(component);
this.addChild(component);
component.initialize();
return component;
}
public hasComponent<T extends Component>(type){
return this.components.getComponent<T>(type, false) != null;
}
public getOrCreateComponent<T extends Component>(type: T){
let comp = this.components.getComponent<T>(type, true);
if (!comp){
comp = this.addComponent<T>(type);
// 销毁所有子项
for (let i = this.transform.childCount - 1; i >= 0; i--) {
let child = this.transform.getChild(i);
child.entity.destroy();
}
}
return comp;
}
/**
* 将实体从场景中分离。下面的生命周期方法将被调用在组件上:OnRemovedFromEntity
*/
public detachFromScene() {
this.scene.entities.remove(this);
this.components.deregisterAllComponents();
public getComponent<T extends Component>(type): T{
return this.components.getComponent(type, false) as T;
}
public getComponents(typeName: string | any, componentList?){
return this.components.getComponents(typeName, componentList);
}
private onEntityTransformChanged(comp: TransformComponent){
this.components.onEntityTransformChanged(comp);
}
public removeComponentForType<T extends Component>(type){
let comp = this.getComponent<T>(type);
if (comp){
this.removeComponent(comp);
return true;
for (let i = 0; i < this.transform.childCount; i++)
this.transform.getChild(i).entity.detachFromScene();
}
return false;
}
/**
* 将一个先前分离的实体附加到一个新的场景
* @param newScene
*/
public attachToScene(newScene: Scene) {
this.scene = newScene;
newScene.entities.add(this);
this.components.registerAllComponents();
public removeComponent(component: Component){
this.components.remove(component);
}
public removeAllComponents(){
for (let i = 0; i < this.components.count; i ++){
this.removeComponent(this.components.buffer[i]);
for (let i = 0; i < this.transform.childCount; i++) {
this.transform.getChild(i).entity.attachToScene(newScene);
}
}
}
public update(){
this.components.update();
}
/**
* 创建此实体的深层克隆。子类可以重写此方法来复制任何自定义字段。
* 当重写时应该调用CopyFrom方法它将为您克隆所有组件、碰撞器和转换子组件。
* 注意克隆的实体不会被添加到任何场景中!你必须自己添加它们!
* @param position
*/
public clone(position: Vector2 = new Vector2()): Entity {
let entity = new Entity(this.name + "(clone)");
entity.copyFrom(this);
entity.transform.position = position;
public onAddedToScene(){
return entity;
}
}
/**
* 将实体的属性、组件和碰撞器复制到此实例
* @param entity
*/
protected copyFrom(entity: Entity) {
this.tag = entity.tag;
this.updateInterval = entity.updateInterval;
this.updateOrder = entity.updateOrder;
this.enabled = entity.enabled;
public onRemovedFromScene(){
if (this._isDestoryed)
this.components.removeAllComponents();
}
this.transform.scale = entity.transform.scale;
this.transform.rotation = entity.transform.rotation;
public destroy(){
this._isDestoryed = true;
this.removeEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
for (let i = 0; i < entity.components.count; i++)
this.addComponent(entity.components.buffer[i].clone());
for (let i = 0; i < entity.components._componentsToAdd.length; i++)
this.addComponent(entity.components._componentsToAdd[i].clone());
this.scene.entities.remove(this);
this.removeChildren();
for (let i = 0; i < entity.transform.childCount; i++) {
let child = entity.transform.getChild(i).entity;
let childClone = child.clone();
childClone.transform.copyFrom(child.transform);
childClone.transform.parent = this.transform;
}
}
if (this.parent)
this.parent.removeChild(this);
/**
* 在提交了所有挂起的实体更改后,将此实体添加到场景时调用
*/
public onAddedToScene() {
}
for (let i = this.numChildren - 1; i >= 0; i --){
let child = this.getChildAt(i);
(child as Component).entity.destroy();
/**
* 当此实体从场景中删除时调用
*/
public onRemovedFromScene() {
// 如果已经被销毁了,移走我们的组件。如果我们只是分离,我们需要保持我们的组件在实体上。
if (this._isDestroyed)
this.components.removeAllComponents();
}
/**
* 每帧进行调用进行更新组件
*/
public update() {
this.components.update();
}
/**
* 将组件添加到组件列表中。返回组件。
* @param component
*/
public addComponent<T extends Component>(component: T): T {
component.entity = this;
this.components.add(component);
component.initialize();
return component;
}
/**
* 获取类型T的第一个组件并返回它。如果没有找到组件则返回null。
* @param type
*/
public getComponent<T extends Component>(type): T {
return this.components.getComponent(type, false) as T;
}
/**
* 检查实体是否具有该组件
* @param type
*/
public hasComponent<T extends Component>(type) {
return this.components.getComponent<T>(type, false) != null;
}
/**
* 获取类型T的第一个组件并返回它。如果没有找到组件将创建组件。
* @param type
*/
public getOrCreateComponent<T extends Component>(type: T) {
let comp = this.components.getComponent<T>(type, true);
if (!comp) {
comp = this.addComponent<T>(type);
}
return comp;
}
/**
* 获取typeName类型的所有组件但不使用列表分配
* @param typeName
* @param componentList
*/
public getComponents(typeName: string | any, componentList?) {
return this.components.getComponents(typeName, componentList);
}
/**
* 从组件列表中删除组件
* @param component
*/
public removeComponent(component: Component) {
this.components.remove(component);
}
/**
* 从组件列表中删除类型为T的第一个组件
* @param type
*/
public removeComponentForType<T extends Component>(type) {
let comp = this.getComponent<T>(type);
if (comp) {
this.removeComponent(comp);
return true;
}
return false;
}
/**
* 从实体中删除所有组件
*/
public removeAllComponents() {
for (let i = 0; i < this.components.count; i++) {
this.removeComponent(this.components.buffer[i]);
}
}
public toString(): string {
return `[Entity: name: ${this.name}, tag: ${this.tag}, enabled: ${this.enabled}, depth: ${this.updateOrder}]`;
}
}
}
enum TransformComponent {
rotation,
scale,
position
}

View File

@@ -1,213 +1,360 @@
/** 场景 */
class Scene extends egret.DisplayObjectContainer {
public camera: Camera;
public readonly entities: EntityList;
public readonly renderableComponents: RenderableComponentList;
public readonly content: ContentManager;
public enablePostProcessing = true;
module es {
/** 场景 */
export class Scene extends egret.DisplayObjectContainer {
/**
* 默认场景摄像机
*/
public camera: Camera;
/**
* 场景特定内容管理器。使用它来加载仅由这个场景需要的任何资源。如果你有全局/多场景资源你可以使用SceneManager.content。
* contentManager来加载它们因为Nez不会卸载它们。
*/
public readonly content: ContentManager;
/**
* 全局切换后处理器
*/
public enablePostProcessing = true;
/**
* 这个场景中的实体列表
*/
public readonly entities: EntityList;
/**
* 管理当前在场景实体上的所有可呈现组件的列表
*/
public readonly renderableComponents: RenderableComponentList;
/**
* 管理所有实体处理器
*/
public readonly entityProcessors: EntityProcessorList;
private _renderers: Renderer[] = [];
private _postProcessors: PostProcessor[] = [];
private _didSceneBegin;
public _renderers: Renderer[] = [];
public readonly _postProcessors: PostProcessor[] = [];
public _didSceneBegin;
public readonly entityProcessors: EntityProcessorList;
constructor() {
super();
this.entityProcessors = new EntityProcessorList();
this.renderableComponents = new RenderableComponentList();
this.entities = new EntityList(this);
this.content = new ContentManager();
this.width = SceneManager.stage.stageWidth;
this.height = SceneManager.stage.stageHeight;
this.addEventListener(egret.Event.ACTIVATE, this.onActive, this);
this.addEventListener(egret.Event.DEACTIVATE, this.onDeactive, this);
}
public createEntity(name: string) {
let entity = new Entity(name);
entity.position = new Vector2(0, 0);
return this.addEntity(entity);
}
public addEntity(entity: Entity) {
this.entities.add(entity);
entity.scene = this;
this.addChild(entity);
for (let i = 0; i < entity.numChildren; i++)
this.addEntity((entity.getChildAt(i) as Component).entity);
return entity;
}
public destroyAllEntities() {
for (let i = 0; i < this.entities.count; i++) {
this.entities.buffer[i].destroy();
}
}
public findEntity(name: string): Entity {
return this.entities.findEntity(name);
}
/**
* 在场景中添加一个EntitySystem处理器
* @param processor 处理器
*/
public addEntityProcessor(processor: EntitySystem) {
processor.scene = this;
this.entityProcessors.add(processor);
return processor;
}
public removeEntityProcessor(processor: EntitySystem) {
this.entityProcessors.remove(processor);
}
public getEntityProcessor<T extends EntitySystem>(): T {
return this.entityProcessors.getProcessor<T>();
}
public addRenderer<T extends Renderer>(renderer: T) {
this._renderers.push(renderer);
this._renderers.sort();
renderer.onAddedToScene(this);
return renderer;
}
public getRenderer<T extends Renderer>(type): T {
for (let i = 0; i < this._renderers.length; i++) {
if (this._renderers[i] instanceof type)
return this._renderers[i] as T;
/**
* 辅助器创建一个场景与DefaultRenderer附加并准备使用
*/
public static createWithDefaultRenderer(){
let scene = new Scene();
scene.addRenderer(new DefaultRenderer())
return scene;
}
return null;
}
constructor() {
super();
this.entities = new EntityList(this);
this.renderableComponents = new RenderableComponentList();
this.content = new ContentManager();
public removeRenderer(renderer: Renderer) {
this._renderers.remove(renderer);
renderer.unload();
}
this.entityProcessors = new EntityProcessorList();
public begin() {
if (SceneManager.sceneTransition){
SceneManager.stage.addChildAt(this, SceneManager.stage.numChildren - 1);
}else{
SceneManager.stage.addChild(this);
}
if (this._renderers.length == 0) {
this.addRenderer(new DefaultRenderer());
console.warn("场景开始时没有渲染器 自动添加DefaultRenderer以保证能够正常渲染");
}
/** 初始化默认相机 */
this.camera = this.createEntity("camera").getOrCreateComponent(new Camera());
this.width = SceneManager.stage.stageWidth;
this.height = SceneManager.stage.stageHeight;
Physics.reset();
if (this.entityProcessors)
this.entityProcessors.begin();
this.camera.onSceneSizeChanged(this.stage.stageWidth, this.stage.stageHeight);
this._didSceneBegin = true;
this.onStart();
}
public end() {
this._didSceneBegin = false;
this.removeEventListener(egret.Event.DEACTIVATE, this.onDeactive, this);
this.removeEventListener(egret.Event.ACTIVATE, this.onActive, this);
for (let i = 0; i < this._renderers.length; i++) {
this._renderers[i].unload();
this.initialize();
}
for (let i = 0; i < this._postProcessors.length; i++) {
this._postProcessors[i].unload();
/**
* 在场景子类中重写这个并在这里进行加载。在场景设置好之后在调用begin之前从构造器中调用。
*/
public initialize(){}
/**
* 在场景子类中重写这个。当SceneManager将此场景设置为活动场景时将调用此操作。
*/
public async onStart() {}
/**
* 在场景子类中重写这个并在这里做任何必要的卸载。当SceneManager从活动槽中删除此场景时调用。
*/
public unload() { }
/**
* 在场景子类中重写这个,当该场景当获得焦点时调用
*/
public onActive() {}
/**
* 在场景子类中重写这个,当该场景当失去焦点时调用
*/
public onDeactive() {}
public async begin() {
// 如果是场景转换需要在最顶层
if (SceneManager.sceneTransition){
SceneManager.stage.addChildAt(this, SceneManager.stage.numChildren - 1);
}else{
SceneManager.stage.addChild(this);
}
if (this._renderers.length == 0) {
this.addRenderer(new DefaultRenderer());
console.warn("场景开始时没有渲染器 自动添加DefaultRenderer以保证能够正常渲染");
}
this.camera = this.createEntity("camera").getOrCreateComponent(new Camera());
Physics.reset();
if (this.entityProcessors)
this.entityProcessors.begin();
this.addEventListener(egret.Event.ACTIVATE, this.onActive, this);
this.addEventListener(egret.Event.DEACTIVATE, this.onDeactive, this);
this.camera.onSceneSizeChanged(this.stage.stageWidth, this.stage.stageHeight);
this._didSceneBegin = true;
this.onStart();
}
this.entities.removeAllEntities();
this.removeChildren();
public end() {
this._didSceneBegin = false;
Physics.clear();
this.removeEventListener(egret.Event.DEACTIVATE, this.onDeactive, this);
this.removeEventListener(egret.Event.ACTIVATE, this.onActive, this);
this.camera = null;
this.content.dispose();
for (let i = 0; i < this._renderers.length; i++) {
this._renderers[i].unload();
}
if (this.entityProcessors)
this.entityProcessors.end();
this.unload();
if (this.parent)
this.parent.removeChild(this);
}
protected async onStart() {
}
/** 场景激活 */
protected onActive() {
}
/** 场景失去焦点 */
protected onDeactive() {
}
protected unload() { }
public update() {
this.entities.updateLists();
if (this.entityProcessors)
this.entityProcessors.update()
this.entities.update();
if (this.entityProcessors)
this.entityProcessors.lateUpdate();
this.renderableComponents.updateList();
}
public postRender() {
let enabledCounter = 0;
if (this.enablePostProcessing) {
for (let i = 0; i < this._postProcessors.length; i++) {
if (this._postProcessors[i].enable) {
let isEven = MathHelper.isEven(enabledCounter);
enabledCounter ++;
this._postProcessors[i].unload();
}
this._postProcessors[i].process();
this.entities.removeAllEntities();
this.removeChildren();
this.camera = null;
this.content.dispose();
if (this.entityProcessors)
this.entityProcessors.end();
if (this.parent)
this.parent.removeChild(this);
this.unload();
}
public update() {
// 更新我们的列表,以防它们有任何变化
this.entities.updateLists();
// 更新我们的实体解析器
if (this.entityProcessors)
this.entityProcessors.update();
// 更新我们的实体组
this.entities.update();
if (this.entityProcessors)
this.entityProcessors.lateUpdate();
// 我们在实体之后更新我们的呈现。如果添加了任何新的渲染,请进行更新
this.renderableComponents.updateList();
}
public render() {
if (this._renderers.length == 0){
console.error("there are no renderers in the scene!");
return;
}
for (let i = 0; i < this._renderers.length; i++) {
this._renderers[i].render(this);
}
}
/**
* 现在的任何后处理器都要完成它的处理
* 只有在SceneTransition请求渲染时它才会有一个值。
*/
public postRender() {
if (this.enablePostProcessing) {
for (let i = 0; i < this._postProcessors.length; i++) {
if (this._postProcessors[i].enabled) {
this._postProcessors[i].process();
}
}
}
}
}
public render() {
for (let i = 0; i < this._renderers.length; i++) {
this._renderers[i].render(this);
}
}
/**
* 为场景添加一个渲染器
* @param renderer
*/
public addRenderer<T extends Renderer>(renderer: T) {
this._renderers.push(renderer);
this._renderers.sort();
public addPostProcessor<T extends PostProcessor>(postProcessor: T): T{
this._postProcessors.push(postProcessor);
this._postProcessors.sort();
postProcessor.onAddedToScene(this);
renderer.onAddedToScene(this);
if (this._didSceneBegin){
postProcessor.onSceneBackBufferSizeChanged(this.stage.stageWidth, this.stage.stageHeight);
return renderer;
}
return postProcessor;
/**
* 获取类型为T的第一个渲染器
* @param type
*/
public getRenderer<T extends Renderer>(type): T {
for (let i = 0; i < this._renderers.length; i++) {
if (this._renderers[i] instanceof type)
return this._renderers[i] as T;
}
return null;
}
/**
* 从场景中移除渲染器
* @param renderer
*/
public removeRenderer(renderer: Renderer) {
if (!this._renderers.contains(renderer))
return;
this._renderers.remove(renderer);
renderer.unload();
}
/**
* 添加一个后处理器到场景。设置场景字段并调用后处理器。onAddedToScene使后处理器可以使用场景ContentManager加载资源。
* @param postProcessor
*/
public addPostProcessor<T extends PostProcessor>(postProcessor: T): T{
this._postProcessors.push(postProcessor);
this._postProcessors.sort();
postProcessor.onAddedToScene(this);
if (this._didSceneBegin){
postProcessor.onSceneBackBufferSizeChanged(this.stage.stageWidth, this.stage.stageHeight);
}
return postProcessor;
}
/**
* 获取类型为T的第一个后处理器
* @param type
*/
public getPostProcessor<T extends PostProcessor>(type): T{
for (let i = 0; i < this._postProcessors.length; i ++){
if (this._postProcessors[i] instanceof type)
return this._postProcessors[i] as T;
}
return null;
}
/**
* 删除一个后处理程序。注意在删除时不会调用unload因此如果不再需要PostProcessor请确保调用unload来释放资源。
* @param postProcessor
*/
public removePostProcessor(postProcessor: PostProcessor){
if (!this._postProcessors.contains(postProcessor))
return;
this._postProcessors.remove(postProcessor);
postProcessor.unload();
}
/**
* 将实体添加到此场景,并返回它
* @param name
*/
public createEntity(name: string) {
let entity = new Entity(name);
return this.addEntity(entity);
}
/**
* 在场景的实体列表中添加一个实体
* @param entity
*/
public addEntity(entity: Entity) {
if (this.entities.buffer.contains(entity))
console.warn(`You are attempting to add the same entity to a scene twice: ${entity}`);
this.entities.add(entity);
entity.scene = this;
for (let i = 0; i < entity.transform.childCount; i++)
this.addEntity(entity.transform.getChild(i).entity);
return entity;
}
/**
* 从场景中删除所有实体
*/
public destroyAllEntities() {
for (let i = 0; i < this.entities.count; i++) {
this.entities.buffer[i].destroy();
}
}
/**
* 搜索并返回第一个具有名称的实体
* @param name
*/
public findEntity(name: string): Entity {
return this.entities.findEntity(name);
}
/**
* 返回具有给定标记的所有实体
* @param tag
*/
public findEntitiesWithTag(tag: number): Entity[]{
return this.entities.entitiesWithTag(tag);
}
/**
* 返回类型为T的所有实体
* @param type
*/
public entitiesOfType<T extends Entity>(type): T[]{
return this.entities.entitiesOfType<T>(type);
}
/**
* 返回第一个启用加载的类型为T的组件
* @param type
*/
public findComponentOfType<T extends Component>(type): T {
return this.entities.findComponentOfType<T>(type);
}
/**
* 返回类型为T的所有已启用已加载组件的列表
* @param type
*/
public findComponentsOfType<T extends Component>(type): T[] {
return this.entities.findComponentsOfType<T>(type);
}
/**
* 在场景中添加一个EntitySystem处理器
* @param processor 处理器
*/
public addEntityProcessor(processor: EntitySystem) {
processor.scene = this;
this.entityProcessors.add(processor);
return processor;
}
/**
* 从场景中删除EntitySystem处理器
* @param processor
*/
public removeEntityProcessor(processor: EntitySystem) {
this.entityProcessors.remove(processor);
}
/**
* 获取EntitySystem处理器
*/
public getEntityProcessor<T extends EntitySystem>(): T {
return this.entityProcessors.getProcessor<T>();
}
}
}

View File

@@ -12,6 +12,7 @@ class SceneManager {
public static content: ContentManager;
/** 简化对内部类的全局内容实例的访问 */
private static _instnace: SceneManager;
private static timerRuler: TimeRuler;
public static get Instance(){
return this._instnace;
}
@@ -25,6 +26,7 @@ class SceneManager {
SceneManager.stage = stage;
SceneManager.initialize(stage);
SceneManager.timerRuler = new TimeRuler();
}
public static get scene() {
@@ -50,6 +52,7 @@ class SceneManager {
}
public static update() {
SceneManager.startDebugUpdate();
Time.update(egret.getTimer());
if (SceneManager._scene) {
@@ -74,6 +77,7 @@ class SceneManager {
}
}
SceneManager.endDebugUpdate();
SceneManager.render();
}
@@ -128,4 +132,13 @@ class SceneManager {
SceneManager.emitter.emit(CoreEvents.SceneChanged);
Time.sceneChanged();
}
private static startDebugUpdate(){
TimeRuler.Instance.startFrame();
TimeRuler.Instance.beginMark("update", 0x00FF00);
}
private static endDebugUpdate(){
TimeRuler.Instance.endMark("update");
}
}

138
source/src/ECS/Transform.ts Normal file
View File

@@ -0,0 +1,138 @@
module es {
export class Transform {
/** 与此转换关联的实体 */
public readonly entity: Entity;
private _parent: Transform;
/**
* 获取此转换的父转换
*/
public get parent() {
return this._parent;
}
/**
* 设置此转换的父转换
* @param value
*/
public set parent(value: Transform) {
this.setParent(value);
}
/**
* 这个转换的所有子元素
*/
public get childCount() {
return this._children.length;
}
/**
* 变换在世界空间中的位置
*/
public position: Vector2;
/**
* 变换在世界空间的旋转度
*/
public rotation: number;
/**
* 变换在世界空间的缩放
*/
public scale: Vector2;
public _children: Transform[];
constructor(entity: Entity) {
this.entity = entity;
this.scale = Vector2.one;
this._children = [];
}
/**
* 返回在索引处的转换子元素
* @param index
*/
public getChild(index: number): Transform {
return this._children[index];
}
/**
* 设置此转换的父转换
* @param parent
*/
public setParent(parent: Transform): Transform {
if (this._parent == parent)
return this;
if (!this._parent) {
this._parent._children.remove(this);
this._parent._children.push(this);
}
this._parent = parent;
return this;
}
/**
* 设置转换在世界空间中的位置
* @param x
* @param y
*/
public setPosition(x: number, y: number): Transform {
this.position = new Vector2(x, y);
return this;
}
/**
* 设置变换在世界空间的旋转度
* @param degrees
*/
public setRotation(degrees: number): Transform {
this.rotation = degrees;
return this;
}
/**
* 设置变换在世界空间中的缩放
* @param scale
*/
public setScale(scale: Vector2): Transform {
this.scale = scale;
return this;
}
/**
* 旋转精灵的顶部,使其朝向位置
* @param pos
*/
public lookAt(pos: Vector2) {
let sign = this.position.x > pos.x ? -1 : 1;
let vectorToAlignTo = Vector2.normalize(Vector2.subtract(this.position, pos));
this.rotation = sign * Math.acos(Vector2.dot(vectorToAlignTo, Vector2.unitY));
}
/**
* 对精灵坐标进行四舍五入
*/
public roundPosition() {
this.position = this.position.round();
}
/**
* 从另一个transform属性进行拷贝
* @param transform
*/
public copyFrom(transform: Transform) {
this.position = transform.position;
this.rotation = transform.rotation;
this.scale = transform.scale;
}
}
}
module Transform {
export enum Component {
position,
scale,
rotation,
}
}

View File

@@ -1,224 +1,241 @@
class ComponentList {
private _entity: Entity;
/** 添加到实体的组件列表 */
private _components: Component[] = [];
/** 添加到此框架的组件列表。用来对组件进行分组,这样我们就可以同时进行加工 */
private _componentsToAdd: Component[] = [];
/** 标记要删除此框架的组件列表。用来对组件进行分组,这样我们就可以同时进行加工 */
private _componentsToRemove: Component[] = [];
private _tempBufferList: Component[] = [];
module es {
export class ComponentList {
public _entity: Entity;
constructor(entity: Entity) {
this._entity = entity;
}
/**
* 添加到实体的组件列表
*/
public _components: Component[] = [];
/**
* 添加到此框架的组件列表。用来对组件进行分组,这样我们就可以同时进行加工
*/
public _componentsToAdd: Component[] = [];
/**
* 标记要删除此框架的组件列表。用来对组件进行分组,这样我们就可以同时进行加工
*/
public _componentsToRemove: Component[] = [];
public _tempBufferList: Component[] = [];
public get count() {
return this._components.length;
}
public get buffer() {
return this._components;
}
public add(component: Component) {
this._componentsToAdd.push(component);
}
public remove(component: Component) {
if (this._componentsToRemove.contains(component))
console.warn(`You are trying to remove a Component (${component}) that you already removed`)
// 这可能不是一个活动的组件,所以我们必须注意它是否还没有被处理,它可能正在同一帧中被删除
if (this._componentsToAdd.contains(component)) {
this._componentsToAdd.remove(component);
return;
constructor(entity: Entity) {
this._entity = entity;
}
this._componentsToRemove.push(component);
}
/**
* 立即从组件列表中删除所有组件
*/
public removeAllComponents() {
for (let i = 0; i < this._components.length; i++) {
this.handleRemove(this._components[i]);
public get count() {
return this._components.length;
}
this._components.length = 0;
this._componentsToAdd.length = 0;
this._componentsToRemove.length = 0;
}
public get buffer() {
return this._components;
}
public deregisterAllComponents() {
for (let i = 0; i < this._components.length; i++) {
let component = this._components[i];
public add(component: Component) {
this._componentsToAdd.push(component);
}
public remove(component: Component) {
if (this._componentsToRemove.contains(component))
console.warn(`You are trying to remove a Component (${component}) that you already removed`)
// 这可能不是一个活动的组件,所以我们必须注意它是否还没有被处理,它可能正在同一帧中被删除
if (this._componentsToAdd.contains(component)) {
this._componentsToAdd.remove(component);
return;
}
this._componentsToRemove.push(component);
}
/**
* 立即从组件列表中删除所有组件
*/
public removeAllComponents() {
for (let i = 0; i < this._components.length; i++) {
this.handleRemove(this._components[i]);
}
this._components.length = 0;
this._componentsToAdd.length = 0;
this._componentsToRemove.length = 0;
}
public deregisterAllComponents() {
for (let i = 0; i < this._components.length; i++) {
let component = this._components[i];
// 处理渲染层列表
if (component instanceof RenderableComponent)
this._entity.scene.renderableComponents.remove(component);
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(component), false);
this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
}
}
public registerAllComponents() {
for (let i = 0; i < this._components.length; i++) {
let component = this._components[i];
if (component instanceof RenderableComponent)
this._entity.scene.renderableComponents.add(component);
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(component));
this._entity.scene.entityProcessors.onComponentAdded(this._entity);
}
}
/**
* 处理任何需要删除或添加的组件
*/
public updateLists() {
if (this._componentsToRemove.length > 0) {
for (let i = 0; i < this._componentsToRemove.length; i++) {
this.handleRemove(this._componentsToRemove[i]);
this._components.remove(this._componentsToRemove[i]);
}
this._componentsToRemove.length = 0;
}
if (this._componentsToAdd.length > 0) {
for (let i = 0, count = this._componentsToAdd.length; i < count; i++) {
let component = this._componentsToAdd[i];
if (component instanceof RenderableComponent)
this._entity.scene.renderableComponents.add(component);
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(component));
this._entity.scene.entityProcessors.onComponentAdded(this._entity);
this._components.push(component);
this._tempBufferList.push(component);
}
// 在调用onAddedToEntity之前清除以防添加更多组件
this._componentsToAdd.length = 0;
// 现在所有的组件都添加到了场景中我们再次循环并调用onAddedToEntity/onEnabled
for (let i = 0; i < this._tempBufferList.length; i++) {
let component = this._tempBufferList[i];
component.onAddedToEntity();
// enabled检查实体和组件
if (component.enabled) {
component.onEnabled();
}
}
this._tempBufferList.length = 0;
}
}
public handleRemove(component: Component) {
// 处理渲染层列表
if (component instanceof RenderableComponent)
this._entity.scene.renderableComponents.remove(component);
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(component), false);
this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
}
}
public registerAllComponents() {
for (let i = 0; i < this._components.length; i++) {
let component = this._components[i];
if (component instanceof RenderableComponent)
this._entity.scene.renderableComponents.add(component);
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(component));
this._entity.scene.entityProcessors.onComponentAdded(this._entity);
}
}
/**
* 处理任何需要删除或添加的组件
*/
public updateLists() {
if (this._componentsToRemove.length > 0) {
for (let i = 0; i < this._componentsToRemove.length; i++) {
this.handleRemove(this._componentsToRemove[i]);
this._components.remove(this._componentsToRemove[i]);
}
this._componentsToRemove.length = 0;
component.onRemovedFromEntity();
component.entity = null;
}
if (this._componentsToAdd.length > 0) {
for (let i = 0, count = this._componentsToAdd.length; i < count; i++) {
let component = this._componentsToAdd[i];
if (component instanceof RenderableComponent)
this._entity.scene.renderableComponents.add(component);
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(component));
this._entity.scene.entityProcessors.onComponentAdded(this._entity);
this._components.push(component);
this._tempBufferList.push(component);
}
// 在调用onAddedToEntity之前清除以防添加更多组件
this._componentsToAdd.length = 0;
// 现在所有的组件都添加到了场景中我们再次循环并调用onAddedToEntity/onEnabled
for (let i = 0; i < this._tempBufferList.length; i++) {
let component = this._tempBufferList[i];
component.onAddedToEntity();
// enabled检查实体和组件
if (component.enabled) {
component.onEnabled();
}
}
this._tempBufferList.length = 0;
}
}
public onEntityTransformChanged(comp: TransformComponent) {
for (let i = 0; i < this._components.length; i++) {
if (this._components[i].enabled)
this._components[i].onEntityTransformChanged(comp);
}
for (let i = 0; i < this._componentsToAdd.length; i++) {
if (this._componentsToAdd[i].enabled)
this._componentsToAdd[i].onEntityTransformChanged(comp);
}
}
private handleRemove(component: Component) {
if (component instanceof RenderableComponent)
this._entity.scene.renderableComponents.remove(component);
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(component), false);
this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
component.onRemovedFromEntity();
component.entity = null;
}
/**
* 获取类型T的第一个组件并返回它
* 可以选择跳过检查未初始化的组件(尚未调用onAddedToEntity方法的组件)
* 如果没有找到组件则返回null。
* @param type
* @param onlyReturnInitializedComponents
*/
public getComponent<T extends Component>(type, onlyReturnInitializedComponents: boolean): T {
for (let i = 0; i < this._components.length; i++) {
let component = this._components[i];
if (component instanceof type)
return component as T;
}
// 我们可以选择检查挂起的组件以防addComponent和getComponent在同一个框架中被调用
if (!onlyReturnInitializedComponents) {
for (let i = 0; i < this._componentsToAdd.length; i++) {
let component = this._componentsToAdd[i];
/**
* 获取类型T的第一个组件并返回它
* 可以选择跳过检查未初始化的组件(尚未调用onAddedToEntity方法的组件)
* 如果没有找到组件则返回null。
* @param type
* @param onlyReturnInitializedComponents
*/
public getComponent<T extends Component>(type, onlyReturnInitializedComponents: boolean): T {
for (let i = 0; i < this._components.length; i++) {
let component = this._components[i];
if (component instanceof type)
return component as T;
}
// 我们可以选择检查挂起的组件以防addComponent和getComponent在同一个框架中被调用
if (!onlyReturnInitializedComponents) {
for (let i = 0; i < this._componentsToAdd.length; i++) {
let component = this._componentsToAdd[i];
if (component instanceof type)
return component as T;
}
}
return null;
}
return null;
}
/**
* 获取T类型的所有组件但不使用列表分配
* @param typeName
* @param components
*/
public getComponents(typeName: string | any, components?) {
if (!components)
components = [];
/**
* 获取T类型的所有组件但不使用列表分配
* @param typeName
* @param components
*/
public getComponents(typeName: string | any, components?) {
if (!components)
components = [];
for (let i = 0; i < this._components.length; i++) {
let component = this._components[i];
if (typeof (typeName) == "string") {
if (egret.is(component, typeName)) {
components.push(component);
}
} else {
if (component instanceof typeName) {
components.push(component);
}
}
}
for (let i = 0; i < this._components.length; i++) {
let component = this._components[i];
if (typeof (typeName) == "string") {
if (egret.is(component, typeName)) {
components.push(component);
}
} else {
if (component instanceof typeName) {
components.push(component);
for (let i = 0; i < this._componentsToAdd.length; i++) {
let component = this._componentsToAdd[i];
if (typeof (typeName) == "string") {
if (egret.is(component, typeName)) {
components.push(component);
}
} else {
if (component instanceof typeName) {
components.push(component);
}
}
}
return components;
}
public update() {
this.updateLists();
for (let i = 0; i < this._components.length; i++) {
let updatableComponent = this._components[i];
if (updatableComponent.enabled &&
(updatableComponent.updateInterval == 1 ||
Time.frameCount % updatableComponent.updateInterval == 0))
updatableComponent.update();
}
}
for (let i = 0; i < this._componentsToAdd.length; i++) {
let component = this._componentsToAdd[i];
if (typeof (typeName) == "string") {
if (egret.is(component, typeName)) {
components.push(component);
}
} else {
if (component instanceof typeName) {
components.push(component);
}
public onEntityTransformChanged(comp: Transform.Component) {
for (let i = 0; i < this._components.length; i++) {
if (this._components[i].enabled)
this._components[i].onEntityTransformChanged(comp);
}
for (let i = 0; i < this._componentsToAdd.length; i++) {
if (this._componentsToAdd[i].enabled)
this._componentsToAdd[i].onEntityTransformChanged(comp);
}
}
return components;
}
public onEntityEnabled() {
for (let i = 0; i < this._components.length; i++)
this._components[i].onEnabled();
}
public update() {
this.updateLists();
for (let i = 0; i < this._components.length; i++) {
let updatable = this._components[i];
let updateableComponent;
if (updatable instanceof Component)
updateableComponent = updatable as Component;
if (updatable.enabled &&
updateableComponent.enabled &&
(updateableComponent.updateInterval == 1 ||
Time.frameCount % updateableComponent.updateInterval == 0))
updatable.update();
public onEntityDisabled() {
for (let i = 0; i < this._components.length; i++)
this._components[i].onDisabled();
}
}
}
}

View File

@@ -1,134 +1,213 @@
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[] = [];
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[] = [];
constructor(scene: Scene){
this.scene = scene;
}
public get count(){
return this._entities.length;
}
public get buffer(){
return this._entities;
}
public add(entity: Entity){
if (this._entitiesToAdded.indexOf(entity) == -1)
this._entitiesToAdded.push(entity);
}
public remove(entity: Entity){
if (this._entitiesToAdded.contains(entity)){
this._entitiesToAdded.remove(entity);
return;
constructor(scene: Scene){
this.scene = scene;
}
if (!this._entitiesToRemove.contains(entity))
this._entitiesToRemove.push(entity);
}
public findEntity(name: string){
for (let i = 0; i < this._entities.length; i ++){
if (this._entities[i].name == name)
return this._entities[i];
public get count(){
return this._entities.length;
}
return this._entitiesToAdded.firstOrDefault(entity => entity.name == name);
}
public getTagList(tag: number){
let list = this._entityDict.get(tag);
if (!list){
list = [];
this._entityDict.set(tag, list);
public get buffer(){
return this._entities;
}
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]._isDestoryed = true;
this._entities[i].onRemovedFromScene();
this._entities[i].scene = null;
public add(entity: Entity){
if (this._entitiesToAdded.indexOf(entity) == -1)
this._entitiesToAdded.push(entity);
}
this._entities.length = 0;
this._entityDict.clear();
}
public remove(entity: Entity){
if (this._entitiesToAdded.contains(entity)){
this._entitiesToAdded.remove(entity);
return;
}
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;
if (!this._entitiesToRemove.contains(entity))
this._entitiesToRemove.push(entity);
}
this.scene.entityProcessors.onEntityRemoved(entity);
public findEntity(name: string){
for (let i = 0; i < this._entities.length; i ++){
if (this._entities[i].name == name)
return this._entities[i];
}
return this._entitiesToAdded.firstOrDefault(entity => entity.name == name);
}
/**
* 返回带有标记的所有实体的列表。如果没有实体具有标记则返回一个空列表。可以通过ListPool.free将返回的列表放回池中。
* @param tag
*/
public entitiesWithTag(tag: number){
let list = this.getTagList(tag);
let returnList = ListPool.obtain<Entity>();
for (let i = 0; i < list.length; i ++)
returnList.push(list[i]);
return returnList;
}
/**
* 返回t类型的所有实体的列表。返回的列表可以通过ListPool.free放回池中。
* @param type
*/
public entitiesOfType<T extends Entity>(type): T[]{
let list = ListPool.obtain<T>();
for (let i = 0; i < this._entities.length; i ++){
if (this._entities[i] instanceof type)
list.push(this._entities[i] as T);
}
this._entitiesToAdded.forEach(entity => {
if (entity instanceof type)
list.push(entity as T);
});
this._tempEntityList.length = 0;
return list;
}
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)
/**
* 返回在类型为T的场景中找到的第一个组件
* @param type
*/
public findComponentOfType<T extends Component>(type): T {
for (let i = 0; i < this._entities.length; i ++){
if (this._entities[i].enabled){
let comp = this._entities[i].getComponent<T>(type);
if (comp)
return comp;
}
});
}
this._tempEntityList.forEach(entity => entity.onAddedToScene());
this._tempEntityList.length = 0;
for (let i = 0; i < this._entitiesToAdded.length; i ++){
let entity = this._entitiesToAdded[i];
if (entity.enabled){
let comp = entity.getComponent<T>(type);
if (comp)
return comp;
}
}
return null;
}
if (this._unsortedTags.length > 0){
this._unsortedTags.forEach(tag => {
this._entityDict.get(tag).sort();
});
/**
* 返回在类型t的场景中找到的所有组件。返回的列表可以通过ListPool.free放回池中。
* @param type
*/
public findComponentsOfType<T extends Component>(type): T[]{
let comps = ListPool.obtain<T>();
for (let i = 0; i < this._entities.length; i ++){
if (this._entities[i].enabled)
this._entities[i].getComponents(type, comps);
}
this._unsortedTags.length = 0;
for (let i = 0; i < this._entitiesToAdded.length; i ++){
let entity = this._entitiesToAdded[i];
if (entity.enabled)
entity.getComponents(type,comps);
}
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]._isDestoryed = 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;
}
}
}
}
}