新增渲染接口
This commit is contained in:
142
source/bin/framework.d.ts
vendored
142
source/bin/framework.d.ts
vendored
@@ -194,6 +194,7 @@ declare module es {
|
||||
* @param comp
|
||||
*/
|
||||
onEntityTransformChanged(comp: transform.Component): void;
|
||||
debugRender(batcher: IBatcher): void;
|
||||
/**
|
||||
*当父实体或此组件启用时调用
|
||||
*/
|
||||
@@ -359,6 +360,7 @@ declare module es {
|
||||
* 每帧进行调用进行更新组件
|
||||
*/
|
||||
update(): void;
|
||||
debugRender(batcher: IBatcher): void;
|
||||
/**
|
||||
* 创建组件的新实例。返回实例组件
|
||||
* @param componentType
|
||||
@@ -643,15 +645,14 @@ declare module es {
|
||||
declare module es {
|
||||
/** 场景 */
|
||||
class Scene {
|
||||
/**
|
||||
* 这个场景中的实体列表
|
||||
*/
|
||||
camera: ICamera;
|
||||
/** 这个场景中的实体列表 */
|
||||
readonly entities: EntityList;
|
||||
/**
|
||||
* 管理所有实体处理器
|
||||
*/
|
||||
readonly renderableComponents: RenderableComponentList;
|
||||
/** 管理所有实体处理器 */
|
||||
readonly entityProcessors: EntityProcessorList;
|
||||
readonly _sceneComponents: SceneComponent[];
|
||||
_renderers: Renderer[];
|
||||
readonly identifierPool: IdentifierPool;
|
||||
private _didSceneBegin;
|
||||
constructor();
|
||||
@@ -672,6 +673,10 @@ declare module es {
|
||||
begin(): void;
|
||||
end(): void;
|
||||
update(): void;
|
||||
render(): void;
|
||||
addRenderer<T extends Renderer>(renderer: T): T;
|
||||
getRenderer<T extends Renderer>(type: new (...args: any[]) => T): T;
|
||||
removeRenderer(renderer: Renderer): void;
|
||||
/**
|
||||
* 向组件列表添加并返回SceneComponent
|
||||
* @param component
|
||||
@@ -1076,6 +1081,7 @@ declare module es {
|
||||
* @param value
|
||||
*/
|
||||
setGlue(value: number): ArcadeRigidbody;
|
||||
setVelocity(velocity: Vector2): ArcadeRigidbody;
|
||||
/**
|
||||
* 用刚体的质量给刚体加上一个瞬间的力脉冲。力是一个加速度,单位是每秒像素每秒。将力乘以100000,使数值使用更合理
|
||||
* @param force
|
||||
@@ -1178,7 +1184,7 @@ declare module es {
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
class Collider extends Component {
|
||||
abstract class Collider extends Component {
|
||||
/**
|
||||
* 对撞机的基本形状
|
||||
*/
|
||||
@@ -1302,7 +1308,7 @@ declare module es {
|
||||
* @param width
|
||||
* @param height
|
||||
*/
|
||||
constructor(x: number, y: number, width: number, height: number);
|
||||
constructor(x?: number, y?: number, width?: number, height?: number);
|
||||
width: number;
|
||||
height: number;
|
||||
/**
|
||||
@@ -1321,6 +1327,7 @@ declare module es {
|
||||
* @param height
|
||||
*/
|
||||
setHeight(height: number): void;
|
||||
debugRender(batcher: IBatcher): void;
|
||||
toString(): string;
|
||||
}
|
||||
}
|
||||
@@ -1333,13 +1340,14 @@ declare module es {
|
||||
*
|
||||
* @param radius
|
||||
*/
|
||||
constructor(radius: number);
|
||||
constructor(radius?: number);
|
||||
radius: number;
|
||||
/**
|
||||
* 设置圆的半径
|
||||
* @param radius
|
||||
*/
|
||||
setRadius(radius: number): CircleCollider;
|
||||
debugRender(batcher: IBatcher): void;
|
||||
toString(): string;
|
||||
}
|
||||
}
|
||||
@@ -1355,6 +1363,40 @@ declare module es {
|
||||
constructor(points: Vector2[]);
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
interface IRenderable {
|
||||
enabled: boolean;
|
||||
renderLayer: number;
|
||||
isVisibleFromCamera(camera: ICamera): boolean;
|
||||
render(batcher: IBatcher, camera: ICamera): void;
|
||||
debugRender(batcher: IBatcher): void;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
abstract class RenderableComponent extends es.Component implements IRenderable {
|
||||
getwidth(): number;
|
||||
getheight(): number;
|
||||
protected _bounds: es.Rectangle;
|
||||
getbounds(): es.Rectangle;
|
||||
readonly bounds: Rectangle;
|
||||
protected _areBoundsDirty: boolean;
|
||||
renderLayer: number;
|
||||
protected _renderLayer: number;
|
||||
onEntityTransformChanged(comp: transform.Component): void;
|
||||
localOffset: es.Vector2;
|
||||
setLocalOffset(offset: es.Vector2): this;
|
||||
isVisible: boolean;
|
||||
debugRenderEnabled: boolean;
|
||||
protected _isVisible: boolean;
|
||||
protected _localOffset: es.Vector2;
|
||||
abstract render(batcher: IBatcher, camera: ICamera): void;
|
||||
protected onBecameVisible(): void;
|
||||
protected onBecameInvisible(): void;
|
||||
setRenderLayer(renderLayer: number): RenderableComponent;
|
||||
isVisibleFromCamera(cam: ICamera): boolean;
|
||||
debugRender(batcher: IBatcher): void;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
interface Map<K, V> {
|
||||
clear(): void;
|
||||
@@ -1703,6 +1745,7 @@ declare module es {
|
||||
onEntityTransformChanged(comp: transform.Component): void;
|
||||
onEntityEnabled(): void;
|
||||
onEntityDisabled(): void;
|
||||
debugRender(batcher: IBatcher): void;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
@@ -1894,6 +1937,24 @@ declare module es {
|
||||
one(...types: any[]): this;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
class RenderableComponentList {
|
||||
private _components;
|
||||
private _componentsByRenderLayer;
|
||||
private _unsortedRenderLayers;
|
||||
private _componentsNeedSort;
|
||||
readonly count: number;
|
||||
get(index: number): IRenderable;
|
||||
add(component: IRenderable): void;
|
||||
remove(component: IRenderable): void;
|
||||
updateRenderableRenderLayer(component: IRenderable, oldRenderLayer: number, newRenderLayer: number): void;
|
||||
setRenderLayerNeedsComponentSort(renderLayer: number): void;
|
||||
setNeedsComponentSort(): void;
|
||||
private addToRenderLayerList;
|
||||
componentsWithRenderLayer(renderLayer: number): IRenderable[];
|
||||
updateLists(): void;
|
||||
}
|
||||
}
|
||||
declare class StringUtils {
|
||||
/**
|
||||
* 特殊符号字符串
|
||||
@@ -2093,6 +2154,62 @@ declare module es {
|
||||
static workerMessage(worker: Worker): (...message: any[]) => Promise<{}>;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
class Graphics {
|
||||
static instance: Graphics;
|
||||
batcher: IBatcher;
|
||||
constructor(batcher: IBatcher);
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
class Color {
|
||||
a: number;
|
||||
r: number;
|
||||
g: number;
|
||||
b: number;
|
||||
constructor(r: number, g: number, b: number, a?: number);
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
interface IBatcher {
|
||||
begin(cam: ICamera): any;
|
||||
end(): any;
|
||||
drawPoints(points: Vector2[], color: Color, thickness?: number): any;
|
||||
drawPolygon(poisition: Vector2, points: Vector2[], color: Color, closePoly: boolean, thickness?: number): any;
|
||||
drawHollowRect(x: number, y: number, width: number, height: number, color: Color, thickness?: number): any;
|
||||
drawCircle(position: Vector2, raidus: number, color: Color, thickness?: number): any;
|
||||
drawCircleLow(position: es.Vector2, radius: number, color: Color, thickness?: number, resolution?: number): any;
|
||||
drawRect(x: number, y: number, width: number, height: number, color: Color): any;
|
||||
drawLine(start: Vector2, end: Vector2, color: Color, thickness: number): any;
|
||||
drawPixel(position: Vector2, color: Color, size?: number): any;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
interface ICamera extends Component {
|
||||
bounds: Rectangle;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
abstract class Renderer {
|
||||
camera: ICamera;
|
||||
readonly renderOrder: number;
|
||||
shouldDebugRender: boolean;
|
||||
constructor(renderOrder: number, camera: ICamera);
|
||||
onAddedToScene(scene: es.Scene): void;
|
||||
unload(): void;
|
||||
protected beginRender(cam: ICamera): void;
|
||||
protected endRender(): void;
|
||||
abstract render(scene: Scene): void;
|
||||
protected renderAfterStateCheck(renderable: IRenderable, cam: ICamera): void;
|
||||
protected debugRender(scene: Scene): void;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
class DefaultRenderer extends Renderer {
|
||||
constructor(renderOrder?: number, camera?: ICamera);
|
||||
render(scene: Scene): void;
|
||||
}
|
||||
}
|
||||
declare module es {
|
||||
/**
|
||||
* 三次方和二次方贝塞尔帮助器(cubic and quadratic bezier helper)
|
||||
@@ -2657,18 +2774,21 @@ declare module es {
|
||||
* @param radians
|
||||
*/
|
||||
static createRotation(radians: number): Matrix2D;
|
||||
static createRotationOut(radians: number, result: Matrix2D): void;
|
||||
/**
|
||||
* 创建一个新的缩放矩阵2D
|
||||
* @param xScale
|
||||
* @param yScale
|
||||
*/
|
||||
static createScale(xScale: number, yScale: number): Matrix2D;
|
||||
static createScaleOut(xScale: number, yScale: number, result: Matrix2D): void;
|
||||
/**
|
||||
* 创建一个新的平移矩阵2D
|
||||
* @param xPosition
|
||||
* @param yPosition
|
||||
*/
|
||||
static createTranslation(xPosition: number, yPosition: number): Matrix2D;
|
||||
static createTranslationOut(position: Vector2, result: Matrix2D): void;
|
||||
static invert(matrix: Matrix2D): Matrix2D;
|
||||
/**
|
||||
* 创建一个新的matrix, 它包含两个矩阵的和。
|
||||
@@ -3078,6 +3198,7 @@ declare module es {
|
||||
* 从SpatialHash中移除所有碰撞器
|
||||
*/
|
||||
static clear(): void;
|
||||
static debugDraw(secondsToDisplay: any): void;
|
||||
/**
|
||||
* 检查是否有对撞机落在一个圆形区域内。返回遇到的第一个对撞机
|
||||
* @param center
|
||||
@@ -3222,6 +3343,8 @@ declare module es {
|
||||
*/
|
||||
removeWithBruteForce(obj: Collider): void;
|
||||
clear(): void;
|
||||
debugDraw(secondsToDisplay: number): void;
|
||||
private debugDrawCellDetails;
|
||||
/**
|
||||
* 返回边框与单元格相交的所有对象
|
||||
* @param bounds
|
||||
@@ -4593,6 +4716,7 @@ declare module es {
|
||||
* @param points
|
||||
*/
|
||||
static boundsFromPolygonPoints(points: Vector2[]): Rectangle;
|
||||
static calculateBounds(rect: Rectangle, parentPosition: Vector2, position: Vector2, origin: Vector2, scale: Vector2, rotation: number, width: number, height: number): void;
|
||||
/**
|
||||
* 缩放矩形
|
||||
* @param rect
|
||||
|
||||
@@ -512,6 +512,7 @@ var es;
|
||||
*/
|
||||
Component.prototype.onEntityTransformChanged = function (comp) {
|
||||
};
|
||||
Component.prototype.debugRender = function (batcher) { };
|
||||
/**
|
||||
*当父实体或此组件启用时调用
|
||||
*/
|
||||
@@ -946,6 +947,9 @@ var es;
|
||||
Entity.prototype.update = function () {
|
||||
this.components.update();
|
||||
};
|
||||
Entity.prototype.debugRender = function (batcher) {
|
||||
this.components.debugRender(batcher);
|
||||
};
|
||||
/**
|
||||
* 创建组件的新实例。返回实例组件
|
||||
* @param componentType
|
||||
@@ -1156,7 +1160,7 @@ var es;
|
||||
Vector2.multiplyScaler = function (value1, value2) {
|
||||
var result = es.Vector2.zero;
|
||||
result.x = value1.x * value2;
|
||||
result.y = value1.x * value2;
|
||||
result.y = value1.y * value2;
|
||||
return result;
|
||||
};
|
||||
/**
|
||||
@@ -1443,7 +1447,9 @@ var es;
|
||||
var Scene = /** @class */ (function () {
|
||||
function Scene() {
|
||||
this._sceneComponents = [];
|
||||
this._renderers = [];
|
||||
this.entities = new es.EntityList(this);
|
||||
this.renderableComponents = new es.RenderableComponentList();
|
||||
this.entityProcessors = new es.EntityProcessorList();
|
||||
this.identifierPool = new es.IdentifierPool();
|
||||
this.initialize();
|
||||
@@ -1466,6 +1472,9 @@ var es;
|
||||
Scene.prototype.unload = function () {
|
||||
};
|
||||
Scene.prototype.begin = function () {
|
||||
if (this._renderers.length == 0) {
|
||||
this.addRenderer(new es.DefaultRenderer());
|
||||
}
|
||||
es.Physics.reset();
|
||||
if (this.entityProcessors != null)
|
||||
this.entityProcessors.begin();
|
||||
@@ -1474,11 +1483,14 @@ var es;
|
||||
};
|
||||
Scene.prototype.end = function () {
|
||||
this._didSceneBegin = false;
|
||||
for (var i = 0; i < this._renderers.length; i++)
|
||||
this._renderers[i].unload();
|
||||
this.entities.removeAllEntities();
|
||||
for (var i = 0; i < this._sceneComponents.length; i++) {
|
||||
this._sceneComponents[i].onRemovedFromScene();
|
||||
}
|
||||
this._sceneComponents.length = 0;
|
||||
this.camera = null;
|
||||
es.Physics.clear();
|
||||
if (this.entityProcessors)
|
||||
this.entityProcessors.end();
|
||||
@@ -1498,6 +1510,30 @@ var es;
|
||||
this.entities.update();
|
||||
if (this.entityProcessors != null)
|
||||
this.entityProcessors.lateUpdate();
|
||||
this.renderableComponents.updateLists();
|
||||
this.render();
|
||||
};
|
||||
Scene.prototype.render = function () {
|
||||
for (var i = 0; i < this._renderers.length; i++) {
|
||||
this._renderers[i].render(this);
|
||||
}
|
||||
};
|
||||
Scene.prototype.addRenderer = function (renderer) {
|
||||
this._renderers.push(renderer);
|
||||
this._renderers.sort(function (self, other) { return self.renderOrder - other.renderOrder; });
|
||||
renderer.onAddedToScene(this);
|
||||
return renderer;
|
||||
};
|
||||
Scene.prototype.getRenderer = function (type) {
|
||||
for (var i = 0; i < this._renderers.length; i++) {
|
||||
if (this._renderers[i] instanceof type)
|
||||
return this._renderers[i];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
Scene.prototype.removeRenderer = function (renderer) {
|
||||
new es.List(this._renderers).remove(renderer);
|
||||
renderer.unload();
|
||||
};
|
||||
/**
|
||||
* 向组件列表添加并返回SceneComponent
|
||||
@@ -1758,7 +1794,7 @@ var es;
|
||||
Object.defineProperty(Transform.prototype, "worldToLocalTransform", {
|
||||
get: function () {
|
||||
if (this._worldToLocalDirty) {
|
||||
if (!this.parent) {
|
||||
if (this.parent == null) {
|
||||
this._worldToLocalTransform = es.Matrix2D.identity;
|
||||
}
|
||||
else {
|
||||
@@ -1914,15 +1950,16 @@ var es;
|
||||
* @param parent
|
||||
*/
|
||||
Transform.prototype.setParent = function (parent) {
|
||||
var _this = this;
|
||||
if (this._parent == parent)
|
||||
return this;
|
||||
if (this._parent != null) {
|
||||
var children = new es.List(this._parent._children);
|
||||
children.remove(this);
|
||||
var index = this._parent._children.findIndex(function (t) { return t == _this; });
|
||||
if (index != -1)
|
||||
this._parent._children.splice(index, 1);
|
||||
}
|
||||
if (parent != null) {
|
||||
var children = new es.List(parent._children);
|
||||
children.add(this);
|
||||
parent._children.push(this);
|
||||
}
|
||||
this._parent = parent;
|
||||
this.setDirty(DirtyType.positionDirty);
|
||||
@@ -1939,7 +1976,7 @@ var es;
|
||||
return this;
|
||||
this._position = position;
|
||||
if (this.parent != null) {
|
||||
this.localPosition = es.Vector2.transform(this._position, this._worldToLocalTransform);
|
||||
this.localPosition = es.Vector2.transform(this._position, this.worldToLocalTransform);
|
||||
}
|
||||
else {
|
||||
this.localPosition = position;
|
||||
@@ -1965,7 +2002,7 @@ var es;
|
||||
*/
|
||||
Transform.prototype.setRotation = function (radians) {
|
||||
this._rotation = radians;
|
||||
if (this.parent) {
|
||||
if (this.parent != null) {
|
||||
this.localRotation = this.parent.rotation + radians;
|
||||
}
|
||||
else {
|
||||
@@ -2012,7 +2049,7 @@ var es;
|
||||
*/
|
||||
Transform.prototype.setScale = function (scale) {
|
||||
this._scale = scale;
|
||||
if (this.parent) {
|
||||
if (this.parent != null) {
|
||||
this.localScale = es.Vector2.divide(scale, this.parent._scale);
|
||||
}
|
||||
else {
|
||||
@@ -2337,18 +2374,29 @@ var es;
|
||||
this._glue = es.MathHelper.clamp(value, 0, 10);
|
||||
return this;
|
||||
};
|
||||
ArcadeRigidbody.prototype.setVelocity = function (velocity) {
|
||||
this.velocity = velocity;
|
||||
return this;
|
||||
};
|
||||
/**
|
||||
* 用刚体的质量给刚体加上一个瞬间的力脉冲。力是一个加速度,单位是每秒像素每秒。将力乘以100000,使数值使用更合理
|
||||
* @param force
|
||||
*/
|
||||
ArcadeRigidbody.prototype.addImpulse = function (force) {
|
||||
if (!this.isImmovable) {
|
||||
this.velocity = this.velocity.add(es.Vector2.multiplyScaler(force, 100000)
|
||||
this.velocity.add(es.Vector2.multiplyScaler(force, 100000)
|
||||
.multiplyScaler(this._inverseMass * es.Time.deltaTime * es.Time.deltaTime));
|
||||
}
|
||||
};
|
||||
ArcadeRigidbody.prototype.onAddedToEntity = function () {
|
||||
this._collider = this.entity.getComponent(es.Collider);
|
||||
this._collider = null;
|
||||
for (var i = 0; i < this.entity.components.buffer.length; i++) {
|
||||
var component = this.entity.components.buffer[i];
|
||||
if (component instanceof es.Collider) {
|
||||
this._collider = component;
|
||||
break;
|
||||
}
|
||||
}
|
||||
es.Debug.warnIf(this._collider == null, "ArcadeRigidbody 没有 Collider。ArcadeRigidbody需要一个Collider!");
|
||||
};
|
||||
ArcadeRigidbody.prototype.update = function () {
|
||||
@@ -2358,8 +2406,8 @@ var es;
|
||||
return;
|
||||
}
|
||||
if (this.shouldUseGravity)
|
||||
this.velocity = this.velocity.add(es.Vector2.multiplyScaler(es.Physics.gravity, es.Time.deltaTime));
|
||||
this.entity.transform.position = this.entity.transform.position.add(es.Vector2.multiplyScaler(this.velocity, es.Time.deltaTime));
|
||||
this.velocity.add(es.Vector2.multiplyScaler(es.Physics.gravity, es.Time.deltaTime));
|
||||
this.entity.position = this.entity.position.add(es.Vector2.multiplyScaler(this.velocity, es.Time.deltaTime));
|
||||
var collisionResult = new es.CollisionResult();
|
||||
// 捞取我们在新的位置上可能会碰撞到的任何东西
|
||||
var neighbors = es.Physics.boxcastBroadphaseExcludingSelfNonRect(this._collider, this._collider.collidesWithLayers.value);
|
||||
@@ -2379,10 +2427,10 @@ var es;
|
||||
}
|
||||
else {
|
||||
// 没有ArcadeRigidbody,所以我们假设它是不动的,只移动我们自己的
|
||||
this.entity.transform.position = this.entity.transform.position.subtract(collisionResult.minimumTranslationVector);
|
||||
this.entity.position = this.entity.position.subtract(collisionResult.minimumTranslationVector);
|
||||
var relativeVelocity = this.velocity.clone();
|
||||
this.calculateResponseVelocity(relativeVelocity, collisionResult.minimumTranslationVector, relativeVelocity);
|
||||
this.velocity = this.velocity.add(relativeVelocity);
|
||||
this.velocity.add(relativeVelocity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2402,14 +2450,14 @@ var es;
|
||||
*/
|
||||
ArcadeRigidbody.prototype.processOverlap = function (other, minimumTranslationVector) {
|
||||
if (this.isImmovable) {
|
||||
other.entity.transform.position = other.entity.transform.position.add(minimumTranslationVector);
|
||||
other.entity.position = other.entity.position.add(minimumTranslationVector);
|
||||
}
|
||||
else if (other.isImmovable) {
|
||||
this.entity.transform.position = this.entity.transform.position.subtract(minimumTranslationVector);
|
||||
this.entity.position = this.entity.position.subtract(minimumTranslationVector);
|
||||
}
|
||||
else {
|
||||
this.entity.transform.position = this.entity.transform.position.subtract(es.Vector2.multiplyScaler(minimumTranslationVector, 0.5));
|
||||
other.entity.transform.position = other.entity.transform.position.add(es.Vector2.multiplyScaler(minimumTranslationVector, 0.5));
|
||||
this.entity.position = this.entity.position.subtract(es.Vector2.multiplyScaler(minimumTranslationVector, 0.5));
|
||||
other.entity.position = other.entity.position.add(es.Vector2.multiplyScaler(minimumTranslationVector, 0.5));
|
||||
}
|
||||
};
|
||||
/**
|
||||
@@ -2427,8 +2475,8 @@ var es;
|
||||
var totalinverseMass = this._inverseMass + other._inverseMass;
|
||||
var ourResponseFraction = this._inverseMass / totalinverseMass;
|
||||
var otherResponseFraction = other._inverseMass / totalinverseMass;
|
||||
this.velocity = this.velocity.add(es.Vector2.multiplyScaler(relativeVelocity, ourResponseFraction));
|
||||
other.velocity = other.velocity.subtract(es.Vector2.multiplyScaler(relativeVelocity, otherResponseFraction));
|
||||
this.velocity.add(es.Vector2.multiplyScaler(relativeVelocity, ourResponseFraction));
|
||||
other.velocity.subtract(es.Vector2.multiplyScaler(relativeVelocity, otherResponseFraction));
|
||||
};
|
||||
/**
|
||||
* 给定两个物体和MTV之间的相对速度,本方法修改相对速度,使其成为碰撞响应
|
||||
@@ -2453,8 +2501,10 @@ var es;
|
||||
if (tangentialVelocityComponent.lengthSquared() < this._glue)
|
||||
coefficientOfFriction = 1.01;
|
||||
// 弹性影响速度的法向分量,摩擦力影响速度的切向分量
|
||||
responseVelocity = es.Vector2.multiplyScaler(normalVelocityComponent, -(1 + this._elasticity))
|
||||
var r = es.Vector2.multiplyScaler(normalVelocityComponent, -(1 + this._elasticity))
|
||||
.subtract(es.Vector2.multiplyScaler(tangentialVelocityComponent, coefficientOfFriction));
|
||||
responseVelocity.x = r.x;
|
||||
responseVelocity.y = r.y;
|
||||
};
|
||||
return ArcadeRigidbody;
|
||||
}(es.Component));
|
||||
@@ -2518,28 +2568,36 @@ var es;
|
||||
* @param collisionResult
|
||||
*/
|
||||
Mover.prototype.calculateMovement = function (motion, collisionResult) {
|
||||
if (this.entity.getComponent(es.Collider) == null || this._triggerHelper == null) {
|
||||
var collider = null;
|
||||
for (var i = 0; i < this.entity.components.buffer.length; i++) {
|
||||
var component = this.entity.components.buffer[i];
|
||||
if (component instanceof es.Collider) {
|
||||
collider = component;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (collider == null || this._triggerHelper == null) {
|
||||
return false;
|
||||
}
|
||||
// 移动所有的非触发碰撞器并获得最近的碰撞
|
||||
var colliders = this.entity.getComponents(es.Collider);
|
||||
var _loop_1 = function (i) {
|
||||
var collider = colliders[i];
|
||||
var collider_1 = colliders[i];
|
||||
// 不检测触发器 在我们移动后会重新访问它
|
||||
if (collider.isTrigger)
|
||||
if (collider_1.isTrigger)
|
||||
return "continue";
|
||||
// 获取我们在新位置可能发生碰撞的任何东西
|
||||
var bounds = collider.bounds.clone();
|
||||
var bounds = collider_1.bounds.clone();
|
||||
bounds.x += motion.x;
|
||||
bounds.y += motion.y;
|
||||
var neighbors = es.Physics.boxcastBroadphaseExcludingSelf(collider, bounds, collider.collidesWithLayers.value);
|
||||
var neighbors = es.Physics.boxcastBroadphaseExcludingSelf(collider_1, bounds, collider_1.collidesWithLayers.value);
|
||||
neighbors.forEach(function (value) {
|
||||
var neighbor = value;
|
||||
// 不检测触发器
|
||||
if (neighbor.isTrigger)
|
||||
return;
|
||||
var _internalcollisionResult = new es.CollisionResult();
|
||||
if (collider.collidesWith(neighbor, motion, _internalcollisionResult)) {
|
||||
if (collider_1.collidesWith(neighbor, motion, _internalcollisionResult)) {
|
||||
// 如果碰撞 则退回之前的移动量
|
||||
motion.subtract(_internalcollisionResult.minimumTranslationVector);
|
||||
// 如果我们碰到多个对象,为了简单起见,只取第一个。
|
||||
@@ -2594,7 +2652,15 @@ var es;
|
||||
return _this;
|
||||
}
|
||||
ProjectileMover.prototype.onAddedToEntity = function () {
|
||||
this._collider = this.entity.getComponent(es.Collider);
|
||||
var collider = null;
|
||||
for (var i = 0; i < this.entity.components.buffer.length; i++) {
|
||||
var component = this.entity.components.buffer[i];
|
||||
if (component instanceof es.Collider) {
|
||||
collider = component;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this._collider = collider;
|
||||
es.Debug.warnIf(this._collider == null, "ProjectileMover没有Collider。ProjectilMover需要一个Collider!");
|
||||
};
|
||||
/**
|
||||
@@ -2703,10 +2769,10 @@ var es;
|
||||
});
|
||||
Object.defineProperty(Collider.prototype, "bounds", {
|
||||
get: function () {
|
||||
if (this._isPositionDirty || this._isRotationDirty) {
|
||||
this.shape.recalculateBounds(this);
|
||||
this._isPositionDirty = this._isRotationDirty = false;
|
||||
}
|
||||
// if (this._isPositionDirty || this._isRotationDirty) {
|
||||
this.shape.recalculateBounds(this);
|
||||
// this._isPositionDirty = this._isRotationDirty = false;
|
||||
// }
|
||||
return this.shape.bounds;
|
||||
},
|
||||
enumerable: true,
|
||||
@@ -2756,6 +2822,30 @@ var es;
|
||||
return this;
|
||||
};
|
||||
Collider.prototype.onAddedToEntity = function () {
|
||||
if (this._colliderRequiresAutoSizing) {
|
||||
var renderable = null;
|
||||
for (var i = 0; i < this.entity.components.buffer.length; i++) {
|
||||
var component = this.entity.components.buffer[i];
|
||||
if (component instanceof es.RenderableComponent) {
|
||||
renderable = component;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (renderable != null) {
|
||||
var renderableBounds = renderable.bounds.clone();
|
||||
var width = renderableBounds.width / this.entity.transform.scale.x;
|
||||
var height = renderableBounds.height / this.entity.transform.scale.y;
|
||||
if (this instanceof es.CircleCollider) {
|
||||
this.radius = Math.max(width, height) * 0.5;
|
||||
this.localOffset = es.Vector2.subtract(renderableBounds.center, this.entity.transform.position);
|
||||
}
|
||||
else if (this instanceof es.BoxCollider) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.localOffset = es.Vector2.subtract(renderableBounds.center, this.entity.transform.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
this._isParentEntityAddedToScene = true;
|
||||
this.registerColliderWithPhysicsSystem();
|
||||
};
|
||||
@@ -2927,8 +3017,17 @@ var es;
|
||||
* @param height
|
||||
*/
|
||||
function BoxCollider(x, y, width, height) {
|
||||
if (x === void 0) { x = 0; }
|
||||
if (y === void 0) { y = 0; }
|
||||
if (width === void 0) { width = 1; }
|
||||
if (height === void 0) { height = 1; }
|
||||
var _this = _super.call(this) || this;
|
||||
_this._localOffset = new es.Vector2(x + width / 2, y + height / 2);
|
||||
if (width == 1 && height == 1) {
|
||||
_this._colliderRequiresAutoSizing = true;
|
||||
}
|
||||
else {
|
||||
_this._localOffset = new es.Vector2(x + width / 2, y + height / 2);
|
||||
}
|
||||
_this.shape = new es.Box(width, height);
|
||||
return _this;
|
||||
}
|
||||
@@ -2980,7 +3079,7 @@ var es;
|
||||
// 更新框,改变边界,如果我们需要更新物理系统中的边界
|
||||
box.updateBox(width, box.height);
|
||||
this._isPositionDirty = true;
|
||||
if (this.entity && this._isParentEntityAddedToScene)
|
||||
if (this.entity != null && this._isParentEntityAddedToScene)
|
||||
es.Physics.updateCollider(this);
|
||||
}
|
||||
return this;
|
||||
@@ -3000,6 +3099,17 @@ var es;
|
||||
es.Physics.updateCollider(this);
|
||||
}
|
||||
};
|
||||
BoxCollider.prototype.debugRender = function (batcher) {
|
||||
var poly = this.shape;
|
||||
batcher.drawHollowRect(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height, new es.Color(76, 76, 76, 76), 2);
|
||||
batcher.end();
|
||||
batcher.drawPolygon(this.shape.position, poly.points, new es.Color(139, 0, 0, 255), true, 2);
|
||||
batcher.end();
|
||||
batcher.drawPixel(this.entity.position, new es.Color(255, 255, 0), 4);
|
||||
batcher.end();
|
||||
batcher.drawPixel(es.Vector2.add(this.transform.position, this.shape.center), new es.Color(255, 0, 0), 2);
|
||||
batcher.end();
|
||||
};
|
||||
BoxCollider.prototype.toString = function () {
|
||||
return "[BoxCollider: bounds: " + this.bounds + "]";
|
||||
};
|
||||
@@ -3019,8 +3129,12 @@ var es;
|
||||
* @param radius
|
||||
*/
|
||||
function CircleCollider(radius) {
|
||||
if (radius === void 0) { radius = 1; }
|
||||
var _this = _super.call(this) || this;
|
||||
_this.shape = new es.Circle(radius);
|
||||
if (radius == 1) {
|
||||
_this._colliderRequiresAutoSizing = true;
|
||||
}
|
||||
return _this;
|
||||
}
|
||||
Object.defineProperty(CircleCollider.prototype, "radius", {
|
||||
@@ -3049,6 +3163,16 @@ var es;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
CircleCollider.prototype.debugRender = function (batcher) {
|
||||
batcher.drawHollowRect(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height, new es.Color(76, 76, 76, 76), 2);
|
||||
batcher.end();
|
||||
batcher.drawCircle(this.shape.position, this.radius, new es.Color(139, 0, 0), 2);
|
||||
batcher.end();
|
||||
batcher.drawPixel(this.entity.transform.position, new es.Color(255, 255, 0), 4);
|
||||
batcher.end();
|
||||
batcher.drawPixel(this.shape.position, new es.Color(255, 0, 0), 2);
|
||||
batcher.end();
|
||||
};
|
||||
CircleCollider.prototype.toString = function () {
|
||||
return "[CircleCollider: bounds: " + this.bounds + ", radius: " + this.shape.radius + "]";
|
||||
};
|
||||
@@ -3086,6 +3210,127 @@ var es;
|
||||
es.PolygonCollider = PolygonCollider;
|
||||
})(es || (es = {}));
|
||||
var es;
|
||||
(function (es) {
|
||||
var RenderableComponent = /** @class */ (function (_super) {
|
||||
__extends(RenderableComponent, _super);
|
||||
function RenderableComponent() {
|
||||
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||
_this._bounds = new es.Rectangle();
|
||||
_this._areBoundsDirty = true;
|
||||
_this._renderLayer = 0;
|
||||
_this.debugRenderEnabled = true;
|
||||
_this._isVisible = false;
|
||||
_this._localOffset = new es.Vector2();
|
||||
return _this;
|
||||
}
|
||||
RenderableComponent.prototype.getwidth = function () {
|
||||
return this.bounds.width;
|
||||
};
|
||||
RenderableComponent.prototype.getheight = function () {
|
||||
return this.bounds.height;
|
||||
};
|
||||
RenderableComponent.prototype.getbounds = function () {
|
||||
if (this._areBoundsDirty) {
|
||||
this._bounds.calculateBounds(this.entity.transform.position, this._localOffset, new es.Vector2(this.getwidth() / 2, this.getheight() / 2), this.entity.transform.scale, this.entity.transform.rotation, this.getwidth(), this.getheight());
|
||||
this._areBoundsDirty = false;
|
||||
}
|
||||
return this._bounds;
|
||||
};
|
||||
Object.defineProperty(RenderableComponent.prototype, "bounds", {
|
||||
get: function () {
|
||||
return this.getbounds();
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(RenderableComponent.prototype, "renderLayer", {
|
||||
get: function () {
|
||||
return this._renderLayer;
|
||||
},
|
||||
set: function (value) {
|
||||
this.setRenderLayer(value);
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
RenderableComponent.prototype.onEntityTransformChanged = function (comp) {
|
||||
this._areBoundsDirty = true;
|
||||
};
|
||||
Object.defineProperty(RenderableComponent.prototype, "localOffset", {
|
||||
get: function () {
|
||||
return this._localOffset;
|
||||
},
|
||||
set: function (value) {
|
||||
this.setLocalOffset(value);
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
RenderableComponent.prototype.setLocalOffset = function (offset) {
|
||||
if (!this._localOffset.equals(offset)) {
|
||||
this._localOffset = offset;
|
||||
this._areBoundsDirty = true;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
Object.defineProperty(RenderableComponent.prototype, "isVisible", {
|
||||
get: function () {
|
||||
return this._isVisible;
|
||||
},
|
||||
set: function (value) {
|
||||
if (this._isVisible != value) {
|
||||
this._isVisible = value;
|
||||
if (this._isVisible) {
|
||||
this.onBecameVisible();
|
||||
}
|
||||
else {
|
||||
this.onBecameInvisible();
|
||||
}
|
||||
}
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
RenderableComponent.prototype.onBecameVisible = function () {
|
||||
};
|
||||
RenderableComponent.prototype.onBecameInvisible = function () {
|
||||
};
|
||||
RenderableComponent.prototype.setRenderLayer = function (renderLayer) {
|
||||
if (renderLayer != this._renderLayer) {
|
||||
var oldRenderLayer = this._renderLayer;
|
||||
this._renderLayer = renderLayer;
|
||||
if (this.entity != null && this.entity.scene != null)
|
||||
es.Core.scene.renderableComponents.updateRenderableRenderLayer(this, oldRenderLayer, this._renderLayer);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
RenderableComponent.prototype.isVisibleFromCamera = function (cam) {
|
||||
this.isVisible = cam.bounds.intersects(this.bounds);
|
||||
return this.isVisible;
|
||||
};
|
||||
RenderableComponent.prototype.debugRender = function (batcher) {
|
||||
if (!this.debugRenderEnabled)
|
||||
return;
|
||||
var collider = null;
|
||||
for (var i = 0; i < this.entity.components.buffer.length; i++) {
|
||||
var component = this.entity.components.buffer[i];
|
||||
if (component instanceof es.Collider) {
|
||||
collider = component;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (collider == null) {
|
||||
batcher.drawHollowRect(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height, new es.Color(255, 255, 0));
|
||||
batcher.end();
|
||||
}
|
||||
batcher.drawPixel(es.Vector2.add(this.entity.transform.position, this._localOffset), new es.Color(153, 50, 204), 4);
|
||||
batcher.end();
|
||||
};
|
||||
return RenderableComponent;
|
||||
}(es.Component));
|
||||
es.RenderableComponent = RenderableComponent;
|
||||
})(es || (es = {}));
|
||||
var es;
|
||||
(function (es) {
|
||||
function decode(key) {
|
||||
switch (typeof key) {
|
||||
@@ -3731,6 +3976,8 @@ var es;
|
||||
var component = this._components[i];
|
||||
if (!component)
|
||||
continue;
|
||||
if (component instanceof es.RenderableComponent)
|
||||
this._entity.scene.renderableComponents.remove(component);
|
||||
// 处理IUpdatable
|
||||
if (es.isIUpdatable(component))
|
||||
new es.List(this._updatableComponents).remove(component);
|
||||
@@ -3743,6 +3990,8 @@ var es;
|
||||
if (this._components.length > 0) {
|
||||
for (var i = 0, s = this._components.length; i < s; ++i) {
|
||||
var component = this._components[i];
|
||||
if (component instanceof es.RenderableComponent)
|
||||
this._entity.scene.renderableComponents.remove(component);
|
||||
if (es.isIUpdatable(component))
|
||||
this._updatableComponents.push(component);
|
||||
this.addBits(component);
|
||||
@@ -3783,6 +4032,8 @@ var es;
|
||||
if (this._componentsToAddList.length > 0) {
|
||||
for (var i = 0, l = this._componentsToAddList.length; i < l; ++i) {
|
||||
var component = this._componentsToAddList[i];
|
||||
if (component instanceof es.RenderableComponent)
|
||||
this._entity.scene.renderableComponents.add(component);
|
||||
if (es.isIUpdatable(component))
|
||||
this._updatableComponents.push(component);
|
||||
this.addBits(component);
|
||||
@@ -3811,6 +4062,8 @@ var es;
|
||||
}
|
||||
};
|
||||
ComponentList.prototype.handleRemove = function (component) {
|
||||
if (component instanceof es.RenderableComponent)
|
||||
this._entity.scene.renderableComponents.remove(component);
|
||||
if (es.isIUpdatable(component) && this._updatableComponents.length > 0) {
|
||||
var index = this._updatableComponents.findIndex(function (c) { return c.id == component.id; });
|
||||
if (index != -1)
|
||||
@@ -3922,6 +4175,13 @@ var es;
|
||||
this._components[i].onDisabled();
|
||||
}
|
||||
};
|
||||
ComponentList.prototype.debugRender = function (batcher) {
|
||||
for (var i = 0; i < this._components.length; i++) {
|
||||
if (this._components[i].enabled) {
|
||||
this._components[i].debugRender(batcher);
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 组件列表的全局updateOrder排序
|
||||
*/
|
||||
@@ -4594,6 +4854,82 @@ var es;
|
||||
}());
|
||||
es.Matcher = Matcher;
|
||||
})(es || (es = {}));
|
||||
var es;
|
||||
(function (es) {
|
||||
var RenderableComponentList = /** @class */ (function () {
|
||||
function RenderableComponentList() {
|
||||
this._components = [];
|
||||
this._componentsByRenderLayer = new Map();
|
||||
this._unsortedRenderLayers = [];
|
||||
this._componentsNeedSort = true;
|
||||
}
|
||||
Object.defineProperty(RenderableComponentList.prototype, "count", {
|
||||
get: function () {
|
||||
return this._components.length;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
RenderableComponentList.prototype.get = function (index) {
|
||||
return this._components[index];
|
||||
};
|
||||
RenderableComponentList.prototype.add = function (component) {
|
||||
this._components.push(component);
|
||||
this.addToRenderLayerList(component, component.renderLayer);
|
||||
};
|
||||
RenderableComponentList.prototype.remove = function (component) {
|
||||
new es.List(this._components).remove(component);
|
||||
new es.List(this._componentsByRenderLayer.get(component.renderLayer)).remove(component);
|
||||
};
|
||||
RenderableComponentList.prototype.updateRenderableRenderLayer = function (component, oldRenderLayer, newRenderLayer) {
|
||||
if (this._componentsByRenderLayer.has(oldRenderLayer) && new es.List(this._componentsByRenderLayer.get(oldRenderLayer)).contains(component)) {
|
||||
new es.List(this._componentsByRenderLayer.get(oldRenderLayer)).remove(component);
|
||||
this.addToRenderLayerList(component, newRenderLayer);
|
||||
}
|
||||
};
|
||||
RenderableComponentList.prototype.setRenderLayerNeedsComponentSort = function (renderLayer) {
|
||||
var unsortedRenderLayersList = new es.List(this._unsortedRenderLayers);
|
||||
if (!unsortedRenderLayersList.contains(renderLayer))
|
||||
unsortedRenderLayersList.add(renderLayer);
|
||||
this._componentsNeedSort = true;
|
||||
};
|
||||
RenderableComponentList.prototype.setNeedsComponentSort = function () {
|
||||
this._componentsNeedSort = true;
|
||||
};
|
||||
RenderableComponentList.prototype.addToRenderLayerList = function (component, renderLayer) {
|
||||
var list = this.componentsWithRenderLayer(renderLayer);
|
||||
es.Insist.isFalse(!!list.find(function (c) { return c == component; }), "组件renderLayer列表已包含此组件");
|
||||
list.push(component);
|
||||
var unsortedRenderLayersList = new es.List(this._unsortedRenderLayers);
|
||||
if (!unsortedRenderLayersList.contains(renderLayer))
|
||||
unsortedRenderLayersList.add(renderLayer);
|
||||
this._componentsNeedSort = true;
|
||||
};
|
||||
RenderableComponentList.prototype.componentsWithRenderLayer = function (renderLayer) {
|
||||
if (!this._componentsByRenderLayer.get(renderLayer)) {
|
||||
this._componentsByRenderLayer.set(renderLayer, []);
|
||||
}
|
||||
return this._componentsByRenderLayer.get(renderLayer);
|
||||
};
|
||||
RenderableComponentList.prototype.updateLists = function () {
|
||||
if (this._componentsNeedSort) {
|
||||
this._components.sort(function (self, other) { return other.renderLayer - self.renderLayer; });
|
||||
this._componentsNeedSort = false;
|
||||
}
|
||||
if (this._unsortedRenderLayers.length > 0) {
|
||||
for (var i = 0, count = this._unsortedRenderLayers.length; i < count; i++) {
|
||||
var renderLayerComponents = this._componentsByRenderLayer.get(this._unsortedRenderLayers[i]);
|
||||
if (renderLayerComponents) {
|
||||
renderLayerComponents.sort(function (self, other) { return other.renderLayer - self.renderLayer; });
|
||||
}
|
||||
this._unsortedRenderLayers.length = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
return RenderableComponentList;
|
||||
}());
|
||||
es.RenderableComponentList = RenderableComponentList;
|
||||
})(es || (es = {}));
|
||||
var StringUtils = /** @class */ (function () {
|
||||
function StringUtils() {
|
||||
}
|
||||
@@ -5132,6 +5468,93 @@ var es;
|
||||
es.WorkerUtils = WorkerUtils;
|
||||
})(es || (es = {}));
|
||||
var es;
|
||||
(function (es) {
|
||||
var Graphics = /** @class */ (function () {
|
||||
function Graphics(batcher) {
|
||||
this.batcher = batcher;
|
||||
}
|
||||
return Graphics;
|
||||
}());
|
||||
es.Graphics = Graphics;
|
||||
})(es || (es = {}));
|
||||
var es;
|
||||
(function (es) {
|
||||
var Color = /** @class */ (function () {
|
||||
function Color(r, g, b, a) {
|
||||
if (a === void 0) { a = 255; }
|
||||
this.a = 255;
|
||||
this.r = 255;
|
||||
this.g = 255;
|
||||
this.b = 255;
|
||||
this.a = a;
|
||||
this.r = r;
|
||||
this.g = g;
|
||||
this.b = b;
|
||||
}
|
||||
return Color;
|
||||
}());
|
||||
es.Color = Color;
|
||||
})(es || (es = {}));
|
||||
var es;
|
||||
(function (es) {
|
||||
var Renderer = /** @class */ (function () {
|
||||
function Renderer(renderOrder, camera) {
|
||||
this.renderOrder = 0;
|
||||
this.shouldDebugRender = true;
|
||||
this.renderOrder = renderOrder;
|
||||
this.camera = camera;
|
||||
}
|
||||
Renderer.prototype.onAddedToScene = function (scene) { };
|
||||
Renderer.prototype.unload = function () { };
|
||||
Renderer.prototype.beginRender = function (cam) {
|
||||
es.Graphics.instance.batcher.begin(cam);
|
||||
};
|
||||
Renderer.prototype.endRender = function () {
|
||||
es.Graphics.instance.batcher.end();
|
||||
};
|
||||
Renderer.prototype.renderAfterStateCheck = function (renderable, cam) {
|
||||
renderable.render(es.Graphics.instance.batcher, cam);
|
||||
};
|
||||
Renderer.prototype.debugRender = function (scene) {
|
||||
for (var i = 0; i < scene.entities.count; i++) {
|
||||
var entity = scene.entities.buffer[i];
|
||||
if (entity.enabled) {
|
||||
entity.debugRender(es.Graphics.instance.batcher);
|
||||
}
|
||||
}
|
||||
};
|
||||
return Renderer;
|
||||
}());
|
||||
es.Renderer = Renderer;
|
||||
})(es || (es = {}));
|
||||
///<reference path="Renderer.ts" />
|
||||
var es;
|
||||
///<reference path="Renderer.ts" />
|
||||
(function (es) {
|
||||
var DefaultRenderer = /** @class */ (function (_super) {
|
||||
__extends(DefaultRenderer, _super);
|
||||
function DefaultRenderer(renderOrder, camera) {
|
||||
if (renderOrder === void 0) { renderOrder = 0; }
|
||||
if (camera === void 0) { camera = null; }
|
||||
return _super.call(this, renderOrder, camera) || this;
|
||||
}
|
||||
DefaultRenderer.prototype.render = function (scene) {
|
||||
var cam = this.camera ? this.camera : scene.camera;
|
||||
this.beginRender(cam);
|
||||
for (var i = 0; i < scene.renderableComponents.count; i++) {
|
||||
var renderable = scene.renderableComponents.get(i);
|
||||
if (renderable.enabled && renderable.isVisibleFromCamera(scene.camera))
|
||||
this.renderAfterStateCheck(renderable, cam);
|
||||
}
|
||||
if (this.shouldDebugRender && es.Core.debugRenderEndabled)
|
||||
this.debugRender(scene);
|
||||
this.endRender();
|
||||
};
|
||||
return DefaultRenderer;
|
||||
}(es.Renderer));
|
||||
es.DefaultRenderer = DefaultRenderer;
|
||||
})(es || (es = {}));
|
||||
var es;
|
||||
(function (es) {
|
||||
/**
|
||||
* 三次方和二次方贝塞尔帮助器(cubic and quadratic bezier helper)
|
||||
@@ -6148,6 +6571,14 @@ var es;
|
||||
result.m22 = val1;
|
||||
return result;
|
||||
};
|
||||
Matrix2D.createRotationOut = function (radians, result) {
|
||||
var val1 = Math.cos(radians);
|
||||
var val2 = Math.sin(radians);
|
||||
result.m11 = val1;
|
||||
result.m12 = val2;
|
||||
result.m21 = -val2;
|
||||
result.m22 = val1;
|
||||
};
|
||||
/**
|
||||
* 创建一个新的缩放矩阵2D
|
||||
* @param xScale
|
||||
@@ -6163,6 +6594,14 @@ var es;
|
||||
result.m32 = 0;
|
||||
return result;
|
||||
};
|
||||
Matrix2D.createScaleOut = function (xScale, yScale, result) {
|
||||
result.m11 = xScale;
|
||||
result.m12 = 0;
|
||||
result.m21 = 0;
|
||||
result.m22 = yScale;
|
||||
result.m31 = 0;
|
||||
result.m32 = 0;
|
||||
};
|
||||
/**
|
||||
* 创建一个新的平移矩阵2D
|
||||
* @param xPosition
|
||||
@@ -6178,6 +6617,14 @@ var es;
|
||||
result.m32 = yPosition;
|
||||
return result;
|
||||
};
|
||||
Matrix2D.createTranslationOut = function (position, result) {
|
||||
result.m11 = 1;
|
||||
result.m12 = 0;
|
||||
result.m21 = 0;
|
||||
result.m22 = 1;
|
||||
result.m31 = position.x;
|
||||
result.m32 = position.y;
|
||||
};
|
||||
Matrix2D.invert = function (matrix) {
|
||||
var det = 1 / matrix.determinant();
|
||||
var result = this.identity;
|
||||
@@ -7333,6 +7780,9 @@ var es;
|
||||
Physics.clear = function () {
|
||||
this._spatialHash.clear();
|
||||
};
|
||||
Physics.debugDraw = function (secondsToDisplay) {
|
||||
this._spatialHash.debugDraw(secondsToDisplay);
|
||||
};
|
||||
/**
|
||||
* 检查是否有对撞机落在一个圆形区域内。返回遇到的第一个对撞机
|
||||
* @param center
|
||||
@@ -7478,7 +7928,7 @@ var es;
|
||||
return this._spatialHash.overlapRectangle(rect, results, layerMask);
|
||||
};
|
||||
/** 用于在全局范围内存储重力值的方便字段 */
|
||||
Physics.gravity = new es.Vector2(0, 300);
|
||||
Physics.gravity = new es.Vector2(0, -300);
|
||||
/** 调用reset并创建一个新的SpatialHash时使用的单元格大小 */
|
||||
Physics.spatialHashCellSize = 100;
|
||||
/** 接受layerMask的所有方法的默认值 */
|
||||
@@ -7600,6 +8050,20 @@ var es;
|
||||
SpatialHash.prototype.clear = function () {
|
||||
this._cellDict.clear();
|
||||
};
|
||||
SpatialHash.prototype.debugDraw = function (secondsToDisplay) {
|
||||
for (var x = this.gridBounds.x; x <= this.gridBounds.right; x++) {
|
||||
for (var y = this.gridBounds.y; y <= this.gridBounds.bottom; y++) {
|
||||
var cell = this.cellAtPosition(x, y);
|
||||
if (cell != null && cell.length > 0)
|
||||
this.debugDrawCellDetails(x, y, secondsToDisplay);
|
||||
}
|
||||
}
|
||||
};
|
||||
SpatialHash.prototype.debugDrawCellDetails = function (x, y, secondsToDisplay) {
|
||||
if (secondsToDisplay === void 0) { secondsToDisplay = 0.5; }
|
||||
es.Graphics.instance.batcher.drawHollowRect(x * this._cellSize, y * this._cellSize, this._cellSize, this._cellSize, new es.Color(255, 0, 0), secondsToDisplay);
|
||||
es.Graphics.instance.batcher.end();
|
||||
};
|
||||
/**
|
||||
* 返回边框与单元格相交的所有对象
|
||||
* @param bounds
|
||||
@@ -7667,17 +8131,17 @@ var es;
|
||||
var tDeltaY = ray.direction.y != 0 ? this._cellSize / (ray.direction.y * stepY) : Number.MAX_VALUE;
|
||||
// 开始遍历并返回交叉单元格。
|
||||
var cell = this.cellAtPosition(currentCell.x, currentCell.y);
|
||||
if (cell && this._raycastParser.checkRayIntersection(currentCell.x, currentCell.y, cell)) {
|
||||
if (cell != null && this._raycastParser.checkRayIntersection(currentCell.x, currentCell.y, cell)) {
|
||||
this._raycastParser.reset();
|
||||
return this._raycastParser.hitCounter;
|
||||
}
|
||||
while (currentCell.x != lastCell.x || currentCell.y != lastCell.y) {
|
||||
if (tMaxX < tMaxY) {
|
||||
currentCell.x = Math.trunc(es.MathHelper.approach(currentCell.x, lastCell.x, Math.abs(stepX)));
|
||||
currentCell.x = es.MathHelper.approach(currentCell.x, lastCell.x, Math.abs(stepX));
|
||||
tMaxX += tDeltaX;
|
||||
}
|
||||
else {
|
||||
currentCell.y = Math.trunc(es.MathHelper.approach(currentCell.y, lastCell.y, Math.abs(stepY)));
|
||||
currentCell.y = es.MathHelper.approach(currentCell.y, lastCell.y, Math.abs(stepY));
|
||||
tMaxY += tDeltaY;
|
||||
}
|
||||
cell = this.cellAtPosition(currentCell.x, currentCell.y);
|
||||
@@ -8646,7 +9110,7 @@ var es;
|
||||
// TODO: 这是得到分数的正确和最有效的方法吗?
|
||||
// 先检查x分数。如果是NaN,就用y代替
|
||||
var distanceFraction = (intersection.x - start.x) / (end.x - start.x);
|
||||
if (Number.isNaN(distanceFraction) || Number.isFinite(distanceFraction))
|
||||
if (Number.isNaN(distanceFraction) || Math.abs(distanceFraction) == Infinity)
|
||||
distanceFraction = (intersection.y - start.y) / (end.y - start.y);
|
||||
if (distanceFraction < fraction) {
|
||||
var edge = es.Vector2.subtract(edge2, edge1);
|
||||
@@ -8678,7 +9142,9 @@ var es;
|
||||
var u = (c.x * b.y - c.y * b.x) / bDotDPerp;
|
||||
if (u < 0 || u > 1)
|
||||
return false;
|
||||
intersection = es.Vector2.add(a1, es.Vector2.multiplyScaler(b, t));
|
||||
var r = es.Vector2.add(a1, es.Vector2.multiplyScaler(b, t));
|
||||
intersection.x = r.x;
|
||||
intersection.y = r.y;
|
||||
return true;
|
||||
};
|
||||
ShapeCollisionsLine.lineToCircle = function (start, end, s, hit) {
|
||||
@@ -11820,6 +12286,45 @@ var es;
|
||||
}
|
||||
return this.fromMinMaxVector(new es.Vector2(Math.trunc(minX), Math.trunc(minY)), new es.Vector2(Math.trunc(maxX), Math.trunc(maxY)));
|
||||
};
|
||||
RectangleExt.calculateBounds = function (rect, parentPosition, position, origin, scale, rotation, width, height) {
|
||||
if (rotation == 0) {
|
||||
rect.x = Math.trunc(parentPosition.x + position.x - origin.x * scale.x);
|
||||
rect.y = Math.trunc(parentPosition.y + position.y - origin.y * scale.y);
|
||||
rect.width = Math.trunc(width * scale.x);
|
||||
rect.height = Math.trunc(height * scale.y);
|
||||
}
|
||||
else {
|
||||
// 我们需要找到我们的绝对最小/最大值,并据此创建边界
|
||||
var worldPosX = parentPosition.x + position.x;
|
||||
var worldPosY = parentPosition.y + position.y;
|
||||
var tempMat = void 0;
|
||||
// 考虑到原点,将参考点设置为世界参考
|
||||
var transformMatrix = es.Matrix2D.createTranslation(-worldPosX - origin.x, -worldPosY - origin.y);
|
||||
tempMat = es.Matrix2D.createScale(scale.x, scale.y);
|
||||
transformMatrix = transformMatrix.multiply(tempMat);
|
||||
tempMat = es.Matrix2D.createRotation(rotation);
|
||||
transformMatrix = transformMatrix.multiply(tempMat);
|
||||
tempMat = es.Matrix2D.createTranslation(worldPosX, worldPosY);
|
||||
transformMatrix = transformMatrix.multiply(tempMat);
|
||||
// TODO: 我们可以把世界变换留在矩阵中,避免在世界空间中得到所有的四个角
|
||||
var topLeft = new es.Vector2(worldPosX, worldPosY);
|
||||
var topRight = new es.Vector2(worldPosX + width, worldPosY);
|
||||
var bottomLeft = new es.Vector2(worldPosX, worldPosY + height);
|
||||
var bottomRight = new es.Vector2(worldPosX + width, worldPosY + height);
|
||||
es.Vector2Ext.transformR(topLeft, transformMatrix, topLeft);
|
||||
es.Vector2Ext.transformR(topRight, transformMatrix, topRight);
|
||||
es.Vector2Ext.transformR(bottomLeft, transformMatrix, bottomLeft);
|
||||
es.Vector2Ext.transformR(bottomRight, transformMatrix, bottomRight);
|
||||
// 找出最小值和最大值,这样我们就可以计算出我们的边界框。
|
||||
var minX = Math.trunc(Math.min(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x));
|
||||
var maxX = Math.trunc(Math.max(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x));
|
||||
var minY = Math.trunc(Math.min(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y));
|
||||
var maxY = Math.trunc(Math.max(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y));
|
||||
rect.location = new es.Vector2(minX, minY);
|
||||
rect.width = Math.trunc(maxX - minX);
|
||||
rect.height = Math.trunc(maxY - minY);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 缩放矩形
|
||||
* @param rect
|
||||
|
||||
2
source/bin/framework.min.js
vendored
2
source/bin/framework.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -83,6 +83,8 @@ module es {
|
||||
public onEntityTransformChanged(comp: transform.Component) {
|
||||
}
|
||||
|
||||
public debugRender(batcher: IBatcher) {}
|
||||
|
||||
/**
|
||||
*当父实体或此组件启用时调用
|
||||
*/
|
||||
|
||||
@@ -116,19 +116,31 @@ module es {
|
||||
return this;
|
||||
}
|
||||
|
||||
public setVelocity(velocity: Vector2): ArcadeRigidbody {
|
||||
this.velocity = velocity;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用刚体的质量给刚体加上一个瞬间的力脉冲。力是一个加速度,单位是每秒像素每秒。将力乘以100000,使数值使用更合理
|
||||
* @param force
|
||||
*/
|
||||
public addImpulse(force: Vector2) {
|
||||
if (!this.isImmovable) {
|
||||
this.velocity = this.velocity.add(Vector2.multiplyScaler(force, 100000)
|
||||
this.velocity.add(Vector2.multiplyScaler(force, 100000)
|
||||
.multiplyScaler(this._inverseMass * Time.deltaTime * Time.deltaTime));
|
||||
}
|
||||
}
|
||||
|
||||
public onAddedToEntity() {
|
||||
this._collider = this.entity.getComponent(es.Collider);
|
||||
this._collider = null;
|
||||
for (let i = 0; i < this.entity.components.buffer.length; i++) {
|
||||
let component = this.entity.components.buffer[i];
|
||||
if (component instanceof Collider) {
|
||||
this._collider = component;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Debug.warnIf(this._collider == null, "ArcadeRigidbody 没有 Collider。ArcadeRigidbody需要一个Collider!");
|
||||
}
|
||||
|
||||
@@ -139,9 +151,9 @@ module es {
|
||||
}
|
||||
|
||||
if (this.shouldUseGravity)
|
||||
this.velocity = this.velocity.add(Vector2.multiplyScaler(Physics.gravity, Time.deltaTime));
|
||||
this.velocity.add(Vector2.multiplyScaler(Physics.gravity, Time.deltaTime));
|
||||
|
||||
this.entity.transform.position = this.entity.transform.position.add(Vector2.multiplyScaler(this.velocity, Time.deltaTime));
|
||||
this.entity.position = this.entity.position.add(Vector2.multiplyScaler(this.velocity, Time.deltaTime));
|
||||
let collisionResult = new CollisionResult();
|
||||
|
||||
// 捞取我们在新的位置上可能会碰撞到的任何东西
|
||||
@@ -160,10 +172,10 @@ module es {
|
||||
this.processCollision(neighborRigidbody, collisionResult.minimumTranslationVector);
|
||||
} else {
|
||||
// 没有ArcadeRigidbody,所以我们假设它是不动的,只移动我们自己的
|
||||
this.entity.transform.position = this.entity.transform.position.subtract(collisionResult.minimumTranslationVector);
|
||||
this.entity.position = this.entity.position.subtract(collisionResult.minimumTranslationVector);
|
||||
let relativeVelocity = this.velocity.clone();
|
||||
this.calculateResponseVelocity(relativeVelocity, collisionResult.minimumTranslationVector, relativeVelocity);
|
||||
this.velocity = this.velocity.add(relativeVelocity);
|
||||
this.velocity.add(relativeVelocity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -176,12 +188,12 @@ module es {
|
||||
*/
|
||||
public processOverlap(other: ArcadeRigidbody, minimumTranslationVector: Vector2) {
|
||||
if (this.isImmovable) {
|
||||
other.entity.transform.position = other.entity.transform.position.add(minimumTranslationVector);
|
||||
other.entity.position = other.entity.position.add(minimumTranslationVector);
|
||||
} else if (other.isImmovable) {
|
||||
this.entity.transform.position = this.entity.transform.position.subtract(minimumTranslationVector);
|
||||
this.entity.position = this.entity.position.subtract(minimumTranslationVector);
|
||||
} else {
|
||||
this.entity.transform.position = this.entity.transform.position.subtract(Vector2.multiplyScaler(minimumTranslationVector, 0.5));
|
||||
other.entity.transform.position = other.entity.transform.position.add(Vector2.multiplyScaler(minimumTranslationVector, 0.5));
|
||||
this.entity.position = this.entity.position.subtract(Vector2.multiplyScaler(minimumTranslationVector, 0.5));
|
||||
other.entity.position = other.entity.position.add(Vector2.multiplyScaler(minimumTranslationVector, 0.5));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,8 +215,8 @@ module es {
|
||||
let ourResponseFraction = this._inverseMass / totalinverseMass;
|
||||
let otherResponseFraction = other._inverseMass / totalinverseMass;
|
||||
|
||||
this.velocity = this.velocity.add(Vector2.multiplyScaler(relativeVelocity, ourResponseFraction));
|
||||
other.velocity = other.velocity.subtract(Vector2.multiplyScaler(relativeVelocity, otherResponseFraction));
|
||||
this.velocity.add(Vector2.multiplyScaler(relativeVelocity, ourResponseFraction));
|
||||
other.velocity.subtract(Vector2.multiplyScaler(relativeVelocity, otherResponseFraction));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,8 +246,10 @@ module es {
|
||||
coefficientOfFriction = 1.01;
|
||||
|
||||
// 弹性影响速度的法向分量,摩擦力影响速度的切向分量
|
||||
responseVelocity = Vector2.multiplyScaler(normalVelocityComponent, -(1 + this._elasticity))
|
||||
let r = Vector2.multiplyScaler(normalVelocityComponent, -(1 + this._elasticity))
|
||||
.subtract(Vector2.multiplyScaler(tangentialVelocityComponent, coefficientOfFriction));
|
||||
responseVelocity.x = r.x;
|
||||
responseVelocity.y = r.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,15 @@ module es {
|
||||
* @param width
|
||||
* @param height
|
||||
*/
|
||||
constructor(x: number, y: number, width: number, height: number) {
|
||||
constructor(x: number = 0, y: number = 0, width: number = 1, height: number = 1) {
|
||||
super();
|
||||
|
||||
this._localOffset = new Vector2(x + width / 2, y + height / 2);
|
||||
if (width == 1 && height == 1) {
|
||||
this._colliderRequiresAutoSizing = true;
|
||||
} else {
|
||||
this._localOffset = new Vector2(x + width / 2, y + height / 2);
|
||||
}
|
||||
|
||||
this.shape = new Box(width, height);
|
||||
}
|
||||
|
||||
@@ -61,7 +66,7 @@ module es {
|
||||
// 更新框,改变边界,如果我们需要更新物理系统中的边界
|
||||
box.updateBox(width, box.height);
|
||||
this._isPositionDirty = true;
|
||||
if (this.entity && this._isParentEntityAddedToScene)
|
||||
if (this.entity != null && this._isParentEntityAddedToScene)
|
||||
Physics.updateCollider(this);
|
||||
}
|
||||
|
||||
@@ -84,6 +89,18 @@ module es {
|
||||
}
|
||||
}
|
||||
|
||||
public debugRender(batcher: IBatcher) {
|
||||
let poly = this.shape as Polygon;
|
||||
batcher.drawHollowRect(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height, new Color(76, 76, 76, 76), 2);
|
||||
batcher.end();
|
||||
batcher.drawPolygon(this.shape.position, poly.points, new Color(139, 0, 0, 255), true, 2);
|
||||
batcher.end();
|
||||
batcher.drawPixel(this.entity.position, new Color(255, 255, 0), 4);
|
||||
batcher.end();
|
||||
batcher.drawPixel(es.Vector2.add(this.transform.position, this.shape.center), new Color(255, 0, 0), 2);
|
||||
batcher.end();
|
||||
}
|
||||
|
||||
public toString() {
|
||||
return `[BoxCollider: bounds: ${this.bounds}]`;
|
||||
}
|
||||
|
||||
@@ -7,10 +7,13 @@ module es {
|
||||
*
|
||||
* @param radius
|
||||
*/
|
||||
constructor(radius: number) {
|
||||
constructor(radius: number = 1) {
|
||||
super();
|
||||
|
||||
this.shape = new Circle(radius);
|
||||
if (radius == 1) {
|
||||
this._colliderRequiresAutoSizing = true;
|
||||
}
|
||||
}
|
||||
|
||||
public get radius(): number {
|
||||
@@ -40,6 +43,17 @@ module es {
|
||||
return this;
|
||||
}
|
||||
|
||||
public debugRender(batcher: IBatcher) {
|
||||
batcher.drawHollowRect(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height, new Color(76, 76, 76, 76), 2);
|
||||
batcher.end();
|
||||
batcher.drawCircle(this.shape.position, this.radius, new Color(139, 0, 0), 2);
|
||||
batcher.end();
|
||||
batcher.drawPixel(this.entity.transform.position, new Color(255, 255, 0), 4);
|
||||
batcher.end();
|
||||
batcher.drawPixel(this.shape.position, new Color(255, 0, 0), 2);
|
||||
batcher.end();
|
||||
}
|
||||
|
||||
public toString() {
|
||||
return `[CircleCollider: bounds: ${this.bounds}, radius: ${(this.shape as Circle).radius}]`
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module es {
|
||||
export class Collider extends Component {
|
||||
export abstract class Collider extends Component {
|
||||
/**
|
||||
* 对撞机的基本形状
|
||||
*/
|
||||
@@ -59,10 +59,10 @@ module es {
|
||||
}
|
||||
|
||||
public get bounds(): Rectangle {
|
||||
if (this._isPositionDirty || this._isRotationDirty) {
|
||||
// if (this._isPositionDirty || this._isRotationDirty) {
|
||||
this.shape.recalculateBounds(this);
|
||||
this._isPositionDirty = this._isRotationDirty = false;
|
||||
}
|
||||
// this._isPositionDirty = this._isRotationDirty = false;
|
||||
// }
|
||||
|
||||
return this.shape.bounds;
|
||||
}
|
||||
@@ -114,6 +114,33 @@ module es {
|
||||
}
|
||||
|
||||
public onAddedToEntity() {
|
||||
if (this._colliderRequiresAutoSizing) {
|
||||
let renderable = null;
|
||||
for (let i = 0; i < this.entity.components.buffer.length; i ++) {
|
||||
let component = this.entity.components.buffer[i];
|
||||
if (component instanceof RenderableComponent){
|
||||
renderable = component;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (renderable != null) {
|
||||
let renderableBounds = renderable.bounds.clone();
|
||||
|
||||
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;
|
||||
this.localOffset = Vector2.subtract(renderableBounds.center, this.entity.transform.position);
|
||||
} else if (this instanceof BoxCollider) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.localOffset = Vector2.subtract(renderableBounds.center, this.entity.transform.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
this._isParentEntityAddedToScene = true;
|
||||
this.registerColliderWithPhysicsSystem();
|
||||
}
|
||||
|
||||
@@ -19,7 +19,15 @@ module es {
|
||||
* @param collisionResult
|
||||
*/
|
||||
public calculateMovement(motion: Vector2, collisionResult: CollisionResult): boolean {
|
||||
if (this.entity.getComponent(Collider) == null || this._triggerHelper == null) {
|
||||
let collider = null;
|
||||
for (let i = 0; i < this.entity.components.buffer.length; i++) {
|
||||
let component = this.entity.components.buffer[i];
|
||||
if (component instanceof Collider) {
|
||||
collider = component;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (collider == null || this._triggerHelper == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,15 @@ module es {
|
||||
private _collider: Collider;
|
||||
|
||||
public onAddedToEntity() {
|
||||
this._collider = this.entity.getComponent(Collider);
|
||||
let collider = null;
|
||||
for (let i = 0; i < this.entity.components.buffer.length; i++) {
|
||||
let component = this.entity.components.buffer[i];
|
||||
if (component instanceof Collider) {
|
||||
collider = component;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this._collider = collider;
|
||||
Debug.warnIf(this._collider == null, "ProjectileMover没有Collider。ProjectilMover需要一个Collider!");
|
||||
}
|
||||
|
||||
|
||||
9
source/src/ECS/Components/Renderables/IRenderable.ts
Normal file
9
source/src/ECS/Components/Renderables/IRenderable.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
module es {
|
||||
export interface IRenderable {
|
||||
enabled: boolean;
|
||||
renderLayer: number;
|
||||
isVisibleFromCamera(camera: ICamera): boolean;
|
||||
render(batcher: IBatcher, camera: ICamera): void;
|
||||
debugRender(batcher: IBatcher): void;
|
||||
}
|
||||
}
|
||||
125
source/src/ECS/Components/Renderables/RenderableComponent.ts
Normal file
125
source/src/ECS/Components/Renderables/RenderableComponent.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
module es {
|
||||
export abstract class RenderableComponent extends es.Component implements IRenderable {
|
||||
public getwidth() {
|
||||
return this.bounds.width;
|
||||
}
|
||||
|
||||
public getheight() {
|
||||
return this.bounds.height;
|
||||
}
|
||||
|
||||
protected _bounds: es.Rectangle = new es.Rectangle();
|
||||
public getbounds(): es.Rectangle {
|
||||
if (this._areBoundsDirty) {
|
||||
this._bounds.calculateBounds(this.entity.transform.position, this._localOffset, new es.Vector2(this.getwidth() / 2, this.getheight() / 2),
|
||||
this.entity.transform.scale, this.entity.transform.rotation, this.getwidth(), this.getheight());
|
||||
this._areBoundsDirty = false;
|
||||
}
|
||||
return this._bounds;
|
||||
}
|
||||
public get bounds() {
|
||||
return this.getbounds();
|
||||
}
|
||||
protected _areBoundsDirty: boolean = true;
|
||||
|
||||
public get renderLayer() {
|
||||
return this._renderLayer;
|
||||
}
|
||||
public set renderLayer(value: number) {
|
||||
this.setRenderLayer(value);
|
||||
}
|
||||
|
||||
protected _renderLayer: number = 0;
|
||||
|
||||
public onEntityTransformChanged(comp: transform.Component) {
|
||||
this._areBoundsDirty = true;
|
||||
}
|
||||
|
||||
public get localOffset() {
|
||||
return this._localOffset;
|
||||
}
|
||||
public set localOffset(value: es.Vector2) {
|
||||
this.setLocalOffset(value);
|
||||
}
|
||||
|
||||
public setLocalOffset(offset: es.Vector2) {
|
||||
if (!this._localOffset.equals(offset)) {
|
||||
this._localOffset = offset;
|
||||
this._areBoundsDirty = true;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public get isVisible() {
|
||||
return this._isVisible;
|
||||
}
|
||||
|
||||
public set isVisible(value: boolean) {
|
||||
if (this._isVisible != value) {
|
||||
this._isVisible = value;
|
||||
|
||||
if (this._isVisible) {
|
||||
this.onBecameVisible();
|
||||
} else {
|
||||
this.onBecameInvisible();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public debugRenderEnabled: boolean = true;
|
||||
|
||||
protected _isVisible: boolean = false;
|
||||
protected _localOffset: es.Vector2 = new es.Vector2();
|
||||
|
||||
public abstract render(batcher: IBatcher, camera: ICamera): void;
|
||||
|
||||
protected onBecameVisible() {
|
||||
|
||||
}
|
||||
|
||||
protected onBecameInvisible() {
|
||||
|
||||
}
|
||||
|
||||
public setRenderLayer(renderLayer: number): RenderableComponent {
|
||||
if (renderLayer != this._renderLayer) {
|
||||
let oldRenderLayer = this._renderLayer;
|
||||
this._renderLayer = renderLayer;
|
||||
|
||||
if (this.entity != null && this.entity.scene != null)
|
||||
es.Core.scene.renderableComponents.updateRenderableRenderLayer(this, oldRenderLayer, this._renderLayer);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public isVisibleFromCamera(cam: ICamera): boolean {
|
||||
this.isVisible = cam.bounds.intersects(this.bounds);
|
||||
|
||||
return this.isVisible;
|
||||
}
|
||||
|
||||
public debugRender(batcher: IBatcher) {
|
||||
if (!this.debugRenderEnabled)
|
||||
return;
|
||||
|
||||
let collider = null;
|
||||
for (let i = 0; i < this.entity.components.buffer.length; i++) {
|
||||
let component = this.entity.components.buffer[i];
|
||||
if (component instanceof Collider) {
|
||||
collider = component;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (collider == null) {
|
||||
batcher.drawHollowRect(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height, new Color(255, 255, 0));
|
||||
batcher.end();
|
||||
}
|
||||
|
||||
batcher.drawPixel(es.Vector2.add(this.entity.transform.position, this._localOffset), new Color(153, 50, 204), 4);
|
||||
batcher.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -376,6 +376,10 @@ module es {
|
||||
this.components.update();
|
||||
}
|
||||
|
||||
public debugRender(batcher: IBatcher) {
|
||||
this.components.debugRender(batcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建组件的新实例。返回实例组件
|
||||
* @param componentType
|
||||
|
||||
@@ -2,22 +2,22 @@
|
||||
module es {
|
||||
/** 场景 */
|
||||
export class Scene {
|
||||
/**
|
||||
* 这个场景中的实体列表
|
||||
*/
|
||||
public camera: ICamera;
|
||||
/** 这个场景中的实体列表 */
|
||||
public readonly entities: EntityList;
|
||||
|
||||
/**
|
||||
* 管理所有实体处理器
|
||||
*/
|
||||
public readonly renderableComponents: RenderableComponentList;
|
||||
/** 管理所有实体处理器 */
|
||||
public readonly entityProcessors: EntityProcessorList;
|
||||
|
||||
public readonly _sceneComponents: SceneComponent[] = [];
|
||||
public _renderers: Renderer[] = [];
|
||||
public readonly identifierPool: IdentifierPool;
|
||||
private _didSceneBegin: boolean;
|
||||
|
||||
constructor() {
|
||||
this.entities = new EntityList(this);
|
||||
this.renderableComponents = new RenderableComponentList();
|
||||
|
||||
this.entityProcessors = new EntityProcessorList();
|
||||
this.identifierPool = new IdentifierPool();
|
||||
|
||||
@@ -45,6 +45,10 @@ module es {
|
||||
}
|
||||
|
||||
public begin() {
|
||||
if (this._renderers.length == 0) {
|
||||
this.addRenderer(new DefaultRenderer());
|
||||
}
|
||||
|
||||
Physics.reset();
|
||||
|
||||
if (this.entityProcessors != null)
|
||||
@@ -58,6 +62,9 @@ module es {
|
||||
public end() {
|
||||
this._didSceneBegin = false;
|
||||
|
||||
for (let i = 0; i < this._renderers.length; i ++)
|
||||
this._renderers[i].unload();
|
||||
|
||||
this.entities.removeAllEntities();
|
||||
|
||||
for (let i = 0; i < this._sceneComponents.length; i++) {
|
||||
@@ -65,6 +72,7 @@ module es {
|
||||
}
|
||||
this._sceneComponents.length = 0;
|
||||
|
||||
this.camera = null;
|
||||
Physics.clear();
|
||||
|
||||
if (this.entityProcessors)
|
||||
@@ -91,6 +99,38 @@ module es {
|
||||
|
||||
if (this.entityProcessors != null)
|
||||
this.entityProcessors.lateUpdate();
|
||||
|
||||
this.renderableComponents.updateLists();
|
||||
this.render();
|
||||
}
|
||||
|
||||
public render() {
|
||||
for (let i = 0; i < this._renderers.length; i ++) {
|
||||
this._renderers[i].render(this);
|
||||
}
|
||||
}
|
||||
|
||||
public addRenderer<T extends Renderer>(renderer: T): T {
|
||||
this._renderers.push(renderer);
|
||||
this._renderers.sort((self, other) => self.renderOrder - other.renderOrder);
|
||||
|
||||
renderer.onAddedToScene(this);
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
public getRenderer<T extends Renderer>(type: new (...args: any[]) => T): T {
|
||||
for (let i = 0; i < this._renderers.length; i ++) {
|
||||
if (this._renderers[i] instanceof type)
|
||||
return this._renderers[i] as T;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public removeRenderer(renderer: Renderer) {
|
||||
new List(this._renderers).remove(renderer);
|
||||
renderer.unload();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -106,7 +106,7 @@ module es {
|
||||
|
||||
public get worldToLocalTransform(): Matrix2D {
|
||||
if (this._worldToLocalDirty) {
|
||||
if (!this.parent) {
|
||||
if (this.parent == null) {
|
||||
this._worldToLocalTransform = Matrix2D.identity;
|
||||
} else {
|
||||
this.parent.updateTransform();
|
||||
@@ -267,13 +267,13 @@ module es {
|
||||
return this;
|
||||
|
||||
if (this._parent != null) {
|
||||
let children = new es.List(this._parent._children);
|
||||
children.remove(this);
|
||||
const index = this._parent._children.findIndex(t => t == this);
|
||||
if (index != -1)
|
||||
this._parent._children.splice(index, 1);
|
||||
}
|
||||
|
||||
if (parent != null) {
|
||||
let children = new es.List(parent._children);
|
||||
children.add(this);
|
||||
parent._children.push(this);
|
||||
}
|
||||
|
||||
this._parent = parent;
|
||||
@@ -294,7 +294,7 @@ module es {
|
||||
|
||||
this._position = position;
|
||||
if (this.parent != null) {
|
||||
this.localPosition = Vector2.transform(this._position, this._worldToLocalTransform);
|
||||
this.localPosition = Vector2.transform(this._position, this.worldToLocalTransform);
|
||||
} else {
|
||||
this.localPosition = position;
|
||||
}
|
||||
@@ -325,7 +325,7 @@ module es {
|
||||
*/
|
||||
public setRotation(radians: number): Transform {
|
||||
this._rotation = radians;
|
||||
if (this.parent) {
|
||||
if (this.parent != null) {
|
||||
this.localRotation = this.parent.rotation + radians;
|
||||
} else {
|
||||
this.localRotation = radians;
|
||||
@@ -378,7 +378,7 @@ module es {
|
||||
*/
|
||||
public setScale(scale: Vector2): Transform {
|
||||
this._scale = scale;
|
||||
if (this.parent) {
|
||||
if (this.parent != null) {
|
||||
this.localScale = Vector2.divide(scale, this.parent._scale);
|
||||
} else {
|
||||
this.localScale = scale;
|
||||
|
||||
@@ -95,6 +95,9 @@ module es {
|
||||
let component = this._components[i];
|
||||
if (!component) continue;
|
||||
|
||||
if (component instanceof RenderableComponent)
|
||||
this._entity.scene.renderableComponents.remove(component);
|
||||
|
||||
// 处理IUpdatable
|
||||
if (isIUpdatable(component))
|
||||
new es.List(this._updatableComponents).remove(component);
|
||||
@@ -109,6 +112,9 @@ module es {
|
||||
if (this._components.length > 0) {
|
||||
for (let i = 0, s = this._components.length; i < s; ++ i) {
|
||||
let component = this._components[i];
|
||||
if (component instanceof RenderableComponent)
|
||||
this._entity.scene.renderableComponents.remove(component);
|
||||
|
||||
if (isIUpdatable(component))
|
||||
this._updatableComponents.push(component);
|
||||
|
||||
@@ -151,6 +157,9 @@ module es {
|
||||
if (this._componentsToAddList.length > 0) {
|
||||
for (let i = 0, l = this._componentsToAddList.length; i < l; ++ i) {
|
||||
let component = this._componentsToAddList[i];
|
||||
if (component instanceof RenderableComponent)
|
||||
this._entity.scene.renderableComponents.add(component);
|
||||
|
||||
if (isIUpdatable(component))
|
||||
this._updatableComponents.push(component);
|
||||
|
||||
@@ -186,6 +195,9 @@ module es {
|
||||
}
|
||||
|
||||
public handleRemove(component: Component) {
|
||||
if (component instanceof RenderableComponent)
|
||||
this._entity.scene.renderableComponents.remove(component);
|
||||
|
||||
if (isIUpdatable(component) && this._updatableComponents.length > 0) {
|
||||
let index = this._updatableComponents.findIndex((c) => (<any>c as Component).id == component.id);
|
||||
if (index != -1)
|
||||
@@ -313,5 +325,13 @@ module es {
|
||||
this._components[i].onDisabled();
|
||||
}
|
||||
}
|
||||
|
||||
public debugRender(batcher: IBatcher) {
|
||||
for (let i = 0; i < this._components.length; i ++) {
|
||||
if (this._components[i].enabled) {
|
||||
this._components[i].debugRender(batcher);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
81
source/src/ECS/Utils/RenderableComponentList.ts
Normal file
81
source/src/ECS/Utils/RenderableComponentList.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
module es {
|
||||
export class RenderableComponentList {
|
||||
private _components: IRenderable[] = [];
|
||||
private _componentsByRenderLayer: Map<number, IRenderable[]> = new Map();
|
||||
private _unsortedRenderLayers: number[] = [];
|
||||
private _componentsNeedSort = true;
|
||||
|
||||
public get count() {
|
||||
return this._components.length;
|
||||
}
|
||||
|
||||
public get(index: number) {
|
||||
return this._components[index];
|
||||
}
|
||||
|
||||
public add(component: IRenderable) {
|
||||
this._components.push(component);
|
||||
this.addToRenderLayerList(component, component.renderLayer);
|
||||
}
|
||||
|
||||
public remove(component: IRenderable) {
|
||||
new List(this._components).remove(component);
|
||||
new List(this._componentsByRenderLayer.get(component.renderLayer)).remove(component);
|
||||
}
|
||||
|
||||
public updateRenderableRenderLayer(component: IRenderable, oldRenderLayer: number, newRenderLayer: number) {
|
||||
if (this._componentsByRenderLayer.has(oldRenderLayer) && new List(this._componentsByRenderLayer.get(oldRenderLayer)).contains(component)) {
|
||||
new List(this._componentsByRenderLayer.get(oldRenderLayer)).remove(component);
|
||||
this.addToRenderLayerList(component, newRenderLayer);
|
||||
}
|
||||
}
|
||||
|
||||
public setRenderLayerNeedsComponentSort(renderLayer: number) {
|
||||
const unsortedRenderLayersList = new List(this._unsortedRenderLayers);
|
||||
if (!unsortedRenderLayersList.contains(renderLayer))
|
||||
unsortedRenderLayersList.add(renderLayer);
|
||||
this._componentsNeedSort = true;
|
||||
}
|
||||
|
||||
public setNeedsComponentSort() {
|
||||
this._componentsNeedSort = true;
|
||||
}
|
||||
|
||||
private addToRenderLayerList(component: IRenderable, renderLayer: number) {
|
||||
let list = this.componentsWithRenderLayer(renderLayer);
|
||||
es.Insist.isFalse(!!list.find(c => c == component), "组件renderLayer列表已包含此组件");
|
||||
|
||||
list.push(component);
|
||||
const unsortedRenderLayersList = new List(this._unsortedRenderLayers);
|
||||
if (!unsortedRenderLayersList.contains(renderLayer))
|
||||
unsortedRenderLayersList.add(renderLayer);
|
||||
this._componentsNeedSort = true;
|
||||
}
|
||||
|
||||
public componentsWithRenderLayer(renderLayer: number) {
|
||||
if (!this._componentsByRenderLayer.get(renderLayer)) {
|
||||
this._componentsByRenderLayer.set(renderLayer, []);
|
||||
}
|
||||
|
||||
return this._componentsByRenderLayer.get(renderLayer);
|
||||
}
|
||||
|
||||
public updateLists() {
|
||||
if (this._componentsNeedSort) {
|
||||
this._components.sort((self, other) => other.renderLayer - self.renderLayer);
|
||||
this._componentsNeedSort = false;
|
||||
}
|
||||
|
||||
if (this._unsortedRenderLayers.length > 0) {
|
||||
for (let i = 0, count = this._unsortedRenderLayers.length; i < count; i ++) {
|
||||
const renderLayerComponents = this._componentsByRenderLayer.get(this._unsortedRenderLayers[i]);
|
||||
if (renderLayerComponents) {
|
||||
renderLayerComponents.sort((self, other) => other.renderLayer - self.renderLayer);
|
||||
}
|
||||
|
||||
this._unsortedRenderLayers.length = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
source/src/Graphics/Batcher/Color.ts
Normal file
15
source/src/Graphics/Batcher/Color.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
module es {
|
||||
export class Color {
|
||||
public a: number = 255;
|
||||
public r: number = 255;
|
||||
public g: number = 255;
|
||||
public b: number = 255;
|
||||
|
||||
constructor(r: number, g: number, b: number, a: number = 255) {
|
||||
this.a = a;
|
||||
this.r = r;
|
||||
this.g = g;
|
||||
this.b = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
source/src/Graphics/Batcher/IBatcher.ts
Normal file
15
source/src/Graphics/Batcher/IBatcher.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
module es {
|
||||
export interface IBatcher {
|
||||
begin(cam: ICamera);
|
||||
end();
|
||||
drawPoints(points: Vector2[], color: Color, thickness?: number);
|
||||
drawPolygon(poisition: Vector2, points: Vector2[], color: Color, closePoly: boolean, thickness?: number);
|
||||
drawHollowRect(x: number, y: number, width: number, height: number, color: Color, thickness?: number);
|
||||
drawCircle(position: Vector2, raidus: number, color: Color, thickness?: number);
|
||||
drawCircleLow(position: es.Vector2, radius: number, color: Color, thickness?: number, resolution?: number);
|
||||
drawRect(x: number, y: number, width: number, height: number, color: Color);
|
||||
drawLine(start: Vector2, end: Vector2, color: Color, thickness: number);
|
||||
drawPixel(position: Vector2, color: Color, size?: number);
|
||||
}
|
||||
}
|
||||
|
||||
5
source/src/Graphics/Batcher/ICamera.ts
Normal file
5
source/src/Graphics/Batcher/ICamera.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
module es {
|
||||
export interface ICamera extends Component {
|
||||
bounds: Rectangle;
|
||||
}
|
||||
}
|
||||
10
source/src/Graphics/Graphics.ts
Normal file
10
source/src/Graphics/Graphics.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
module es {
|
||||
export class Graphics {
|
||||
public static instance: Graphics;
|
||||
public batcher: IBatcher;
|
||||
|
||||
constructor(batcher: IBatcher) {
|
||||
this.batcher = batcher;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
source/src/Graphics/Renderers/DefaultRenderer.ts
Normal file
24
source/src/Graphics/Renderers/DefaultRenderer.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
///<reference path="Renderer.ts" />
|
||||
module es {
|
||||
export class DefaultRenderer extends Renderer {
|
||||
constructor(renderOrder: number = 0, camera: ICamera = null) {
|
||||
super(renderOrder, camera);
|
||||
}
|
||||
|
||||
public render(scene: Scene): void {
|
||||
let cam = this.camera ? this.camera : scene.camera;
|
||||
this.beginRender(cam);
|
||||
|
||||
for (let i = 0; i < scene.renderableComponents.count; i ++) {
|
||||
let renderable = scene.renderableComponents.get(i);
|
||||
if (renderable.enabled && renderable.isVisibleFromCamera(scene.camera))
|
||||
this.renderAfterStateCheck(renderable, cam);
|
||||
}
|
||||
|
||||
if (this.shouldDebugRender && es.Core.debugRenderEndabled)
|
||||
this.debugRender(scene);
|
||||
|
||||
this.endRender();
|
||||
}
|
||||
}
|
||||
}
|
||||
39
source/src/Graphics/Renderers/Renderer.ts
Normal file
39
source/src/Graphics/Renderers/Renderer.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
module es {
|
||||
export abstract class Renderer {
|
||||
public camera: ICamera;
|
||||
public readonly renderOrder: number = 0;
|
||||
public shouldDebugRender: boolean = true;
|
||||
|
||||
constructor(renderOrder: number, camera: ICamera) {
|
||||
this.renderOrder = renderOrder;
|
||||
this.camera = camera;
|
||||
}
|
||||
|
||||
public onAddedToScene(scene: es.Scene) { }
|
||||
|
||||
public unload() { }
|
||||
|
||||
protected beginRender(cam: ICamera) {
|
||||
Graphics.instance.batcher.begin(cam);
|
||||
}
|
||||
|
||||
protected endRender() {
|
||||
Graphics.instance.batcher.end();
|
||||
}
|
||||
|
||||
public abstract render(scene: Scene): void;
|
||||
|
||||
protected renderAfterStateCheck(renderable: IRenderable, cam: ICamera) {
|
||||
renderable.render(Graphics.instance.batcher, cam);
|
||||
}
|
||||
|
||||
protected debugRender(scene: Scene) {
|
||||
for (let i = 0; i < scene.entities.count; i ++) {
|
||||
let entity = scene.entities.buffer[i];
|
||||
if (entity.enabled) {
|
||||
entity.debugRender(Graphics.instance.batcher);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,6 +109,16 @@ module es {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static createRotationOut(radians: number, result: Matrix2D) {
|
||||
let val1 = Math.cos(radians);
|
||||
let val2 = Math.sin(radians);
|
||||
|
||||
result.m11 = val1;
|
||||
result.m12 = val2;
|
||||
result.m21 = -val2;
|
||||
result.m22 = val1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个新的缩放矩阵2D
|
||||
* @param xScale
|
||||
@@ -128,6 +138,17 @@ module es {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static createScaleOut(xScale: number, yScale: number, result: Matrix2D) {
|
||||
result.m11 = xScale;
|
||||
result.m12 = 0;
|
||||
|
||||
result.m21 = 0;
|
||||
result.m22 = yScale;
|
||||
|
||||
result.m31 = 0;
|
||||
result.m32 = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个新的平移矩阵2D
|
||||
* @param xPosition
|
||||
@@ -147,6 +168,17 @@ module es {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static createTranslationOut(position: Vector2, result: Matrix2D) {
|
||||
result.m11 = 1;
|
||||
result.m12 = 0;
|
||||
|
||||
result.m21 = 0;
|
||||
result.m22 = 1;
|
||||
|
||||
result.m31 = position.x;
|
||||
result.m32 = position.y;
|
||||
}
|
||||
|
||||
public static invert(matrix: Matrix2D) {
|
||||
let det = 1 / matrix.determinant();
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ module es {
|
||||
public static multiplyScaler(value1: Vector2, value2: number) {
|
||||
let result = es.Vector2.zero;
|
||||
result.x = value1.x * value2;
|
||||
result.y = value1.x * value2;
|
||||
result.y = value1.y * value2;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ module es {
|
||||
export class Physics {
|
||||
public static _spatialHash: SpatialHash;
|
||||
/** 用于在全局范围内存储重力值的方便字段 */
|
||||
public static gravity = new Vector2(0, 300);
|
||||
public static gravity = new Vector2(0, -300);
|
||||
/** 调用reset并创建一个新的SpatialHash时使用的单元格大小 */
|
||||
public static spatialHashCellSize = 100;
|
||||
/** 接受layerMask的所有方法的默认值 */
|
||||
@@ -42,6 +42,10 @@ module es {
|
||||
this._spatialHash.clear();
|
||||
}
|
||||
|
||||
public static debugDraw(secondsToDisplay) {
|
||||
this._spatialHash.debugDraw(secondsToDisplay);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否有对撞机落在一个圆形区域内。返回遇到的第一个对撞机
|
||||
* @param center
|
||||
|
||||
@@ -16,7 +16,7 @@ module es {
|
||||
// TODO: 这是得到分数的正确和最有效的方法吗?
|
||||
// 先检查x分数。如果是NaN,就用y代替
|
||||
let distanceFraction = (intersection.x - start.x) / (end.x - start.x);
|
||||
if (Number.isNaN(distanceFraction) || Number.isFinite(distanceFraction))
|
||||
if (Number.isNaN(distanceFraction) || Math.abs(distanceFraction) == Infinity)
|
||||
distanceFraction = (intersection.y - start.y) / (end.y - start.y);
|
||||
|
||||
if (distanceFraction < fraction){
|
||||
@@ -56,7 +56,9 @@ module es {
|
||||
if (u < 0 || u > 1)
|
||||
return false;
|
||||
|
||||
intersection = Vector2.add(a1, Vector2.multiplyScaler(b, t));
|
||||
let r = Vector2.add(a1, Vector2.multiplyScaler(b, t));
|
||||
intersection.x = r.x;
|
||||
intersection.y = r.y;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -94,6 +94,21 @@ module es {
|
||||
this._cellDict.clear();
|
||||
}
|
||||
|
||||
public debugDraw(secondsToDisplay: number) {
|
||||
for (let x = this.gridBounds.x; x <= this.gridBounds.right; x ++) {
|
||||
for (let y = this.gridBounds.y; y <= this.gridBounds.bottom; y ++) {
|
||||
let cell = this.cellAtPosition(x, y);
|
||||
if (cell != null && cell.length > 0)
|
||||
this.debugDrawCellDetails(x, y, secondsToDisplay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private debugDrawCellDetails(x: number, y: number, secondsToDisplay: number = 0.5) {
|
||||
Graphics.instance.batcher.drawHollowRect(x * this._cellSize, y * this._cellSize, this._cellSize, this._cellSize, new Color(255, 0, 0), secondsToDisplay);
|
||||
Graphics.instance.batcher.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回边框与单元格相交的所有对象
|
||||
* @param bounds
|
||||
@@ -174,18 +189,18 @@ module es {
|
||||
// 开始遍历并返回交叉单元格。
|
||||
let cell = this.cellAtPosition(currentCell.x, currentCell.y);
|
||||
|
||||
if (cell && this._raycastParser.checkRayIntersection(currentCell.x, currentCell.y, cell)){
|
||||
if (cell != null && this._raycastParser.checkRayIntersection(currentCell.x, currentCell.y, cell)){
|
||||
this._raycastParser.reset();
|
||||
return this._raycastParser.hitCounter;
|
||||
}
|
||||
|
||||
while (currentCell.x != lastCell.x || currentCell.y != lastCell.y){
|
||||
if (tMaxX < tMaxY){
|
||||
currentCell.x = Math.trunc(MathHelper.approach(currentCell.x, lastCell.x, Math.abs(stepX)));
|
||||
currentCell.x = MathHelper.approach(currentCell.x, lastCell.x, Math.abs(stepX));
|
||||
|
||||
tMaxX += tDeltaX;
|
||||
}else{
|
||||
currentCell.y = Math.trunc(MathHelper.approach(currentCell.y, lastCell.y, Math.abs(stepY)));
|
||||
currentCell.y = MathHelper.approach(currentCell.y, lastCell.y, Math.abs(stepY));
|
||||
|
||||
tMaxY += tDeltaY;
|
||||
}
|
||||
|
||||
@@ -330,6 +330,52 @@ module es {
|
||||
return this.fromMinMaxVector(new Vector2(Math.trunc(minX), Math.trunc(minY)), new Vector2(Math.trunc(maxX), Math.trunc(maxY)));
|
||||
}
|
||||
|
||||
public static calculateBounds(rect: Rectangle, parentPosition: Vector2, position: Vector2, origin: Vector2, scale: Vector2,
|
||||
rotation: number, width: number, height: number) {
|
||||
if (rotation == 0) {
|
||||
rect.x = Math.trunc(parentPosition.x + position.x - origin.x * scale.x);
|
||||
rect.y = Math.trunc(parentPosition.y + position.y - origin.y * scale.y);
|
||||
rect.width = Math.trunc(width * scale.x);
|
||||
rect.height = Math.trunc(height * scale.y);
|
||||
} else {
|
||||
// 我们需要找到我们的绝对最小/最大值,并据此创建边界
|
||||
let worldPosX = parentPosition.x + position.x;
|
||||
let worldPosY = parentPosition.y + position.y;
|
||||
|
||||
let tempMat: Matrix2D;
|
||||
|
||||
// 考虑到原点,将参考点设置为世界参考
|
||||
let transformMatrix = Matrix2D.createTranslation(-worldPosX - origin.x, -worldPosY - origin.y);
|
||||
tempMat = Matrix2D.createScale(scale.x, scale.y);
|
||||
transformMatrix = transformMatrix.multiply(tempMat);
|
||||
tempMat = Matrix2D.createRotation(rotation);
|
||||
transformMatrix =transformMatrix.multiply(tempMat);
|
||||
tempMat = Matrix2D.createTranslation(worldPosX, worldPosY);
|
||||
transformMatrix = transformMatrix.multiply(tempMat);
|
||||
|
||||
// TODO: 我们可以把世界变换留在矩阵中,避免在世界空间中得到所有的四个角
|
||||
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);
|
||||
|
||||
Vector2Ext.transformR(topLeft, transformMatrix, topLeft);
|
||||
Vector2Ext.transformR(topRight, transformMatrix, topRight);
|
||||
Vector2Ext.transformR(bottomLeft, transformMatrix, bottomLeft);
|
||||
Vector2Ext.transformR(bottomRight, transformMatrix, bottomRight);
|
||||
|
||||
// 找出最小值和最大值,这样我们就可以计算出我们的边界框。
|
||||
let minX = Math.trunc(Math.min(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x));
|
||||
let maxX = Math.trunc(Math.max(topLeft.x, bottomRight.x, topRight.x, bottomLeft.x));
|
||||
let minY = Math.trunc(Math.min(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y));
|
||||
let maxY = Math.trunc(Math.max(topLeft.y, bottomRight.y, topRight.y, bottomLeft.y));
|
||||
|
||||
rect.location = new Vector2(minX, minY);
|
||||
rect.width = Math.trunc(maxX - minX);
|
||||
rect.height = Math.trunc(maxY - minY);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 缩放矩形
|
||||
* @param rect
|
||||
|
||||
Reference in New Issue
Block a user