移除所有egret 依赖。移除renderablecomponent及所有依赖,移除camera。保持ecs基础框架

This commit is contained in:
yhh
2020-11-23 16:05:06 +08:00
parent 0fd6a24f5a
commit 14a73e4010
76 changed files with 1410 additions and 28750 deletions

View File

@@ -1,40 +0,0 @@
///<reference path="../ECS/Core.ts" />
module es {
export class Colors {
public static renderableBounds = 0xffff00;
public static renderableCenter = 0x9932CC;
public static colliderBounds = 0x555555;
public static colliderEdge = 0x8B0000;
public static colliderPosition = 0xFFFF00;
public static colliderCenter = 0xFF0000;
}
export class Size {
public static get lineSizeMultiplier(){
return Math.max(Math.ceil(Core.scene.x / Core.scene.width), 1);
}
}
export class Debug {
private static _debugDrawItems: DebugDrawItem[] = [];
public static drawHollowRect(rectanle: Rectangle, color: number, duration = 0) {
this._debugDrawItems.push(new DebugDrawItem(rectanle, color, duration));
}
public static render() {
if (this._debugDrawItems.length > 0) {
let debugShape = new egret.Shape();
if (Core.scene) {
Core.scene.addChild(debugShape);
}
for (let i = this._debugDrawItems.length - 1; i >= 0; i--) {
let item = this._debugDrawItems[i];
if (item.draw(debugShape))
this._debugDrawItems.removeAt(i);
}
}
}
}
}

View File

@@ -1,49 +0,0 @@
module es {
export enum DebugDrawType {
line,
hollowRectangle,
pixel,
text
}
export class DebugDrawItem {
public rectangle: Rectangle;
public color: number;
public duration: number;
public drawType: DebugDrawType;
public text: string;
public start: Vector2;
public end: Vector2;
public x: number;
public y: number;
public size: number;
constructor(rectangle: Rectangle, color: number, duration: number) {
this.rectangle = rectangle;
this.color = color;
this.duration = duration;
this.drawType = DebugDrawType.hollowRectangle;
}
public draw(shape: egret.Shape): boolean {
switch (this.drawType) {
case DebugDrawType.line:
// DrawUtils.drawLine(shape, this.start, this.end, this.color);
break;
case DebugDrawType.hollowRectangle:
// DrawUtils.drawHollowRect(shape, this.rectangle, this.color);
break;
case DebugDrawType.pixel:
// DrawUtils.drawPixel(shape, new Vector2(this.x, this.y), this.color, this.size);
break;
case DebugDrawType.text:
break;
}
this.duration -= Time.deltaTime;
return this.duration < 0;
}
}
}

View File

