移除所有egret 依赖。移除renderablecomponent及所有依赖,移除camera。保持ecs基础框架
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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';
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ module es {
|
||||
}
|
||||
public set componentsNeedSort(value: boolean) {
|
||||
this._componentsNeedSort = value;
|
||||
Core.scene.sortableChildren = value;
|
||||
}
|
||||
|
||||
public get count() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user