新增相机bounds与可渲染组件bounds 并添加可渲染组件的剔除方法

This commit is contained in:
yhh
2020-06-10 17:41:53 +08:00
parent f62f449d99
commit fa4c3c5d0b
10 changed files with 642 additions and 10 deletions

View File

@@ -8,6 +8,42 @@ class Camera extends Component {
private _minimumZoom = 0.3;
private _maximumZoom = 3;
private _areMatrixesDirty = true;
private _inset: CameraInset;
private _bounds: Rectangle;
private _areBoundsDirty = true;
public get bounds(){
if (this._areMatrixesDirty)
this.updateMatrixes();
if (this._areBoundsDirty){
let stage = this.entity.scene.stage;
let topLeft = this.screenToWorldPoint(new Vector2(this._inset.left, this._inset.top));
let bottomRight = this.screenToWorldPoint(new Vector2(stage.stageWidth - this._inset.right, stage.stageHeight - this._inset.bottom));
if (this.entity.transform.rotation != 0){
let topRight = this.screenToWorldPoint(new Vector2(stage.stageWidth - this._inset.right, this._inset.top));
let bottomLeft = this.screenToWorldPoint(new Vector2(this._inset.left, stage.stageHeight - this._inset.bottom));
let minX = MathHelper.minOf(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x);
let maxX = MathHelper.maxOf(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x);
let minY = MathHelper.minOf(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y);
let maxY = MathHelper.maxOf(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 get zoom(){
if (this._zoom == 0)
@@ -51,11 +87,17 @@ class Camera extends Component {
}
public get transformMatrix(){
this.updateMatrixes();
if (this._areBoundsDirty)
this.updateMatrixes();
return this._transformMatrix;
}
public get inverseTransformMatrix(){
if (this._areBoundsDirty)
this.updateMatrixes();
return this._inverseTransformMatrix;
}
constructor() {
super();
@@ -123,10 +165,28 @@ class Camera extends Component {
this._inverseTransformMatrix = Matrix2D.invert(this._transformMatrix);
this._areBoundsDirty = true;
this._areMatrixesDirty = false;
}
public screenToWorldPoint(screenPosition: Vector2){
this.updateMatrixes();
return Vector2.transform(screenPosition, this._inverseTransformMatrix);
}
public worldToScreenPoint(worldPosition: Vector2){
this.updateMatrixes();
return Vector2.transform(worldPosition, this._transformMatrix);
}
public destory() {
}
}
class CameraInset {
public left;
public right;
public top;
public bottom;
}

View File

@@ -2,5 +2,48 @@
* 所有可渲染组件的基类
*/
abstract class RenderableComponent extends Component {
private _isVisible: boolean;
private _areBoundsDirty = true;
private _bounds: Rectangle;
private _localOffset: Vector2;
public get width(){
return this.bounds.width;
}
public get height(){
return this.bounds.height;
}
public get isVisible(){
return this._isVisible;
}
public set isVisible(value: boolean){
this._isVisible = value;
if (this._isVisible)
this.onBecameVisible();
else
this.onBecameInvisible();
}
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;
}
protected onBecameVisible(){}
protected onBecameInvisible(){}
public isVisibleFromCamera(camera: Camera): boolean{
this.isVisible = camera.bounds.intersects(this.bounds);
return this.isVisible;
}
}

View File

@@ -36,4 +36,12 @@ class MathHelper {
return value;
}
public static minOf(a: number, b: number, c: number, d: number){
return Math.min(a, Math.min(b, Math.min(c, d)));
}
public static maxOf(a: number, b: number, c: number, d: number){
return Math.max(a, Math.max(b, Math.max(c, d)));
}
}

View File

@@ -4,10 +4,85 @@ class Rectangle {
public width: number;
public height: number;
constructor(x: number, y: number, width: number, height: number){
private _tempMat: Matrix2D;
private _transformMat: Matrix2D;
public get left() {
return this.x;
}
public get right() {
return this.x + this.width;
}
public get top() {
return this.y;
}
public get bottom() {
return this.y + this.height;
}
public get location() {
return new Vector2(this.x, this.y);
}
public set location(value: Vector2) {
this.x = value.x;
this.y = value.y;
}
constructor(x: number, y: number, width: number, height: number) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public intersects(value: Rectangle) {
return value.left < this.right &&
this.left < value.right &&
value.top < this.bottom &&
this.top < value.bottom;
}
public calculateBounds(parentPosition: Vector2, position: Vector2, origin: Vector2, scale: Vector2,
rotation: number, width: number, height: number) {
if (rotation == 0) {
this.x = parentPosition.x + position.x - origin.x * scale.x;
this.y = parentPosition.y + position.y - origin.y * scale.y;
this.width = width * scale.x;
this.height = height * scale.y;
}else{
let worldPosX = parentPosition.x + position.x;
let worldPosY = parentPosition.y + position.y;
this._transformMat = Matrix2D.createTranslation(-worldPosX - origin.x, -worldPosY - origin.y);
this._tempMat = Matrix2D.createScale(scale.x, scale.y);
this._transformMat = Matrix2D.multiply(this._transformMat, this._tempMat);
this._tempMat = Matrix2D.createRotation(rotation);
this._transformMat = Matrix2D.multiply(this._transformMat, this._tempMat);
this._tempMat = Matrix2D.createTranslation(worldPosX, worldPosY);
this._transformMat = Matrix2D.multiply(this._transformMat, this._tempMat);
let topLeft = new Vector2(worldPosX, worldPosY);
let topRight = new Vector2(worldPosX + width, worldPosY);
let bottomLeft = new Vector2(worldPosX, worldPosY + height);
let bottomRight = new Vector2(worldPosX + width, worldPosY + height);
topLeft = Vector2.transform(topLeft, this._transformMat);
topRight = Vector2.transform(topRight, this._transformMat);
bottomLeft = Vector2.transform(bottomLeft, this._transformMat);
bottomRight = Vector2.transform(bottomRight, this._transformMat);
let minX = MathHelper.minOf(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x);
let maxX = MathHelper.maxOf(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x);
let minY = MathHelper.minOf(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y);
let maxY = MathHelper.maxOf(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y);
this.location = new Vector2(minX, minY);
this.width = maxX - minX;
this.height = maxY - minY;
}
}
}