Merge branch 'master' of https://github.com/esengine/egret-framework
# Conflicts: # demo/libs/framework/framework.d.ts # demo/libs/framework/framework.min.js # demo/src/game/MainScene.ts # source/bin/framework.d.ts # source/bin/framework.min.js
This commit is contained in:
@@ -4,6 +4,7 @@ abstract class Component extends egret.DisplayObjectContainer {
|
||||
public updateInterval: number = 1;
|
||||
/** 允许用户为实体存入信息 */
|
||||
public userData: any;
|
||||
private _updateOrder = 0;
|
||||
|
||||
public get enabled(){
|
||||
return this.entity ? this.entity.enabled && this._enabled : this._enabled;
|
||||
@@ -13,6 +14,10 @@ abstract class Component extends egret.DisplayObjectContainer {
|
||||
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;
|
||||
@@ -27,8 +32,23 @@ abstract class Component extends egret.DisplayObjectContainer {
|
||||
return this;
|
||||
}
|
||||
|
||||
public initialize(){
|
||||
/** 更新此实体上组件的顺序 */
|
||||
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(){
|
||||
@@ -47,14 +67,18 @@ abstract class Component extends egret.DisplayObjectContainer {
|
||||
|
||||
}
|
||||
|
||||
public update(){
|
||||
|
||||
}
|
||||
|
||||
public debugRender(){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 当实体的位置改变时调用。这允许组件知道它们由于父实体的移动而移动了。
|
||||
* @param comp
|
||||
*/
|
||||
public onEntityTransformChanged(comp: TransformComponent){
|
||||
|
||||
}
|
||||
|
||||
/** 内部使用 运行时不应该调用 */
|
||||
public registerComponent(){
|
||||
this.entity.componentBits.set(ComponentTypeManager.getIndexFor(this), false);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
///<reference path="../Component.ts"/>
|
||||
class Camera extends Component {
|
||||
class Camera extends Component implements IUpdatable {
|
||||
private _zoom;
|
||||
private _origin: Vector2 = Vector2.zero;
|
||||
|
||||
private _minimumZoom = 0.3;
|
||||
private _maximumZoom = 3;
|
||||
|
||||
private _position: Vector2 = Vector2.zero;
|
||||
/**
|
||||
* 如果相机模式为cameraWindow 则会进行缓动移动
|
||||
* 该值为移动速度
|
||||
@@ -67,11 +68,24 @@ class Camera extends Component {
|
||||
}
|
||||
|
||||
public get position(){
|
||||
return this.entity.position;
|
||||
return this._position;
|
||||
}
|
||||
|
||||
public set position(value: Vector2){
|
||||
this.entity.position = value;
|
||||
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() {
|
||||
|
||||
@@ -8,12 +8,16 @@ class BoxCollider extends Collider {
|
||||
this.setWidth(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置BoxCollider的宽度
|
||||
* @param width
|
||||
*/
|
||||
public setWidth(width: number): BoxCollider{
|
||||
this._colliderRequiresAutoSizing = false;
|
||||
let box = this.shape as Box;
|
||||
if (width != box.width){
|
||||
// 更新框,改变边界,如果我们需要更新物理系统中的边界
|
||||
box.updateBox(width, box.height);
|
||||
this._isPositionDirty = true;
|
||||
if (this.entity && this._isParentEntityAddedToScene)
|
||||
Physics.updateCollider(this);
|
||||
}
|
||||
@@ -29,20 +33,28 @@ class BoxCollider extends Collider {
|
||||
this.setHeight(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置BoxCollider的高度
|
||||
* @param height
|
||||
*/
|
||||
public setHeight(height: number){
|
||||
this._colliderRequiresAutoSizing = false;
|
||||
let box = this.shape as Box;
|
||||
if (height != box.height){
|
||||
// 更新框,改变边界,如果我们需要更新物理系统中的边界
|
||||
box.updateBox(box.width, height);
|
||||
this._isPositionDirty = true;
|
||||
if (this.entity && this._isParentEntityAddedToScene)
|
||||
Physics.updateCollider(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 零参数构造函数要求RenderableComponent在实体上,这样碰撞器可以在实体被添加到场景时调整自身的大小。
|
||||
*/
|
||||
constructor(){
|
||||
super();
|
||||
|
||||
// 我们在这里插入一个1x1框作为占位符,直到碰撞器在下一阵被添加到实体并可以获得更精确的自动调整大小数据
|
||||
this.shape = new Box(1, 1);
|
||||
this._colliderRequiresAutoSizing = true;
|
||||
}
|
||||
@@ -51,8 +63,8 @@ class BoxCollider extends Collider {
|
||||
this._colliderRequiresAutoSizing = false;
|
||||
let box = this.shape as Box;
|
||||
if (width != box.width || height != box.height){
|
||||
// 更新框,改变边界,如果我们需要更新物理系统中的边界
|
||||
box.updateBox(width, height);
|
||||
this._isPositionDirty = true;
|
||||
if (this.entity && this._isParentEntityAddedToScene)
|
||||
Physics.updateCollider(this);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
class CircleCollider extends Collider {
|
||||
public get radius(): number{
|
||||
return (this.shape as Circle).radius;
|
||||
}
|
||||
public set radius(value: number){
|
||||
this.setRadius(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个有半径的圆
|
||||
*
|
||||
* @param radius
|
||||
*/
|
||||
constructor(radius?: number){
|
||||
super();
|
||||
|
||||
if (radius)
|
||||
this._colliderRequiresAutoSizing = true;
|
||||
// 我们在这里插入一个1px的圆圈作为占位符
|
||||
// 直到碰撞器被添加到实体并可以获得更精确的自动调整大小数据的下一帧
|
||||
this.shape = new Circle(radius ? radius : 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置圆的半径
|
||||
* @param radius
|
||||
*/
|
||||
public setRadius(radius: number): CircleCollider{
|
||||
this._colliderRequiresAutoSizing = false;
|
||||
let circle = this.shape as Circle;
|
||||
if (radius != circle.radius){
|
||||
circle.radius = radius;
|
||||
circle._originalRadius = radius;
|
||||
|
||||
if (this.entity && this._isParentEntityAddedToScene)
|
||||
Physics.updateCollider(this);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,65 +1,89 @@
|
||||
abstract class Collider extends Component{
|
||||
abstract class Collider extends Component implements IUpdatable {
|
||||
/** 对撞机的基本形状 */
|
||||
public shape: Shape;
|
||||
/** 在处理冲突时,physicsLayer可以用作过滤器。Flags类有帮助位掩码的方法。 */
|
||||
public physicsLayer = 1 << 0;
|
||||
/** 如果这个碰撞器是一个触发器,它将不会引起碰撞,但它仍然会触发事件 */
|
||||
public isTrigger: boolean;
|
||||
public registeredPhysicsBounds: Rectangle;
|
||||
public shouldColliderScaleAndRotationWithTransform = true;
|
||||
/**
|
||||
* 这个对撞机在物理系统注册时的边界。
|
||||
* 存储这个允许我们始终能够安全地从物理系统中移除对撞机,即使它在试图移除它之前已经被移动了。
|
||||
*/
|
||||
public registeredPhysicsBounds: Rectangle = new Rectangle();
|
||||
/** 如果为true,碰撞器将根据附加的变换缩放和旋转 */
|
||||
public shouldColliderScaleAndRotateWithTransform = true;
|
||||
/** 默认为所有层。 */
|
||||
public collidesWithLayers = Physics.allLayers;
|
||||
|
||||
public _localOffsetLength: number;
|
||||
public _isPositionDirty = true;
|
||||
public _isRotationDirty = true;
|
||||
/** 标记来跟踪我们的实体是否被添加到场景中 */
|
||||
protected _isParentEntityAddedToScene;
|
||||
protected _colliderRequiresAutoSizing;
|
||||
protected _localOffset: Vector2 = new Vector2(0, 0);
|
||||
/** 标记来记录我们是否注册了物理系统 */
|
||||
protected _isColliderRegistered;
|
||||
|
||||
public get bounds(): Rectangle {
|
||||
if (this._isPositionDirty || this._isRotationDirty){
|
||||
this.shape.recalculateBounds(this);
|
||||
this._isPositionDirty = this._isRotationDirty = false;
|
||||
}
|
||||
|
||||
this.shape.recalculateBounds(this);
|
||||
return this.shape.bounds;
|
||||
}
|
||||
|
||||
public get localOffset(){
|
||||
public get localOffset() {
|
||||
return this._localOffset;
|
||||
}
|
||||
|
||||
public set localOffset(value: Vector2){
|
||||
/**
|
||||
* 将localOffset添加到实体。获取碰撞器的最终位置。这允许您向一个实体添加多个碰撞器并分别定位它们。
|
||||
*/
|
||||
public set localOffset(value: Vector2) {
|
||||
this.setLocalOffset(value);
|
||||
}
|
||||
|
||||
public setLocalOffset(offset: Vector2){
|
||||
if (this._localOffset != offset){
|
||||
public setLocalOffset(offset: Vector2) {
|
||||
if (this._localOffset != offset) {
|
||||
this.unregisterColliderWithPhysicsSystem();
|
||||
this._localOffset = offset;
|
||||
this._localOffsetLength = this._localOffset.length();
|
||||
this._isPositionDirty = true;
|
||||
this.registerColliderWithPhysicsSystem();
|
||||
}
|
||||
}
|
||||
|
||||
public registerColliderWithPhysicsSystem(){
|
||||
if (this._isParentEntityAddedToScene && !this._isColliderRegistered){
|
||||
/**
|
||||
* 父实体会在不同的时间调用它(当添加到场景,启用,等等)
|
||||
*/
|
||||
public registerColliderWithPhysicsSystem() {
|
||||
// 如果在将我们添加到实体之前更改了origin等属性,则实体可以为null
|
||||
if (this._isParentEntityAddedToScene && !this._isColliderRegistered) {
|
||||
Physics.addCollider(this);
|
||||
this._isColliderRegistered = true;
|
||||
}
|
||||
}
|
||||
|
||||
public unregisterColliderWithPhysicsSystem(){
|
||||
if (this._isParentEntityAddedToScene && this._isColliderRegistered){
|
||||
/**
|
||||
* 父实体会在不同的时候调用它(从场景中移除,禁用,等等)
|
||||
*/
|
||||
public unregisterColliderWithPhysicsSystem() {
|
||||
if (this._isParentEntityAddedToScene && this._isColliderRegistered) {
|
||||
Physics.removeCollider(this);
|
||||
}
|
||||
this._isColliderRegistered = false;
|
||||
}
|
||||
|
||||
public overlaps(other: Collider){
|
||||
/**
|
||||
* 检查这个形状是否与物理系统中的其他对撞机重叠
|
||||
* @param other
|
||||
*/
|
||||
public overlaps(other: Collider) {
|
||||
return this.shape.overlaps(other.shape);
|
||||
}
|
||||
|
||||
public collidesWith(collider: Collider, motion: Vector2){
|
||||
/**
|
||||
* 检查这个与运动应用的碰撞器(移动向量)是否与碰撞器碰撞。如果是这样,将返回true,并且结果将填充碰撞数据。
|
||||
* @param collider
|
||||
* @param motion
|
||||
*/
|
||||
public collidesWith(collider: Collider, motion: Vector2) {
|
||||
// 改变形状的位置,使它在移动后的位置,这样我们可以检查重叠
|
||||
let oldPosition = this.shape.position;
|
||||
this.shape.position = Vector2.add(this.shape.position, motion);
|
||||
|
||||
@@ -67,49 +91,71 @@ abstract class Collider extends Component{
|
||||
if (result)
|
||||
result.collider = collider;
|
||||
|
||||
// 将图形位置返回到检查前的位置
|
||||
this.shape.position = oldPosition;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public onAddedToEntity(){
|
||||
if (this._colliderRequiresAutoSizing){
|
||||
if (!(this instanceof BoxCollider)){
|
||||
public onAddedToEntity() {
|
||||
if (this._colliderRequiresAutoSizing) {
|
||||
if (!(this instanceof BoxCollider || this instanceof CircleCollider)) {
|
||||
console.error("Only box and circle colliders can be created automatically");
|
||||
}
|
||||
|
||||
let renderable = this.entity.getComponent<RenderableComponent>(RenderableComponent);
|
||||
if (renderable){
|
||||
let renderbaleBounds = renderable.bounds;
|
||||
if (renderable) {
|
||||
let bounds = renderable.bounds;
|
||||
|
||||
let width = renderbaleBounds.width / this.entity.scale.x;
|
||||
let height = renderbaleBounds.height / this.entity.scale.y;
|
||||
// 这里我们需要大小*反尺度,因为当我们自动调整碰撞器的大小时,它需要没有缩放的渲染
|
||||
let width = bounds.width / this.entity.scale.x;
|
||||
let height = bounds.height / this.entity.scale.y;
|
||||
|
||||
if (this instanceof BoxCollider){
|
||||
let boxCollider = this as BoxCollider;
|
||||
// 圆碰撞器需要特别注意原点
|
||||
if (this instanceof CircleCollider){
|
||||
let circleCollider = this as CircleCollider;
|
||||
circleCollider.radius = Math.max(width, height) * 0.5;
|
||||
|
||||
this.localOffset = bounds.location;
|
||||
} else {
|
||||
let boxCollider = this;
|
||||
boxCollider.width = width;
|
||||
boxCollider.height = height;
|
||||
|
||||
this.localOffset = Vector2.subtract(renderbaleBounds.center, this.entity.position);
|
||||
this.localOffset = bounds.location;
|
||||
}
|
||||
} else {
|
||||
console.warn("Collider has no shape and no RenderableComponent. Can't figure out how to size it.");
|
||||
}
|
||||
}
|
||||
|
||||
this._isParentEntityAddedToScene = true;
|
||||
this.registerColliderWithPhysicsSystem();
|
||||
}
|
||||
|
||||
public onRemovedFromEntity(){
|
||||
|
||||
public onRemovedFromEntity() {
|
||||
this.unregisterColliderWithPhysicsSystem();
|
||||
this._isParentEntityAddedToScene = false;
|
||||
}
|
||||
|
||||
public onEnabled(){
|
||||
public onEnabled() {
|
||||
this.registerColliderWithPhysicsSystem();
|
||||
this._isPositionDirty = this._isRotationDirty = true;
|
||||
}
|
||||
|
||||
public onDisabled(){
|
||||
public onDisabled() {
|
||||
this.unregisterColliderWithPhysicsSystem();
|
||||
}
|
||||
|
||||
public onEntityTransformChanged(comp: TransformComponent) {
|
||||
if (this._isColliderRegistered)
|
||||
Physics.updateCollider(this);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* 多边形应该以顺时针方式定义
|
||||
*/
|
||||
class PolygonCollider extends Collider {
|
||||
/**
|
||||
* 如果这些点没有居中,它们将以localOffset的差异为居中。
|
||||
* @param points
|
||||
*/
|
||||
constructor(points: Vector2[]){
|
||||
super();
|
||||
|
||||
// 第一点和最后一点决不能相同。我们想要一个开放的多边形
|
||||
let isPolygonClosed = points[0] == points[points.length - 1];
|
||||
|
||||
// 最后一个移除
|
||||
if (isPolygonClosed)
|
||||
points.splice(points.length - 1, 1);
|
||||
|
||||
let center = Polygon.findPolygonCenter(points);
|
||||
this.setLocalOffset(center);
|
||||
Polygon.recenterPolygonVerts(points);
|
||||
this.shape = new Polygon(points);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,10 @@
|
||||
/**
|
||||
* 辅助类说明了一种处理移动的方法,它考虑了包括触发器在内的所有冲突。
|
||||
* ITriggerListener接口用于管理对移动过程中违反的任何触发器的回调。
|
||||
* 一个物体只能通过移动器移动。要正确报告触发器的move方法。
|
||||
*
|
||||
* 请注意,多个移动者相互交互将多次调用ITriggerListener。
|
||||
*/
|
||||
class Mover extends Component {
|
||||
private _triggerHelper: ColliderTriggerHelper;
|
||||
|
||||
@@ -5,6 +12,10 @@ class Mover extends Component {
|
||||
this._triggerHelper = new ColliderTriggerHelper(this.entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算修改运动矢量的运动,以考虑移动时可能发生的碰撞
|
||||
* @param motion
|
||||
*/
|
||||
public calculateMovement(motion: Vector2){
|
||||
let collisionResult = new CollisionResult();
|
||||
|
||||
@@ -16,23 +27,30 @@ class Mover extends Component {
|
||||
for (let i = 0; i < colliders.length; i ++){
|
||||
let collider = colliders[i];
|
||||
|
||||
// 不检测触发器
|
||||
if (collider.isTrigger)
|
||||
continue;
|
||||
|
||||
// 获取我们在新位置可能发生碰撞的任何东西
|
||||
let bounds = collider.bounds;
|
||||
bounds.x += motion.x;
|
||||
bounds.y += motion.y;
|
||||
let neighbors = Physics.boxcastBroadphaseExcludingSelf(collider, bounds, collider.collidesWithLayers);
|
||||
let boxcastResult = Physics.boxcastBroadphaseExcludingSelf(collider, bounds, collider.collidesWithLayers);
|
||||
bounds = boxcastResult.bounds;
|
||||
let neighbors = boxcastResult.tempHashSet;
|
||||
|
||||
for (let j = 0; j < neighbors.length; j ++){
|
||||
let neighbor = neighbors[j];
|
||||
// 不检测触发器
|
||||
if (neighbor.isTrigger)
|
||||
continue;
|
||||
|
||||
let _internalcollisionResult = collider.collidesWith(neighbor, motion);
|
||||
if (_internalcollisionResult){
|
||||
// 如果碰撞 则退回之前的移动量
|
||||
motion = Vector2.subtract(motion, _internalcollisionResult.minimumTranslationVector);
|
||||
|
||||
// 如果我们碰到多个对象,为了简单起见,只取第一个。
|
||||
if (_internalcollisionResult.collider){
|
||||
collisionResult = _internalcollisionResult;
|
||||
}
|
||||
@@ -42,7 +60,7 @@ class Mover extends Component {
|
||||
|
||||
ListPool.free(colliders);
|
||||
|
||||
return collisionResult;
|
||||
return {collisionResult: collisionResult, motion: motion};
|
||||
}
|
||||
|
||||
public applyMovement(motion: Vector2){
|
||||
@@ -53,7 +71,9 @@ class Mover extends Component {
|
||||
}
|
||||
|
||||
public move(motion: Vector2){
|
||||
let collisionResult = this.calculateMovement(motion);
|
||||
let movementResult = this.calculateMovement(motion);
|
||||
let collisionResult = movementResult.collisionResult;
|
||||
motion = movementResult.motion;
|
||||
|
||||
this.applyMovement(motion);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///<reference path="./SpriteRenderer.ts" />
|
||||
class SpriteAnimator extends SpriteRenderer {
|
||||
class SpriteAnimator extends SpriteRenderer implements IUpdatable {
|
||||
/** 在动画完成时触发,包括动画名称; */
|
||||
public onAnimationCompletedEvent: Function;
|
||||
/** 动画播放速度 */
|
||||
|
||||
@@ -1,25 +1,12 @@
|
||||
class SpriteRenderer extends RenderableComponent {
|
||||
private _origin: Vector2;
|
||||
private _sprite: Sprite;
|
||||
protected bitmap: egret.Bitmap;
|
||||
|
||||
public get origin(){
|
||||
return this._origin;
|
||||
}
|
||||
public set origin(value: Vector2){
|
||||
this.setOrigin(value);
|
||||
}
|
||||
public setOrigin(origin: Vector2){
|
||||
if (this._origin != origin){
|
||||
this._origin = origin;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
/** 应该由这个精灵显示的精灵。当设置时,精灵的原点也被设置为匹配精灵.origin。 */
|
||||
/** 应该由这个精灵显示的精灵 */
|
||||
public get sprite(): Sprite{
|
||||
return this._sprite;
|
||||
}
|
||||
/** 应该由这个精灵显示的精灵。当设置时,精灵的原点也被设置为匹配精灵.origin。 */
|
||||
/** 应该由这个精灵显示的精灵 */
|
||||
public set sprite(value: Sprite){
|
||||
this.setSprite(value);
|
||||
}
|
||||
@@ -27,7 +14,10 @@ class SpriteRenderer extends RenderableComponent {
|
||||
public setSprite(sprite: Sprite): SpriteRenderer{
|
||||
this.removeChildren();
|
||||
this._sprite = sprite;
|
||||
if (this._sprite) this._origin = this._sprite.origin;
|
||||
if (this._sprite) {
|
||||
this.anchorOffsetX = this._sprite.origin.x / this._sprite.sourceRect.width;
|
||||
this.anchorOffsetY = this._sprite.origin.y / this._sprite.sourceRect.height;
|
||||
}
|
||||
this.bitmap = new egret.Bitmap(sprite.texture2D);
|
||||
this.addChild(this.bitmap);
|
||||
|
||||
@@ -58,8 +48,8 @@ class SpriteRenderer extends RenderableComponent {
|
||||
|
||||
/** 渲染处理 在每个模块中处理各自的渲染逻辑 */
|
||||
public render(camera: Camera){
|
||||
this.x = this.entity.position.x - this.origin.x - camera.position.x + camera.origin.x;
|
||||
this.y = this.entity.position.y - this.origin.y - camera.position.y + camera.origin.y;
|
||||
this.x = -camera.position.x + camera.origin.x;
|
||||
this.y = -camera.position.y + camera.origin.y;
|
||||
}
|
||||
|
||||
public onRemovedFromEntity(){
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
class Entity extends egret.DisplayObjectContainer {
|
||||
private static _idGenerator: number;
|
||||
|
||||
private _position: Vector2 = Vector2.zero;
|
||||
public name: string;
|
||||
public readonly id: number;
|
||||
/** 当前实体所属的场景 */
|
||||
@@ -20,11 +19,13 @@ class Entity extends egret.DisplayObjectContainer {
|
||||
}
|
||||
|
||||
public get position(){
|
||||
return this._position;
|
||||
return new Vector2(this.x, this.y);
|
||||
}
|
||||
|
||||
public set position(value: Vector2){
|
||||
this._position = value;
|
||||
this.$setX(value.x);
|
||||
this.$setY(value.y);
|
||||
this.onEntityTransformChanged(TransformComponent.position);
|
||||
}
|
||||
|
||||
public get scale(){
|
||||
@@ -32,8 +33,18 @@ class Entity extends egret.DisplayObjectContainer {
|
||||
}
|
||||
|
||||
public set scale(value: Vector2){
|
||||
this.scaleX = value.x;
|
||||
this.scaleY = value.y;
|
||||
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(){
|
||||
@@ -74,6 +85,11 @@ class Entity extends egret.DisplayObjectContainer {
|
||||
this.id = Entity._idGenerator ++;
|
||||
|
||||
this.componentBits = new BitSet();
|
||||
this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
|
||||
}
|
||||
|
||||
private onAddToStage(){
|
||||
this.onEntityTransformChanged(TransformComponent.position);
|
||||
}
|
||||
|
||||
public get updateOrder(){
|
||||
@@ -160,6 +176,10 @@ class Entity extends egret.DisplayObjectContainer {
|
||||
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){
|
||||
@@ -195,12 +215,23 @@ class Entity extends egret.DisplayObjectContainer {
|
||||
|
||||
public destroy(){
|
||||
this._isDestoryed = true;
|
||||
this.removeEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
|
||||
|
||||
this.scene.entities.remove(this);
|
||||
this.removeChildren();
|
||||
|
||||
if (this.parent)
|
||||
this.parent.removeChild(this);
|
||||
|
||||
for (let i = this.numChildren - 1; i >= 0; i --){
|
||||
let child = this.getChildAt(i);
|
||||
(child as Component).entity.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum TransformComponent {
|
||||
rotation,
|
||||
scale,
|
||||
position
|
||||
}
|
||||
6
source/src/ECS/IUpdatable.ts
Normal file
6
source/src/ECS/IUpdatable.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/** 当将该接口添加到组件时,只要启用了组件和实体,它就需要调用每帧的更新方法。 */
|
||||
interface IUpdatable {
|
||||
enabled: boolean;
|
||||
updateOrder: number;
|
||||
update();
|
||||
}
|
||||
@@ -144,6 +144,9 @@ class Scene extends egret.DisplayObjectContainer {
|
||||
this.entityProcessors.end();
|
||||
|
||||
this.unload();
|
||||
|
||||
if (this.parent)
|
||||
this.parent.removeChild(this);
|
||||
}
|
||||
|
||||
protected async onStart() {
|
||||
|
||||
@@ -81,6 +81,9 @@ class SceneManager {
|
||||
}
|
||||
} else if (this._scene) {
|
||||
this._scene.render();
|
||||
|
||||
Debug.render();
|
||||
|
||||
this._scene.postRender();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,37 @@
|
||||
class ComponentList {
|
||||
private _entity: Entity;
|
||||
/** 添加到实体的组件列表 */
|
||||
private _components: Component[] = [];
|
||||
/** 添加到此框架的组件列表。用来对组件进行分组,这样我们就可以同时进行加工 */
|
||||
private _componentsToAdd: Component[] = [];
|
||||
/** 标记要删除此框架的组件列表。用来对组件进行分组,这样我们就可以同时进行加工 */
|
||||
private _componentsToRemove: Component[] = [];
|
||||
/** 需要调用更新的所有组件的列表 */
|
||||
private _updatableComponents: IUpdatable[] = [];
|
||||
private _tempBufferList: Component[] = [];
|
||||
|
||||
constructor(entity: Entity){
|
||||
constructor(entity: Entity) {
|
||||
this._entity = entity;
|
||||
}
|
||||
|
||||
public get count(){
|
||||
public get count() {
|
||||
return this._components.length;
|
||||
}
|
||||
|
||||
public get buffer(){
|
||||
public get buffer() {
|
||||
return this._components;
|
||||
}
|
||||
|
||||
public add(component: Component){
|
||||
public add(component: Component) {
|
||||
this._componentsToAdd.push(component);
|
||||
}
|
||||
|
||||
public remove(component: Component){
|
||||
if (this._componentsToAdd.contains(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;
|
||||
}
|
||||
@@ -30,43 +39,58 @@ class ComponentList {
|
||||
this._componentsToRemove.push(component);
|
||||
}
|
||||
|
||||
public removeAllComponents(){
|
||||
for (let i = 0; i < this._components.length; i ++){
|
||||
/**
|
||||
* 立即从组件列表中删除所有组件
|
||||
*/
|
||||
public removeAllComponents() {
|
||||
for (let i = 0; i < this._components.length; i++) {
|
||||
this.handleRemove(this._components[i]);
|
||||
}
|
||||
|
||||
this._components.length = 0;
|
||||
this._updatableComponents.length = 0;
|
||||
this._componentsToAdd.length = 0;
|
||||
this._componentsToRemove.length = 0;
|
||||
}
|
||||
|
||||
public deregisterAllComponents(){
|
||||
for (let i = 0; i < this._components.length; i ++){
|
||||
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);
|
||||
|
||||
// 处理IUpdatable
|
||||
if (egret.is(component, "IUpdatable"))
|
||||
this._updatableComponents.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 ++){
|
||||
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);
|
||||
|
||||
if (egret.is(component, "IUpdatable"))
|
||||
this._updatableComponents.push(component as any);
|
||||
|
||||
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 ++){
|
||||
/**
|
||||
* 处理任何需要删除或添加的组件
|
||||
*/
|
||||
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]);
|
||||
}
|
||||
@@ -74,11 +98,15 @@ class ComponentList {
|
||||
this._componentsToRemove.length = 0;
|
||||
}
|
||||
|
||||
if (this._componentsToAdd.length > 0){
|
||||
for (let i = 0, count = this._componentsToAdd.length; i < count; i ++){
|
||||
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);
|
||||
|
||||
if (egret.is(component, "IUpdatable"))
|
||||
this._updatableComponents.push(component as any);
|
||||
|
||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(component));
|
||||
this._entity.scene.entityProcessors.onComponentAdded(this._entity);
|
||||
|
||||
@@ -86,13 +114,16 @@ class ComponentList {
|
||||
this._tempBufferList.push(component);
|
||||
}
|
||||
|
||||
// 在调用onAddedToEntity之前清除,以防添加更多组件
|
||||
this._componentsToAdd.length = 0;
|
||||
|
||||
for (let i = 0; i < this._tempBufferList.length; i++){
|
||||
// 现在所有的组件都添加到了场景中,我们再次循环并调用onAddedToEntity/onEnabled
|
||||
for (let i = 0; i < this._tempBufferList.length; i++) {
|
||||
let component = this._tempBufferList[i];
|
||||
component.onAddedToEntity();
|
||||
|
||||
if (component.enabled){
|
||||
// enabled检查实体和组件
|
||||
if (component.enabled) {
|
||||
component.onEnabled();
|
||||
}
|
||||
}
|
||||
@@ -101,10 +132,25 @@ class ComponentList {
|
||||
}
|
||||
}
|
||||
|
||||
private handleRemove(component: Component){
|
||||
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);
|
||||
|
||||
if (egret.is(component, "IUpdatable"))
|
||||
this._updatableComponents.remove(component);
|
||||
|
||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(component), false);
|
||||
this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
|
||||
|
||||
@@ -112,15 +158,23 @@ class ComponentList {
|
||||
component.entity = null;
|
||||
}
|
||||
|
||||
public getComponent<T extends Component>(type, onlyReturnInitializedComponents: boolean): T{
|
||||
for (let i = 0; i < this._components.length; 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;
|
||||
}
|
||||
|
||||
if (!onlyReturnInitializedComponents){
|
||||
for (let i = 0; i < this._componentsToAdd.length; i ++){
|
||||
// 我们可以选择检查挂起的组件,以防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;
|
||||
@@ -130,31 +184,36 @@ class ComponentList {
|
||||
return null;
|
||||
}
|
||||
|
||||
public getComponents(typeName: string | any, components?){
|
||||
/**
|
||||
* 获取T类型的所有组件,但不使用列表分配
|
||||
* @param typeName
|
||||
* @param components
|
||||
*/
|
||||
public getComponents(typeName: string | any, components?) {
|
||||
if (!components)
|
||||
components = [];
|
||||
|
||||
for (let i = 0; i < this._components.length; i ++){
|
||||
for (let i = 0; i < this._components.length; i++) {
|
||||
let component = this._components[i];
|
||||
if (typeof(typeName) == "string"){
|
||||
if (egret.is(component, typeName)){
|
||||
if (typeof (typeName) == "string") {
|
||||
if (egret.is(component, typeName)) {
|
||||
components.push(component);
|
||||
}
|
||||
}else{
|
||||
if (component instanceof typeName){
|
||||
} else {
|
||||
if (component instanceof typeName) {
|
||||
components.push(component);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._componentsToAdd.length; i ++){
|
||||
for (let i = 0; i < this._componentsToAdd.length; i++) {
|
||||
let component = this._componentsToAdd[i];
|
||||
if (typeof(typeName) == "string"){
|
||||
if (egret.is(component, typeName)){
|
||||
if (typeof (typeName) == "string") {
|
||||
if (egret.is(component, typeName)) {
|
||||
components.push(component);
|
||||
}
|
||||
}else{
|
||||
if (component instanceof typeName){
|
||||
} else {
|
||||
if (component instanceof typeName) {
|
||||
components.push(component);
|
||||
}
|
||||
}
|
||||
@@ -163,12 +222,19 @@ class ComponentList {
|
||||
return components;
|
||||
}
|
||||
|
||||
public update(){
|
||||
public update() {
|
||||
this.updateLists();
|
||||
for (let i = 0; i < this._components.length; i ++){
|
||||
let component = this._components[i];
|
||||
if (component.enabled && (component.updateInterval == 1 || Time.frameCount % component.updateInterval == 0))
|
||||
component.update();
|
||||
for (let i = 0; i < this._updatableComponents.length; i++) {
|
||||
let updatable = this._updatableComponents[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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user