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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,26 +1,14 @@
module es {
export class CircleCollider extends Collider {
private rectShape: egret.Shape = new egret.Shape();
private circleShape: egret.Shape = new egret.Shape();
private pixelShape1: egret.Shape = new egret.Shape();
private pixelShape2: egret.Shape = new egret.Shape();
/**
* 创建一个有半径的圆
*
* @param radius
*/
constructor(radius?: number) {
constructor(radius: number) {
super();
if (radius == undefined){
// 我们在这里插入一个1px的圆圈作为占位符
// 直到碰撞器被添加到实体并可以获得更精确的自动调整大小数据的下一帧
this.shape = new Circle(1);
this._colliderRequiresAutoSizing = true;
}else{
this.shape = new Circle(radius);
}
this.shape = new Circle(radius);
}
public get radius(): number {
@@ -36,7 +24,6 @@ module es {
* @param radius
*/
public setRadius(radius: number): CircleCollider {
this._colliderRequiresAutoSizing = false;
let circle = this.shape as Circle;
if (radius != circle.radius) {
circle.radius = radius;
@@ -50,43 +37,7 @@ module es {
}
public debugRender(camera: Camera) {
if (!this.rectShape.parent)
this.debugDisplayObject.addChild(this.rectShape);
if (!this.circleShape.parent)
this.debugDisplayObject.addChild(this.circleShape);
if (!this.pixelShape1.parent)
this.debugDisplayObject.addChild(this.pixelShape1);
if (!this.pixelShape2.parent)
this.debugDisplayObject.addChild(this.pixelShape2);
this.rectShape.graphics.clear();
this.rectShape.graphics.beginFill(Colors.colliderBounds, 0);
this.rectShape.graphics.lineStyle(Size.lineSizeMultiplier, Colors.colliderBounds);
this.rectShape.graphics.drawRect(this.bounds.x - camera.bounds.x, this.bounds.y - camera.bounds.y, this.bounds.width, this.bounds.height);
this.rectShape.graphics.endFill();
this.circleShape.graphics.clear();
this.circleShape.graphics.beginFill(Colors.colliderEdge, 0);
this.circleShape.graphics.lineStyle(Size.lineSizeMultiplier, Colors.colliderEdge);
this.circleShape.graphics.drawCircle(this.shape.position.x - camera.bounds.x, this.shape.position.y - camera.bounds.y, (this.shape as Circle).radius);
this.circleShape.graphics.endFill();
this.pixelShape1.graphics.clear();
this.pixelShape1.graphics.beginFill(Colors.colliderPosition, 0);
this.pixelShape1.graphics.lineStyle(4 * Size.lineSizeMultiplier, Colors.colliderPosition);
this.pixelShape1.graphics.moveTo(this.entity.transform.position.x - camera.bounds.x, this.entity.transform.position.y - camera.bounds.y);
this.pixelShape1.graphics.lineTo(this.entity.transform.position.x - camera.bounds.y, this.entity.transform.position.y - camera.bounds.y);
this.pixelShape1.graphics.endFill();
this.pixelShape2.graphics.clear();
this.pixelShape2.graphics.beginFill(Colors.colliderCenter, 0);
this.pixelShape2.graphics.lineStyle(2 * Size.lineSizeMultiplier, Colors.colliderCenter);
this.pixelShape2.graphics.moveTo(this.shape.position.x - camera.bounds.x, this.shape.position.y - camera.bounds.y);
this.pixelShape2.graphics.lineTo(this.shape.position.x - camera.bounds.x, this.shape.position.y - camera.bounds.y);
this.pixelShape2.graphics.endFill();
}
public toString() {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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