@@ -7,7 +7,7 @@ module es {
* 删除执行顺序
* - onRemovedFromEntity
*/
export abstract class Component extends egret.HashObject {
export abstract class Component {
/**
* 此组件附加的实体
*/
@@ -16,10 +16,6 @@ module es {
* 更新该组件的时间间隔。这与实体的更新间隔无关。
*/
public updateInterval: number = 1;
/**
* 用于装载debug使用的显示容器
*/
public debugDisplayObject: egret.DisplayObjectContainer = new egret.DisplayObjectContainer();
/**
* 快速访问 this.entity.transform
@@ -99,13 +95,7 @@ module es {
*/
public onDisabled() {
}
/**
* 当该组件启用时每帧进行调用
*/
public update() {
}
public setEnabled(isEnabled: boolean) {
if (this._enabled != isEnabled) {
this._enabled = isEnabled;

View File

@@ -1,369 +0,0 @@
module es {
export interface CameraInset {
left: number, right: number, top: number, bottom: number
}
export class Camera extends Component {
public _inset: CameraInset = {left: 0, right: 0, top: 0, bottom: 0};
public _areMatrixedDirty: boolean = true;
public _areBoundsDirty: boolean = true;
public _isProjectionMatrixDirty = true;
constructor() {
super();
this.setZoom(0);
}
/**
* 对entity.transform.position的快速访问
*/
public get position() {
return this.entity.transform.position;
}
/**
* 对entity.transform.position的快速访问
* @param value
*/
public set position(value: Vector2) {
this.entity.transform.position = value;
}
/**
* 对entity.transform.rotation的快速访问
*/
public get rotation(): number {
return this.entity.transform.rotation;
}
/**
* 对entity.transform.rotation的快速访问
* @param value
*/
public set rotation(value: number) {
this.entity.transform.rotation = value;
}
/**
* 原始的缩放值。这就是用于比例矩阵的精确值。默认值为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。
* 允许你设置适当的最小/最大值,然后使用更直观的-1到1的映射来更改缩放
*/
public get zoom() {
if (this._zoom == 0)
return 1;
if (this._zoom < 1)
return MathHelper.map(this._zoom, this._minimumZoom, 1, -1, 0);
return MathHelper.map(this._zoom, 1, this._maximumZoom, 0, 1);
}
/**
* 缩放值应该在-1和1之间、然后将该值从minimumZoom转换为maximumZoom。
* 允许你设置适当的最小/最大值,然后使用更直观的-1到1的映射来更改缩放
* @param value
*/
public set zoom(value: number) {
this.setZoom(value);
}
public _minimumZoom = 0.3;
/**
* 相机变焦可以达到的最小非缩放值0-number.max。默认为0.3
*/
public get minimumZoom() {
return this._minimumZoom;
}
/**
* 相机变焦可以达到的最小非缩放值0-number.max。默认为0.3
* @param value
*/
public set minimumZoom(value: number) {
this.setMinimumZoom(value);
}
public _maximumZoom = 3;
/**
* 相机变焦可以达到的最大非缩放值0-number.max。默认为3
*/
public get maximumZoom() {
return this._maximumZoom;
}
/**
* 相机变焦可以达到的最大非缩放值0-number.max。默认为3
* @param value
*/
public set maximumZoom(value: number) {
this.setMaximumZoom(value);
}
public _bounds: Rectangle = new Rectangle();
/**
* 相机的世界-空间边界
*/
public get bounds() {
if (this._areMatrixedDirty)
this.updateMatrixes();
if (this._areBoundsDirty) {
// 旋转或非旋转的边界都需要左上角和右下角
let topLeft = this.screenToWorldPoint(new Vector2(this._inset.left, this._inset.top));
let bottomRight = this.screenToWorldPoint(new Vector2(Core.graphicsDevice.viewport.width - this._inset.right,
Core.graphicsDevice.viewport.height - this._inset.bottom));
if (this.entity.transform.rotation != 0) {
// 特别注意旋转的边界。我们需要找到绝对的最小/最大值并从中创建边界
let topRight = this.screenToWorldPoint(new Vector2(Core.graphicsDevice.viewport.width - this._inset.right,
this._inset.top));
let bottomLeft = this.screenToWorldPoint(new Vector2(this._inset.left,
Core.graphicsDevice.viewport.height - this._inset.bottom));
let minX = Math.min(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x);
let maxX = Math.max(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x);
let minY = Math.min(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y);
let maxY = Math.max(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y);
this._bounds.location = new Vector2(minX, minY);
this._bounds.width = maxX - minX;
this._bounds.height = maxY - minY;
} else {
this._bounds.location = topLeft;
this._bounds.width = bottomRight.x - topLeft.x;
this._bounds.height = bottomRight.y - topLeft.y;
}
this._areBoundsDirty = false;
}
return this._bounds;
}
public _transformMatrix: Matrix2D = new Matrix2D().identity();
/**
* 用于从世界坐标转换到屏幕
*/
public get transformMatrix(): Matrix2D {
if (this._areMatrixedDirty)
this.updateMatrixes();
return this._transformMatrix;
}
public _inverseTransformMatrix: Matrix2D = new Matrix2D().identity();
/**
* 用于从屏幕坐标到世界的转换
*/
public get inverseTransformMatrix(): Matrix2D {
if (this._areMatrixedDirty)
this.updateMatrixes();
return this._inverseTransformMatrix;
}
public _origin: Vector2 = Vector2.zero;
public get origin() {
return this._origin;
}
public set origin(value: Vector2) {
if (this._origin != value) {
this._origin = value;
this._areMatrixedDirty = true;
}
}
/**
* 设置用于从视口边缘插入摄像机边界的量
* @param left
* @param right
* @param top
* @param bottom
*/
public setInset(left: number, right: number, top: number, bottom: number): Camera {
this._inset = {left: left, right: right, top: top, bottom: bottom};
this._areBoundsDirty = true;
return this;
}
/**
* 对entity.transform.setPosition快速访问
* @param position
*/
public setPosition(position: Vector2) {
this.entity.transform.setPosition(position.x, position.y);
return this;
}
/**
* 对entity.transform.setRotation的快速访问
* @param rotation
*/
public setRotation(rotation: number): Camera {
this.entity.transform.setRotation(rotation);
return this;
}
/**
* 设置缩放值,缩放值应该在-1到1之间。然后将该值从minimumZoom转换为maximumZoom
* 允许您设置适当的最小/最大值。使用更直观的-1到1的映射来更改缩放
* @param zoom
*/
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);
}
this._areMatrixedDirty = true;
return this;
}
/**
* 相机变焦可以达到的最小非缩放值0-number.max 默认为0.3
* @param minZoom
*/
public setMinimumZoom(minZoom: number): Camera {
if (minZoom <= 0) {
console.error("minimumZoom must be greater than zero");
return;
}
if (this._zoom < minZoom)
this._zoom = this.minimumZoom;
this._minimumZoom = minZoom;
return this;
}
/**
* 相机变焦可以达到的最大非缩放值0-number.max 默认为3
* @param maxZoom
*/
public setMaximumZoom(maxZoom: number): Camera {
if (maxZoom <= 0) {
console.error("maximumZoom must be greater than zero");
return;
}
if (this._zoom > maxZoom)
this._zoom = maxZoom;
this._maximumZoom = maxZoom;
return this;
}
public forceMatrixUpdate(){
// 弄脏矩阵也会自动弄脏边界
this._areMatrixedDirty = true;
}
public onEntityTransformChanged(comp: transform.Component) {
this._areMatrixedDirty = true;
}
public zoomIn(deltaZoom: number) {
this.zoom += deltaZoom;
}
public zoomOut(deltaZoom: number) {
this.zoom -= deltaZoom;
}
/**
* 将一个点从世界坐标转换到屏幕
* @param worldPosition
*/
public worldToScreenPoint(worldPosition: Vector2): Vector2 {
this.updateMatrixes();
Vector2Ext.transformR(worldPosition, this._transformMatrix, worldPosition);
return worldPosition;
}
/**
* 将点从屏幕坐标转换为世界坐标
* @param screenPosition
*/
public screenToWorldPoint(screenPosition: Vector2): Vector2 {
this.updateMatrixes();
Vector2Ext.transformR(screenPosition, this._inverseTransformMatrix, screenPosition);
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));
}
/**
* 返回鼠标在世界空间中的位置
*/
public mouseToWorldPoint(): Vector2 {
return this.screenToWorldPoint(Input.touchPosition);
}
protected updateMatrixes() {
if (!this._areMatrixedDirty)
return;
let tempMat: Matrix2D;
this._transformMatrix = Matrix2D.create().translate(-this.entity.transform.position.x, -this.entity.transform.position.y);
if (this._zoom != 1) {
tempMat = Matrix2D.create().scale(this._zoom, this._zoom);
this._transformMatrix = this._transformMatrix.multiply(tempMat);
}
if (this.entity.transform.rotation != 0) {
tempMat = Matrix2D.create().rotate(this.entity.transform.rotation);
this._transformMatrix = this._transformMatrix.multiply(tempMat);
}
tempMat = Matrix2D.create().translate(Math.floor(this._origin.x), Math.floor(this._origin.y));
this._transformMatrix = this._transformMatrix.multiply(tempMat);
this._inverseTransformMatrix = this._transformMatrix.invert();
// 无论何时矩阵改变边界都是无效的
this._areBoundsDirty = true;
this._areMatrixedDirty = false;
}
}
}

View File

@@ -1,50 +0,0 @@
module es {
export class CameraShake extends Component {
public _shakeDirection: Vector2 = Vector2.zero;
public _shakeOffset: Vector2 = Vector2.zero;
public _shakeIntensity = 0;
public _shakeDegredation = 0.95;
/**
* 如果震动已经在运行,只有震动强度>当前shakeIntensity, 将覆盖当前值
* 如果shake当前不是活动的它将被启动。
* @param shakeIntensify 震动强度
* @param shakeDegredation 较高的值会导致更快的停止震动
* @param shakeDirection 0只会导致x/y轴上的振动。任何其他的值将导致通过在抖动方向*强度是相机移动偏移
*/
public shake(shakeIntensify = 15, shakeDegredation = 0.9, shakeDirection = Vector2.zero){
this.enabled = true;
if (this._shakeIntensity < shakeIntensify) {
this._shakeDirection = shakeDirection;
this._shakeIntensity = shakeIntensify;
if (shakeDegredation < 0 || shakeDegredation >= 1){
shakeDegredation = 0.95;
}
this._shakeDegredation = shakeDegredation;
}
}
public update() {
if (Math.abs(this._shakeIntensity) > 0){
this._shakeOffset = this._shakeDirection;
if (this._shakeOffset.x != 0 || this._shakeOffset.y != 0){
this._shakeOffset.normalize();
}else{
this._shakeOffset.x = this._shakeOffset.x + Math.random() - 0.5;
this._shakeOffset.y = this._shakeOffset.y + Math.random() - 0.5;
}
// TODO: 这需要乘相机变焦
this._shakeOffset.multiply(new Vector2(this._shakeIntensity));
this._shakeIntensity *= -this._shakeDegredation;
if (Math.abs(this._shakeIntensity) <= 0.01){
this._shakeIntensity = 0;
this.enabled = false;
}
}
this.entity.scene.camera.position.add(this._shakeOffset);
}
}
}

View File

@@ -1,186 +0,0 @@
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(camera: Camera) {
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 - camera.bounds.x, this._worldSpaceDeadZone.y - 5 - camera.bounds.y,
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 - camera.bounds.x, this._worldSpaceDeadZone.y - camera.bounds.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

@@ -1,4 +1,7 @@
module es {
/**
* 接口当添加到一个Component时只要Component和实体被启用它就会在每个框架中调用更新方法。
*/
export interface IUpdatable {
enabled: boolean;
updateOrder: number;
@@ -9,8 +12,10 @@ module es {
* 用于比较组件更新排序
*/
export class IUpdatableComparer implements IComparer<IUpdatable> {
public compare(a: Component, b: Component) {
public compare(a: IUpdatable, b: IUpdatable) {
return a.updateOrder - b.updateOrder;
}
}
export var isIUpdatable = (props: any): props is IUpdatable => typeof (props as IUpdatable)['js'] !== 'undefined';
}

View File

@@ -1,31 +1,14 @@
///<reference path="./Collider.ts" />
module es {
export class BoxCollider extends Collider {
public hollowShape: egret.Shape = new egret.Shape();
public polygonShape: egret.Shape = new egret.Shape();
public pixelShape1: egret.Shape = new egret.Shape();
public pixelShape2: egret.Shape = new egret.Shape();
/**
* 零参数构造函数要求RenderableComponent在实体上这样碰撞器可以在实体被添加到场景时调整自身的大小。
*/
constructor(x?: number, y?: number, width?: number, height?: number) {
constructor(x: number, y: number, width: number, height: number) {
super();
if (x == undefined && y == undefined){
if (width == undefined && height == undefined){
// 我们在这里插入一个1x1框作为占位符直到碰撞器在下一阵被添加到实体并可以获得更精确的自动调整大小数据
this.shape = new Box(1, 1);
this._colliderRequiresAutoSizing = true;
}else if (width != undefined && height != undefined){
x = -width / 2;
y = -height / 2;
this._localOffset = new Vector2(x + width / 2, y + height / 2);
this.shape = new Box(width, height);
}
}else if (x != undefined && y != undefined && width != undefined && height != undefined){
this._localOffset = new Vector2(x + width / 2, y + height / 2);
this.shape = new Box(width, height);
}
this._localOffset = new Vector2(x + width / 2, y + height / 2);
this.shape = new Box(width, height);
}
public get width() {
@@ -50,7 +33,6 @@ module es {
* @param height
*/
public setSize(width: number, height: number) {
this._colliderRequiresAutoSizing = false;
let box = this.shape as Box;
if (width != box.width || height != box.height) {
// 更新框,改变边界,如果我们需要更新物理系统中的边界
@@ -67,7 +49,6 @@ module es {
* @param width
*/
public setWidth(width: number): BoxCollider {
this._colliderRequiresAutoSizing = false;
let box = this.shape as Box;
if (width != box.width) {
// 更新框,改变边界,如果我们需要更新物理系统中的边界
@@ -84,7 +65,6 @@ module es {
* @param height
*/
public setHeight(height: number) {
this._colliderRequiresAutoSizing = false;
let box = this.shape as Box;
if (height != box.height) {
// 更新框,改变边界,如果我们需要更新物理系统中的边界
@@ -95,56 +75,6 @@ module es {
}
public debugRender(camera: Camera) {
let poly = this.shape as Polygon;
if (!this.hollowShape.parent)
this.debugDisplayObject.addChild(this.hollowShape);
if (!this.polygonShape.parent)
this.debugDisplayObject.addChild(this.polygonShape);
if (!this.pixelShape1.parent)
this.debugDisplayObject.addChild(this.pixelShape1);
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 - camera.bounds.x, this.bounds.y - camera.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 = 0; i < poly.points.length; i ++){
if (i == 0){
this.polygonShape.graphics.moveTo(poly.position.x + poly.points[i].x - camera.bounds.x, poly.position.y + poly.points[i].y - camera.bounds.y);
}else{
this.polygonShape.graphics.lineTo(poly.position.x + poly.points[i].x - camera.bounds.x, poly.position.y + poly.points[i].y - camera.bounds.y);
}
}
this.polygonShape.graphics.lineTo(poly.position.x + poly.points[poly.points.length - 1].x - camera.bounds.x, poly.position.y + poly.points[0].y - camera.bounds.y);
this.polygonShape.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 - camera.bounds.x, this.entity.transform.position.y - camera.bounds.y);
this.pixelShape1.graphics.lineTo(this.entity.transform.position.x - camera.bounds.x, this.entity.transform.position.y - camera.bounds.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.entity.transform.position.x + this.shape.center.x - camera.bounds.x,
this.entity.transform.position.y + this.shape.center.y - camera.bounds.y);
this.pixelShape2.graphics.lineTo(this.entity.transform.position.x + this.shape.center.x - camera.bounds.x,
this.entity.transform.position.y + this.shape.center.y - camera.bounds.y);
this.pixelShape2.graphics.endFill();
}
public toString() {

View File

@@ -1,26 +1,14 @@
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();
/**
* 创建一个有半径的圆
*
* @param radius
*/
constructor(radius?: number) {
constructor(radius: number) {
super();
if (radius == undefined){
// 我们在这里插入一个1px的圆圈作为占位符
// 直到碰撞器被添加到实体并可以获得更精确的自动调整大小数据的下一帧
this.shape = new Circle(1);
this._colliderRequiresAutoSizing = true;
}else{
this.shape = new Circle(radius);
}
this.shape = new Circle(radius);
}
public get radius(): number {
@@ -36,7 +24,6 @@ module es {
* @param radius
*/
public setRadius(radius: number): CircleCollider {
this._colliderRequiresAutoSizing = false;
let circle = this.shape as Circle;
if (radius != circle.radius) {
circle.radius = radius;
@@ -50,43 +37,7 @@ module es {
}
public debugRender(camera: Camera) {
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 - camera.bounds.x, this.bounds.y - camera.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 - camera.bounds.x, this.shape.position.y - camera.bounds.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 - camera.bounds.x, this.entity.transform.position.y - camera.bounds.y);
this.pixelShape1.graphics.lineTo(this.entity.transform.position.x - camera.bounds.y, this.entity.transform.position.y - camera.bounds.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 - camera.bounds.x, this.shape.position.y - camera.bounds.y);
this.pixelShape2.graphics.lineTo(this.shape.position.x - camera.bounds.x, this.shape.position.y - camera.bounds.y);
this.pixelShape2.graphics.endFill();
}
public toString() {

View File

@@ -29,7 +29,6 @@ module es {
public _localOffsetLength: number;
public _isPositionDirty: boolean = true;
public _isRotationDirty: boolean = true;
protected _colliderRequiresAutoSizing;
/**
* 标记来跟踪我们的实体是否被添加到场景中
*/
@@ -112,34 +111,6 @@ module es {
}
public onAddedToEntity() {
if (this._colliderRequiresAutoSizing) {
if (!(this instanceof BoxCollider || this instanceof CircleCollider)) {
console.error("Only box and circle colliders can be created automatically");
return;
}
let renderable = this.entity.getComponent<RenderableComponent>(RenderableComponent);
if (renderable) {
let renderableBounds = renderable.bounds;
// 这里我们需要大小*反尺度,因为当我们自动调整碰撞器的大小时,它需要没有缩放的渲染
let width = renderableBounds.width / this.entity.transform.scale.x;
let height = renderableBounds.height / this.entity.transform.scale.y;
// 圆碰撞器需要特别注意原点
if (this instanceof CircleCollider) {
this.radius = Math.max(width, height) * 0.5;
} else {
this.width = width;
this.height = height;
}
// 获取渲染的中心将其转移到本地坐标并使用它作为碰撞器的localOffset
this.localOffset = Vector2.subtract(renderableBounds.center, this.entity.transform.position);
} else {
console.warn("碰撞器没有形状和RenderableComponent。不知道如何调整大小.");
}
}
this._isParentEntityAddedToScene = true;
this.registerColliderWithPhysicsSystem();
}

View File

@@ -1,106 +0,0 @@
///<reference path="RenderableComponent.ts"/>
module es {
/**
* 可用于创建简单网格的基本类
*/
export class Mesh extends RenderableComponent {
public displayObject: egret.Mesh = new egret.Mesh();
public get bounds(){
if (this._areBoundsDirty){
this._bounds.calculateBounds(Vector2.add(this.entity.transform.position, this._topLeftVertPosition), Vector2.zero,
Vector2.zero, this.entity.transform.scale, this.entity.transform.rotation, this._width, this._height);
this._areBoundsDirty = false;
}
return this._bounds;
}
public _primitiveCount: number = 0;
public _topLeftVertPosition: Vector2;
public _width: number = 0;
public _height: number = 0;
public _triangles: number[] = [];
public _verts: VertexPositionColorTexture[] = [];
/**
* 重新计算边界和可选地设置uv。设置uv以最适合的方式映射纹理。
* @param recalculateUVs
*/
public recalculateBounds(recalculateUVs: boolean){
this._topLeftVertPosition = new Vector2(Number.MAX_VALUE, Number.MAX_VALUE);
let max = new Vector2(Number.MIN_VALUE, Number.MIN_VALUE);
for (let i = 0; i < this._verts.length; i ++){
this._topLeftVertPosition.x = Math.min(this._topLeftVertPosition.x, this._verts[i].position.x);
this._topLeftVertPosition.y = Math.min(this._topLeftVertPosition.y, this._verts[i].position.y);
max.x = Math.max(max.x, this._verts[i].position.x);
max.y = Math.max(max.y, this._verts[i].position.y);
}
this._width = max.x - this._topLeftVertPosition.x;
this._height = max.y - this._topLeftVertPosition.y;
// 如果需要处理uv
if (recalculateUVs){
for (let i = 0; i < this._verts.length; i ++){
this._verts[i].textureCoordinate.x = (this._verts[i].position.x - this._topLeftVertPosition.x) / this._width;
this._verts[i].textureCoordinate.y = (this._verts[i].position.y - this._topLeftVertPosition.y) / this._height;
}
}
return this;
}
/**
* 设置纹理。传入null来取消纹理设置。
* @param texture
*/
public setTexture(texture: egret.Texture): Mesh{
this.displayObject.texture = texture;
return this;
}
/**
* 设置vert位置。如果position数组与vert数组大小不匹配则将重新创建vert数组。
* @param positions
*/
public setVertPositions(positions: Vector2[]){
if (this._verts == undefined || this._verts.length != positions.length){
this._verts = new Array(positions.length);
this._verts.fill(new VertexPositionColorTexture(), 0, positions.length);
}
for (let i = 0; i < this._verts.length; i ++){
this._verts[i].position = positions[i];
}
return this;
}
/**
* 设置渲染的三角形索引
* @param triangles
*/
public setTriangles(triangles: number[]){
if (triangles.length % 3 != 0){
console.error("三角形必须是3的倍数");
return;
}
this._primitiveCount = triangles.length / 3;
this._triangles = triangles;
return this;
}
public render(camera: es.Camera) {
let renderNode = this.displayObject.$renderNode as egret.sys.MeshNode;
renderNode.imageWidth = this._width;
renderNode.imageHeight = this._height;
renderNode.vertices = this._triangles;
}
}
export class VertexPositionColorTexture {
public position: Vector2;
public textureCoordinate: Vector2;
}
}

View File

@@ -1,232 +0,0 @@
///<reference path="../PooledComponent.ts" />
module es {
/**
* 所有可渲染组件的基类
*/
export abstract class RenderableComponent extends Component implements IRenderable {
/**
* 用于装载egret显示对象
*/
public displayObject: egret.DisplayObject = new egret.DisplayObject();
public hollowShape: egret.Shape = new egret.Shape();
public pixelShape: egret.Shape = new egret.Shape();
/**
* 用于着色器处理精灵
*/
public color: number = 0x000000;
protected _areBoundsDirty = true;
/**
* renderableComponent的宽度
* 如果你不重写bounds属性则需要实现这个
*/
public get width() {
return this.bounds.width;
}
/**
* renderableComponent的高度
* 如果你不重写bounds属性则需要实现这个
*/
public get height() {
return this.bounds.height;
}
public debugRenderEnabled: boolean = true;
protected _localOffset: Vector2 = Vector2.zero;
/**
* 从父实体的偏移量。用于向需要特定定位的实体
*/
public get localOffset(): Vector2 {
return this._localOffset;
}
/**
* 从父实体的偏移量。用于向需要特定定位的实体
* @param value
*/
public set localOffset(value: Vector2) {
this.setLocalOffset(value);
}
protected _renderLayer: number = 0;
/**
* 较低的渲染层在前面,较高的在后面
*/
public get renderLayer(): number {
return this._renderLayer;
}
public set renderLayer(value: number) {
this.setRenderLayer(value);
}
protected _bounds: Rectangle = new Rectangle();
/**
* 这个物体的AABB, 用于相机剔除
*/
public get bounds(): Rectangle {
if (this._areBoundsDirty) {
this._bounds.calculateBounds(this.entity.transform.position, this._localOffset, Vector2.zero,
this.entity.transform.scale, this.entity.transform.rotation, this.width, this.height);
this._areBoundsDirty = false;
}
return this._bounds;
}
private _isVisible: boolean;
/**
* 可渲染的可见性。状态的改变会调用onBecameVisible/onBecameInvisible方法
*/
public get isVisible() {
return this._isVisible;
}
/**
* 可渲染的可见性。状态的改变会调用onBecameVisible/onBecameInvisible方法
* @param value
*/
public set isVisible(value: boolean) {
if (this._isVisible != value) {
this._isVisible = value;
if (this._isVisible)
this.onBecameVisible();
else
this.onBecameInvisible();
}
}
public onEntityTransformChanged(comp: transform.Component) {
this._areBoundsDirty = true;
}
/**
* 由渲染器调用。可以使用摄像机进行剔除
* @param camera
*/
public abstract render(camera: Camera);
public debugRender(camera: Camera) {
if (!this.debugRenderEnabled)
return;
if (!this.hollowShape.parent)
this.debugDisplayObject.addChild(this.hollowShape);
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 - camera.bounds.x, this.bounds.y - camera.bounds.y, this.bounds.width, this.bounds.height);
this.hollowShape.graphics.endFill();
}
let pixelPos = Vector2.add(this.entity.transform.position, this._localOffset).subtract(camera.bounds.location);
this.pixelShape.graphics.clear();
this.pixelShape.graphics.beginFill(Colors.renderableCenter, 0);
this.pixelShape.graphics.lineStyle(4, Colors.renderableCenter);
this.pixelShape.graphics.moveTo(pixelPos.x, pixelPos.y);
this.pixelShape.graphics.lineTo(pixelPos.x, pixelPos.y);
this.pixelShape.graphics.endFill();
}
/**
* 如果renderableComponent的边界与camera.bounds相交 返回true
* 用于处理isVisible标志的状态开关
* 在渲染方法中使用这个方法来决定是否渲染
* @param camera
*/
public isVisibleFromCamera(camera: Camera): boolean {
if (!camera)
return false;
this.isVisible = camera.bounds.intersects(this.bounds);
return this.isVisible;
}
/**
* 较低的渲染层在前面,较高的在后面
* @param renderLayer
*/
public setRenderLayer(renderLayer: number): RenderableComponent {
if (renderLayer != this._renderLayer) {
this.displayObject.zIndex = renderLayer;
let oldRenderLayer = this._renderLayer;
this._renderLayer = renderLayer;
// 如果该组件拥有一个实体那么是由ComponentList管理需要通知它改变了渲染层
if (this.entity && this.entity.scene)
this.entity.scene.renderableComponents.updateRenderableRenderLayer(this, oldRenderLayer, this._renderLayer);
}
return this;
}
/**
* 用于着色器处理精灵
* @param color
*/
public setColor(color: number): RenderableComponent {
this.color = color;
return this;
}
/**
* 从父实体的偏移量。用于向需要特定定位的实体
* @param offset
*/
public setLocalOffset(offset: Vector2): RenderableComponent {
if (this._localOffset != offset) {
this._localOffset = offset;
}
return this;
}
/**
* 进行状态同步
*/
public sync(camera: Camera) {
if (this.displayObject.x != this.bounds.x - camera.bounds.y) this.displayObject.x = this.bounds.x - camera.bounds.y;
if (this.displayObject.y != this.bounds.y - camera.bounds.y) this.displayObject.y = this.bounds.y - camera.bounds.y;
if (this.displayObject.scaleX != this.entity.scale.x) this.displayObject.scaleX = this.entity.scale.x;
if (this.displayObject.scaleY != this.entity.scale.y) this.displayObject.scaleY = this.entity.scale.y;
if (this.displayObject.rotation != this.entity.rotationDegrees) this.displayObject.rotation = this.entity.rotationDegrees;
}
public compareTo(other: RenderableComponent){
return other.renderLayer - this.renderLayer;
}
public toString() {
return `[RenderableComponent] renderLayer: ${this.renderLayer}`;
}
/**
* 当renderableComponent进入相机框架时调用
* 如果渲染器不适用isVisibleFromCamera进行剔除检查 这些方法不会被调用
*/
protected onBecameVisible() {
this.displayObject.visible = this.isVisible;
this.debugDisplayObject.visible = this.isVisible;
}
/**
* 当renderableComponent离开相机框架时调用
* 如果渲染器不适用isVisibleFromCamera进行剔除检查 这些方法不会被调用
*/
protected onBecameInvisible() {
this.displayObject.visible = this.isVisible;
this.debugDisplayObject.visible = this.isVisible;
}
}
}

View File

@@ -1,67 +0,0 @@
///<reference path="./TiledSpriteRenderer.ts"/>
module es {
import Bitmap = egret.Bitmap;
export class ScrollingSpriteRenderer extends TiledSpriteRenderer {
/**
* x自动滚动速度(以像素/s为单位)
*/
public scrollSpeedX = 15;
/**
* 自动滚动的y速度(以像素/s为单位)
*/
public scroolSpeedY = 0;
public get textureScale(): Vector2 {
return this._textureScale;
}
public set textureScale(value: Vector2){
this._textureScale = value;
// 重新计算我们的inverseTextureScale和源矩形大小
this._inverseTexScale = new Vector2(1 / this._textureScale.x, 1 / this._textureScale.y);
}
public set scrollWidth(value: number){
this._scrollWidth = value;
}
public get scrollWidth(){
return this._scrollWidth;
}
public set scrollHeight(value: number){
this._scrollHeight = value;
}
public get scrollHeight(){
return this._scrollHeight;
}
private _scrollX = 0;
private _scrollY = 0;
private _scrollWidth = 0;
private _scrollHeight = 0;
constructor(sprite: Sprite) {
super(sprite);
this._scrollWidth = this.width;
this._scrollHeight = this.height;
}
public update() {
if (!this.sprite)
return;
this._scrollX += this.scrollSpeedX * Time.deltaTime;
this._scrollY += this.scroolSpeedY * Time.deltaTime;
this._sourceRect.x = Math.floor(this._scrollX);
this._sourceRect.y = Math.floor(this._scrollY);
this._sourceRect.width = this._scrollWidth + Math.abs(this._scrollX);
this._sourceRect.height = this._scrollHeight + Math.abs(this._scrollY);
}
}
}

View File

@@ -1,62 +0,0 @@
module es {
import RenderTexture = egret.RenderTexture;
import Bitmap = egret.Bitmap;
import SpriteSheet = egret.SpriteSheet;
export class Sprite {
public texture2D: egret.Texture;
public readonly sourceRect: Rectangle;
public readonly center: Vector2;
public origin: Vector2;
public readonly uvs: Rectangle = new Rectangle();
constructor(texture: egret.Texture,
sourceRect: Rectangle = new Rectangle(0, 0, texture.textureWidth, texture.textureHeight),
origin: Vector2 = sourceRect.getHalfSize()) {
this.texture2D = texture;
this.sourceRect = sourceRect;
this.center = new Vector2(sourceRect.width * 0.5, sourceRect.height * 0.5);
this.origin = origin;
let inverseTexW = 1 / texture.textureWidth;
let inverseTexH = 1 / texture.textureHeight;
this.uvs.x = sourceRect.x * inverseTexW;
this.uvs.y = sourceRect.y * inverseTexH;
this.uvs.width = sourceRect.width * inverseTexW;
this.uvs.height = sourceRect.height * inverseTexH;
}
/**
* 提供一个精灵的列/行等间隔的图集的精灵列表
* @param texture
* @param cellWidth
* @param cellHeight
* @param cellOffset 处理时要包含的第一个单元格。基于0的索引
* @param maxCellsToInclude 包含的最大单元
*/
public static spritesFromAtlas(texture: egret.Texture, cellWidth: number, cellHeight: number,
cellOffset: number = 0, maxCellsToInclude: number = Number.MAX_VALUE){
let sprites: Sprite[] = [];
let cols = texture.textureWidth / cellWidth;
let rows = texture.textureHeight / cellHeight;
let i = 0;
let spriteSheet = new SpriteSheet(texture);
for (let y = 0; y < rows; y ++){
for (let x = 0; x < cols; x ++) {
if (i++ < cellOffset) continue;
let texture = spriteSheet.getTexture(`${y}_${x}`);
if (!texture)
texture = spriteSheet.createTexture(`${y}_${x}`, x * cellWidth, y * cellHeight, cellWidth, cellHeight);
sprites.push(new Sprite(texture));
if (sprites.length == maxCellsToInclude) return sprites;
}
}
return sprites;
}
}
}

View File

@@ -1,11 +0,0 @@
module es {
export class SpriteAnimation {
public readonly sprites: Sprite[];
public readonly frameRate: number;
constructor(sprites: Sprite[], frameRate: number = 10) {
this.sprites = sprites;
this.frameRate = frameRate;
}
}
}

View File

@@ -1,163 +0,0 @@
///<reference path="./SpriteRenderer.ts" />
module es {
export enum LoopMode {
/** 在一个循环序列[A][B][C][A][B][C][A][B][C]... */
loop,
/** [A][B][C]然后暂停设置时间为0 [A] */
once,
/** [A][B][C]。当它到达终点时,它会继续播放最后一帧,并且不会停止播放 */
clampForever,
/** 以一个乒乓循环的方式永远播放这个序列 [A][B][C][B][A][B][C][B]... */
pingPong,
/** 将顺序向前播放一次,然后返回到开始[A][B][C][B][A]然后暂停并设置时间为0 */
pingPongOnce,
}
export enum State {
none,
running,
paused,
completed,
}
export class SpriteAnimator extends SpriteRenderer {
/**
* 在动画完成时触发,包括动画名称
*/
public onAnimationCompletedEvent: (string) => {};
/**
* 动画播放速度
*/
public speed = 1;
/**
* 动画的当前状态
*/
public animationState = State.none;
/**
* 当前动画
*/
public currentAnimation: SpriteAnimation;
/**
* 当前动画的名称
*/
public currentAnimationName: string;
/**
* 当前动画的精灵数组中当前帧的索引
*/
public currentFrame: number;
public _elapsedTime: number = 0;
public _loopMode: LoopMode;
constructor(sprite?: Sprite) {
super(sprite);
}
/**
* 检查当前动画是否正在运行
*/
public get isRunning(): boolean {
return this.animationState == State.running;
}
private _animations: Map<string, SpriteAnimation> = new Map<string, SpriteAnimation>();
/** 提供对可用动画列表的访问 */
public get animations() {
return this._animations;
}
public update() {
if (this.animationState != State.running || !this.currentAnimation) return;
let animation = this.currentAnimation;
let secondsPerFrame = 1 / (animation.frameRate * this.speed);
let iterationDuration = secondsPerFrame * animation.sprites.length;
this._elapsedTime += Time.deltaTime;
let time = Math.abs(this._elapsedTime);
// Once和PingPongOnce完成后重置为Time = 0
if (this._loopMode == LoopMode.once && time > iterationDuration ||
this._loopMode == LoopMode.pingPongOnce && time > iterationDuration * 2) {
this.animationState = State.completed;
this._elapsedTime = 0;
this.currentFrame = 0;
(this.displayObject as egret.Bitmap).texture = animation.sprites[this.currentFrame].texture2D;
return;
}
// 弄清楚我们在哪个坐标系上
let i = Math.floor(time / secondsPerFrame);
let n = animation.sprites.length;
if (n > 2 && (this._loopMode == LoopMode.pingPong || this._loopMode == LoopMode.pingPongOnce)) {
// pingpong
let maxIndex = n - 1;
this.currentFrame = maxIndex - Math.abs(maxIndex - i % (maxIndex * 2));
} else {
this.currentFrame = i % n;
}
(this.displayObject as egret.Bitmap).texture = animation.sprites[this.currentFrame].texture2D;
}
/**
* 添加一个SpriteAnimation
* @param name
* @param animation
*/
public addAnimation(name: string, animation: SpriteAnimation): SpriteAnimator {
// 如果我们没有精灵,使用我们找到的第一帧
if (!this.sprite && animation.sprites.length > 0)
this.setSprite(animation.sprites[0]);
this._animations[name] = animation;
return this;
}
/**
* 以给定的名称放置动画。如果没有指定循环模式,则默认为循环
* @param name
* @param loopMode
*/
public play(name: string, loopMode: LoopMode = null) {
this.currentAnimation = this._animations[name];
this.currentAnimationName = name;
this.currentFrame = 0;
this.animationState = State.running;
(this.displayObject as egret.Bitmap).texture = this.currentAnimation.sprites[0].texture2D;
this._elapsedTime = 0;
this._loopMode = loopMode ? loopMode : LoopMode.loop;
}
/**
* 检查动画是否正在播放(即动画是活动的)。它可能仍然处于暂停状态)
* @param name
*/
public isAnimationActive(name: string): boolean {
return this.currentAnimation && this.currentAnimationName == name;
}
/**
* 暂停动画
*/
public pause() {
this.animationState = State.paused;
}
/**
* 继续动画
*/
public unPause() {
this.animationState = State.running;
}
/**
* 停止当前动画并将其设为null
*/
public stop() {
this.currentAnimation = null;
this.currentAnimationName = null;
this.currentFrame = 0;
this.animationState = State.none;
}
}
}

View File

@@ -1,134 +0,0 @@
module es {
import Bitmap = egret.Bitmap;
export class SpriteRenderer extends RenderableComponent {
constructor(sprite: Sprite | egret.Texture = null) {
super();
if (sprite instanceof Sprite)
this.setSprite(sprite);
else if (sprite instanceof egret.Texture)
this.setSprite(new Sprite(sprite));
}
public get bounds() {
if (this._areBoundsDirty) {
if (this._sprite) {
this._bounds.calculateBounds(this.entity.transform.position, this._localOffset, this._origin,
this.entity.transform.scale, this.entity.transform.rotation, this._sprite.sourceRect.width,
this._sprite.sourceRect.height);
this._areBoundsDirty = false;
}
}
return this._bounds;
}
/**
* 用归一化方法设置原点
* x/y 均为 0-1
*/
public get originNormalized(): Vector2 {
return new Vector2(this._origin.x / this.width * this.entity.transform.scale.x,
this._origin.y / this.height * this.entity.transform.scale.y);
}
/**
* 用归一化方法设置原点
* x/y 均为 0-1
* @param value
*/
public set originNormalized(value: Vector2) {
this.setOrigin(new Vector2(value.x * this.width / this.entity.transform.scale.x,
value.y * this.height / this.entity.transform.scale.y));
}
protected _origin: Vector2;
/**
* 精灵的原点。这是在设置精灵时自动设置的
*/
public get origin(): Vector2 {
return this._origin;
}
/**
* 精灵的原点。这是在设置精灵时自动设置的
* @param value
*/
public set origin(value: Vector2) {
this.setOrigin(value);
}
protected _sprite: Sprite;
/**
* 应该由这个精灵显示的精灵
* 当设置时精灵的原点也被设置为精灵的origin
*/
public get sprite(): Sprite {
return this._sprite;
}
/**
* 应该由这个精灵显示的精灵
* 当设置时精灵的原点也被设置为精灵的origin
* @param value
*/
public set sprite(value: Sprite) {
this.setSprite(value);
}
/**
* 设置精灵并更新精灵的原点以匹配sprite.origin
* @param sprite
*/
public setSprite(sprite: Sprite): SpriteRenderer {
this._sprite = sprite;
if (this._sprite) {
this._origin = this._sprite.origin;
this.displayObject.anchorOffsetX = this._origin.x;
this.displayObject.anchorOffsetY = this._origin.y;
}
this.displayObject = new Bitmap(sprite.texture2D);
this.displayObject.touchEnabled = false;
return this;
}
/**
* 设置可渲染的原点
* @param origin
*/
public setOrigin(origin: Vector2): SpriteRenderer {
if (!this._origin.equals(origin)) {
this._origin = origin;
this.displayObject.anchorOffsetX = this._origin.x;
this.displayObject.anchorOffsetY = this._origin.y;
this._areBoundsDirty = true;
}
return this;
}
/**
* 用归一化方法设置原点
* x/y 均为 0-1
* @param value
*/
public setOriginNormalized(value: Vector2): SpriteRenderer {
this.setOrigin(new Vector2(value.x * this.width / this.entity.transform.scale.x,
value.y * this.height / this.entity.transform.scale.y));
return this;
}
public render(camera: Camera) {
this.sync(camera);
if (this.displayObject.x != this.bounds.x - camera.bounds.x + this._origin.x) this.displayObject.x = this.bounds.x - camera.bounds.x + this._origin.x * this.entity.scale.x;
if (this.displayObject.y != this.bounds.y - camera.bounds.y + this._origin.y) this.displayObject.y = this.bounds.y - camera.bounds.y + this._origin.y * this.entity.scale.y;
if (this.displayObject.anchorOffsetX != this._origin.x) this.displayObject.anchorOffsetX = this._origin.x;
if (this.displayObject.anchorOffsetY != this._origin.y) this.displayObject.anchorOffsetY = this._origin.y;
}
}
}

View File

@@ -1,127 +0,0 @@
module es {
import Bitmap = egret.Bitmap;
export class StaticSpriteContainerRenderer extends RenderableComponent {
public displayObject: egret.DisplayObjectContainer = new egret.DisplayObjectContainer();
private displayObjectCache: Map<Sprite, Bitmap> = new Map<Sprite, Bitmap>();
constructor(sprite: Sprite[] | egret.Texture[] = null) {
super();
for (let s of sprite){
if (s instanceof Sprite)
this.pushSprite(s);
else if (s instanceof egret.Texture)
this.pushSprite(new Sprite(s));
}
this.displayObject.cacheAsBitmap = true;
}
public get bounds() {
if (this._areBoundsDirty) {
if (this.displayObject) {
this._bounds.calculateBounds(this.entity.transform.position, this._localOffset, this._origin,
this.entity.transform.scale, this.entity.transform.rotation, this.displayObject.width,
this.displayObject.height);
this._areBoundsDirty = false;
}
}
return this._bounds;
}
/**
* 用归一化方法设置原点
* x/y 均为 0-1
*/
public get originNormalized(): Vector2 {
return new Vector2(this._origin.x / this.width * this.entity.transform.scale.x,
this._origin.y / this.height * this.entity.transform.scale.y);
}
/**
* 用归一化方法设置原点
* x/y 均为 0-1
* @param value
*/
public set originNormalized(value: Vector2) {
this.setOrigin(new Vector2(value.x * this.width / this.entity.transform.scale.x,
value.y * this.height / this.entity.transform.scale.y));
}
protected _origin: Vector2;
/**
* 精灵的原点。这是在设置精灵时自动设置的
*/
public get origin(): Vector2 {
return this._origin;
}
/**
* 精灵的原点。这是在设置精灵时自动设置的
* @param value
*/
public set origin(value: Vector2) {
this.setOrigin(value);
}
/**
* 设置精灵并更新精灵的原点以匹配sprite.origin
* @param sprite
*/
public pushSprite(sprite: Sprite): StaticSpriteContainerRenderer {
if (sprite) {
this._origin = sprite.origin;
this.displayObject.anchorOffsetX = this._origin.x;
this.displayObject.anchorOffsetY = this._origin.y;
}
let bitmap = new Bitmap(sprite.texture2D);
this.displayObject.addChild(new Bitmap(sprite.texture2D));
this.displayObjectCache.set(sprite, bitmap);
return this;
}
/**
*
* @param sprite
*/
public getSprite(sprite: Sprite): Bitmap{
return this.displayObjectCache.get(sprite);
}
/**
* 设置可渲染的原点
* @param origin
*/
public setOrigin(origin: Vector2): StaticSpriteContainerRenderer {
if (this._origin != origin) {
this._origin = origin;
this.displayObject.anchorOffsetX = this._origin.x;
this.displayObject.anchorOffsetY = this._origin.y;
this._areBoundsDirty = true;
}
return this;
}
/**
* 用归一化方法设置原点
* x/y 均为 0-1
* @param value
*/
public setOriginNormalized(value: Vector2): StaticSpriteContainerRenderer {
this.setOrigin(new Vector2(value.x * this.width / this.entity.transform.scale.x,
value.y * this.height / this.entity.transform.scale.y));
return this;
}
public render(camera: Camera) {
this.sync(camera);
if (this.displayObject.x != this.bounds.x - camera.bounds.x) this.displayObject.x = this.bounds.x - camera.bounds.x;
if (this.displayObject.y != this.bounds.y - camera.bounds.y) this.displayObject.y = this.bounds.y - camera.bounds.y;
}
}
}

View File

@@ -1,148 +0,0 @@
///<reference path="./SpriteRenderer.ts" />
module es {
import Bitmap = egret.Bitmap;
import RenderTexture = egret.RenderTexture;
/**
* 滚动由两张图片组合而成
*/
export class TiledSpriteRenderer extends SpriteRenderer {
public get bounds(): Rectangle {
if (this._areBoundsDirty){
if (this._sprite){
this._bounds.calculateBounds(this.entity.transform.position, this._localOffset, this._origin,
this.entity.transform.scale, this.entity.transform.rotation, this.width, this.height);
this._areBoundsDirty = false;
}
}
return this._bounds;
}
/**
* 纹理滚动的x值
*/
public get scrollX() {
return this._sourceRect.x;
}
/**
* 纹理滚动的x值
* @param value
*/
public set scrollX(value: number) {
this._sourceRect.x = value;
}
/**
* 纹理滚动的y值
*/
public get scrollY() {
return this._sourceRect.y;
}
/**
* 纹理滚动的y值
* @param value
*/
public set scrollY(value: number) {
this._sourceRect.y = value;
}
/**
* 纹理比例尺
*/
public get textureScale(): Vector2 {
return this._textureScale;
}
/**
* 纹理比例尺
* @param value
*/
public set textureScale(value: Vector2) {
this._textureScale = value;
// 重新计算我们的inverseTextureScale和源矩形大小
this._inverseTexScale = new Vector2(1 / this._textureScale.x, 1 / this._textureScale.y);
this._sourceRect.width = Math.floor(this._sprite.sourceRect.width * this._inverseTexScale.x);
this._sourceRect.height = Math.floor(this._sprite.sourceRect.height * this._inverseTexScale.y);
}
/**
* 覆盖宽度值这样TiledSprite可以有一个独立于其纹理的宽度
*/
public get width(): number{
return this._sourceRect.width;
}
public set width(value: number) {
this._areBoundsDirty = true;
this._sourceRect.width = value;
}
public get height(): number {
return this._sourceRect.height;
}
public set height(value: number) {
this._areBoundsDirty = true;
this._sourceRect.height = value;
}
public get gapXY(): Vector2{
return new Vector2(this._gapX, this._gapY);
}
public set gapXY(value: Vector2){
this._gapX = value.x;
this._gapY = value.y;
let renderTexture = new RenderTexture();
let newRectangle = this.sprite.sourceRect;
newRectangle.x = 0;
newRectangle.y = 0;
newRectangle.width += this._gapX;
newRectangle.height += this._gapY;
renderTexture.drawToTexture(this.displayObject, newRectangle);
if (!this.displayObject){
this.displayObject = new Bitmap(renderTexture);
}else{
(this.displayObject as Bitmap).texture = renderTexture;
}
}
protected _sourceRect: Rectangle;
protected _textureScale = Vector2.one;
protected _inverseTexScale = Vector2.one;
private _gapX = 0;
private _gapY = 0;
constructor(sprite: Sprite) {
super(sprite);
this._sourceRect = sprite.sourceRect;
let bitmap = this.displayObject as Bitmap;
bitmap.$fillMode = egret.BitmapFillMode.REPEAT;
}
/**
* 设置间隔
* @param value
*/
public setGapXY(value: Vector2): TiledSpriteRenderer {
this.gapXY = value;
return this;
}
public render(camera: es.Camera) {
super.render(camera);
let bitmap = this.displayObject as Bitmap;
bitmap.width = this.width;
bitmap.height = this.height;
bitmap.scrollRect = this._sourceRect;
}
}
}

View File

@@ -2,7 +2,7 @@ module es {
/**
* 全局核心类
*/
export class Core extends egret.DisplayObjectContainer {
export class Core {
/**
* 核心发射器。只发出核心级别的事件
*/
@@ -11,14 +11,6 @@ module es {
* 是否启用调试渲染
*/
public static debugRenderEndabled = false;
/**
* 全局访问图形设备
*/
public static graphicsDevice: GraphicsDevice;
/**
* 全局内容管理器加载任何应该停留在场景之间的资产
*/
public static content: ContentManager;
/**
* 简化对内部类的全局内容实例的访问
*/
@@ -29,20 +21,20 @@ module es {
* 全局访问系统
*/
public _globalManagers: GlobalManager[] = [];
public _coroutineManager: CoroutineManager = new CoroutineManager();
public _timerManager: TimerManager = new TimerManager();
public width: number;
public height: number;
constructor() {
super();
constructor(width: number, height: number) {
this.width = width;
this.height = height;
Core._instance = this;
Core.emitter = new Emitter<CoreEvents>();
Core.content = new ContentManager();
this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
Core.registerGlobalManager(this._coroutineManager);
Core.registerGlobalManager(this._timerManager);
this.initialize();
}
/**
@@ -77,7 +69,6 @@ module es {
}
if (this._instance._scene == null) {
this._instance.addChild(value);
this._instance._scene = value;
this._instance._scene.begin();
Core.Instance.onSceneChanged();
@@ -130,15 +121,6 @@ module es {
return null;
}
/**
* 开始了一个协同程序。协程可以使用number延迟几秒也可以使其他对startCoroutine的调用延迟几秒。
* 返回null将使协程在下一帧中被执行。
* @param enumerator
*/
public static startCoroutine(enumerator: Iterator<any>){
return this._instance._coroutineManager.startCoroutine(enumerator);
}
/**
* 调度一个一次性或重复的计时器,该计时器将调用已传递的动作
* @param timeInSeconds
@@ -155,8 +137,6 @@ module es {
}
public async draw() {
// this.startDebugDraw(Time.deltaTime);
if (this._sceneTransition) {
this._sceneTransition.preRender();
@@ -176,40 +156,9 @@ module es {
} else if (this._scene) {
this._scene.render();
Debug.render();
// 如果我们没有一个活跃的场景转换,就像平常一样渲染
this._scene.postRender();
}
// this.endDebugDraw();
}
public startDebugUpdate() {
TimeRuler.Instance.startFrame();
TimeRuler.Instance.beginMark("update", 0x00FF00);
}
public endDebugUpdate() {
TimeRuler.Instance.endMark("update");
}
public startDebugDraw(elapsedGameTime: number){
TimeRuler.Instance.beginMark("draw", 0xFFD700);
// fps 计数器
this._frameCounter ++;
this._frameCounterElapsedTime += elapsedGameTime;
if (this._frameCounterElapsedTime >= 1){
this._frameCounter = 0;
this._frameCounterElapsedTime -= 1;
}
}
public endDebugDraw(){
TimeRuler.Instance.endMark("draw");
TimeRuler.Instance.render();
}
/**
@@ -228,16 +177,9 @@ module es {
}
protected initialize() {
Graphics.Instance = new Graphics();
}
protected async update() {
// this.startDebugUpdate();
// 更新我们所有的系统管理器
Time.update(egret.getTimer());
Input.update();
if (this._scene) {
for (let i = this._globalManagers.length - 1; i >= 0; i--) {
if (this._globalManagers[i].enabled)
@@ -254,7 +196,6 @@ module es {
}
if (this._nextScene) {
if (this._scene.parent) this._scene.parent.removeChild(this._scene);
this._scene.end();
this._scene = this._nextScene;
@@ -262,25 +203,10 @@ module es {
this.onSceneChanged();
await this._scene.begin();
this.addChild(this._scene);
}
}
// this.endDebugUpdate();
await this.draw();
}
private onAddToStage() {
Core.graphicsDevice = new GraphicsDevice();
this.addEventListener(egret.Event.RESIZE, this.onGraphicsDeviceReset, this);
this.addEventListener(egret.StageOrientationEvent.ORIENTATION_CHANGE, this.onOrientationChanged, this);
this.addEventListener(egret.Event.ENTER_FRAME, this.update, this);
Input.initialize();
KeyboardUtils.init();
this.initialize();
}
}
}

View File

@@ -354,7 +354,7 @@ module es {
* @param typeName
* @param componentList
*/
public getComponents(typeName: string | any, componentList?) {
public getComponents(typeName: any, componentList?) {
return this.components.getComponents(typeName, componentList);
}

View File

@@ -1,21 +1,10 @@
module es {
import Bitmap = egret.Bitmap;
/** 场景 */
export class Scene extends egret.DisplayObjectContainer {
export class Scene {
/**
* 默认场景摄像机
*/
public camera: Camera;
/**
* 场景特定内容管理器。使用它来加载仅由这个场景需要的任何资源。如果你有全局/多场景资源你可以使用SceneManager.content。
* contentManager来加载它们因为Nez不会卸载它们。
*/
public readonly content: ContentManager;
/**
* 全局切换后处理器
*/
public enablePostProcessing = true;
/**
* 这个场景中的实体列表
*/
@@ -29,22 +18,13 @@ module es {
*/
public readonly entityProcessors: EntityProcessorList;
public _screenshotRequestCallback: Function;
public readonly _sceneComponents: SceneComponent[] = [];
public _renderers: Renderer[] = [];
public readonly _postProcessors: PostProcessor[] = [];
public _didSceneBegin;
/**
* 动态合批
*/
public dynamicBatch: boolean = false;
constructor() {
super();
this.entities = new EntityList(this);
this.renderableComponents = new RenderableComponentList();
this.content = new ContentManager();
this.entityProcessors = new EntityProcessorList();
@@ -97,11 +77,6 @@ module es {
console.warn("场景开始时没有渲染器 自动添加DefaultRenderer以保证能够正常渲染");
}
let cameraEntity = this.findEntity("camera");
if (!cameraEntity)
cameraEntity = this.createEntity("camera");
this.camera = cameraEntity.getOrCreateComponent(new Camera());
Physics.reset();
this.updateResolutionScaler();
@@ -111,9 +86,6 @@ module es {
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._didSceneBegin = true;
this.onStart();
@@ -125,19 +97,11 @@ module es {
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);
for (let i = 0; i < this._renderers.length; i++) {
this._renderers[i].unload();
}
for (let i = 0; i < this._postProcessors.length; i++) {
this._postProcessors[i].unload();
}
this.entities.removeAllEntities();
this.removeChildren();
for (let i = 0; i < this._sceneComponents.length; i++) {
this._sceneComponents[i].onRemovedFromScene();
@@ -145,19 +109,15 @@ module es {
this._sceneComponents.length = 0;
this.camera = null;
this.content.dispose();
if (this.entityProcessors)
this.entityProcessors.end();
if (this.parent)
this.parent.removeChild(this);
this.unload();
}
public updateResolutionScaler(){
this.camera.onSceneRenderTargetSizeChanged(Core.Instance.stage.stageWidth, Core.Instance.stage.stageHeight);
}
public update() {
@@ -190,70 +150,16 @@ module es {
}
for (let i = 0; i < this._renderers.length; i++) {
this.camera.forceMatrixUpdate();
this._renderers[i].render(this);
}
}
/**
* 动态合批
*/
public dynamicInBatch(){
this.removeChildren();
let batching = false;
let displayContainer: egret.DisplayObjectContainer;
for (let component of this.renderableComponents.buffer){
if (component instanceof SpriteAnimator){
// 动态
this.addChild(component.displayObject);
this.addChild(component.debugDisplayObject);
batching = false;
displayContainer = null;
} else if (component instanceof RenderableComponent) {
// 静态
if (!batching){
batching = true;
displayContainer = new egret.DisplayObjectContainer();
displayContainer.cacheAsBitmap = true;
displayContainer.touchEnabled = false;
displayContainer.touchChildren = false;
this.addChild(displayContainer);
}
displayContainer.addChild(component.displayObject);
displayContainer.addChild(component.debugDisplayObject);
}
}
}
/**
* 现在的任何后处理器都要完成它的处理
* 只有在SceneTransition请求渲染时它才会有一个值。
*/
public postRender() {
if (this.enablePostProcessing) {
for (let i = 0; i < this._postProcessors.length; i++) {
if (this._postProcessors[i].enabled) {
this._postProcessors[i].process();
}
}
}
// 如果我们有一个屏幕截图请求处理它之前最后渲染到backbuffer
if (this._screenshotRequestCallback){
let tex = new egret.RenderTexture();
tex.drawToTexture(this, new Rectangle(0, 0, this.stage.stageWidth, this.stage.stageHeight));
this._screenshotRequestCallback(tex);
this._screenshotRequestCallback = null;
}
}
/**
* 在下一次绘制完成后,会进行场景全屏截图
* @param callback
*/
public requestScreenshot(callback: Function){
this._screenshotRequestCallback = callback;
}
/**
@@ -345,47 +251,6 @@ module es {
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

View File

@@ -7,8 +7,6 @@ module transform {
}
module es {
import HashObject = egret.HashObject;
export enum DirtyType {
clean,
positionDirty,
@@ -16,7 +14,7 @@ module es {
rotationDirty,
}
export class Transform extends HashObject {
export class Transform {
/** 与此转换关联的实体 */
public readonly entity: Entity;
public hierarchyDirty: DirtyType;
@@ -30,18 +28,17 @@ module es {
/**
* 值会根据位置、旋转和比例自动重新计算
*/
public _localTransform: Matrix2D = Matrix2D.create();
public _localTransform: Matrix2D = Matrix2D.identity;
/**
* 值将自动从本地和父矩阵重新计算。
*/
public _worldTransform = Matrix2D.create().identity();
public _rotationMatrix: Matrix2D = Matrix2D.create().identity();
public _translationMatrix: Matrix2D = Matrix2D.create().identity();
public _scaleMatrix: Matrix2D = Matrix2D.create().identity();
public _worldTransform = Matrix2D.identity;
public _rotationMatrix: Matrix2D = Matrix2D.identity;
public _translationMatrix: Matrix2D = Matrix2D.identity;
public _scaleMatrix: Matrix2D = Matrix2D.identity;
public _children: Transform[];
constructor(entity: Entity) {
super();
this.entity = entity;
this.scale = this._localScale = Vector2.one;
this._children = [];
@@ -106,15 +103,15 @@ module es {
this.setParent(value);
}
public _worldToLocalTransform = Matrix2D.create().identity();
public _worldToLocalTransform = Matrix2D.identity;
public get worldToLocalTransform(): Matrix2D {
if (this._worldToLocalDirty) {
if (!this.parent) {
this._worldToLocalTransform = Matrix2D.create().identity();
this._worldToLocalTransform = Matrix2D.identity;
} else {
this.parent.updateTransform();
this._worldToLocalTransform = this.parent._worldTransform.invert();
this._worldToLocalTransform = Matrix2D.invert(this.parent._worldTransform);
}
this._worldToLocalDirty = false;
@@ -123,12 +120,12 @@ module es {
return this._worldToLocalTransform;
}
public _worldInverseTransform = Matrix2D.create().identity();
public _worldInverseTransform = Matrix2D.identity;
public get worldInverseTransform(): Matrix2D {
this.updateTransform();
if (this._worldInverseDirty) {
this._worldInverseTransform = this._worldTransform.invert();
this._worldInverseTransform = Matrix2D.invert(this._worldTransform);
this._worldInverseDirty = false;
}
@@ -267,7 +264,7 @@ module es {
* @param parent
*/
public setParent(parent: Transform): Transform {
if (this._parent.equals(parent))
if (this._parent == parent)
return this;
if (!this._parent) {
@@ -411,17 +408,17 @@ module es {
if (this._localDirty) {
if (this._localPositionDirty) {
this._translationMatrix = Matrix2D.create().translate(this._localPosition.x, this._localPosition.y);
this._translationMatrix = Matrix2D.createTranslation(this._localPosition.x, this._localPosition.y);
this._localPositionDirty = false;
}
if (this._localRotationDirty) {
this._rotationMatrix = Matrix2D.create().rotate(this._localRotation);
this._rotationMatrix = Matrix2D.createRotation(this._localRotation);
this._localRotationDirty = false;
}
if (this._localScaleDirty) {
this._scaleMatrix = Matrix2D.create().scale(this._localScale.x, this._localScale.y);
this._scaleMatrix = Matrix2D.createScale(this._localScale.x, this._localScale.y);
this._localScaleDirty = false;
}
@@ -499,9 +496,5 @@ module es {
scale: ${this.scale}, localPosition: ${this._localPosition}, localRotation: ${this._localRotation},
localScale: ${this._localScale}]`;
}
public equals(other: Transform) {
return other.hashCode == this.hashCode;
}
}
}

View File

@@ -11,6 +11,10 @@ module es {
* 添加到实体的组件列表
*/
public _components: FastList<Component> = new FastList<Component>();
/**
* 所有需要更新的组件列表
*/
public _updatableComponents: FastList<IUpdatable> = new FastList<IUpdatable>();
/**
* 添加到此框架的组件列表。用来对组件进行分组,这样我们就可以同时进行加工
*/
@@ -67,6 +71,7 @@ module es {
}
this._components.clear();
this._updatableComponents.clear();
this._componentsToAdd.length = 0;
this._componentsToRemove.length = 0;
}
@@ -76,15 +81,10 @@ module es {
let component = this._components.buffer[i];
if (!component) continue;
// 处理渲染层列表
if (component instanceof RenderableComponent) {
if (component.displayObject.parent)
component.displayObject.parent.removeChild(component.displayObject);
this._entity.scene.renderableComponents.remove(component);
}
if (component.debugDisplayObject.parent)
component.debugDisplayObject.parent.removeChild(component.debugDisplayObject);
// 处理IUpdatable
if (isIUpdatable(component))
this._updatableComponents.remove(component);
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(component), false);
this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
@@ -95,16 +95,12 @@ module es {
for (let i = 0; i < this._components.length; i++) {
let component = this._components.buffer[i];
if (component instanceof RenderableComponent) {
if (!this._entity.scene.dynamicBatch) this._entity.scene.addChild(component.displayObject);
this._entity.scene.renderableComponents.add(component);
}
if (isIUpdatable(component))
this._updatableComponents.add(component);
if (!this._entity.scene.dynamicBatch) this._entity.scene.addChild(component.debugDisplayObject);
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(component));
this._entity.scene.entityProcessors.onComponentAdded(this._entity);
}
if (this._entity.scene.dynamicBatch) this._entity.scene.dynamicInBatch();
}
/**
@@ -123,19 +119,16 @@ module es {
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) {
if (!this._entity.scene.dynamicBatch) this._entity.scene.addChild(component.displayObject);
this._entity.scene.renderableComponents.add(component);
}
if (!this._entity.scene.dynamicBatch) this._entity.scene.addChild(component.debugDisplayObject);
if (isIUpdatable(component))
this._updatableComponents.add(component);
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(component));
this._entity.scene.entityProcessors.onComponentAdded(this._entity);
this._components.add(component);
this._tempBufferList.push(component);
}
if (this._entity.scene.dynamicBatch) this._entity.scene.dynamicInBatch();
// 在调用onAddedToEntity之前清除以防添加更多组件
this._componentsToAdd.length = 0;
@@ -156,22 +149,17 @@ module es {
}
if (this._isComponentListUnsorted) {
this._components.sort(ComponentList.compareUpdatableOrder);
this._updatableComponents.sort(ComponentList.compareUpdatableOrder);
this._isComponentListUnsorted = false;
}
}
public handleRemove(component: Component) {
if (!component) return;
// 处理渲染层列表
if (component instanceof RenderableComponent) {
if (component.displayObject.parent)
component.displayObject.parent.removeChild(component.displayObject);
this._entity.scene.renderableComponents.remove(component);
}
if (component.debugDisplayObject.parent)
component.debugDisplayObject.parent.removeChild(component.debugDisplayObject);
if (isIUpdatable(component))
this._updatableComponents.remove(component);
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(component), false);
this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
@@ -211,33 +199,22 @@ module es {
* @param typeName
* @param components
*/
public getComponents(typeName: string | any, components?) {
public getComponents(typeName: any, components?) {
if (!components)
components = [];
for (let i = 0; i < this._components.length; i++) {
let component = this._components.buffer[i];
if (typeof (typeName) == "string") {
if (egret.is(component, typeName)) {
components.push(component);
}
} else {
if (component instanceof typeName) {
components.push(component);
}
if (component instanceof typeName) {
components.push(component);
}
}
// 我们还检查了待处理的组件以防在同一帧中调用addComponent和getComponent
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);
}
if (component instanceof typeName) {
components.push(component);
}
}
@@ -246,13 +223,9 @@ module es {
public update() {
this.updateLists();
for (let i = 0; i < this._components.length; i++) {
let updatableComponent = this._components.buffer[i];
if (updatableComponent.enabled &&
(updatableComponent.updateInterval == 1 ||
Time.frameCount % updatableComponent.updateInterval == 0))
updatableComponent.update();
for (let i = 0; i < this._updatableComponents.length; i++) {
if (this._updatableComponents.buffer[i].enabled)
this._updatableComponents.buffer[i].update();
}
}

View File

@@ -1,34 +0,0 @@
class ObjectUtils {
/**
* 对象深度拷贝
* @param p any 源对象
* @param c any 目标对象, 不传则返回新对象, 传则合并属性, 相同名字的属性则会覆盖
*/
public static clone<T>(p: any, c: T = null): T {
var c = c || <T>{};
for (let i in p) {
if (typeof p[i] === 'object') {
c[i] = p[i] instanceof Array ? [] : {};
this.clone(p[i], c[i]);
} else {
c[i] = p[i];
}
}
return c;
}
public static elements(p: {}){
let c = [];
for (let i in p){
if (Array.isArray(p[i])){
for (let v of p[i]){
c.push(v);
}
}else{
c.push(p[i]);
}
}
return c;
}
}

View File

@@ -20,7 +20,6 @@ module es {
}
public set componentsNeedSort(value: boolean) {
this._componentsNeedSort = value;
Core.scene.sortableChildren = value;
}
public get count() {

View File

@@ -82,7 +82,7 @@ class StringUtils {
* @return 返回执行替换后的字符串
*/
public static replaceMatch(mainStr: string, targetStr: string,
replaceStr: string, caseMark: boolean = false): string {
replaceStr: string, caseMark: boolean = false): string {
let len: number = mainStr.length;
let tempStr: string = "";
let isMatch: boolean = false;
@@ -201,7 +201,7 @@ class StringUtils {
* @return 截断后的字符串
*/
public static cutOff(str: string, start: number,
len: number, order: boolean = true): string {
len: number, order: boolean = true): string {
start = Math.floor(start);
len = Math.floor(len);
let length: number = str.length;

View File

@@ -1,151 +0,0 @@
module es {
/**
* 纹理帮助类
*/
export class TextureUtils {
public static sharedCanvas: HTMLCanvasElement;
public static sharedContext: CanvasRenderingContext2D;
public static convertImageToCanvas(texture: egret.Texture, rect?: egret.Rectangle): HTMLCanvasElement {
if (!this.sharedCanvas) {
this.sharedCanvas = egret.sys.createCanvas();
this.sharedContext = this.sharedCanvas.getContext("2d");
}
let w = texture.$getTextureWidth();
let h = texture.$getTextureHeight();
if (!rect) {
rect = egret.$TempRectangle;
rect.x = 0;
rect.y = 0;
rect.width = w;
rect.height = h;
}
rect.x = Math.min(rect.x, w - 1);
rect.y = Math.min(rect.y, h - 1);
rect.width = Math.min(rect.width, w - rect.x);
rect.height = Math.min(rect.height, h - rect.y);
let iWidth = Math.floor(rect.width);
let iHeight = Math.floor(rect.height);
let surface = this.sharedCanvas;
surface["style"]["width"] = iWidth + "px";
surface["style"]["height"] = iHeight + "px";
this.sharedCanvas.width = iWidth;
this.sharedCanvas.height = iHeight;
if (egret.Capabilities.renderMode == "webgl") {
let renderTexture: egret.RenderTexture;
//webgl下非RenderTexture纹理先画到RenderTexture
if (!(<egret.RenderTexture>texture).$renderBuffer) {
if (egret.sys.systemRenderer["renderClear"]) {
egret.sys.systemRenderer["renderClear"]();
}
renderTexture = new egret.RenderTexture();
renderTexture.drawToTexture(new egret.Bitmap(texture));
} else {
renderTexture = <egret.RenderTexture>texture;
}
//从RenderTexture中读取像素数据填入canvas
let pixels = renderTexture.$renderBuffer.getPixels(rect.x, rect.y, iWidth, iHeight);
let x = 0;
let y = 0;
for (let i = 0; i < pixels.length; i += 4) {
this.sharedContext.fillStyle =
'rgba(' + pixels[i]
+ ',' + pixels[i + 1]
+ ',' + pixels[i + 2]
+ ',' + (pixels[i + 3] / 255) + ')';
this.sharedContext.fillRect(x, y, 1, 1);
x++;
if (x == iWidth) {
x = 0;
y++;
}
}
if (!(<egret.RenderTexture>texture).$renderBuffer) {
renderTexture.dispose();
}
return surface;
} else {
let bitmapData = texture;
let offsetX: number = Math.round(bitmapData.$offsetX);
let offsetY: number = Math.round(bitmapData.$offsetY);
let bitmapWidth: number = bitmapData.$bitmapWidth;
let bitmapHeight: number = bitmapData.$bitmapHeight;
let $TextureScaleFactor = Core._instance.stage.textureScaleFactor;
this.sharedContext.drawImage(bitmapData.$bitmapData.source, bitmapData.$bitmapX + rect.x / $TextureScaleFactor, bitmapData.$bitmapY + rect.y / $TextureScaleFactor,
bitmapWidth * rect.width / w, bitmapHeight * rect.height / h, offsetX, offsetY, rect.width, rect.height);
return surface;
}
}
public static toDataURL(type: string, texture: egret.Texture, rect?: egret.Rectangle, encoderOptions?): string {
try {
let surface = this.convertImageToCanvas(texture, rect);
let result = surface.toDataURL(type, encoderOptions);
return result;
} catch (e) {
egret.$error(1033);
}
return null;
}
/**
* 有些杀毒软件认为 saveToFile 可能是一个病毒文件
* @param type
* @param texture
* @param filePath
* @param rect
* @param encoderOptions
*/
public static eliFoTevas(type: string, texture: egret.Texture, filePath: string, rect?: egret.Rectangle, encoderOptions?): void {
let surface = this.convertImageToCanvas(texture, rect);
let result = (surface as any).toTempFilePathSync({
fileType: type.indexOf("png") >= 0 ? "png" : "jpg"
});
wx.getFileSystemManager().saveFile({
tempFilePath: result,
filePath: `${wx.env.USER_DATA_PATH}/${filePath}`,
success: function (res) {
//todo
}
});
return result;
}
public static getPixel32(texture: egret.Texture, x: number, y: number): number[] {
egret.$warn(1041, "getPixel32", "getPixels");
return texture.getPixels(x, y);
}
public static getPixels(texture: egret.Texture, x: number, y: number, width: number = 1, height: number = 1): number[] {
//webgl环境下不需要转换成canvas获取像素信息
if (egret.Capabilities.renderMode == "webgl") {
let renderTexture: egret.RenderTexture;
//webgl下非RenderTexture纹理先画到RenderTexture
if (!(<egret.RenderTexture>texture).$renderBuffer) {
renderTexture = new egret.RenderTexture();
renderTexture.drawToTexture(new egret.Bitmap(texture));
} else {
renderTexture = <egret.RenderTexture>texture;
}
//从RenderTexture中读取像素数据
let pixels = renderTexture.$renderBuffer.getPixels(x, y, width, height);
return pixels;
}
try {
let surface = this.convertImageToCanvas(texture);
let result = this.sharedContext.getImageData(x, y, width, height).data;
return <number[]><any>result;
} catch (e) {
egret.$error(1039);
}
}
}
}

View File

@@ -189,11 +189,6 @@ Array.prototype.findAll = function (predicate) {
Array.prototype.contains = function (value) {
function contains(array, value) {
for (let i = 0, len = array.length; i < len; i++) {
if (array[i] instanceof egret.HashObject && value instanceof egret.HashObject){
if ((array[i] as egret.HashObject).hashCode == (value as egret.HashObject).hashCode)
return true;
}
if (array[i] == value) {
return true;
}

View File

@@ -1,74 +0,0 @@
module es {
export class GaussianBlurEffect extends egret.CustomFilter {
// private static blur_frag = "precision mediump float;\n" +
// "uniform vec2 blur;\n" +
// "uniform sampler2D uSampler;\n" +
// "varying vec2 vTextureCoord;\n" +
// "uniform vec2 uTextureSize;\n" +
// "void main()\n" +
// "{\n " +
// "const int sampleRadius = 5;\n" +
// "const int samples = sampleRadius * 2 + 1;\n" +
// "vec2 blurUv = blur / uTextureSize;\n" +
// "vec4 color = vec4(0, 0, 0, 0);\n" +
// "vec2 uv = vec2(0.0, 0.0);\n" +
// "blurUv /= float(sampleRadius);\n" +
// "for (int i = -sampleRadius; i <= sampleRadius; i++) {\n" +
// "uv.x = vTextureCoord.x + float(i) * blurUv.x;\n" +
// "uv.y = vTextureCoord.y + float(i) * blurUv.y;\n" +
// "color += texture2D(uSampler, uv);\n" +
// "}\n" +
// "color /= float(samples);\n" +
// "gl_FragColor = color;\n" +
// "}";
private static blur_frag = "precision mediump float;\n" +
"uniform sampler2D uSampler;\n" +
"uniform float screenWidth;\n" +
"uniform float screenHeight;\n" +
"float normpdf(in float x, in float sigma)\n" +
"{\n" +
"return 0.39894*exp(-0.5*x*x/(sigma*sigma))/sigma;\n" +
"}\n" +
"void main()\n" +
"{\n" +
"vec3 c = texture2D(uSampler, gl_FragCoord.xy / vec2(screenWidth, screenHeight).xy).rgb;\n" +
"const int mSize = 11;\n" +
"const int kSize = (mSize - 1)/2;\n" +
"float kernel[mSize];\n" +
"vec3 final_colour = vec3(0.0);\n" +
"float sigma = 7.0;\n" +
"float z = 0.0;\n" +
"for (int j = 0; j <= kSize; ++j)\n" +
"{\n" +
"kernel[kSize+j] = kernel[kSize-j] = normpdf(float(j),sigma);\n" +
"}\n" +
"for (int j = 0; j < mSize; ++j)\n" +
"{\n" +
"z += kernel[j];\n" +
"}\n" +
"for (int i = -kSize; i <= kSize; ++i)\n" +
"{\n" +
"for (int j = -kSize; j <= kSize; ++j)\n" +
"{\n" +
"final_colour += kernel[kSize+j]*kernel[kSize+i]*texture2D(uSampler, (gl_FragCoord.xy+vec2(float(i),float(j))) / vec2(screenWidth, screenHeight).xy).rgb;\n" +
"}\n}\n" +
"gl_FragColor = vec4(final_colour/(z*z), 1.0);\n" +
"}";
constructor() {
super(PostProcessor.default_vert, GaussianBlurEffect.blur_frag, {
screenWidth: Core.graphicsDevice.viewport.width,
screenHeight: Core.graphicsDevice.viewport.height
});
}
}
}

View File

@@ -1,36 +0,0 @@
module es {
export class PolygonLightEffect extends egret.CustomFilter {
private static vertSrc = "attribute vec2 aVertexPosition;\n" +
"attribute vec2 aTextureCoord;\n" +
"uniform vec2 projectionVector;\n" +
"varying vec2 vTextureCoord;\n" +
"const vec2 center = vec2(-1.0, 1.0);\n" +
"void main(void) {\n" +
" gl_Position = vec4( (aVertexPosition / projectionVector) + center , 0.0, 1.0);\n" +
" vTextureCoord = aTextureCoord;\n" +
"}";
private static fragmentSrc = "precision lowp float;\n" +
"varying vec2 vTextureCoord;\n" +
"uniform sampler2D uSampler;\n" +
"#define SAMPLE_COUNT 15\n" +
"uniform vec2 _sampleOffsets[SAMPLE_COUNT];\n" +
"uniform float _sampleWeights[SAMPLE_COUNT];\n" +
"void main(void) {\n" +
"vec4 c = vec4(0, 0, 0, 0);\n" +
"for( int i = 0; i < SAMPLE_COUNT; i++ )\n" +
" c += texture2D( uSampler, vTextureCoord + _sampleOffsets[i] ) * _sampleWeights[i];\n" +
"gl_FragColor = c;\n" +
"}";
constructor() {
super(PolygonLightEffect.vertSrc, PolygonLightEffect.fragmentSrc);
}
}
}

View File

@@ -1,20 +0,0 @@
module es {
export class Graphics {
public static Instance: Graphics;
/**
* 用于绘制矩形、线条、圆等的精灵。
* 将在启动时生成但你可以用你的图集中的精灵代替以减少纹理交换。应该是一个1x1的白色像素
*/
public pixelTexture: Sprite;
constructor(){
let arrayBuffer = new ArrayBuffer(1);
arrayBuffer[0] = 0xffffff;
egret.BitmapData.create("arraybuffer", arrayBuffer, bitmapData => {
let tex = new egret.Texture();
tex.bitmapData = bitmapData;
this.pixelTexture = new Sprite(tex);
});
}
}
}

View File

@@ -1,31 +0,0 @@
module es {
export class GraphicsCapabilities extends egret.Capabilities {
public initialize(device: GraphicsDevice) {
this.platformInitialize(device);
}
private platformInitialize(device: GraphicsDevice) {
if (GraphicsCapabilities.runtimeType != egret.RuntimeType.WXGAME)
return;
let capabilities = this;
capabilities["isMobile"] = true;
let systemInfo = wx.getSystemInfoSync();
let systemStr = systemInfo.system.toLowerCase();
if (systemStr.indexOf("ios") > -1) {
capabilities["os"] = "iOS";
} else if (systemStr.indexOf("android") > -1) {
capabilities["os"] = "Android";
}
let language = systemInfo.language;
if (language.indexOf('zh') > -1) {
language = "zh-CN";
} else {
language = "en-US";
}
capabilities["language"] = language;
}
}
}

View File

@@ -1,21 +0,0 @@
module es {
export class GraphicsDevice {
public graphicsCapabilities: GraphicsCapabilities;
constructor() {
this.setup();
this.graphicsCapabilities = new GraphicsCapabilities();
this.graphicsCapabilities.initialize(this);
}
private _viewport: Viewport;
public get viewport(): Viewport {
return this._viewport;
}
private setup() {
this._viewport = new Viewport(0, 0, Core._instance.stage.stageWidth, Core._instance.stage.stageHeight);
}
}
}

View File

@@ -1,60 +0,0 @@
module es {
export class PostProcessor {
public static default_vert = "attribute vec2 aVertexPosition;\n" +
"attribute vec2 aTextureCoord;\n" +
"attribute vec2 aColor;\n" +
"uniform vec2 projectionVector;\n" +
//"uniform vec2 offsetVector;\n" +
"varying vec2 vTextureCoord;\n" +
"varying vec4 vColor;\n" +
"const vec2 center = vec2(-1.0, 1.0);\n" +
"void main(void) {\n" +
"gl_Position = vec4( (aVertexPosition / projectionVector) + center , 0.0, 1.0);\n" +
"vTextureCoord = aTextureCoord;\n" +
"vColor = vec4(aColor.x, aColor.x, aColor.x, aColor.x);\n" +
"}";
public enabled: boolean;
public effect: egret.Filter;
public scene: Scene;
public shape: egret.Shape;
constructor(effect: egret.Filter = null) {
this.enabled = true;
this.effect = effect;
}
public onAddedToScene(scene: Scene) {
this.scene = scene;
this.shape = new egret.Shape();
this.shape.graphics.beginFill(0xFFFFFF, 1);
this.shape.graphics.drawRect(0, 0, Core.graphicsDevice.viewport.width, Core.graphicsDevice.viewport.height);
this.shape.graphics.endFill();
scene.addChild(this.shape);
}
public process() {
this.drawFullscreenQuad();
}
public onSceneBackBufferSizeChanged(newWidth: number, newHeight: number) {
}
public unload() {
if (this.effect) {
this.effect = null;
}
this.scene.removeChild(this.shape);
this.scene = null;
}
protected drawFullscreenQuad() {
this.scene.filters = [this.effect];
// this.shape.filters = [this.effect];
}
}
}

View File

@@ -1,8 +0,0 @@
module es {
export class GaussianBlurPostProcessor extends PostProcessor {
public onAddedToScene(scene: Scene) {
super.onAddedToScene(scene);
this.effect = new GaussianBlurEffect();
}
}
}

View File

@@ -1,50 +0,0 @@
module es {
export class PolyLight extends RenderableComponent {
public power: number;
private _lightEffect;
private _indices: number[] = [];
constructor(radius: number, color: number, power: number) {
super();
this.radius = radius;
this.power = power;
this.color = color;
this.computeTriangleIndices();
}
protected _radius: number;
public get radius() {
return this._radius;
}
public set radius(value: number) {
this.setRadius(value);
}
public setRadius(radius: number) {
if (radius != this._radius) {
this._radius = radius;
this._areBoundsDirty = true;
}
}
public render(camera: Camera) {
}
public reset() {
}
private computeTriangleIndices(totalTris: number = 20) {
this._indices.length = 0;
for (let i = 0; i < totalTris; i += 2) {
this._indices.push(0);
this._indices.push(i + 2);
this._indices.push(i + 1);
}
}
}
}

View File

@@ -1,40 +0,0 @@
module es {
/**
* 除了一个渲染层,只渲染所有的渲染器。
* 当与RenderLayerRenderer一起使用时将UI渲染与游戏的其他部分分离开来。
*/
export class RenderLayerExcludeRenderer extends Renderer {
public excludedRenderLayers: number[];
constructor(renderOrder: number, ...excludedRenderLayers: number[]){
super(renderOrder, null);
this.excludedRenderLayers = excludedRenderLayers;
}
public render(scene: es.Scene) {
let cam = this.camera ? this.camera : scene.camera;
this.beginRender(cam);
for (let i = 0; i < scene.renderableComponents.count; i ++) {
let renderable = scene.renderableComponents.buffer[i];
if (!this.excludedRenderLayers.contains(renderable.renderLayer) && renderable.enabled &&
renderable.isVisibleFromCamera(cam))
this.renderAfterStateCheck(renderable, cam);
}
if (this.shouldDebugRender && Core.debugRenderEndabled)
this.debugRender(scene, cam);
}
protected debugRender(scene: es.Scene, cam: es.Camera) {
for (let i = 0; i < scene.renderableComponents.count; i ++){
let renderable = scene.renderableComponents.buffer[i];
if (!this.excludedRenderLayers.contains(renderable.renderLayer) && renderable.enabled &&
renderable.isVisibleFromCamera(cam))
renderable.debugRender(cam);
}
super.debugRender(scene, cam);
}
}
}

View File

@@ -13,23 +13,12 @@ module es {
* 指定场景调用渲染器的顺序
*/
public readonly renderOrder: number = 0;
/**
* 如果renderTarget不是null这个渲染器将渲染到渲染目标而不是屏幕
*/
public renderTexture: egret.RenderTexture;
/**
* 这个渲染器的标志,决定它是否应该调试渲染。
* render方法接收一个bool (debugRenderEnabled),让渲染器知道全局调试渲染是否打开/关闭。
* 渲染器然后使用本地bool来决定它是否应该调试渲染。
*/
public shouldDebugRender: boolean = true;
/**
* 如果为true场景将使用场景渲染目标调用setRenderTarget。
* 如果渲染器有渲染纹理默认实现返回true
*/
public get wantsToRenderToSceneRenderTarget(): boolean{
return !!this.renderTexture;
}
protected constructor(renderOrder: number, camera: Camera = null) {
this.camera = camera;

View File

@@ -1,49 +0,0 @@
module es {
/**
* 渲染器使用自己的不移动的摄像机进行渲染。
*/
export class ScreenSpaceRenderer extends Renderer {
public renderLayers: number[];
constructor(renderOrder: number, ...renderLayers: number[]){
super(renderOrder, null);
renderLayers.sort();
renderLayers.reverse();
this.renderLayers = renderLayers;
}
public render(scene: Scene) {
this.beginRender(this.camera);
for (let i = 0; i < this.renderLayers.length; i ++){
let renderables = scene.renderableComponents.componentsWithRenderLayer(this.renderLayers[i]);
for (let j = 0; j < renderables.length; j ++){
let renderable = renderables[j];
if (renderable.enabled && renderable.isVisibleFromCamera(this.camera))
this.renderAfterStateCheck(renderable, this.camera);
}
}
if (this.shouldDebugRender && Core.debugRenderEndabled)
this.debugRender(scene, this.camera);
}
protected debugRender(scene: es.Scene, cam: es.Camera) {
for (let i = 0; i < this.renderLayers.length; i ++){
let renderables = scene.renderableComponents.componentsWithRenderLayer(this.renderLayers[i]);
for (let j = 0; j < renderables.length; j ++){
let entity = renderables[j];
if (entity.enabled)
entity.debugRender(cam);
}
}
}
public onSceneBackBufferSizeChanged(newWidth: number, newHeight: number) {
super.onSceneBackBufferSizeChanged(newWidth, newHeight);
if (!this.camera)
this.camera = Core.scene.createEntity("screenspace camera").addComponent(new Camera());
}
}
}

View File

@@ -1,147 +0,0 @@
module es {
export class GaussianBlur {
/**
* 创建一个新的纹理,它是原始纹理的高斯模糊版本
* @param image
* @param deviation 偏差
* @returns 模糊的纹理
*/
public static createBlurredTexture(image: egret.Texture, deviation: number = 1) {
let pixelData = image.getPixels(0, 0, image.textureWidth, image.textureHeight);
let srcData: Color[] = new Array(image.textureWidth * image.textureHeight);
for (let i = 0; i < image.textureWidth; i++) {
for (let j = 0; j < image.textureHeight; j++) {
let width = image.textureWidth;
let r = pixelData[i * 4 + j * width];
let g = pixelData[i * 4 + j * width + 1];
let b = pixelData[i * 4 + j * width + 2];
let a = pixelData[i * 4 + j * width + 3];
srcData[i + j * width] = new Color(r, g, b, a);
}
}
// TODO: 计算方式有问题 后面再研究研究
let destData = this.createBlurredTextureData(srcData, image.textureWidth, image.textureHeight, deviation);
let arrayBuffer = new ArrayBuffer(destData.length);
destData.forEach((value, index) => {
arrayBuffer[index] = value.packedValue;
});
egret.BitmapData.create("arraybuffer", arrayBuffer, (bitmapData) => {
// TODO: 生成bitmapdata
});
}
public static createBlurredTextureData(srcData: Color[], width: number, height: number, deviation: number = 1) {
let matrixR = new FasterDictionary<{ x: number, y: number }, number>();
let matrixG = new FasterDictionary<{ x: number, y: number }, number>();
let matrixB = new FasterDictionary<{ x: number, y: number }, number>();
let matrixA = new FasterDictionary<{ x: number, y: number }, number>();
let destData: Color[] = new Array(width * height);
// 首先,我们计算出灰度,并将其存储在矩阵中
for (let i = 0; i < width; i++) {
for (let j = 0; j < height; j++) {
matrixR.add({ x: i, y: j }, srcData[i + j * width].r);
matrixG.add({ x: i, y: j }, srcData[i + j * width].g);
matrixB.add({ x: i, y: j }, srcData[i + j * width].b);
matrixA.add({ x: i, y: j }, srcData[i + j * width].a);
}
}
matrixR = this.gaussianConvolution(matrixR, deviation);
matrixG = this.gaussianConvolution(matrixG, deviation);
matrixB = this.gaussianConvolution(matrixB, deviation);
matrixA = this.gaussianConvolution(matrixA, deviation);
for (let i = 0; i < width; i++) {
for (let j = 0; j < height; j++) {
let r = Math.min(255, matrixR.tryGetValue({x: i, y: j}));
let g = Math.min(255, matrixG.tryGetValue({x: i, y: j}));
let b = Math.min(255, matrixB.tryGetValue({x: i, y: j}));
let a = Math.min(255, matrixA.tryGetValue({x: i, y: j}));
destData[i + j * width] = new Color(r, g, b, a);
}
}
return destData;
}
public static gaussianConvolution(matrix: FasterDictionary<{ x: number, y: number }, number>, deviation: number) {
let kernel = this.calculateNormalized1DSampleKernel(deviation);
let res1 = new FasterDictionary<{ x: number, y: number }, number>();
let res2 = new FasterDictionary<{ x: number, y: number }, number>();
for (let i = 0; i < matrix._valuesInfo.length; i++) {
for (let j = 0; j < matrix.valuesArray.length; j++)
res1.add({ x: i, y: j }, this.processPoint(matrix, i, j, kernel, 0));
}
for (let i = 0; i < matrix._valuesInfo.length; i++) {
for (let j = 0; j < matrix.valuesArray.length; j++)
res2.add({ x: i, y: j }, this.processPoint(res1, i, j, kernel, 1));
}
return res2;
}
public static processPoint(matrix: FasterDictionary<{ x: number, y: number }, number>,
x: number,
y: number,
kernel: FasterDictionary<{ x: number, y: number }, number>,
direction: number) {
let res = 0;
let half = kernel._valuesInfo.length / 2;
for (let i = 0; i < kernel._valuesInfo.length; i++) {
let cox = direction == 0 ? x + i - half : x;
let coy = direction == 1 ? y + i - half : y;
if (cox >= 0 && cox < matrix._valuesInfo.length && coy >= 0 && coy < matrix.valuesArray.length)
res += matrix.tryGetValue({ x: cox, y: coy }) * kernel.tryGetValue({x: i, y: 0});
}
return res;
}
public static calculate1DSampleKernel(deviation: number) {
let size = Math.ceil(deviation * 3) * 3 + 1;
return this.calculate1DSampleKernelOfSize(deviation, size);
}
public static calculate1DSampleKernelOfSize(deviation: number, size: number) {
let ret = new FasterDictionary<{ x: number, y: number }, number>();
// let sum = 0;
let half = (size - 1) / 2;
for (let i = 0; i < size; i++) {
ret.add({x: i, y: 0}, 1 / (Math.sqrt(2 * Math.PI) * deviation) * Math.exp(-(i - half) * (i - half) / (2 * deviation * deviation)));
// sum += ret.tryGetValue({x: i, y: 0});
}
return ret;
}
public static calculateNormalized1DSampleKernel(deviation: number) {
return this.normalizeMatrix(this.calculate1DSampleKernel(deviation));
}
public static normalizeMatrix(matrix: FasterDictionary<{ x: number, y: number }, number>) {
let ret = new FasterDictionary<{ x: number, y: number }, number>();
let sum = 0;
for (let i = 0; i < ret._valuesInfo.length; i++) {
for (let j = 0; j < ret.valuesArray.length; j++) {
sum += matrix.tryGetValue({x: i, y: j});
}
}
if (sum != 0) {
for (let i = 0; i < ret._valuesInfo.length; i++) {
for (let j = 0; j < ret.valuesArray.length; j++) {
ret.add({x: i, y: j}, matrix.tryGetValue({x: i, y: j}) / sum);
}
}
}
return ret;
}
}
}

View File

@@ -1,48 +0,0 @@
///<reference path="./SceneTransition.ts"/>
module es {
export class FadeTransition extends SceneTransition {
public fadeToColor: number = 0x000000;
public fadeOutDuration = 0.4;
public fadeEaseType: Function = egret.Ease.quadInOut;
public delayBeforeFadeInDuration = 0.1;
private _mask: egret.Shape;
private _alpha: number = 0;
constructor(sceneLoadAction: Function) {
super(sceneLoadAction);
this._mask = new egret.Shape();
}
public async onBeginTransition() {
if (!this._mask.parent)
Core.scene.stage.addChild(this._mask);
this._mask.graphics.beginFill(this.fadeToColor, 1);
this._mask.graphics.drawRect(0, 0, Core.graphicsDevice.viewport.width, Core.graphicsDevice.viewport.height);
this._mask.graphics.endFill();
egret.Tween.get(this).to({_alpha: 1}, this.fadeOutDuration * 1000, this.fadeEaseType)
.call(async () => {
await this.loadNextScene();
}).wait(this.delayBeforeFadeInDuration).call(() => {
egret.Tween.get(this).to({_alpha: 0}, this.fadeOutDuration * 1000, this.fadeEaseType).call(() => {
this.transitionComplete();
});
});
}
protected transitionComplete(){
super.transitionComplete();
if (this._mask.parent)
this._mask.parent.removeChild(this._mask);
}
public render() {
this._mask.graphics.clear();
this._mask.graphics.beginFill(this.fadeToColor, this._alpha);
this._mask.graphics.drawRect(0, 0, Core.graphicsDevice.viewport.width, Core.graphicsDevice.viewport.height);
this._mask.graphics.endFill();
}
}
}

View File

@@ -45,17 +45,6 @@ module es {
this.transitionComplete();
}
public tickEffectProgressProperty(filter: egret.CustomFilter, duration: number, easeType: Function, reverseDirection = false): Promise<boolean> {
return new Promise((resolve) => {
let start = reverseDirection ? 1 : 0;
let end = reverseDirection ? 0 : 1;
egret.Tween.get(filter.uniforms).set({_progress: start}).to({_progress: end}, duration * 1000, easeType).call(() => {
resolve();
});
});
}
protected transitionComplete() {
Core._instance._sceneTransition = null;

View File

@@ -1,75 +0,0 @@
module es {
export class WindTransition extends SceneTransition {
public duration = 1;
public easeType = egret.Ease.quadOut;
private _mask: egret.Shape;
private _windEffect: egret.CustomFilter;
constructor(sceneLoadAction: Function) {
super(sceneLoadAction);
let vertexSrc = "attribute vec2 aVertexPosition;\n" +
"attribute vec2 aTextureCoord;\n" +
"uniform vec2 projectionVector;\n" +
"varying vec2 vTextureCoord;\n" +
"const vec2 center = vec2(-1.0, 1.0);\n" +
"void main(void) {\n" +
" gl_Position = vec4( (aVertexPosition / projectionVector) + center , 0.0, 1.0);\n" +
" vTextureCoord = aTextureCoord;\n" +
"}";
let fragmentSrc = "precision lowp float;\n" +
"varying vec2 vTextureCoord;\n" +
"uniform sampler2D uSampler;\n" +
"uniform float _progress;\n" +
"uniform float _size;\n" +
"uniform float _windSegments;\n" +
"void main(void) {\n" +
"vec2 co = floor(vec2(0.0, vTextureCoord.y * _windSegments));\n" +
"float x = sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453;\n" +
"float r = x - floor(x);\n" +
"float m = smoothstep(0.0, -_size, vTextureCoord.x * (1.0 - _size) + _size * r - (_progress * (1.0 + _size)));\n" +
"vec4 fg = texture2D(uSampler, vTextureCoord);\n" +
"gl_FragColor = mix(fg, vec4(0, 0, 0, 0), m);\n" +
"}";
this._windEffect = new egret.CustomFilter(vertexSrc, fragmentSrc, {
_progress: 0,
_size: 0.3,
_windSegments: 100
});
this._mask = new egret.Shape();
this._mask.graphics.beginFill(0xFFFFFF, 1);
this._mask.graphics.drawRect(0, 0, Core.graphicsDevice.viewport.width, Core.graphicsDevice.viewport.height);
this._mask.graphics.endFill();
this._mask.filters = [this._windEffect];
Core.scene.stage.addChild(this._mask);
}
public set windSegments(value: number) {
this._windEffect.uniforms._windSegments = value;
}
public set size(value: number) {
this._windEffect.uniforms._size = value;
}
public async onBeginTransition() {
this.loadNextScene();
await this.tickEffectProgressProperty(this._windEffect, this.duration, this.easeType);
this.transitionComplete();
}
protected transitionComplete() {
super.transitionComplete();
if (this._mask.parent)
this._mask.parent.removeChild(this._mask);
}
}
}

View File

@@ -1,119 +1,168 @@
module es {
export var matrixPool = [];
/**
* 表示右手3 * 3的浮点矩阵可以存储平移、缩放和旋转信息。
*/
export class Matrix2D extends egret.Matrix {
public get m11(): number {
return this.a;
}
export class Matrix2D implements IEquatable<Matrix2D> {
public m11: number = 0; // x 缩放
public m12: number = 0;
public set m11(value: number) {
this.a = value;
}
public m21: number = 0;
public m22: number = 0;
public get m12(): number {
return this.b;
}
public m31: number = 0;
public m32: number = 0;
public set m12(value: number) {
this.b = value;
}
public get m21(): number {
return this.c;
}
public set m21(value: number) {
this.c = value;
}
public get m22(): number {
return this.d;
}
public set m22(value: number) {
this.d = value;
}
public get m31(): number {
return this.tx;
}
public set m31(value: number) {
this.tx = value;
}
public get m32(): number {
return this.ty;
}
public set m32(value: number) {
this.ty = value;
/**
* 返回标识矩阵
*/
public static get identity(): Matrix2D {
return this._identity;
}
/**
* 从对象池中取出或创建一个新的Matrix对象。
* 储存在该矩阵中的位置
*/
public static create(): Matrix2D {
let matrix = matrixPool.pop();
if (!matrix)
matrix = new Matrix2D();
return matrix;
public get translation(): Vector2 {
return new Vector2(this.m31, this.m32);
}
public identity(): Matrix2D {
this.a = this.d = 1;
this.b = this.c = this.tx = this.ty = 0;
return this;
public set translation(value: Vector2) {
this.m31 = value.x;
this.m32 = value.y;
}
public translate(dx: number, dy: number): Matrix2D {
this.tx += dx;
this.ty += dy;
return this;
/**
* 以弧度为单位的旋转,存储在这个矩阵中
*/
public get rotation(): number {
return Math.atan2(this.m21, this.m11);
}
public scale(sx: number, sy: number): Matrix2D {
if (sx !== 1) {
this.a *= sx;
this.c *= sx;
this.tx *= sx;
}
if (sy !== 1) {
this.b *= sy;
this.d *= sy;
this.ty *= sy;
}
return this;
public set rotation(value: number){
let val1 = Math.cos(value);
let val2 = Math.sin(value);
this.m11 = val1;
this.m12 = val2;
this.m21 = -val2;
this.m22 = val1;
}
public rotate(angle: number): Matrix2D {
angle = +angle;
if (angle !== 0) {
angle = angle / DEG_TO_RAD;
let u = Math.cos(angle);
let v = Math.sin(angle);
let ta = this.a;
let tb = this.b;
let tc = this.c;
let td = this.d;
let ttx = this.tx;
let tty = this.ty;
this.a = ta * u - tb * v;
this.b = ta * v + tb * u;
this.c = tc * u - td * v;
this.d = tc * v + td * u;
this.tx = ttx * u - tty * v;
this.ty = ttx * v + tty * u;
}
return this;
/**
* 矩阵中存储的旋转度数
*/
public get rotationDegrees() {
return MathHelper.toDegrees(this.rotation);
}
public invert(): Matrix2D {
this.$invertInto(this);
return this;
public set rotationDegrees(value: number) {
this.rotation = MathHelper.toRadians(value);
}
/**
* 储存在这个矩阵中的缩放
*/
public get scale(): Vector2 {
return new Vector2(this.m11, this.m22);
}
public set scale(value: Vector2) {
this.m11 = value.x;
this.m22 = value.y;
}
static _identity: Matrix2D = new Matrix2D(1, 0, 0, 1, 0, 0);
/**
* 构建一个矩阵
* @param m11
* @param m12
* @param m21
* @param m22
* @param m31
* @param m32
*/
constructor(m11: number, m12: number, m21: number, m22: number, m31: number, m32: number){
this.m11 = m11;
this.m12 = m12;
this.m21 = m21;
this.m22 = m22;
this.m31 = m31;
this.m32 = m32;
}
/**
* 创建一个新的围绕Z轴的旋转矩阵2D
* @param radians
*/
public static createRotation(radians: number){
let result: Matrix2D = this.identity;
let val1 = Math.cos(radians);
let val2 = Math.sin(radians);
result.m11 = val1;
result.m12 = val2;
result.m21 = -val2;
result.m22 = val1;
return result;
}
/**
* 创建一个新的缩放矩阵2D
* @param xScale
* @param yScale
*/
public static createScale(xScale: number, yScale: number){
let result: Matrix2D = this.identity;
result.m11 = xScale;
result.m12 = 0;
result.m21 = 0;
result.m22 = yScale;
result.m31 = 0;
result.m32 = 0;
return result;
}
/**
* 创建一个新的平移矩阵2D
* @param xPosition
* @param yPosition
*/
public static createTranslation(xPosition: number, yPosition: number) {
let result: Matrix2D = this.identity;
result.m11 = 1;
result.m12 = 0;
result.m21 = 0;
result.m22 = 1;
result.m31 = xPosition;
result.m32 = yPosition;
return result;
}
public static invert(matrix: Matrix2D) {
let det = 1 / matrix.determinant();
let result = this.identity;
result.m11 = matrix.m22 * det;
result.m12 = -matrix.m12 * det;
result.m21 = -matrix.m21 * det;
result.m22 = matrix.m11 * det;
result.m31 = (matrix.m32 * matrix.m21 - matrix.m31 * matrix.m22) * det;
result.m32 = -(matrix.m32 * matrix.m11 - matrix.m31 * matrix.m12) * det;
return result;
}
/**
@@ -185,10 +234,56 @@ module es {
return this.m11 * this.m22 - this.m12 * this.m21;
}
public release(matrix: Matrix2D) {
if (!matrix)
return;
matrixPool.push(matrix);
/**
* 创建一个新的Matrix2D包含指定矩阵中的线性插值。
* @param matrix1
* @param matrix2
* @param amount
*/
public static lerp(matrix1: Matrix2D, matrix2: Matrix2D, amount: number){
matrix1.m11 = matrix1.m11 + ((matrix2.m11 - matrix1.m11) * amount);
matrix1.m12 = matrix1.m12 + ((matrix2.m12 - matrix1.m12) * amount);
matrix1.m21 = matrix1.m21 + ((matrix2.m21 - matrix1.m21) * amount);
matrix1.m22 = matrix1.m22 + ((matrix2.m22 - matrix1.m22) * amount);
matrix1.m31 = matrix1.m31 + ((matrix2.m31 - matrix1.m31) * amount);
matrix1.m32 = matrix1.m32 + ((matrix2.m32 - matrix1.m32) * amount);
return matrix1;
}
/**
* 交换矩阵的行和列
* @param matrix
*/
public static transpose(matrix: Matrix2D) {
let ret: Matrix2D = this.identity;
ret.m11 = matrix.m11;
ret.m12 = matrix.m21;
ret.m21 = matrix.m12;
ret.m22 = matrix.m22;
ret.m31 = 0;
ret.m32 = 0;
return ret;
}
public mutiplyTranslation(x: number, y: number){
let trans = Matrix2D.createTranslation(x, y);
return MatrixHelper.mutiply(this, trans);
}
/**
* 比较当前实例是否等于指定的Matrix2D
* @param other
*/
public equals(other: Matrix2D){
return this == other;
}
public toString() {
return `{m11:${this.m11} m12:${this.m12} m21:${this.m21} m22:${this.m22} m31:${this.m31} m32:${this.m32}}`
}
}
}

View File

@@ -0,0 +1,99 @@
module es {
export class MatrixHelper {
/**
* 创建一个新的Matrix2D其中包含两个矩阵的和
* @param matrix1
* @param matrix2
*/
public static add(matrix1: Matrix2D, matrix2: Matrix2D): Matrix2D {
let result = Matrix2D.identity;
result.m11 = matrix1.m11 + matrix2.m11;
result.m12 = matrix1.m12 + matrix2.m12;
result.m21 = matrix1.m21 + matrix2.m21;
result.m22 = matrix1.m22 + matrix2.m22;
result.m31 = matrix1.m31 + matrix2.m31;
result.m32 = matrix1.m32 + matrix2.m32;
return result;
}
/**
* 将一个Matrix2D的元素除以另一个矩阵的元素
* @param matrix1
* @param matrix2
*/
public static divide(matrix1: Matrix2D, matrix2: Matrix2D) {
let result = Matrix2D.identity;
result.m11 = matrix1.m11 / matrix2.m11;
result.m12 = matrix1.m12 / matrix2.m12;
result.m21 = matrix1.m21 / matrix2.m21;
result.m22 = matrix1.m22 / matrix2.m22;
result.m31 = matrix1.m31 / matrix2.m31;
result.m32 = matrix1.m32 / matrix2.m32;
return result;
}
/**
* 创建一个新的Matrix2D包含两个矩阵的乘法
* @param matrix1
* @param matrix2
*/
public static mutiply(matrix1: Matrix2D, matrix2: Matrix2D | number) {
let result = Matrix2D.identity;
if (matrix2 instanceof Matrix2D) {
let m11 = (matrix1.m11 * matrix2.m11) + (matrix1.m12 * matrix2.m21);
let m12 = (matrix2.m11 * matrix2.m12) + (matrix1.m12 * matrix2.m22);
let m21 = (matrix1.m21 * matrix2.m11) + (matrix1.m22 * matrix2.m21);
let m22 = (matrix1.m21 * matrix2.m12) + (matrix1.m22 * matrix2.m22);
let m31 = (matrix1.m31 * matrix2.m11) + (matrix1.m32 * matrix2.m21) + matrix2.m31;
let m32 = (matrix1.m31 * matrix2.m12) + (matrix1.m32 * matrix2.m22) + matrix2.m32;
result.m11 = m11;
result.m12 = m12;
result.m21 = m21;
result.m22 = m22;
result.m31 = m31;
result.m32 = m32;
} else if (typeof matrix2 == "number"){
result.m11 = matrix1.m11 * matrix2;
result.m12 = matrix1.m12 * matrix2;
result.m21 = matrix1.m21 * matrix2;
result.m22 = matrix1.m22 * matrix2;
result.m31 = matrix1.m31 * matrix2;
result.m32 = matrix1.m32 * matrix2;
}
return result;
}
/**
* 创建一个新的Matrix2D包含一个矩阵与另一个矩阵的减法。
* @param matrix1
* @param matrix2
*/
public static subtract(matrix1: Matrix2D, matrix2: Matrix2D) {
let result = Matrix2D.identity;
result.m11 = matrix1.m11 - matrix2.m11;
result.m12 = matrix1.m12 - matrix2.m12;
result.m21 = matrix1.m21 - matrix2.m21;
result.m22 = matrix1.m22 - matrix2.m22;
result.m31 = matrix1.m31 - matrix2.m31;
result.m32 = matrix1.m32 - matrix2.m32;
return result;
}
}
}

View File

@@ -1,7 +1,68 @@
module es {
export class Rectangle extends egret.Rectangle {
public _tempMat: Matrix2D;
public _transformMat: Matrix2D;
export class Rectangle implements IEquatable<Rectangle> {
static emptyRectangle: Rectangle = new Rectangle();
/**
* 该矩形的左上角的x坐标
*/
public x: number = 0;
/**
* 该矩形的左上角的y坐标
*/
public y: number = 0;
/**
* 该矩形的宽度
*/
public width: number = 0;
/**
* 该矩形的高度
*/
public height: number = 0;
/**
* 返回X=0, Y=0, Width=0, Height=0的矩形
*/
public static get empty(): Rectangle {
return this.emptyRectangle;
}
/**
* 返回一个Number.Min/Max值的矩形
*/
public static get maxRect(): Rectangle {
return new Rectangle(Number.MIN_VALUE / 2, Number.MIN_VALUE / 2, Number.MAX_VALUE, Number.MAX_VALUE);
}
/**
* 返回此矩形左边缘的X坐标
*/
public get left(): number {
return this.x;
}
/**
* 返回此矩形右边缘的X坐标
*/
public get right(): number {
return this.x + this.width;
}
/**
* 返回此矩形顶边的y坐标
*/
public get top(): number {
return this.y;
}
/**
* 返回此矩形底边的y坐标
*/
public get bottom(): number {
return this.y + this.height;
}
/**
* 获取矩形的最大点,即右下角
@@ -10,22 +71,26 @@ module es {
return new Vector2(this.right, this.bottom);
}
/** 中心点坐标 */
public get center() {
return new Vector2(this.x + (this.width / 2), this.y + (this.height / 2));
/**
* 这个矩形的宽和高是否为0位置是否为00
*/
public isEmpty(): boolean {
return ((((this.width == 0) && (this.height == 0)) && (this.x == 0)) && (this.y == 0));
}
/** 左上角坐标 */
/** 这个矩形的左上角坐标 */
public get location() {
return new Vector2(this.x, this.y);
}
/** 左上角的坐标 */
public set location(value: Vector2) {
this.x = value.x;
this.y = value.y;
}
/**
* 这个矩形的宽-高坐标
*/
public get size() {
return new Vector2(this.width, this.height);
}
@@ -35,8 +100,35 @@ module es {
this.height = value.y;
}
/**
* 位于这个矩形中心的一个点
* 如果 "宽度 "或 "高度 "是奇数,则中心点将向下舍入
*/
public get center() {
return new Vector2(this.x + (this.width / 2), this.y + (this.height / 2));
}
// temp 用于计算边界的矩阵
public _tempMat: Matrix2D;
public _transformMat: Matrix2D;
/**
* 创建一个矩形的最小/最大点(左上角,右下角的点)
* 创建一个新的Rectanglestruct实例指定位置、宽度和高度。
* @param x 创建的矩形的左上角的X坐标
* @param y 创建的矩形的左上角的y坐标
* @param width 创建的矩形的宽度
* @param height 创建的矩形的高度
*/
constructor(x: number = 0, y: number = 0, width: number = 0, height: number = 0) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
/**
* 创建一个给定最小/最大点(左上角,右下角)的矩形
* @param minX
* @param minY
* @param maxX
@@ -49,6 +141,7 @@ module es {
/**
* 给定多边形的点,计算边界
* @param points
* @returns 来自多边形的点
*/
public static rectEncompassingPoints(points: Vector2[]) {
// 我们需要求出x/y的最小值/最大值
@@ -71,28 +164,69 @@ module es {
}
/**
* 如果其他相交矩形返回true
* @param value
* 获取指定边缘的位置
* @param edge
*/
public intersects(value: egret.Rectangle) {
public getSide(edge: Edge) {
switch (edge) {
case Edge.top:
return this.top;
case Edge.bottom:
return this.bottom;
case Edge.left:
return this.left;
case Edge.right:
return this.right;
default:
throw new Error("Argument Out Of Range");
}
}
/**
* 获取所提供的坐标是否在这个矩形的范围内
* @param x 检查封堵点的X坐标
* @param y 检查封堵点的Y坐标
*/
public contains(x: number, y: number): boolean {
return ((((this.x <= x) && (x < (this.x + this.width))) &&
(this.y <= y)) && (y < (this.y + this.height)));
}
/**
* 按指定的水平和垂直方向调整此矩形的边缘
* @param horizontalAmount 调整左、右边缘的值
* @param verticalAmount 调整上、下边缘的值
*/
public inflate(horizontalAmount: number, verticalAmount: number) {
this.x -= horizontalAmount;
this.y -= verticalAmount;
this.width += horizontalAmount * 2;
this.height += verticalAmount * 2;
}
/**
* 获取其他矩形是否与这个矩形相交
* @param value 另一个用于测试的矩形
*/
public intersects(value: Rectangle) {
return value.left < this.right &&
this.left < value.right &&
value.top < this.bottom &&
this.top < value.bottom;
}
public rayIntersects(ray: Ray2D, distance: Ref<number>): boolean{
public rayIntersects(ray: Ray2D, distance: Ref<number>): boolean {
distance.value = 0;
let maxValue = Number.MAX_VALUE;
if (Math.abs(ray.direction.x) < 1E-06){
if (Math.abs(ray.direction.x) < 1E-06) {
if ((ray.start.x < this.x) || (ray.start.x > this.x + this.width))
return false;
}else{
} else {
let num11 = 1 / ray.direction.x;
let num8 = (this.x - ray.start.x) * num11;
let num7 = (this.x + this.width - ray.start.x) * num11;
if (num8 > num7){
if (num8 > num7) {
let num14 = num8;
num8 = num7;
num7 = num14;
@@ -104,14 +238,14 @@ module es {
return false;
}
if (Math.abs(ray.direction.y) < 1E-06){
if (Math.abs(ray.direction.y) < 1E-06) {
if ((ray.start.y < this.y) || (ray.start.y > this.y + this.height))
return false;
}else{
} else {
let num10 = 1 / ray.direction.y;
let num6 = (this.y - ray.start.y) * num10;
let num5 = (this.y + this.height - ray.start.y) * num10;
if (num6 > num5){
if (num6 > num5) {
let num13 = num6;
num6 = num5;
num5 = num13;
@@ -136,28 +270,64 @@ module es {
(value.y < (this.y + this.height)));
}
public contains(x: number, y: number): boolean{
return ((((this.x <= x) && (x < (this.x + this.width))) && (this.y <= y)) && (y < (this.y + this.height)));
}
public getHalfSize() {
return new Vector2(this.width * 0.5, this.height * 0.5);
}
public getClosestPointOnBoundsToOrigin() {
let max = this.max;
let minDist = Math.abs(this.location.x);
let boundsPoint = new Vector2(this.location.x, 0);
if (Math.abs(max.x) < minDist) {
minDist = Math.abs(max.x);
boundsPoint.x = max.x;
boundsPoint.y = 0;
}
if (Math.abs(max.y) < minDist) {
minDist = Math.abs(max.y);
boundsPoint.x = 0;
boundsPoint.y = max.y;
}
if (Math.abs(this.location.y) < minDist) {
minDist = Math.abs(this.location.y);
boundsPoint.x = 0;
boundsPoint.y = this.location.y;
}
return boundsPoint;
}
/**
* 返回离给定点最近的点
* @param point 矩形上离点最近的点
*/
public getClosestPointOnRectangleToPoint(point: Vector2) {
// 对于每条轴,如果点在框外,就把它限制在框内,否则就不要管它
let res = new Vector2();
res.x = MathHelper.clamp(point.x, this.left, this.right);
res.y = MathHelper.clamp(point.y, this.top, this.bottom);
return res;
}
/**
* 获取矩形边界上与给定点最近的点
* @param point
* @param edgeNormal
* @returns 矩形边框上离点最近的点
*/
public getClosestPointOnRectangleBorderToPoint(point: Vector2, edgeNormal: Vector2): Vector2 {
edgeNormal = Vector2.zero;
// 对于每轴,如果点在盒子外面
// 对于每轴,如果点在框外,就把它限制在框内,否则就不要管它
let res = new Vector2();
res.x = MathHelper.clamp(point.x, this.left, this.right);
res.y = MathHelper.clamp(point.y, this.top, this.bottom);
// 如果点在矩形内,我们需要res到边界因为它将在矩形内
// 如果点在矩形内,我们需要res到边界,因为它将在矩形内
if (this.contains(res.x, res.y)) {
let dl = res.x - this.left;
let dr = this.right - res.x;
@@ -189,55 +359,81 @@ module es {
}
/**
*
* 创建一个新的RectangleF该RectangleF包含两个其他矩形的重叠区域
* @param value1
* @param value2
* @returns 将两个矩形的重叠区域作为输出参数
*/
public getClosestPointOnBoundsToOrigin() {
let max = this.max;
let minDist = Math.abs(this.location.x);
let boundsPoint = new Vector2(this.location.x, 0);
if (Math.abs(max.x) < minDist) {
minDist = Math.abs(max.x);
boundsPoint.x = max.x;
boundsPoint.y = 0;
public static intersect(value1: Rectangle, value2: Rectangle) {
if (value1.intersects(value2)) {
let right_side = Math.min(value1.x + value1.width, value2.x + value2.width);
let left_side = Math.max(value1.x, value2.x);
let top_side = Math.max(value1.y, value2.y);
let bottom_side = Math.min(value1.y + value1.height, value2.y + value2.height);
return new Rectangle(left_side, top_side, right_side - left_side, bottom_side - top_side);
} else {
return new Rectangle(0, 0, 0, 0);
}
if (Math.abs(max.y) < minDist) {
minDist = Math.abs(max.y);
boundsPoint.x = 0;
boundsPoint.y = max.y;
}
if (Math.abs(this.location.y) < minDist) {
minDist = Math.abs(this.location.y);
boundsPoint.x = 0;
boundsPoint.y = this.location.y;
}
return boundsPoint;
}
public calculateBounds(parentPosition: Vector2, position: Vector2, origin: Vector2, scale: Vector2, rotation: number, width: number, height: number) {
/**
* 改变这个矩形的位置
* @param offsetX 要添加到这个矩形的X坐标
* @param offsetY 要添加到这个矩形的y坐标
*/
public offset(offsetX: number, offsetY: number) {
this.x += offsetX;
this.y += offsetY;
}
/**
* 创建一个完全包含两个其他矩形的新矩形
* @param value1
* @param value2
*/
public static union(value1: Rectangle, value2: Rectangle) {
let x = Math.min(value1.x, value2.x);
let y = Math.min(value1.y, value2.y);
return new Rectangle(x, y,
Math.max(value1.right, value2.right) - x,
Math.max(value1.bottom, value2.bottom) - y);
}
/**
* 在矩形重叠的地方创建一个新的矩形
* @param value1
* @param value2
*/
public static overlap(value1: Rectangle, value2: Rectangle): Rectangle {
let x = Math.max(Math.max(value1.x, value2.x), 0);
let y = Math.max(Math.max(value1.y, value2.y), 0);
return new Rectangle(x, y,
Math.max(Math.min(value1.right, value2.right) - x, 0),
Math.max(Math.min(value1.bottom, value2.bottom) - y, 0));
}
public calculateBounds(parentPosition: Vector2, position: Vector2, origin: Vector2, scale: Vector2,
rotation: number, width: number, height: number) {
if (rotation == 0) {
this.x = parentPosition.x + position.x - origin.x * scale.x;
this.y = parentPosition.y + position.y - origin.y * scale.y;
this.width = width * scale.x;
this.height = height * scale.y;
} else {
// 特别注意旋转的边界。我们需要找到绝对最小/最大值并从中创建边界
// 我们需要找到我们的绝对最小/最大值,并据此创建边界
let worldPosX = parentPosition.x + position.x;
let worldPosY = parentPosition.y + position.y;
// 将参考点设置为世界参考
this._transformMat = Matrix2D.create().translate(-worldPosX - origin.x, -worldPosY - origin.y);
this._tempMat = Matrix2D.create().scale(scale.x, scale.y);
// 考虑到原点,将参考点设置为世界参考
this._transformMat = Matrix2D.createTranslation(-worldPosX - origin.x, -worldPosY - origin.y);
this._tempMat = Matrix2D.createScale(scale.x, scale.y);
this._transformMat = this._transformMat.multiply(this._tempMat);
this._tempMat = Matrix2D.create().rotate(rotation);
this._tempMat = Matrix2D.createRotation(rotation);
this._transformMat = this._transformMat.multiply(this._tempMat);
this._tempMat = Matrix2D.create().translate(worldPosX, worldPosY);
this._tempMat = Matrix2D.createTranslation(worldPosX, worldPosY);
this._transformMat = this._transformMat.multiply(this._tempMat);
// TODO: 这有点傻。我们可以把世界变换留在矩阵中,避免在世界空间中得到所有的四个角
// TODO: 我们可以把世界变换留在矩阵中,避免在世界空间中得到所有的四个角
let topLeft = new Vector2(worldPosX, worldPosY);
let topRight = new Vector2(worldPosX + width, worldPosY);
let bottomLeft = new Vector2(worldPosX, worldPosY + height);
@@ -248,6 +444,7 @@ module es {
Vector2Ext.transformR(bottomLeft, this._transformMat, bottomLeft);
Vector2Ext.transformR(bottomRight, this._transformMat, bottomRight);
// 找出最小值和最大值,这样我们就可以计算出我们的边界框。
let minX = Math.min(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x);
let maxX = Math.max(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x);
let minY = Math.min(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y);
@@ -258,5 +455,105 @@ module es {
this.height = maxY - minY;
}
}
/**
* 返回一个横跨当前矩形和提供的三角形位置的矩形
* @param deltaX
* @param deltaY
*/
public getSweptBroadphaseBounds(deltaX: number, deltaY: number){
let broadphasebox = Rectangle.empty;
broadphasebox.x = deltaX > 0 ? this.x : this.x + deltaX;
broadphasebox.y = deltaY > 0 ? this.y : this.y + deltaY;
broadphasebox.width = deltaX > 0 ? deltaX + this.width : this.width - deltaX;
broadphasebox.height = deltaY > 0 ? deltaY + this.height : this.height - deltaY;
return broadphasebox;
}
/**
* 如果发生碰撞返回true
* moveX和moveY将返回b1为避免碰撞而必须移动的移动量
* @param other
* @param moveX
* @param moveY
*/
public collisionCheck(other: Rectangle, moveX: Ref<number>, moveY: Ref<number>){
moveX.value = moveY.value = 0;
let l = other.x - (this.x + this.width);
let r = (other.x + other.width) - this.x;
let t = (other.y - (this.y + this.height));
let b = (other.y + other.height) - this.y;
// 检验是否有碰撞
if (l > 0 || r < 0 || t > 0 || b < 0)
return false;
// 求两边的偏移量
moveX.value = Math.abs(l) < r ? l : r;
moveY.value = Math.abs(t) < b ? t : b;
// 只使用最小的偏移量
if (Math.abs(moveX.value) < Math.abs(moveY.value))
moveY.value = 0;
else
moveX.value = 0;
return true;
}
/**
* 计算两个矩形之间有符号的交点深度
* @param rectA
* @param rectB
* @returns 两个相交的矩形之间的重叠量。
* 这些深度值可以是负值,取决于矩形/相交的哪些边。
* 这允许调用者确定正确的推送对象的方向,以解决碰撞问题。
* 如果矩形不相交则返回Vector2.Zero
*/
public static getIntersectionDepth(rectA: Rectangle, rectB: Rectangle): Vector2 {
// 计算半尺寸
let halfWidthA = rectA.width / 2;
let halfHeightA = rectA.height / 2;
let halfWidthB = rectB.width / 2;
let halfHeightB = rectB.height / 2;
// 计算中心
let centerA = new Vector2(rectA.left + halfWidthA, rectA.top + halfHeightA);
let centerB = new Vector2(rectB.left + halfWidthB, rectB.top + halfHeightB);
// 计算当前中心间的距离和最小非相交距离
let distanceX = centerA.x - centerB.x;
let distanceY = centerA.y - centerB.y;
let minDistanceX = halfWidthA + halfWidthB;
let minDistanceY = halfHeightA + halfHeightB;
// 如果我们根本不相交,则返回(00)
if (Math.abs(distanceX) >= minDistanceX || Math.abs(distanceY) >= minDistanceY)
return Vector2.zero;
// 计算并返回交叉点深度
let depthX = distanceX > 0 ? minDistanceX - distanceX : -minDistanceX - distanceX;
let depthY = distanceY > 0 ? minDistanceY - distanceY : -minDistanceY - distanceY;
return new Vector2(depthX, depthY);
}
/**
* 比较当前实例是否等于指定的矩形
* @param other
*/
public equals(other: Rectangle) {
return this === other;
}
/**
* 获取这个矩形的哈希码
*/
public getHashCode(): number{
return (this.x ^ this.y ^ this.width ^ this.height);
}
}
}

View File

@@ -79,7 +79,7 @@ module es {
return Vector2.distanceSquared(circleCenter, point) < radius * radius;
}
public static rectToCircle(rect: egret.Rectangle, cPosition: Vector2, cRadius: number): boolean {
public static rectToCircle(rect: Rectangle, cPosition: Vector2, cRadius: number): boolean {
if (this.rectToPoint(rect.x, rect.y, rect.width, rect.height, cPosition))
return true;

View File

@@ -217,10 +217,10 @@ module es {
if (collider.shouldColliderScaleAndRotateWithTransform) {
let hasUnitScale = true;
let tempMat: Matrix2D;
let combinedMatrix = Matrix2D.create().translate(-this._polygonCenter.x, -this._polygonCenter.y);
let combinedMatrix = Matrix2D.createTranslation(-this._polygonCenter.x, -this._polygonCenter.y);
if (!collider.entity.transform.scale.equals(Vector2.one)) {
tempMat = Matrix2D.create().scale(collider.entity.transform.scale.x, collider.entity.transform.scale.y);
tempMat = Matrix2D.createScale(collider.entity.transform.scale.x, collider.entity.transform.scale.y);
combinedMatrix = combinedMatrix.multiply(tempMat);
hasUnitScale = false;
@@ -229,7 +229,7 @@ module es {
}
if (collider.entity.transform.rotation != 0) {
tempMat = Matrix2D.create().rotate(collider.entity.transform.rotation);
tempMat = Matrix2D.createRotation(collider.entity.transform.rotation);
combinedMatrix = combinedMatrix.multiply(tempMat);
// 为了处理偏移原点的旋转我们只需要将圆心在(0,0)附近移动
@@ -241,7 +241,7 @@ module es {
collider.entity.transform.rotationDegrees + offsetAngle);
}
tempMat = Matrix2D.create().translate(this._polygonCenter.x, this._polygonCenter.y);
tempMat = Matrix2D.createTranslation(this._polygonCenter.x, this._polygonCenter.y);
combinedMatrix = combinedMatrix.multiply(tempMat);
// 最后变换原始点

View File

@@ -53,7 +53,7 @@ module es {
for (let y = p1.y; y <= p2.y; y++) {
// 如果没有单元格,我们需要创建它
let c: Collider[] = this.cellAtPosition(x, y, true);
if (!c.firstOrDefault(c => c.hashCode == collider.hashCode))
if (!c.firstOrDefault(c => c == collider))
c.push(collider);
}
}
@@ -134,7 +134,7 @@ module es {
continue;
if (bounds.intersects(collider.bounds)) {
if (!this._tempHashSet.firstOrDefault(c => c.hashCode == collider.hashCode))
if (!this._tempHashSet.firstOrDefault(c => c == collider))
this._tempHashSet.push(collider);
}
}

View File

@@ -1,71 +0,0 @@
module es {
/**
* 支持标题安全区的布局类。
*/
export class Layout {
public clientArea: Rectangle;
public safeArea: Rectangle;
constructor() {
this.clientArea = new Rectangle(0, 0, Core.graphicsDevice.viewport.width, Core.graphicsDevice.viewport.height);
this.safeArea = this.clientArea;
}
public place(size: Vector2, horizontalMargin: number, verticalMargine: number, alignment: Alignment) {
let rc = new Rectangle(0, 0, size.x, size.y);
if ((alignment & Alignment.left) != 0) {
rc.x = this.clientArea.x + (this.clientArea.width * horizontalMargin);
} else if ((alignment & Alignment.right) != 0) {
rc.x = this.clientArea.x + (this.clientArea.width * (1 - horizontalMargin)) - rc.width;
} else if ((alignment & Alignment.horizontalCenter) != 0) {
rc.x = this.clientArea.x + (this.clientArea.width - rc.width) / 2 + (horizontalMargin * this.clientArea.width);
} else {
}
if ((alignment & Alignment.top) != 0) {
rc.y = this.clientArea.y + (this.clientArea.height * verticalMargine);
} else if ((alignment & Alignment.bottom) != 0) {
rc.y = this.clientArea.y + (this.clientArea.height * (1 - verticalMargine)) - rc.height;
} else if ((alignment & Alignment.verticalCenter) != 0) {
rc.y = this.clientArea.y + (this.clientArea.height - rc.height) / 2 + (verticalMargine * this.clientArea.height);
} else {
}
// 确保布局区域在安全区域内。
if (rc.left < this.safeArea.left)
rc.x = this.safeArea.left;
if (rc.right > this.safeArea.right)
rc.x = this.safeArea.right - rc.width;
if (rc.top < this.safeArea.top)
rc.y = this.safeArea.top;
if (rc.bottom > this.safeArea.bottom)
rc.y = this.safeArea.bottom - rc.height;
return rc;
}
}
export enum Alignment {
none = 0,
left = 1,
right = 2,
horizontalCenter = 4,
top = 8,
bottom = 16,
verticalCenter = 32,
topLeft = top | left,
topRight = top | right,
topCenter = top | horizontalCenter,
bottomLeft = bottom | left,
bottomRight = bottom | right,
bottomCenter = bottom | horizontalCenter,
centerLeft = verticalCenter | left,
centerRight = verticalCenter | right,
center = verticalCenter | horizontalCenter
}
}

View File

@@ -1,408 +0,0 @@
module es {
/**
* 通过使用这个类您可以直观地找到瓶颈和基本的CPU使用情况。
*/
export class TimeRuler {
/** 最大条数 8 */
public static readonly maxBars = 8;
/** */
public static readonly maxSamples = 256;
/** 每条的最大嵌套调用 */
public static readonly maxNestCall = 32;
/** 条的高度(以像素为单位) */
public static readonly barHeight = 8;
/** 最大显示帧 */
public static readonly maxSampleFrames = 4;
/** 持续时间(帧数)为采取抓拍日志。 */
public static readonly logSnapDuration = 120;
public static readonly barPadding = 2;
public static readonly autoAdjustDelay = 30;
private static _instance;
/** 获取/设置目标样本帧。 */
public targetSampleFrames: number;
/** 获取/设置计时器标尺宽度。 */
public width: number;
public enabled: true;
/** 获取/设置日志显示或否 */
public showLog = false;
/** 每帧的日志 */
public logs: FrameLog[];
/** 当前显示帧计数 */
private sampleFrames: number;
/** TimerRuler画的位置。 */
private _position: Vector2;
/** 上一帧日志 */
private prevLog: FrameLog;
/** 当前帧日志 */
private curLog: FrameLog;
/** 当前帧数量 */
private frameCount: number;
/** */
private markers: MarkerInfo[] = [];
/** 秒表用来测量时间。 */
private stopwacth: stopwatch.Stopwatch = new stopwatch.Stopwatch();
/** 从标记名映射到标记id的字典。 */
private _markerNameToIdMap: Map<string, number> = new Map<string, number>();
/**
* 你想在游戏开始时调用StartFrame更新方法。
* 当游戏在固定时间步进模式下运行缓慢时,更新会多次调用。
* 在这种情况下我们应该忽略StartFrame调用。
* 为此我们只需一直跟踪StartFrame调用的次数直到Draw被调用。
*/
private _updateCount: number;
private _frameAdjust: number;
/** 画透明背景 */
private _rectShape1: egret.Shape = new egret.Shape();
private _rectShape2: egret.Shape = new egret.Shape();
private _rectShape3: egret.Shape = new egret.Shape();
private _rectShape4: egret.Shape = new egret.Shape();
private _rectShape5: egret.Shape = new egret.Shape();
private _rectShape6: egret.Shape = new egret.Shape();
constructor() {
this.logs = new Array<FrameLog>(2);
for (let i = 0; i < this.logs.length; ++i)
this.logs[i] = new FrameLog();
this.sampleFrames = this.targetSampleFrames = 1;
this.width = Math.floor(Core.graphicsDevice.viewport.width * 0.8);
es.Core.emitter.addObserver(CoreEvents.GraphicsDeviceReset, this.onGraphicsDeviceReset, this);
this.onGraphicsDeviceReset();
es.Core.Instance.stage.addChild(this._rectShape1);
es.Core.Instance.stage.addChild(this._rectShape2);
es.Core.Instance.stage.addChild(this._rectShape3);
es.Core.Instance.stage.addChild(this._rectShape4);
es.Core.Instance.stage.addChild(this._rectShape5);
es.Core.Instance.stage.addChild(this._rectShape6);
}
public static get Instance(): TimeRuler {
if (!this._instance)
this._instance = new TimeRuler();
return this._instance;
}
/**
* 开始新的帧
*/
public startFrame() {
// 当这个方法被多次调用时,我们跳过复位帧。
if (isNaN(this._updateCount))
this._updateCount = 0;
let count = this._updateCount ++;
if (this.enabled && (1 < count && count < TimeRuler.maxSampleFrames))
return;
// 更新当前帧记录
this.prevLog = this.logs[this.frameCount++ & 0x1];
this.curLog = this.logs[this.frameCount & 0x1];
let endFrameTime = this.stopwacth.getTime();
// 更新标记并创建日志。
for (let barIdx = 0; barIdx < this.prevLog.bars.length; ++barIdx) {
let prevBar = this.prevLog.bars[barIdx];
let nextBar = this.curLog.bars[barIdx];
// 重新打开前一帧中没有被调用的EndMark的标记
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[barIdx].color = prevBar.markers[markerIdx].color;
if (!m.logs[barIdx].initialized) {
m.logs[barIdx].min = duration;
m.logs[barIdx].max = duration;
m.logs[barIdx].avg = duration;
m.logs[barIdx].initialized = true;
} else {
m.logs[barIdx].min = Math.min(m.logs[barIdx].min, duration);
m.logs[barIdx].max = Math.min(m.logs[barIdx].max, duration);
m.logs[barIdx].avg += duration;
m.logs[barIdx].avg *= 0.5;
if (m.logs[barIdx].samples++ >= TimeRuler.logSnapDuration) {
m.logs[barIdx].snapMin = m.logs[barIdx].min;
m.logs[barIdx].snapMax = m.logs[barIdx].max;
m.logs[barIdx].snapAvg = m.logs[barIdx].avg;
m.logs[barIdx].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) {
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("超出采样次数可以设置更大的数字为timeruler.maxsaple或者降低采样次数");
}
if (bar.nestCount >= TimeRuler.maxNestCall) {
throw new Error("超出采样次数可以设置更大的数字为timeruler.maxsaple或者降低采样次数");
}
// 获取注册的标记
let markerId = this._markerNameToIdMap.get(markerName);
if (isNaN(markerId)) {
// 如果此标记未注册,则注册此标记。
markerId = this.markers.length;
this._markerNameToIdMap.set(markerName, markerId);
this.markers.push(new MarkerInfo(markerName));
}
// 开始测量
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.markCount ++;
}
/**
*
* @param markerName
* @param barIndex
*/
public endMark(markerName: string, barIndex: number = 0) {
if (barIndex < 0 || barIndex >= TimeRuler.maxBars)
throw new Error("barIndex参数超出范围");
let bar = this.curLog.bars[barIndex];
if (bar.nestCount <= 0) {
throw new Error("先调用beginMark方法再调用endMark方法");
}
let markerId = this._markerNameToIdMap.get(markerName);
if (isNaN(markerId)) {
throw new Error(`标记 ${markerName} 未注册。请确认您指定的名称与 beginMark 方法使用的名称相同`);
}
let markerIdx = bar.markerNests[--bar.nestCount];
if (bar.markers[markerIdx].markerId != markerId) {
throw new Error("beginMark/endMark方法的调用顺序不正确beginMark(A)beginMark(B)endMark(B)endMark(A)但你不能像beginMark(A)beginMark(B)endMark(A)endMark(B)这样调用。");
}
bar.markers[markerIdx].endTime = this.stopwacth.getTime();
}
/**
* 获取给定bar索引和标记名称的平均时间。
* @param barIndex
* @param markerName
*/
public getAverageTime(barIndex: number, markerName: string) {
if (barIndex < 0 || barIndex >= TimeRuler.maxBars) {
throw new Error("barIndex参数超出范围");
}
let result = 0;
let markerId = this._markerNameToIdMap.get(markerName);
if (markerId) {
result = this.markers[markerId].logs[barIndex].avg;
}
return result;
}
/**
*
*/
public resetLog() {
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].samples = 0;
}
});
}
public render(position: Vector2 = this._position, width: number = this.width) {
if (!this.showLog)
return;
let height = 0;
let maxTime = 0;
this.prevLog.bars.forEach(bar => {
if (bar.markCount > 0) {
height += TimeRuler.barHeight + TimeRuler.barPadding * 2;
maxTime = Math.max(maxTime, bar.markers[bar.markCount - 1].endTime);
}
});
const frameSpan = 1 / 60 * 1000;
let sampleSpan = this.sampleFrames * frameSpan;
if (maxTime > sampleSpan) {
this._frameAdjust = Math.max(0, this._frameAdjust) + 1;
} else {
this._frameAdjust = Math.min(0, this._frameAdjust) - 1;
}
if (Math.max(this._frameAdjust) > TimeRuler.autoAdjustDelay) {
this.sampleFrames = Math.min(TimeRuler.maxSampleFrames, this.sampleFrames);
this.sampleFrames = Math.max(this.targetSampleFrames, Math.floor(maxTime / frameSpan) + 1);
this._frameAdjust = 0;
}
let msToPs = width / sampleSpan;
let startY = position.y - (height - TimeRuler.barHeight);
let y = startY;
// 画透明背景
let rc = new Rectangle(position.x, y, width, height);
this._rectShape1.graphics.clear();
this._rectShape1.graphics.beginFill(0x000000, 128 / 255);
this._rectShape1.graphics.drawRect(rc.x, rc.y, rc.width, rc.height);
this._rectShape1.graphics.endFill();
// 为每条线画标记
rc.height = TimeRuler.barHeight;
this._rectShape2.graphics.clear();
for (let bar of this.prevLog.bars){
rc.y = y + TimeRuler.barPadding;
if (bar.markCount > 0){
for (let j = 0; j < bar.markCount; ++j){
let bt = bar.markers[j].beginTime;
let et = bar.markers[j].endTime;
let sx = Math.floor(position.x + bt * msToPs);
let ex = Math.floor(position.x + et * msToPs);
rc.x = sx;
rc.width = Math.max(ex - sx, 1);
this._rectShape2.graphics.beginFill(bar.markers[j].color);
this._rectShape2.graphics.drawRect(rc.x, rc.y, rc.width, rc.height);
this._rectShape2.graphics.endFill();
}
}
y += TimeRuler.barHeight + TimeRuler.barPadding;
}
// 画网格线
// 每个网格代表ms
rc = new Rectangle(position.x, startY, 1, height);
this._rectShape3.graphics.clear();
for (let t = 1; t < sampleSpan; t += 1){
rc.x = Math.floor(position.x + t * msToPs);
this._rectShape3.graphics.beginFill(0x808080);
this._rectShape3.graphics.drawRect(rc.x, rc.y, rc.width, rc.height);
this._rectShape3.graphics.endFill();
}
// 画frame grid
this._rectShape4.graphics.clear();
for (let i = 0; i <= this.sampleFrames; ++i){
rc.x = Math.floor(position.x + frameSpan * i * msToPs);
this._rectShape4.graphics.beginFill(0xFFFFFF);
this._rectShape4.graphics.drawRect(rc.x, rc.y, rc.width, rc.height);
this._rectShape4.graphics.endFill();
}
// TODO: 绘制字体
}
private onGraphicsDeviceReset() {
let layout = new Layout();
this._position = layout.place(new Vector2(this.width, TimeRuler.barHeight), 0, 0.01, Alignment.bottomCenter).location;
}
}
/**
* 日志信息
*/
export class FrameLog {
public bars: MarkerCollection[];
constructor() {
this.bars = new Array<MarkerCollection>(TimeRuler.maxBars);
this.bars.fill(new MarkerCollection(), 0, TimeRuler.maxBars);
}
}
/**
* 标记的集合
*/
export class MarkerCollection {
public markers: Marker[] = new Array<Marker>(TimeRuler.maxSamples);
public markCount: number = 0;
public markerNests: number[] = new Array<number>(TimeRuler.maxNestCall);
public nestCount: number = 0;
constructor() {
this.markers.fill(new Marker(), 0, TimeRuler.maxSamples);
this.markerNests.fill(0, 0, TimeRuler.maxNestCall);
}
}
export class Marker {
public markerId: number = 0;
public beginTime: number = 0;
public endTime: number = 0;
public color: number = 0x000000;
}
export class MarkerInfo {
public name: string;
public logs: MarkerLog[] = new Array<MarkerLog>(TimeRuler.maxBars);
constructor(name) {
this.name = name;
this.logs.fill(new MarkerLog(), 0, TimeRuler.maxBars);
}
}
export class MarkerLog {
public snapMin: number = 0;
public snapMax: number = 0;
public snapAvg: number = 0;
public min: number = 0;
public max: number = 0;
public avg: number = 0;
public samples: number = 0;
public color: number = 0x000000;
public initialized: boolean = false;
}
}

View File

@@ -1,44 +0,0 @@
module es {
export class ContentManager {
protected loadedAssets: Map<string, any> = new Map<string, any>();
/** 异步加载资源 */
public loadRes(name: string, local: boolean = true): Promise<any> {
return new Promise((resolve, reject) => {
let res = this.loadedAssets.get(name);
if (res) {
resolve(res);
return;
}
if (local) {
RES.getResAsync(name).then((data) => {
this.loadedAssets.set(name, data);
resolve(data);
}).catch((err) => {
console.error("资源加载错误:", name, err);
reject(err);
});
} else {
RES.getResByUrl(name).then((data) => {
this.loadedAssets.set(name, data);
resolve(data);
}).catch((err) => {
console.error("资源加载错误:", name, err);
reject(err);
});
}
});
}
public dispose() {
this.loadedAssets.forEach(value => {
let assetsToRemove = value;
if (RES.destroyRes(assetsToRemove))
assetsToRemove.dispose();
});
this.loadedAssets.clear();
}
}
}

View File

@@ -1,38 +0,0 @@
module es {
/**
* startCoroutine返回的接口提供了在执行中停止协同程序的能力
*/
export interface ICoroutine {
/**
* 停止协同程序
*/
stop();
/**
* 设置协程应该使用时间增量还是使用非缩放时间增量来计时
* @param useUnscaledDeltaTime
*/
setUseUnscaledDeltaTime(useUnscaledDeltaTime): ICoroutine;
}
export class Coroutine {
public static waitForSeconds(seconds: number){
return WaitForSeconds.waiter.wait(seconds);
}
}
/**
* 协作程序需要暂停一段时间时的助手类。
* 返回协同程序。
* waitForSeconds返回number。
*/
export class WaitForSeconds {
public static waiter: WaitForSeconds = new WaitForSeconds();
public waitTime: number;
public wait(seconds: number): WaitForSeconds {
WaitForSeconds.waiter.waitTime = seconds;
return WaitForSeconds.waiter;
}
}
}

View File

@@ -1,153 +0,0 @@
module es {
/**
* CoroutineManager使用的内部类用于隐藏协同程序所需的数据
*/
export class CoroutineImpl implements ICoroutine, IPoolable {
public enumerator: Iterator<any>;
/**
* 每当产生延迟时它就被添加到跟踪延迟的waitTimer中
*/
public waitTimer: number;
public isDone: boolean;
public waitForCoroutine: CoroutineImpl;
public useUnscaledDeltaTime: boolean = false;
public stop(){
this.isDone = true;
}
public setUseUnscaledDeltaTime(useUnscaledDeltaTime): es.ICoroutine {
this.useUnscaledDeltaTime = useUnscaledDeltaTime;
return this;
}
public prepareForuse(){
this.isDone = false;
}
public reset() {
this.isDone = true;
this.waitTimer = 0;
this.waitForCoroutine = null;
this.enumerator = null;
this.useUnscaledDeltaTime = false;
}
}
/**
* 基本CoroutineManager。协同程序可以做以下事情:
* - return null(在下一帧继续执行)
* - return Coroutine.waitForSeconds(3)。等待3秒(延时3秒后再次执行)
* - return startCoroutine(another())(在再次执行之前等待另一个协程)
*/
export class CoroutineManager extends GlobalManager {
/**
* 标记来跟踪何时处于更新循环中。
* 如果一个新的协程在更新循环期间启动我们必须将其插入到shouldRunNextFrame列表中以避免在迭代时修改列表。
*/
public _isInUpdate: boolean;
public _unblockedCoroutines: CoroutineImpl[] = [];
public _shouldRunNextFrame: CoroutineImpl[] = [];
/**
* 将i枚举器添加到CoroutineManager。协程在每一帧调用更新之前被执行。
* @param enumerator
*/
public startCoroutine(enumerator: Iterator<any>) {
// 查找或创建CoroutineImpl
let coroutine = Pool.obtain<CoroutineImpl>(CoroutineImpl);
coroutine.prepareForuse();
// 设置协程并添加它
coroutine.enumerator = enumerator;
let shouldContinueCoroutine = this.tickCoroutine(coroutine);
// 防止空协程
if (!shouldContinueCoroutine)
return null;
if (this._isInUpdate)
this._shouldRunNextFrame.push(coroutine);
else
this._unblockedCoroutines.push(coroutine);
return coroutine;
}
public update() {
this._isInUpdate = true;
for (let i = 0; i < this._unblockedCoroutines.length; i ++){
let coroutine = this._unblockedCoroutines[i];
// 检查已停止的协程
if (coroutine.isDone){
Pool.free<CoroutineImpl>(coroutine);
continue;
}
// 我们是否在等待其他协程完成
if (coroutine.waitForCoroutine != null){
if (coroutine.waitForCoroutine.isDone){
coroutine.waitForCoroutine = null;
}else{
this._shouldRunNextFrame.push(coroutine);
continue;
}
}
// 如果我们有计时器,就用它
if (coroutine.waitTimer > 0){
// 还有时间。递减并再次运行下一帧确保递减与适当的deltaTime。
coroutine.waitTimer -= coroutine.useUnscaledDeltaTime ? Time.unscaledDeltaTime : Time.deltaTime;
this._shouldRunNextFrame.push(coroutine);
continue;
}
if (this.tickCoroutine(coroutine))
this._shouldRunNextFrame.push(coroutine);
}
this._unblockedCoroutines.length = 0;
this._unblockedCoroutines.concat(this._shouldRunNextFrame);
this._shouldRunNextFrame.length = 0;
this._isInUpdate = false;
}
/**
* 如果协同程序在下一帧继续运行则返回true。此方法将把完成的协程放回池中!
* @param coroutine
*/
public tickCoroutine(coroutine: CoroutineImpl){
let current = coroutine.enumerator.next();
// 这个协同程序已经完成了
if (!current.value || current.done){
Pool.free<CoroutineImpl>(coroutine);
return false;
}
if (!current.value){
return true;
}
if (current.value instanceof WaitForSeconds){
coroutine.waitTimer = (current.value as WaitForSeconds).waitTime;
return true;
}
if (current.value instanceof Number){
console.warn("协同程序检查返回一个Number类型请不要在生产环境使用");
coroutine.waitTimer = Number(current);
return true;
}
if (current.value instanceof CoroutineImpl){
coroutine.waitForCoroutine = current.value as CoroutineImpl;
return true;
}else {
return true;
}
}
}
}

View File

@@ -1,17 +0,0 @@
module es {
/** 各种辅助方法来辅助绘图 */
export class DrawUtils {
public static getColorMatrix(color: number): egret.ColorMatrixFilter {
let colorMatrix = [
1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0
];
colorMatrix[0] = Math.floor(color / 256 / 256) / 255;
colorMatrix[6] = Math.floor(color / 256 % 256) / 255;
colorMatrix[12] = color % 256 / 255;
return new egret.ColorMatrixFilter(colorMatrix);
}
}
}

View File

@@ -1,193 +0,0 @@
module es {
export class TouchState {
public x = 0;
public y = 0;
public touchPoint: number = -1;
public touchDown: boolean = false;
public get position() {
return new Vector2(this.x, this.y);
}
public reset() {
this.x = 0;
this.y = 0;
this.touchDown = false;
this.touchPoint = -1;
}
}
export class Input {
private static _init: boolean = false;
private static _previousTouchState: TouchState = new TouchState();
private static _resolutionOffset: Vector2 = new Vector2();
private static _touchIndex: number = 0;
private static _gameTouchs: TouchState[] = [];
/**
* 触摸列表 存放最大个数量触摸点信息
* 可通过判断touchPoint是否为-1 来确定是否为有触摸
* 通过判断touchDown 判断触摸点是否有按下
*/
public static get gameTouchs() {
return this._gameTouchs;
}
private static _resolutionScale: Vector2 = Vector2.one;
/** 获取缩放值 默认为1 */
public static get resolutionScale() {
return this._resolutionScale;
}
private static _totalTouchCount: number = 0;
/** 当前触摸点数量 */
public static get totalTouchCount() {
return this._totalTouchCount;
}
/** 返回第一个触摸点的坐标 */
public static get touchPosition() {
if (!this._gameTouchs[0])
return Vector2.zero;
return this._gameTouchs[0].position;
}
public static _virtualInputs: VirtualInput[] = [];
/** 获取最大触摸数 */
public static get maxSupportedTouch() {
return Core._instance.stage.maxTouches;
}
/**
* 设置最大触摸数
*/
public static set maxSupportedTouch(value: number) {
Core._instance.stage.maxTouches = value;
this.initTouchCache();
}
/** 获取第一个触摸点距离上次距离的增量 */
public static get touchPositionDelta() {
let delta = Vector2.subtract(this.touchPosition, this._previousTouchState.position);
if (delta.length() > 0) {
this.setpreviousTouchState(this._gameTouchs[0]);
}
return delta;
}
public static initialize() {
if (this._init)
return;
this._init = true;
Core._instance.stage.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.touchBegin, this);
Core._instance.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE, this.touchMove, this);
Core._instance.stage.addEventListener(egret.TouchEvent.TOUCH_END, this.touchEnd, this);
Core._instance.stage.addEventListener(egret.TouchEvent.TOUCH_CANCEL, this.touchEnd, this);
Core._instance.stage.addEventListener(egret.TouchEvent.TOUCH_RELEASE_OUTSIDE, this.touchEnd, this);
this.initTouchCache();
}
public static update(){
KeyboardUtils.update();
for (let i = 0; i < this._virtualInputs.length; i ++)
this._virtualInputs[i].update();
}
public static scaledPosition(position: Vector2) {
let scaledPos = new Vector2(position.x - this._resolutionOffset.x, position.y - this._resolutionOffset.y);
return Vector2.multiply(scaledPos, this.resolutionScale);
}
/**
* 只有在当前帧按下并且在上一帧没有按下时才算press
* @param key
*/
public static isKeyPressed(key: Keys): boolean{
return KeyboardUtils.currentKeys.contains(key) && !KeyboardUtils.previousKeys.contains(key);
}
public static isKeyPressedBoth(keyA: Keys, keyB: Keys){
return this.isKeyPressed(keyA) || this.isKeyPressed(keyB);
}
public static isKeyDown(key: Keys): boolean {
return KeyboardUtils.currentKeys.contains(key);
}
public static isKeyDownBoth(keyA: Keys, keyB: Keys){
return this.isKeyDown(keyA) || this.isKeyDown(keyB);
}
public static isKeyReleased(key: Keys){
return !KeyboardUtils.currentKeys.contains(key) && KeyboardUtils.previousKeys.contains(key);
}
public static isKeyReleasedBoth(keyA: Keys, keyB: Keys){
return this.isKeyReleased(keyA) || this.isKeyReleased(keyB);
}
private static initTouchCache() {
this._totalTouchCount = 0;
this._touchIndex = 0;
this._gameTouchs.length = 0;
for (let i = 0; i < this.maxSupportedTouch; i++) {
this._gameTouchs.push(new TouchState());
}
}
private static touchBegin(evt: egret.TouchEvent) {
if (this._touchIndex < this.maxSupportedTouch) {
this._gameTouchs[this._touchIndex].touchPoint = evt.touchPointID;
this._gameTouchs[this._touchIndex].touchDown = evt.touchDown;
this._gameTouchs[this._touchIndex].x = evt.stageX;
this._gameTouchs[this._touchIndex].y = evt.stageY;
if (this._touchIndex == 0) {
this.setpreviousTouchState(this._gameTouchs[0]);
}
this._touchIndex++;
this._totalTouchCount++;
}
}
private static touchMove(evt: egret.TouchEvent) {
if (evt.touchPointID == this._gameTouchs[0].touchPoint) {
this.setpreviousTouchState(this._gameTouchs[0]);
}
let touchIndex = this._gameTouchs.findIndex(touch => touch.touchPoint == evt.touchPointID);
if (touchIndex != -1) {
let touchData = this._gameTouchs[touchIndex];
touchData.x = evt.stageX;
touchData.y = evt.stageY;
}
}
private static touchEnd(evt: egret.TouchEvent) {
let touchIndex = this._gameTouchs.findIndex(touch => touch.touchPoint == evt.touchPointID);
if (touchIndex != -1) {
let touchData = this._gameTouchs[touchIndex];
touchData.reset();
if (touchIndex == 0)
this._previousTouchState.reset();
this._totalTouchCount--;
if (this.totalTouchCount == 0) {
this._touchIndex = 0;
}
}
}
private static setpreviousTouchState(touchState: TouchState) {
this._previousTouchState = new TouchState();
this._previousTouchState.x = touchState.position.x;
this._previousTouchState.y = touchState.position.y;
this._previousTouchState.touchPoint = touchState.touchPoint;
this._previousTouchState.touchDown = touchState.touchDown;
}
}
}

View File

@@ -1,47 +0,0 @@
import Keys = es.Keys;
class KeyboardUtils {
/**
* 当前帧按键状态
*/
public static currentKeys: Keys[] = [];
/**
* 上一帧按键状态
*/
public static previousKeys: Keys[] = [];
private static keyStatusKeys: Keys[] = [];
public static init(): void {
document.addEventListener("keydown", KeyboardUtils.onKeyDownHandler);
document.addEventListener("keyup", KeyboardUtils.onKeyUpHandler);
}
public static update(){
KeyboardUtils.previousKeys.length = 0;
for (let key of KeyboardUtils.currentKeys){
KeyboardUtils.previousKeys.push(key);
KeyboardUtils.currentKeys.remove(key);
}
KeyboardUtils.currentKeys.length = 0;
for (let key of KeyboardUtils.keyStatusKeys){
KeyboardUtils.currentKeys.push(key);
}
}
public static destroy(): void {
KeyboardUtils.currentKeys.length = 0;
document.removeEventListener("keyup", KeyboardUtils.onKeyUpHandler);
document.removeEventListener("keypress", KeyboardUtils.onKeyDownHandler);
}
private static onKeyDownHandler(event: KeyboardEvent): void {
if (!KeyboardUtils.keyStatusKeys.contains(event.keyCode))
KeyboardUtils.keyStatusKeys.push(event.keyCode);
}
private static onKeyUpHandler(event: KeyboardEvent): void {
if (KeyboardUtils.keyStatusKeys.contains(event.keyCode))
KeyboardUtils.keyStatusKeys.remove(event.keyCode);
}
}

View File

@@ -1,116 +0,0 @@
module es {
export enum Keys {
none,
back = 8,
tab = 9,
enter = 13,
capsLock = 20,
escape = 27,
space = 32,
pageUp = 33,
pageDown = 34,
end = 35,
home = 36,
left = 37,
up = 38,
right = 39,
down = 40,
select = 41,
print = 42,
execute = 43,
printScreen = 44,
insert = 45,
delete = 46,
help = 47,
d0 = 48,
d1 = 49,
d2 = 50,
d3 = 51,
d4 = 52,
d5 = 53,
d6 = 54,
d7 = 55,
d8 = 56,
d9 = 57,
a = 65,
b = 66,
c = 67,
d = 68,
e = 69,
f = 70,
g = 71,
h = 72,
i = 73,
j = 74,
k = 75,
l = 76,
m = 77,
n = 78,
o = 79,
p = 80,
q = 81,
r = 82,
s = 83,
t = 84,
u = 85,
v = 86,
w = 87,
x = 88,
y = 89,
z = 90,
leftWindows = 91,
rightWindows = 92,
apps = 93,
sleep = 95,
numPad0 = 96,
numPad1 = 97,
numPad2 = 98,
numPad3 = 99,
numPad4 = 100,
numPad5 = 101,
numPad6 = 102,
numPad7 = 103,
numPad8 = 104,
numPad9 = 105,
multiply = 106,
add = 107,
seperator = 108,
subtract = 109,
decimal = 110,
divide = 111,
f1 = 112,
f2 = 113,
f3 = 114,
f4 = 115,
f5 = 116,
f6 = 117,
f7 = 118,
f8 = 119,
f9 = 120,
f10 = 121,
f11 = 122,
f12 = 123,
f13 = 124,
f14 = 125,
f15 = 126,
f16 = 127,
f17 = 128,
f18 = 129,
f19 = 130,
f20 = 131,
f21 = 132,
f22 = 133,
f23 = 134,
f24 = 135,
numLock = 144,
scroll = 145,
leftShift = 160,
rightShift = 161,
leftControl = 162,
rightControl = 163,
leftAlt = 164,
rightAlt = 165,
browserBack = 166,
browserForward = 167
}
}

View File

@@ -1,79 +0,0 @@
///<reference path="VirtualInput.ts"/>
///<reference path="VirtualIntegerAxis.ts"/>
module es {
/**
* 用-1和1之间的浮点数表示的虚拟输入
*/
export class VirtualAxis extends VirtualInput {
public nodes: VirtualAxisNode[] = [];
public get value() {
for (let i = 0; i < this.nodes.length; i++) {
let val = this.nodes[i].value;
if (val != 0)
return val;
}
return 0;
}
constructor(...nodes: VirtualAxisNode[]) {
super();
this.nodes.concat(nodes);
}
public update() {
for (let i = 0; i < this.nodes.length; i++)
this.nodes[i].update();
}
}
export class KeyboardKeys extends VirtualAxisNode {
public overlapBehavior: OverlapBehavior;
public positive: Keys;
public negative: Keys;
public _value: number = 0;
public _turned: boolean;
constructor(overlapBehavior: OverlapBehavior, negative: Keys, positive: Keys) {
super();
this.overlapBehavior = overlapBehavior;
this.negative = negative;
this.positive = positive;
}
public update() {
if (Input.isKeyDown(this.positive)) {
if (Input.isKeyDown(this.negative)) {
switch (this.overlapBehavior) {
default:
case es.OverlapBehavior.cancelOut:
this._value = 0;
break;
case es.OverlapBehavior.takeNewer:
if (!this._turned) {
this._value *= -1;
this._turned = true;
}
break;
case es.OverlapBehavior.takeOlder:
break;
}
} else {
this._turned = false;
this._value = 1;
}
} else if (Input.isKeyDown(this.negative)) {
this._turned = false;
this._value = -1;
} else {
this._turned = false;
this._value = 0;
}
}
public get value(){
return this._value;
}
}
}

View File

@@ -1,134 +0,0 @@
///<reference path="./VirtualInput.ts" />
module es {
/**
* 用布尔值表示的虚拟输入。除了简单地检查当前按钮状态,
* 您还可以询问它是否刚刚被按下或释放了这个框架。
* 您还可以将按下的按钮存储在缓冲区中一段有限的时间或者直到调用consumeBuffer()将其使用为止。
*/
export class VirtualButton extends VirtualInput{
public nodes: Node[] = [];
public bufferTime: number = 0;
public firstRepeatTime: number = 0;
public mutiRepeatTime: number = 0;
public isRepeating: boolean;
public _bufferCounter: number = 0;
public _repeatCounter: number = 0;
public _willRepeat: boolean;
constructor(bufferTime: number = 0, ...nodes: Node[]){
super();
this.nodes = nodes;
this.bufferTime = bufferTime;
}
public setRepeat(firstRepeatTime: number, mutiRepeatTime: number = firstRepeatTime){
this.firstRepeatTime = firstRepeatTime;
this.mutiRepeatTime = mutiRepeatTime;
this._willRepeat = this.firstRepeatTime > 0;
if (!this._willRepeat)
this.isRepeating = false;
}
public update() {
this._bufferCounter -= Time.unscaledDeltaTime;
this.isRepeating = false;
let check = false;
for (let i = 0; i < this.nodes.length; i ++){
this.nodes[i].update();
if (this.nodes[i].isPressed){
this._bufferCounter = this.bufferTime;
check = true;
}else if(this.nodes[i].isDown){
check = true;
}
}
if (!check){
this._repeatCounter = 0;
this._bufferCounter = 0;
}else if(this._willRepeat){
if (this._repeatCounter == 0){
this._repeatCounter = this.firstRepeatTime;
}else{
this._repeatCounter -= Time.unscaledDeltaTime;
if (this._repeatCounter <= 0){
this.isRepeating = true;
this._repeatCounter = this.mutiRepeatTime;
}
}
}
}
public get isDown(){
for (let node of this.nodes){
if (node.isDown)
return true;
}
return false;
}
public get isPressed(){
if (this._bufferCounter > 0 || this.isRepeating)
return true;
for (let node of this.nodes){
if (node.isPressed)
return true;
}
return false;
}
public get isReleased(){
for (let node of this.nodes){
if (node.isReleased)
return true;
}
return false;
}
public consumeBuffer(){
this._bufferCounter = 0;
}
/**
* 添加一个键盘键到这个虚拟按钮
* @param key
*/
public addKeyboardKey(key: Keys): VirtualButton{
this.nodes.push(new KeyboardKey(key));
return this;
}
}
export abstract class Node extends VirtualInputNode {
public abstract isDown: boolean;
public abstract isPressed: boolean;
public abstract isReleased: boolean;
}
export class KeyboardKey extends Node {
public key: Keys;
constructor(key: Keys){
super();
this.key = key;
}
public get isDown(){
return Input.isKeyDown(this.key);
}
public get isPressed(){
return Input.isKeyPressed(this.key);
}
public get isReleased(){
return Input.isKeyReleased(this.key);
}
}
}

View File

@@ -1,43 +0,0 @@
module es {
export enum OverlapBehavior {
/**
* 重复的输入将导致相互抵消,并且不会记录任何输入。
* 例如:按左箭头键,按住时按右箭头键。这将导致相互抵消。
*/
cancelOut,
/**
* 将使用找到的第一个输入
*/
takeOlder,
/**
* 将使用找到的最后一个输入
*/
takeNewer,
}
/**
* 虚拟按钮其状态由其VirtualInputNodes的状态决定
*/
export abstract class VirtualInput {
protected constructor() {
Input._virtualInputs.push(this);
}
/**
* 从输入系统取消虚拟输入的注册。在轮询VirtualInput之后调用这个函数
*/
public deregister(){
Input._virtualInputs.remove(this);
}
public abstract update();
}
/**
* 将它们添加到您的VirtualInput中以定义它如何确定当前输入状态。
* 例如如果你想检查一个键盘键是否被按下创建一个VirtualButton并添加一个VirtualButton.keyboardkey
*/
export abstract class VirtualInputNode {
public update() {}
}
}

View File

@@ -1,44 +0,0 @@
module es {
/**
* 用int(-1、0或1)表示的虚拟输入。它对应的输入可以从上到下到下,
* 如使用两个键盘键作为正/负检查。
*/
export class VirtualIntegerAxis extends VirtualInput {
public nodes: VirtualAxisNode[] = [];
public get value(){
for (let i = 0; i < this.nodes.length; i ++){
let val = this.nodes[i].value;
if (val != 0)
return Math.sign(val);
}
return 0;
}
constructor(...nodes: VirtualAxisNode[]){
super();
this.nodes.concat(nodes);
}
public update() {
for (let i = 0; i < this.nodes.length; i ++)
this.nodes[i].update();
}
/**
* 添加键盘键来模拟这个虚拟输入的左/右或上/下
* @param overlapBehavior
* @param negative
* @param positive
*/
public addKeyboardKeys(overlapBehavior: OverlapBehavior, negative: Keys, positive: Keys){
this.nodes.push(new KeyboardKeys(overlapBehavior, negative, positive));
return this;
}
}
export abstract class VirtualAxisNode extends VirtualInputNode {
public abstract value: number;
}
}

View File

@@ -52,7 +52,7 @@ module es {
public static free<T>(obj: T) {
this._objectQueue.unshift(obj);
if (egret.is(obj, "IPoolable")){
if (isIPoolable(obj)){
obj["reset"]();
}
}
@@ -64,4 +64,6 @@ module es {
*/
reset();
}
export var isIPoolable = (props: any): props is IPoolable => typeof (props as IPoolable)['js'] !== 'undefined';
}

View File

@@ -1,133 +0,0 @@
module es {
import Bitmap = egret.Bitmap;
export class AssetPacker {
protected itemsToRaster: TextureToPack[] = [];
public onProcessCompleted: Function;
public useCache: boolean = false;
public cacheName: string = "";
protected _sprites: Map<string, egret.Texture> = new Map<string, egret.Texture>();
protected allow4096Textures = false;
public addTextureToPack(texture: egret.Texture, customID: string){
this.itemsToRaster.push(new TextureToPack(texture, customID));
}
public async process(allow4096Textures: boolean = false){
this.allow4096Textures = allow4096Textures;
if (this.useCache){
if (this.cacheName == "") {
console.error("未指定缓存名称");
return;
}
let cacheExist = await RES.getResByUrl(this.cacheName);
if (!cacheExist)
this.createPack();
else
this.loadPack();
}else{
this.createPack();
}
}
protected async loadPack() {
let loaderTexture = await RES.getResByUrl(this.cacheName);
if (this.onProcessCompleted) this.onProcessCompleted();
return loaderTexture;
}
protected createPack(){
let textures: egret.Bitmap[] = [];
let images = [];
for (let itemToRaster of this.itemsToRaster){
textures.push(new Bitmap(itemToRaster.texture));
images.push(itemToRaster.id);
}
let textureSize = this.allow4096Textures ? 4096 : 2048;
let rectangles = [];
for (let i = 0; i < textures.length; i ++){
if (textures[i].width > textureSize || textures[i].height > textureSize){
throw new Error("一个纹理的大小比图集的大小大");
}else{
rectangles.push(new Rectangle(0, 0, textures[i].width, textures[i].height));
}
}
const padding = 1;
let numSpriteSheet = 0;
while (rectangles.length > 0){
let texture = new egret.RenderTexture();
let packer: RectanglePacker = new RectanglePacker(textureSize, textureSize, padding);
for (let i = 0; i < rectangles.length; i ++)
packer.insertRectangle(Math.floor(rectangles[i].width), Math.floor(rectangles[i].height), i);
packer.packRectangles();
if (packer.rectangleCount > 0){
let rect = new IntegerRectangle();
let textureAssets: TextureAsset[] = [];
let garbageRect: Rectangle[] = [];
let garabeTextures: egret.Texture[] = [];
let garbageImages: string[] = [];
for (let j = 0; j < packer.rectangleCount; j ++){
rect = packer.getRectangle(j, rect);
let index = packer.getRectangleId(j);
texture.drawToTexture(textures[index], new Rectangle(rect.x, rect.y, rect.width, rect.height));
let textureAsset: TextureAsset = new TextureAsset();
textureAsset.x = rect.x;
textureAsset.y = rect.y;
textureAsset.width = rect.width;
textureAsset.height = rect.height;
textureAsset.name = images[index];
textureAssets.push(textureAsset);
garbageRect.push(rectangles[index]);
garabeTextures.push(textures[index].texture);
garbageImages.push(images[index]);
}
for (let garbage of garbageRect)
rectangles.remove(garbage);
for (let garbage of garabeTextures)
textures.removeAll(a => {return a.texture.hashCode == garbage.hashCode});
for (let garbage of garbageImages)
images.remove(garbage);
if (this.cacheName != ""){
texture.saveToFile("image/png", this.cacheName);
++ numSpriteSheet;
}
for (let textureAsset of textureAssets)
this._sprites.set(textureAsset.name, texture);
}
}
if (this.onProcessCompleted) this.onProcessCompleted();
}
public dispose(){
this._sprites.forEach((asset, name) => {
asset.dispose();
RES.destroyRes(name);
});
this._sprites.clear();
}
public getTexture(id: string){
return this._sprites.get(id);
}
}
}

View File

@@ -1,9 +0,0 @@
module es {
/**
* 类中用于存储矩形值的矩形封装器
* ID参数需要连接矩形和原来插入的矩形
*/
export class IntegerRectangle extends Rectangle{
public id: number;
}
}

View File

@@ -1,278 +0,0 @@
module es {
/**
* 类用于在容器矩形内包装矩形,并具有接近最优解。
*/
export class RectanglePacker {
private _width: number = 0;
private _height: number = 0;
private _padding: number = 8;
private _packedWidth = 0;
private _packedHeight = 0;
private _insertList: SortableSize[] = [];
private _insertedRectangles: IntegerRectangle[] = [];
private _freeAreas: IntegerRectangle[] = [];
private _newFreeAreas: IntegerRectangle[] = [];
private _outsideRectangle: IntegerRectangle;
private _sortableSizeStack: SortableSize[] = [];
private _rectangleStack: IntegerRectangle[] = [];
public get rectangleCount() {
return this._insertedRectangles.length;
}
public get packedWidth() {
return this._packedWidth;
}
public get packedHeight() {
return this._packedHeight;
}
public get padding() {
return this._padding;
}
constructor(width: number, height: number, padding: number = 0) {
this._outsideRectangle = new IntegerRectangle(width + 1, height + 1, 0, 0);
this.reset(width, height, padding);
}
public reset(width: number, height: number, padding: number = 0) {
while (this._insertedRectangles.length > 0)
this.freeRectangle(this._insertedRectangles.pop());
while (this._freeAreas.length > 0)
this.freeRectangle(this._freeAreas.pop());
this._width = width;
this._height = height;
this._packedWidth = 0;
this._packedHeight = 0;
this._freeAreas.push(this.allocateRectangle(0, 0, this._width, this._height));
while (this._insertedRectangles.length > 0)
this.freeSize(this._insertList.pop());
this._padding = padding;
}
public insertRectangle(width: number, height: number, id: number) {
let sortableSize = this.allocateSize(width, height, id);
this._insertList.push(sortableSize);
}
public packRectangles(sort: boolean = true) {
if (sort)
this._insertList.sort((emp1, emp2) => {
return emp1.width - emp2.width;
});
while (this._insertList.length > 0) {
let sortableSize = this._insertList.pop();
let width = sortableSize.width;
let height = sortableSize.height;
let index = this.getFreeAreaIndex(width, height);
if (index >= 0) {
let freeArea = this._freeAreas[index];
let target = this.allocateRectangle(freeArea.x, freeArea.y, width, height);
target.id = sortableSize.id;
this.generateNewFreeAreas(target, this._freeAreas, this._newFreeAreas);
while (this._newFreeAreas.length > 0)
this._freeAreas.push(this._newFreeAreas.pop());
this._insertedRectangles.push(target);
if (target.right > this._packedWidth)
this._packedWidth = target.right;
if (target.bottom > this._packedHeight)
this._packedHeight = target.bottom;
}
this.freeSize(sortableSize);
}
return this.rectangleCount;
}
public getRectangle(index: number, rectangle: IntegerRectangle){
let inserted = this._insertedRectangles[index];
rectangle.x = inserted.x;
rectangle.y = inserted.y;
rectangle.width = inserted.width;
rectangle.height = inserted.height;
return rectangle;
}
public getRectangleId(index: number){
let inserted = this._insertedRectangles[index];
return inserted.id;
}
private generateNewFreeAreas(target: IntegerRectangle, areas: IntegerRectangle[], results: IntegerRectangle[]) {
let x = target.x;
let y = target.y;
let right = target.right + 1 + this._padding;
let bottom = target.bottom + 1 + this._padding;
let targetWithPadding: IntegerRectangle = null;
if (this._padding == 0)
targetWithPadding = target;
for (let i = areas.length - 1; i >= 0; i --){
let area = areas[i];
if (!(x >= area.right || right <= area.x || y >= area.bottom || bottom <= area.y)){
if (targetWithPadding == null)
targetWithPadding = this.allocateRectangle(target.x, target.y, target.width + this._padding, target.height + this._padding);
this.generateDividedAreas(targetWithPadding, area, results);
let topOfStack = areas.pop();
if (i < areas.length){
areas[i] = topOfStack;
}
}
}
if (targetWithPadding != null && targetWithPadding != target)
this.freeRectangle(targetWithPadding);
this.filterSelfSubAreas(results);
}
private filterSelfSubAreas(areas: IntegerRectangle[]){
for (let i = areas.length - 1; i >= 0; i --){
let filtered = areas[i];
for (let j = areas.length - 1; j >= 0; j --){
if (i != j){
let area = areas[j];
if (filtered.x >= area.x && filtered.y >= area.y && filtered.right <= area.right && filtered.bottom <= area.bottom){
this.freeRectangle(filtered);
let topOfStack = areas.pop();
if (i < areas.length){
areas[i] = topOfStack;
}
break;
}
}
}
}
}
private generateDividedAreas(divider: IntegerRectangle, area: IntegerRectangle, results: IntegerRectangle[]){
let count = 0;
let rightDelta = area.right - divider.right;
if (rightDelta > 0){
results.push(this.allocateRectangle(divider.right, area.y, rightDelta, area.height));
count ++;
}
let leftDelta = divider.x - area.x;
if (leftDelta > 0){
results.push(this.allocateRectangle(area.x, area.y, leftDelta, area.height));
count ++;
}
let bottomDelta = area.bottom - divider.bottom;
if (bottomDelta > 0){
results.push(this.allocateRectangle(area.x, divider.bottom, area.width, bottomDelta));
count ++;
}
let topDelta = divider.y - area.y;
if (topDelta > 0){
results.push(this.allocateRectangle(area.x, area.y, area.width, topDelta));
count ++;
}
if (count == 0 && (divider.width < area.width || divider.height < area.height)){
results.push(area);
}else{
this.freeRectangle(area);
}
}
private getFreeAreaIndex(width: number, height: number) {
let best = this._outsideRectangle;
let index = -1;
let paddedWidth = width + this._padding;
let paddedHeight = height + this._padding;
let count = this._freeAreas.length;
for (let i = count - 1; i >= 0; i--) {
let free = this._freeAreas[i];
if (free.x < this._packedWidth || free.y < this.packedHeight) {
if (free.x < best.x && paddedWidth <= free.width && paddedHeight <= free.height) {
index = i;
if ((paddedWidth == free.width && free.width <= free.height && free.right < this._width) ||
(paddedHeight == free.height && free.height <= free.width)) {
break;
}
best = free;
}
} else {
if (free.x < best.x && width <= free.width && height <= free.height) {
index = i;
if ((width == free.width && free.width <= free.height && free.right < this._width) ||
(height == free.height && free.height <= free.width)) {
break;
}
best = free;
}
}
}
return index;
}
private allocateSize(width: number, height: number, id: number): SortableSize {
if (this._sortableSizeStack.length > 0) {
let size: SortableSize = this._sortableSizeStack.pop();
size.width = width;
size.height = height;
size.id = id;
return size;
}
return new SortableSize(width, height, id);
}
private freeSize(size: SortableSize) {
this._sortableSizeStack.push(size);
}
private allocateRectangle(x: number, y: number, width: number, height: number) {
if (this._rectangleStack.length > 0) {
let rectangle = this._rectangleStack.pop();
rectangle.x = x;
rectangle.y = y;
rectangle.width = width;
rectangle.height = height;
rectangle.right = x + width;
rectangle.bottom = y + height;
return rectangle;
}
return new IntegerRectangle(x, y, width, height);
}
private freeRectangle(rectangle: IntegerRectangle) {
this._rectangleStack.push(rectangle);
}
}
}

View File

@@ -1,16 +0,0 @@
module es {
/**
* 用于根据维度对插入的矩形进行排序
*/
export class SortableSize {
public width: number;
public height: number;
public id: number;
constructor(width: number, height: number, id: number){
this.width = width;
this.height = height;
this.id = id;
}
}
}

View File

@@ -1,16 +0,0 @@
module es {
export class TextureAssets {
public assets: TextureAsset[];
constructor(assets: TextureAsset[]){
this.assets = assets;
}
}
export class TextureAsset {
public x: number;
public y: number;
public width: number;
public height: number;
public name: string;
}
}

View File

@@ -1,11 +0,0 @@
module es {
export class TextureToPack {
public texture: egret.Texture;
public id: string;
constructor(texture: egret.Texture, id: string){
this.texture = texture;
this.id = id;
}
}
}