修复Vector2.zero引起的引用混乱问题

This commit is contained in:
yhh
2020-08-26 19:56:48 +08:00
parent 1997b3f348
commit e81f98ff17
33 changed files with 1663 additions and 4645 deletions

View File

@@ -1,9 +1,4 @@
module es {
export enum CameraStyle {
lockOn,
cameraWindow,
}
export class CameraInset {
public left: number = 0;
public right: number = 0;
@@ -16,39 +11,9 @@ module es {
public _areMatrixedDirty: boolean = true;
public _areBoundsDirty: boolean = true;
public _isProjectionMatrixDirty = true;
/**
* 如果相机模式为cameraWindow 则会进行缓动移动
* 该值为移动速度
*/
public followLerp = 0.1;
/**
* 在cameraWindow模式下宽度/高度被用做边界框,允许在不移动相机的情况下移动
* 在lockOn模式下只使用deadZone的x/y值 你可以通过直接setCenteredDeadzone重写它来自定义deadZone
*/
public deadzone: Rectangle = new Rectangle();
/**
* 相机聚焦于屏幕中心的偏移
*/
public focusOffset: Vector2 = Vector2.zero;
/**
* 如果为true 相机位置则不会超出地图矩形0, 0, mapwidth, mapheight
*/
public mapLockEnabled: boolean = false;
/**
* 當前地圖映射的寬度和高度
*/
public mapSize: Rectangle = new Rectangle();
public _targetEntity: Entity;
public _targetCollider: Collider;
public _desiredPositionDelta: Vector2 = new Vector2();
public _cameraStyle: CameraStyle;
public _worldSpaceDeadZone: Rectangle = new Rectangle();
constructor(targetEntity: Entity = null, cameraStyle: CameraStyle = CameraStyle.lockOn) {
constructor() {
super();
this._targetEntity = targetEntity;
this._cameraStyle = cameraStyle;
this.setZoom(0);
}
@@ -82,7 +47,25 @@ module es {
this.entity.transform.rotation = value;
}
public _zoom;
/**
* 原始的缩放值。这就是用于比例矩阵的精确值。默认值为1。
*/
public get rawZoom(){
return this._zoom;
}
/**
* 原始的缩放值。这就是用于比例矩阵的精确值。默认值为1。
* @param value
*/
public set rawZoom(value: number){
if (value != this._zoom){
this._zoom = value;
this._areMatrixedDirty = true;
}
}
public _zoom: number = 0;
/**
* 缩放值应该在-1和1之间、然后将该值从minimumZoom转换为maximumZoom。
@@ -218,18 +201,6 @@ module es {
}
}
/**
* 当场景渲染目标的大小发生变化时,我们会更新相机的原点并调整它的位置以保持它原来的位置
* @param newWidth
* @param newHeight
*/
public onSceneSizeChanged(newWidth: number, newHeight: number) {
let oldOrigin = this._origin;
this.origin = new Vector2(newWidth / 2, newHeight / 2);
this.entity.transform.position = Vector2.add(this.entity.transform.position, Vector2.subtract(this._origin, oldOrigin));
}
/**
* 设置用于从视口边缘插入摄像机边界的量
* @param left
@@ -318,6 +289,11 @@ module es {
return this;
}
public forceMatrixUpdate(){
// 弄脏矩阵也会自动弄脏边界
this._areMatrixedDirty = true;
}
public onEntityTransformChanged(comp: transform.Component) {
this._areMatrixedDirty = true;
}
@@ -336,7 +312,7 @@ module es {
*/
public worldToScreenPoint(worldPosition: Vector2): Vector2 {
this.updateMatrixes();
worldPosition = Vector2.transform(worldPosition, this._transformMatrix);
worldPosition = Vector2Ext.transformR(worldPosition, this._transformMatrix);
return worldPosition;
}
@@ -346,10 +322,23 @@ module es {
*/
public screenToWorldPoint(screenPosition: Vector2): Vector2 {
this.updateMatrixes();
screenPosition = Vector2.transform(screenPosition, this._inverseTransformMatrix);
screenPosition = Vector2Ext.transformR(screenPosition, this._inverseTransformMatrix);
return screenPosition;
}
/**
* 当场景渲染目标的大小发生变化时,我们会更新相机的原点并调整它的位置以保持它原来的位置
* @param newWidth
* @param newHeight
*/
public onSceneRenderTargetSizeChanged(newWidth: number, newHeight: number){
this._isProjectionMatrixDirty = true;
let oldOrigin = this._origin;
this.origin = new Vector2(newWidth / 2, newHeight / 2);
this.entity.transform.position.add(Vector2.subtract(this._origin, oldOrigin));
}
/**
* 返回鼠标在世界空间中的位置
*/
@@ -357,103 +346,6 @@ module es {
return this.screenToWorldPoint(Input.touchPosition);
}
public onAddedToEntity() {
this.follow(this._targetEntity, this._cameraStyle);
}
public update() {
let halfScreen = Vector2.multiply(this.bounds.size, new Vector2(0.5));
this._worldSpaceDeadZone.x = this.position.x - halfScreen.x * Core.scene.scaleX + this.deadzone.x + this.focusOffset.x;
this._worldSpaceDeadZone.y = this.position.y - halfScreen.y * Core.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.transform.roundPosition();
if (this.mapLockEnabled) {
this.position = this.clampToMapSize(this.position);
this.entity.transform.roundPosition();
}
}
/**
* 固定相机 永远不会离开地图的可见区域
* @param position
*/
public clampToMapSize(position: Vector2) {
let halfScreen = Vector2.multiply(this.bounds.size, new Vector2(0.5)).add(new Vector2(this.mapSize.x, this.mapSize.y));
let cameraMax = new Vector2(this.mapSize.width - halfScreen.x, this.mapSize.height - halfScreen.y);
return Vector2.clamp(position, halfScreen, cameraMax);
}
public updateFollow() {
this._desiredPositionDelta.x = this._desiredPositionDelta.y = 0;
if (this._cameraStyle == CameraStyle.lockOn) {
let targetX = this._targetEntity.transform.position.x;
let targetY = this._targetEntity.transform.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;
}
}
}
public follow(targetEntity: Entity, cameraStyle: CameraStyle = CameraStyle.cameraWindow) {
this._targetEntity = targetEntity;
this._cameraStyle = cameraStyle;
switch (this._cameraStyle) {
case CameraStyle.cameraWindow:
let w = this.bounds.width / 6;
let h = this.bounds.height / 3;
this.deadzone = new Rectangle((this.bounds.width - w) / 2, (this.bounds.height - h) / 2, w, h);
break;
case CameraStyle.lockOn:
this.deadzone = new Rectangle(this.bounds.width / 2, this.bounds.height / 2, 10, 10);
break;
}
}
/**
* 以给定的尺寸设置当前相机边界中心的死区
* @param width
* @param height
*/
public setCenteredDeadzone(width: number, height: number) {
this.deadzone = new Rectangle((this.bounds.width - width) / 2, (this.bounds.height - height) / 2, width, height);
}
protected updateMatrixes() {
if (!this._areMatrixedDirty)
return;

View File

@@ -0,0 +1,186 @@
module es {
export enum CameraStyle {
lockOn,
cameraWindow,
}
export class FollowCamera extends Component {
public camera: Camera;
/**
* 如果相机模式为cameraWindow 则会进行缓动移动
* 该值为移动速度
*/
public followLerp = 0.1;
/**
* 在cameraWindow模式下宽度/高度被用做边界框,允许在不移动相机的情况下移动
* 在lockOn模式下只使用deadZone的x/y值 你可以通过直接setCenteredDeadzone重写它来自定义deadZone
*/
public deadzone: Rectangle = new Rectangle();
/**
* 相机聚焦于屏幕中心的偏移
*/
public focusOffset: Vector2 = Vector2.zero;
/**
* 如果为true 相机位置则不会超出地图矩形0, 0, mapwidth, mapheight
*/
public mapLockEnabled: boolean = false;
/**
* 當前地圖映射的寬度和高度
*/
public mapSize: Rectangle = new Rectangle();
public _targetEntity: Entity;
public _targetCollider: Collider;
public _desiredPositionDelta: Vector2 = new Vector2();
public _cameraStyle: CameraStyle;
public _worldSpaceDeadZone: Rectangle = new Rectangle();
private rectShape: egret.Shape = new egret.Shape();
constructor(targetEntity: Entity = null, camera: Camera = null, cameraStyle: CameraStyle = CameraStyle.lockOn) {
super();
this._targetEntity = targetEntity;
this._cameraStyle = cameraStyle;
this.camera = camera;
}
public onAddedToEntity() {
if (!this.camera)
this.camera = this.entity.scene.camera;
this.follow(this._targetEntity, this._cameraStyle);
Core.emitter.addObserver(CoreEvents.GraphicsDeviceReset, this.onGraphicsDeviceReset, this);
}
public onGraphicsDeviceReset(){
// 我们需要这个在下一帧触发 这样相机边界就会更新
Core.schedule(0, false, this, t => {
let self = t.context as FollowCamera;
self.follow(self._targetEntity, self._cameraStyle);
});
}
public update() {
let halfScreen = Vector2.multiply(this.camera.bounds.size, new Vector2(0.5));
this._worldSpaceDeadZone.x = this.camera.position.x - halfScreen.x * Core.scene.scaleX + this.deadzone.x + this.focusOffset.x;
this._worldSpaceDeadZone.y = this.camera.position.y - halfScreen.y * Core.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.camera.position = Vector2.lerp(this.camera.position, Vector2.add(this.camera.position, this._desiredPositionDelta), this.followLerp);
this.entity.transform.roundPosition();
if (this.mapLockEnabled) {
this.camera.position = this.clampToMapSize(this.camera.position);
this.entity.transform.roundPosition();
}
}
public debugRender() {
if (!this.rectShape)
this.debugDisplayObject.addChild(this.rectShape);
this.rectShape.graphics.clear();
if (this._cameraStyle == CameraStyle.lockOn){
this.rectShape.graphics.beginFill(0x8B0000, 0);
this.rectShape.graphics.lineStyle(1, 0x8B0000);
this.rectShape.graphics.drawRect(this._worldSpaceDeadZone.x - 5, this._worldSpaceDeadZone.y - 5,
this._worldSpaceDeadZone.width, this._worldSpaceDeadZone.height);
this.rectShape.graphics.endFill();
} else {
this.rectShape.graphics.beginFill(0x8B0000, 0);
this.rectShape.graphics.lineStyle(1, 0x8B0000);
this.rectShape.graphics.drawRect(this._worldSpaceDeadZone.x, this._worldSpaceDeadZone.y,
this._worldSpaceDeadZone.width, this._worldSpaceDeadZone.height);
this.rectShape.graphics.endFill();
}
}
/**
* 固定相机 永远不会离开地图的可见区域
* @param position
*/
public clampToMapSize(position: Vector2) {
let halfScreen = Vector2.multiply(this.camera.bounds.size, new Vector2(0.5)).add(new Vector2(this.mapSize.x, this.mapSize.y));
let cameraMax = new Vector2(this.mapSize.width - halfScreen.x, this.mapSize.height - halfScreen.y);
return Vector2.clamp(position, halfScreen, cameraMax);
}
public follow(targetEntity: Entity, cameraStyle: CameraStyle = CameraStyle.cameraWindow) {
this._targetEntity = targetEntity;
this._cameraStyle = cameraStyle;
let cameraBounds = this.camera.bounds;
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 updateFollow() {
this._desiredPositionDelta.x = this._desiredPositionDelta.y = 0;
if (this._cameraStyle == CameraStyle.lockOn) {
let targetX = this._targetEntity.transform.position.x;
let targetY = this._targetEntity.transform.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;
}
}
}
/**
* 以给定的尺寸设置当前相机边界中心的死区
* @param width
* @param height
*/
public setCenteredDeadzone(width: number, height: number) {
if (!this.camera){
console.error("相机是null。我们不能得到它的边界。请等到该组件添加到实体之后");
return;
}
let cameraBounds = this.camera.bounds;
this.deadzone = new Rectangle((cameraBounds.width - width) / 2, (cameraBounds.height - height) / 2, width, height);
}
}
}

View File

@@ -110,18 +110,18 @@ module es {
if (!this.pixelShape2.parent)
this.debugDisplayObject.addChild(this.pixelShape2);
this.hollowShape.graphics.clear();
this.hollowShape.graphics.beginFill(Colors.colliderBounds, 0);
this.hollowShape.graphics.lineStyle(Size.lineSizeMultiplier, Colors.colliderBounds);
this.hollowShape.graphics.drawRect(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height);
this.hollowShape.graphics.endFill();
// this.hollowShape.graphics.clear();
// this.hollowShape.graphics.beginFill(Colors.colliderBounds, 0);
// this.hollowShape.graphics.lineStyle(Size.lineSizeMultiplier, Colors.colliderBounds);
// this.hollowShape.graphics.drawRect(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height);
// this.hollowShape.graphics.endFill();
this.polygonShape.graphics.clear();
if (poly.points.length >= 2){
this.polygonShape.graphics.beginFill(Colors.colliderEdge, 0);
this.polygonShape.graphics.lineStyle(Size.lineSizeMultiplier, Colors.colliderEdge);
for (let i = 1; i < poly.points.length; i ++){
if (i == 1){
for (let i = 0; i < poly.points.length; i ++){
if (i == 0){
this.polygonShape.graphics.moveTo(poly.position.x + poly.points[i].x, poly.position.y + poly.points[i].y);
}else{
this.polygonShape.graphics.lineTo(poly.position.x + poly.points[i].x, poly.position.y + poly.points[i].y);
@@ -136,6 +136,7 @@ module es {
this.pixelShape1.graphics.beginFill(Colors.colliderPosition, 0);
this.pixelShape1.graphics.lineStyle(4 * Size.lineSizeMultiplier, Colors.colliderPosition);
this.pixelShape1.graphics.moveTo(this.entity.transform.position.x, this.entity.transform.position.y);
this.pixelShape1.graphics.lineTo(this.entity.transform.position.x, this.entity.transform.position.y);
this.pixelShape1.graphics.endFill();
this.pixelShape2.graphics.clear();
@@ -143,6 +144,8 @@ module es {
this.pixelShape2.graphics.lineStyle(2 * Size.lineSizeMultiplier, Colors.colliderCenter);
this.pixelShape2.graphics.moveTo(this.entity.transform.position.x + this.shape.center.x,
this.entity.transform.position.y + this.shape.center.y);
this.pixelShape2.graphics.lineTo(this.entity.transform.position.x + this.shape.center.x,
this.entity.transform.position.y + this.shape.center.y);
this.pixelShape2.graphics.endFill();
}

View File

@@ -1,5 +1,10 @@
module es {
export class CircleCollider extends Collider {
private rectShape: egret.Shape = new egret.Shape();
private circleShape: egret.Shape = new egret.Shape();
private pixelShape1: egret.Shape = new egret.Shape();
private pixelShape2: egret.Shape = new egret.Shape();
/**
* 创建一个有半径的圆
*
@@ -41,6 +46,46 @@ module es {
return this;
}
public debugRender() {
if (!this.rectShape.parent)
this.debugDisplayObject.addChild(this.rectShape);
if (!this.circleShape.parent)
this.debugDisplayObject.addChild(this.circleShape);
if (!this.pixelShape1.parent)
this.debugDisplayObject.addChild(this.pixelShape1);
if (!this.pixelShape2.parent)
this.debugDisplayObject.addChild(this.pixelShape2);
this.rectShape.graphics.clear();
this.rectShape.graphics.beginFill(Colors.colliderBounds, 0);
this.rectShape.graphics.lineStyle(Size.lineSizeMultiplier, Colors.colliderBounds);
this.rectShape.graphics.drawRect(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height);
this.rectShape.graphics.endFill();
this.circleShape.graphics.clear();
this.circleShape.graphics.beginFill(Colors.colliderEdge, 0);
this.circleShape.graphics.lineStyle(Size.lineSizeMultiplier, Colors.colliderEdge);
this.circleShape.graphics.drawCircle(this.shape.position.x, this.shape.position.y, (this.shape as Circle).radius);
this.circleShape.graphics.endFill();
this.pixelShape1.graphics.clear();
this.pixelShape1.graphics.beginFill(Colors.colliderPosition, 0);
this.pixelShape1.graphics.lineStyle(4 * Size.lineSizeMultiplier, Colors.colliderPosition);
this.pixelShape1.graphics.moveTo(this.entity.transform.position.x, this.entity.transform.position.y);
this.pixelShape1.graphics.lineTo(this.entity.transform.position.x, this.entity.transform.position.y);
this.pixelShape1.graphics.endFill();
this.pixelShape2.graphics.clear();
this.pixelShape2.graphics.beginFill(Colors.colliderCenter, 0);
this.pixelShape2.graphics.lineStyle(2 * Size.lineSizeMultiplier, Colors.colliderCenter);
this.pixelShape2.graphics.moveTo(this.shape.position.x, this.shape.position.y);
this.pixelShape2.graphics.lineTo(this.shape.position.x, this.shape.position.y);
this.pixelShape2.graphics.endFill();
}
public toString() {
return `[CircleCollider: bounds: ${this.bounds}, radius: ${(this.shape as Circle).radius}]`
}

View File

@@ -122,19 +122,20 @@ module es {
if (!this.pixelShape.parent)
this.debugDisplayObject.addChild(this.pixelShape);
if (!this.entity.getComponent(Collider)){
this.hollowShape.graphics.clear();
this.hollowShape.graphics.beginFill(Colors.renderableBounds, 0);
this.hollowShape.graphics.lineStyle(1, Colors.renderableBounds);
this.hollowShape.graphics.drawRect(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height);
this.hollowShape.graphics.endFill();
}
// if (!this.entity.getComponent(Collider)){
// this.hollowShape.graphics.clear();
// this.hollowShape.graphics.beginFill(Colors.renderableBounds, 0);
// this.hollowShape.graphics.lineStyle(1, Colors.renderableBounds);
// this.hollowShape.graphics.drawRect(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height);
// this.hollowShape.graphics.endFill();
// }
let pixelPos = Vector2.add(this.entity.transform.position, this._localOffset);
this.pixelShape.graphics.clear();
this.pixelShape.graphics.beginFill(Colors.renderableCenter, 0);
this.pixelShape.graphics.lineStyle(4, Colors.renderableCenter);
this.pixelShape.graphics.lineTo(pixelPos.x, pixelPos.y);
this.pixelShape.graphics.moveTo(pixelPos.x, pixelPos.y);
this.pixelShape.graphics.endFill();
}

View File

@@ -123,8 +123,10 @@ module es {
public render(camera: Camera) {
this.sync(camera);
if (this.displayObject.x != this.bounds.x) this.displayObject.x = this.bounds.x;
if (this.displayObject.y != this.bounds.y) this.displayObject.y = this.bounds.y;
let afterPos = new Vector2(this.entity.position.x + this.localOffset.x - this.origin.x - camera.position.x + camera.origin.x,
this.entity.position.y + this.localOffset.y - this.origin.y - camera.position.y + camera.origin.y);
if (this.displayObject.x != afterPos.x) this.displayObject.x = afterPos.x;
if (this.displayObject.y != afterPos.y) this.displayObject.y = afterPos.y;
}
}
}

View File

@@ -29,6 +29,7 @@ module es {
* 全局访问系统
*/
public _globalManagers: GlobalManager[] = [];
public _timerManager: TimerManager = new TimerManager();
constructor() {
super();
@@ -38,6 +39,8 @@ module es {
Core.content = new ContentManager();
this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
Core.registerGlobalManager(this._timerManager);
}
/**
@@ -70,8 +73,8 @@ module es {
}
if (this._instance._scene == null) {
this._instance._scene = value;
this._instance.addChild(value);
this._instance._scene = value;
this._instance._scene.begin();
Core.Instance.onSceneChanged();
} else {
@@ -123,6 +126,17 @@ module es {
return null;
}
/**
* 调度一个一次性或重复的计时器,该计时器将调用已传递的动作
* @param timeInSeconds
* @param repeats
* @param context
* @param onTime
*/
public static schedule(timeInSeconds: number, repeats: boolean = false, context: any = null, onTime: (timer: ITimer)=>void){
return this._instance._timerManager.schedule(timeInSeconds, repeats, context, onTime);
}
public onOrientationChanged() {
Core.emitter.emit(CoreEvents.OrientationChanged);
}
@@ -210,8 +224,8 @@ module es {
this._nextScene = null;
this.onSceneChanged();
this.addChild(this._scene);
await this._scene.begin();
this.addChild(this._scene);
}
}

View File

@@ -91,24 +91,34 @@ module es {
console.warn("场景开始时没有渲染器 自动添加DefaultRenderer以保证能够正常渲染");
}
this.camera = this.createEntity("camera").getOrCreateComponent(new Camera());
let cameraEntity = this.findEntity("camera");
if (!cameraEntity)
cameraEntity = this.createEntity("camera");
this.camera = cameraEntity.getOrCreateComponent(new Camera());
Physics.reset();
this.updateResolutionScaler();
if (this.entityProcessors)
this.entityProcessors.begin();
Core.emitter.addObserver(CoreEvents.GraphicsDeviceReset,this.updateResolutionScaler, this);
Core.emitter.addObserver(CoreEvents.OrientationChanged, this.updateResolutionScaler, this);
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();
}
public end() {
this._didSceneBegin = false;
Core.emitter.removeObserver(CoreEvents.GraphicsDeviceReset, this.updateResolutionScaler);
Core.emitter.removeObserver(CoreEvents.OrientationChanged, this.updateResolutionScaler);
this.removeEventListener(egret.Event.DEACTIVATE, this.onDeactive, this);
this.removeEventListener(egret.Event.ACTIVATE, this.onActive, this);
@@ -140,6 +150,10 @@ module es {
this.unload();
}
public updateResolutionScaler(){
this.camera.onSceneRenderTargetSizeChanged(Core.Instance.stage.stageWidth, Core.Instance.stage.stageHeight);
}
public update() {
// 更新我们的列表,以防它们有任何变化
this.entities.updateLists();

View File

@@ -50,9 +50,16 @@ module es {
return value;
}
/**
* 给定圆心、半径和角度得到圆周上的一个点。0度是3点钟。
* @param circleCenter
* @param radius
* @param angleInDegrees
*/
public static pointOnCirlce(circleCenter: Vector2, radius: number, angleInDegrees: number) {
let radians = MathHelper.toRadians(angleInDegrees);
return new Vector2(Math.cos(radians) * radians + circleCenter.x, Math.sin(radians) * radians + circleCenter.y);
return new Vector2(Math.cos(radians) * radians + circleCenter.x,
Math.sin(radians) * radians + circleCenter.y);
}
/**

View File

@@ -1,10 +1,6 @@
module es {
/** 2d 向量 */
export class Vector2 {
private static readonly unitYVector = new Vector2(0, 1);
private static readonly unitXVector = new Vector2(1, 0);
private static readonly unitVector2 = new Vector2(1, 1);
private static readonly zeroVector2 = new Vector2(0, 0);
public x: number = 0;
public y: number = 0;
@@ -19,19 +15,19 @@ module es {
}
public static get zero() {
return Vector2.zeroVector2;
return new Vector2(0, 0);
}
public static get one() {
return Vector2.unitVector2;
return new Vector2(1, 1);
}
public static get unitX() {
return Vector2.unitXVector;
return new Vector2(1, 0);
}
public static get unitY() {
return Vector2.unitYVector;
return new Vector2(0, 1);
}
/**

View File

@@ -219,7 +219,7 @@ module es {
let tempMat: Matrix2D;
let combinedMatrix = Matrix2D.create().translate(-this._polygonCenter.x, -this._polygonCenter.y);
if (collider.entity.transform.scale != Vector2.zero) {
if (collider.entity.transform.scale != Vector2.one) {
tempMat = Matrix2D.create().scale(collider.entity.transform.scale.x, collider.entity.transform.scale.y);
combinedMatrix = combinedMatrix.multiply(tempMat);
hasUnitScale = false;
@@ -238,7 +238,7 @@ module es {
let offsetLength = hasUnitScale ? collider._localOffsetLength :
Vector2.multiply(collider.localOffset, collider.entity.transform.scale).length();
this.center = MathHelper.pointOnCirlce(Vector2.zero, offsetLength,
collider.entity.transform.rotation + offsetAngle);
collider.entity.transform.rotationDegrees + offsetAngle);
}
tempMat = Matrix2D.create().translate(this._polygonCenter.x, this._polygonCenter.y);
@@ -256,7 +256,7 @@ module es {
this.position = Vector2.add(collider.entity.transform.position, this.center);
this.bounds = Rectangle.rectEncompassingPoints(this.points);
this.bounds.location = this.bounds.location.add(this.position);
this.bounds.location.add(this.position);
}
public overlaps(other: Shape) {
@@ -304,7 +304,7 @@ module es {
*/
public containsPoint(point: Vector2) {
// 将点归一化到多边形坐标空间中
point = Vector2.subtract(point, this.position);
point.subtract(this.position);
let isInside = false;
for (let i = 0, j = this.points.length - 1; i < this.points.length; j = i++) {

View File

@@ -311,21 +311,16 @@ module es {
return this._store.get(this.getKey(x, y));
}
public getKey(x: number, y: number){
return `${x}_${y}`;
}
/**
* 清除字典数据
*/
public clear() {
this._store.clear();
}
/**
* 根据x和y值计算并返回散列键
* @param x
* @param y
*/
private getKey(x: number, y: number): string {
return Long.fromNumber(x).shiftLeft(32).or(Long.fromNumber(y, true)).toString();
}
}
export class RaycastResultParser {

View File

@@ -25,8 +25,6 @@ module es {
public enabled: true;
/** 获取/设置日志显示或否 */
public showLog = false;
private _frameKey = 'frame';
private _logKey = 'log';
/** 每帧的日志 */
private _logs: FrameLog[];
/** 当前显示帧计数 */
@@ -85,108 +83,101 @@ module es {
*/
public startFrame() {
// 当这个方法被多次调用时,我们跳过重置帧。
let lock = new LockUtils(this._frameKey);
lock.lock().then(() => {
this._updateCount = parseInt(egret.localStorage.getItem(this._frameKey), 10);
if (isNaN(this._updateCount))
this._updateCount = 0;
let count = this._updateCount;
count += 1;
egret.localStorage.setItem(this._frameKey, count.toString());
if (this.enabled && (1 < count && count < TimeRuler.maxSampleFrames))
return;
if (isNaN(this._updateCount))
this._updateCount = 0;
let count = this._updateCount;
count += 1;
if (this.enabled && (1 < count && count < TimeRuler.maxSampleFrames))
return;
// 更新当前帧日志。
this._prevLog = this._logs[this.frameCount++ & 0x1];
this._curLog = this._logs[this.frameCount & 0x1];
// 更新当前帧日志。
this._prevLog = this._logs[this.frameCount++ & 0x1];
this._curLog = this._logs[this.frameCount & 0x1];
let endFrameTime = this.stopwacth.getTime();
// 更新标记并创建日志。
for (let barIndex = 0; barIndex < this._prevLog.bars.length; ++barIndex) {
let prevBar = this._prevLog.bars[barIndex];
let nextBar = this._curLog.bars[barIndex];
let endFrameTime = this.stopwacth.getTime();
// 更新标记并创建日志。
for (let barIndex = 0; barIndex < this._prevLog.bars.length; ++barIndex) {
let prevBar = this._prevLog.bars[barIndex];
let nextBar = this._curLog.bars[barIndex];
// 重新打开在前一帧中没有调用结束标记的标记。
for (let nest = 0; nest < prevBar.nestCount; ++nest) {
let markerIdx = prevBar.markerNests[nest];
prevBar.markers[markerIdx].endTime = endFrameTime;
nextBar.markerNests[nest] = nest;
nextBar.markers[nest].markerId = prevBar.markers[markerIdx].markerId;
nextBar.markers[nest].beginTime = 0;
nextBar.markers[nest].endTime = -1;
nextBar.markers[nest].color = prevBar.markers[markerIdx].color;
}
// 更新日志标记
for (let markerIdx = 0; markerIdx < prevBar.markCount; ++markerIdx) {
let duration = prevBar.markers[markerIdx].endTime - prevBar.markers[markerIdx].beginTime;
let markerId = prevBar.markers[markerIdx].markerId;
let m = this.markers[markerId];
m.logs[barIndex].color = prevBar.markers[markerIdx].color;
if (!m.logs[barIndex].initialized) {
m.logs[barIndex].min = duration;
m.logs[barIndex].max = duration;
m.logs[barIndex].avg = duration;
m.logs[barIndex].initialized = true;
} else {
m.logs[barIndex].min = Math.min(m.logs[barIndex].min, duration);
m.logs[barIndex].max = Math.min(m.logs[barIndex].max, duration);
m.logs[barIndex].avg += duration;
m.logs[barIndex].avg *= 0.5;
if (m.logs[barIndex].samples++ >= TimeRuler.logSnapDuration) {
m.logs[barIndex].snapMin = m.logs[barIndex].min;
m.logs[barIndex].snapMax = m.logs[barIndex].max;
m.logs[barIndex].snapAvg = m.logs[barIndex].avg;
m.logs[barIndex].samples = 0;
}
}
}
nextBar.markCount = prevBar.nestCount;
nextBar.nestCount = prevBar.nestCount;
// 重新打开在前一帧中没有调用结束标记的标记。
for (let nest = 0; nest < prevBar.nestCount; ++nest) {
let markerIdx = prevBar.markerNests[nest];
prevBar.markers[markerIdx].endTime = endFrameTime;
nextBar.markerNests[nest] = nest;
nextBar.markers[nest].markerId = prevBar.markers[markerIdx].markerId;
nextBar.markers[nest].beginTime = 0;
nextBar.markers[nest].endTime = -1;
nextBar.markers[nest].color = prevBar.markers[markerIdx].color;
}
this.stopwacth.reset();
this.stopwacth.start();
});
// 更新日志标记
for (let markerIdx = 0; markerIdx < prevBar.markCount; ++markerIdx) {
let duration = prevBar.markers[markerIdx].endTime - prevBar.markers[markerIdx].beginTime;
let markerId = prevBar.markers[markerIdx].markerId;
let m = this.markers[markerId];
m.logs[barIndex].color = prevBar.markers[markerIdx].color;
if (!m.logs[barIndex].initialized) {
m.logs[barIndex].min = duration;
m.logs[barIndex].max = duration;
m.logs[barIndex].avg = duration;
m.logs[barIndex].initialized = true;
} else {
m.logs[barIndex].min = Math.min(m.logs[barIndex].min, duration);
m.logs[barIndex].max = Math.min(m.logs[barIndex].max, duration);
m.logs[barIndex].avg += duration;
m.logs[barIndex].avg *= 0.5;
if (m.logs[barIndex].samples++ >= TimeRuler.logSnapDuration) {
m.logs[barIndex].snapMin = m.logs[barIndex].min;
m.logs[barIndex].snapMax = m.logs[barIndex].max;
m.logs[barIndex].snapAvg = m.logs[barIndex].avg;
m.logs[barIndex].samples = 0;
}
}
}
nextBar.markCount = prevBar.nestCount;
nextBar.nestCount = prevBar.nestCount;
}
this.stopwacth.reset();
this.stopwacth.start();
}
/**
* 开始测量时间。
* @param markerName
* @param color
* @param barIndex
*/
public beginMark(markerName: string, color: number, barIndex: number = 0) {
let lock = new LockUtils(this._frameKey);
lock.lock().then(() => {
if (barIndex < 0 || barIndex >= TimeRuler.maxBars)
throw new Error("barIndex argument out of range");
if (barIndex < 0 || barIndex >= TimeRuler.maxBars)
throw new Error("barIndex argument out of range");
let bar = this._curLog.bars[barIndex];
if (bar.markCount >= TimeRuler.maxSamples) {
throw new Error("exceeded sample count. either set larger number to timeruler.maxsaple or lower sample count");
}
let bar = this._curLog.bars[barIndex];
if (bar.markCount >= TimeRuler.maxSamples) {
throw new Error("exceeded sample count. either set larger number to timeruler.maxsaple or lower sample count");
}
if (bar.nestCount >= TimeRuler.maxNestCall) {
throw new Error("exceeded nest count. either set larger number to timeruler.maxnestcall or lower nest calls");
}
if (bar.nestCount >= TimeRuler.maxNestCall) {
throw new Error("exceeded nest count. either set larger number to timeruler.maxnestcall or lower nest calls");
}
// 获取注册的标记
let markerId = this._markerNameToIdMap.get(markerName);
if (isNaN(markerId)) {
// 如果此标记未注册,则注册此标记。
markerId = this.markers.length;
this._markerNameToIdMap.set(markerName, markerId);
}
// 获取注册的标记
let markerId = this._markerNameToIdMap.get(markerName);
if (isNaN(markerId)) {
// 如果此标记未注册,则注册此标记。
markerId = this.markers.length;
this._markerNameToIdMap.set(markerName, markerId);
}
bar.markerNests[bar.nestCount++] = bar.markCount;
bar.markers[bar.markCount].markerId = markerId;
bar.markers[bar.markCount].color = color;
bar.markers[bar.markCount].beginTime = this.stopwacth.getTime();
bar.markers[bar.markCount].endTime = -1;
});
bar.markerNests[bar.nestCount++] = bar.markCount;
bar.markers[bar.markCount].markerId = markerId;
bar.markers[bar.markCount].color = color;
bar.markers[bar.markCount].beginTime = this.stopwacth.getTime();
bar.markers[bar.markCount].endTime = -1;
}
/**
@@ -195,28 +186,25 @@ module es {
* @param barIndex
*/
public endMark(markerName: string, barIndex: number = 0) {
let lock = new LockUtils(this._frameKey);
lock.lock().then(() => {
if (barIndex < 0 || barIndex >= TimeRuler.maxBars)
throw new Error("barIndex argument out of range");
if (barIndex < 0 || barIndex >= TimeRuler.maxBars)
throw new Error("barIndex argument out of range");
let bar = this._curLog.bars[barIndex];
if (bar.nestCount <= 0) {
throw new Error("call beginMark method before calling endMark method");
}
let bar = this._curLog.bars[barIndex];
if (bar.nestCount <= 0) {
throw new Error("call beginMark method before calling endMark method");
}
let markerId = this._markerNameToIdMap.get(markerName);
if (isNaN(markerId)) {
throw new Error(`Marker ${markerName} is not registered. Make sure you specifed same name as you used for beginMark method`);
}
let markerId = this._markerNameToIdMap.get(markerName);
if (isNaN(markerId)) {
throw new Error(`Marker ${markerName} is not registered. Make sure you specifed same name as you used for beginMark method`);
}
let markerIdx = bar.markerNests[--bar.nestCount];
if (bar.markers[markerIdx].markerId != markerId) {
throw new Error("Incorrect call order of beginMark/endMark method. beginMark(A), beginMark(B), endMark(B), endMark(A) But you can't called it like beginMark(A), beginMark(B), endMark(A), endMark(B).");
}
let markerIdx = bar.markerNests[--bar.nestCount];
if (bar.markers[markerIdx].markerId != markerId) {
throw new Error("Incorrect call order of beginMark/endMark method. beginMark(A), beginMark(B), endMark(B), endMark(A) But you can't called it like beginMark(A), beginMark(B), endMark(A), endMark(B).");
}
bar.markers[markerIdx].endTime = this.stopwacth.getTime();
});
bar.markers[markerIdx].endTime = this.stopwacth.getTime();
}
/**
@@ -241,31 +229,23 @@ module es {
*
*/
public resetLog() {
let lock = new LockUtils(this._logKey);
lock.lock().then(() => {
let count = parseInt(egret.localStorage.getItem(this._logKey), 10);
count += 1;
egret.localStorage.setItem(this._logKey, count.toString());
this.markers.forEach(markerInfo => {
for (let i = 0; i < markerInfo.logs.length; ++i) {
markerInfo.logs[i].initialized = false;
markerInfo.logs[i].snapMin = 0;
markerInfo.logs[i].snapMax = 0;
markerInfo.logs[i].snapAvg = 0;
this.markers.forEach(markerInfo => {
for (let i = 0; i < markerInfo.logs.length; ++i) {
markerInfo.logs[i].initialized = false;
markerInfo.logs[i].snapMin = 0;
markerInfo.logs[i].snapMax = 0;
markerInfo.logs[i].snapAvg = 0;
markerInfo.logs[i].min = 0;
markerInfo.logs[i].max = 0;
markerInfo.logs[i].avg = 0;
markerInfo.logs[i].min = 0;
markerInfo.logs[i].max = 0;
markerInfo.logs[i].avg = 0;
markerInfo.logs[i].samples = 0;
}
});
markerInfo.logs[i].samples = 0;
}
});
}
public render(position: Vector2 = this._position, width: number = this.width) {
egret.localStorage.setItem(this._frameKey, "0");
if (!this.showLog)
return;

View File

@@ -1,55 +0,0 @@
const THREAD_ID = `${Math.floor(Math.random() * 1000)}-${Date.now()}`;
const nextTick = fn => {
setTimeout(fn, 0);
};
/**
* 利用共享区域实现快速锁
*/
class LockUtils {
private _keyX: string;
private _keyY: string;
private setItem;
private getItem;
private removeItem;
constructor(key) {
this._keyX = `mutex_key_${key}_X`;
this._keyY = `mutex_key_${key}_Y`;
this.setItem = egret.localStorage.setItem.bind(localStorage);
this.getItem = egret.localStorage.getItem.bind(localStorage);
this.removeItem = egret.localStorage.removeItem.bind(localStorage);
}
public lock() {
return new Promise((resolve, reject) => {
const fn = () => {
this.setItem(this._keyX, THREAD_ID);
if (!this.getItem(this._keyY) === null) {
// restart
nextTick(fn);
}
this.setItem(this._keyY, THREAD_ID);
if (this.getItem(this._keyX) !== THREAD_ID) {
// delay
setTimeout(() => {
if (this.getItem(this._keyY) !== THREAD_ID) {
// restart
nextTick(fn);
return;
}
// critical section
resolve();
this.removeItem(this._keyY);
}, 10);
} else {
resolve();
this.removeItem(this._keyY);
}
};
fn();
});
}
}

View File

@@ -0,0 +1,20 @@
module es {
export interface ITimer {
context: any;
/**
* 调用stop以停止此计时器再次运行。这对非重复计时器没有影响。
*/
stop();
/**
* 将计时器的运行时间重置为0
*/
reset();
/**
*
*/
getContext<T>(): T;
}
}

View File

@@ -0,0 +1,52 @@
module es {
export class Timer implements ITimer{
public context: any;
public _timeInSeconds: number = 0;
public _repeats: boolean = false;
public _onTime: (timer: ITimer) => void;
public _isDone: boolean = false;
public _elapsedTime: number = 0;
public getContext<T>(): T {
return this.context as T;
}
public reset() {
this._elapsedTime = 0;
}
public stop() {
this._isDone = true;
}
public tick(){
// 如果stop在tick之前被调用那么isDone将为true我们不应该再做任何事情
if (!this._isDone && this._elapsedTime > this._timeInSeconds){
this._elapsedTime -= this._timeInSeconds;
this._onTime(this);
if (!this._isDone && !this._repeats)
this._isDone = true;
}
this._elapsedTime += Time.deltaTime;
return this._isDone;
}
public initialize(timeInsSeconds: number, repeats: boolean, context: any, onTime: (timer: ITimer)=>void){
this._timeInSeconds = timeInsSeconds;
this._repeats = repeats;
this.context = context;
this._onTime = onTime;
}
/**
* 空出对象引用以便在js需要时GC可以清理它们的引用
*/
public unload(){
this.context = null;
this._onTime = null;
}
}
}

View File

@@ -0,0 +1,32 @@
module es {
/**
* 允许动作的延迟和重复执行
*/
export class TimerManager extends GlobalManager {
public _timers: Timer[] = [];
public update() {
for (let i = this._timers.length - 1; i >= 0; i --){
if (this._timers[i].tick()){
this._timers[i].unload();
this._timers.removeAt(i);
}
}
}
/**
* 调度一个一次性或重复的计时器,该计时器将调用已传递的动作
* @param timeInSeconds
* @param repeats
* @param context
* @param onTime
*/
public schedule(timeInSeconds: number, repeats: boolean, context: any, onTime: (timer: ITimer)=>void){
let timer = new Timer();
timer.initialize(timeInSeconds, repeats, context, onTime);
this._timers.push(timer);
return timer;
}
}
}