移动类至es模块
This commit is contained in:
@@ -1,74 +1,85 @@
|
||||
///<reference path="./Collider.ts" />
|
||||
class BoxCollider extends Collider {
|
||||
public get width(){
|
||||
return (this.shape as Box).width;
|
||||
}
|
||||
|
||||
public set width(value: number){
|
||||
this.setWidth(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置BoxCollider的宽度
|
||||
* @param width
|
||||
*/
|
||||
public setWidth(width: number): BoxCollider{
|
||||
this._colliderRequiresAutoSizing = false;
|
||||
let box = this.shape as Box;
|
||||
if (width != box.width){
|
||||
// 更新框,改变边界,如果我们需要更新物理系统中的边界
|
||||
box.updateBox(width, box.height);
|
||||
if (this.entity && this._isParentEntityAddedToScene)
|
||||
Physics.updateCollider(this);
|
||||
module es {
|
||||
export class BoxCollider extends Collider {
|
||||
public get width(){
|
||||
return (this.shape as Box).width;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public get height(){
|
||||
return (this.shape as Box).height;
|
||||
}
|
||||
|
||||
public set height(value: number){
|
||||
this.setHeight(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置BoxCollider的高度
|
||||
* @param height
|
||||
*/
|
||||
public setHeight(height: number){
|
||||
this._colliderRequiresAutoSizing = false;
|
||||
let box = this.shape as Box;
|
||||
if (height != box.height){
|
||||
// 更新框,改变边界,如果我们需要更新物理系统中的边界
|
||||
box.updateBox(box.width, height);
|
||||
if (this.entity && this._isParentEntityAddedToScene)
|
||||
Physics.updateCollider(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 零参数构造函数要求RenderableComponent在实体上,这样碰撞器可以在实体被添加到场景时调整自身的大小。
|
||||
*/
|
||||
constructor(){
|
||||
super();
|
||||
|
||||
// 我们在这里插入一个1x1框作为占位符,直到碰撞器在下一阵被添加到实体并可以获得更精确的自动调整大小数据
|
||||
this.shape = new Box(1, 1);
|
||||
this._colliderRequiresAutoSizing = true;
|
||||
}
|
||||
|
||||
public setSize(width: number, height: number){
|
||||
this._colliderRequiresAutoSizing = false;
|
||||
let box = this.shape as Box;
|
||||
if (width != box.width || height != box.height){
|
||||
// 更新框,改变边界,如果我们需要更新物理系统中的边界
|
||||
box.updateBox(width, height);
|
||||
if (this.entity && this._isParentEntityAddedToScene)
|
||||
Physics.updateCollider(this);
|
||||
public set width(value: number){
|
||||
this.setWidth(value);
|
||||
}
|
||||
|
||||
return this;
|
||||
public get height(){
|
||||
return (this.shape as Box).height;
|
||||
}
|
||||
|
||||
public set height(value: number){
|
||||
this.setHeight(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 零参数构造函数要求RenderableComponent在实体上,这样碰撞器可以在实体被添加到场景时调整自身的大小。
|
||||
*/
|
||||
constructor(){
|
||||
super();
|
||||
|
||||
// 我们在这里插入一个1x1框作为占位符,直到碰撞器在下一阵被添加到实体并可以获得更精确的自动调整大小数据
|
||||
this.shape = new Box(1, 1);
|
||||
this._colliderRequiresAutoSizing = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置BoxCollider的大小
|
||||
* @param width
|
||||
* @param height
|
||||
*/
|
||||
public setSize(width: number, height: number){
|
||||
this._colliderRequiresAutoSizing = false;
|
||||
let box = this.shape as Box;
|
||||
if (width != box.width || height != box.height){
|
||||
// 更新框,改变边界,如果我们需要更新物理系统中的边界
|
||||
box.updateBox(width, height);
|
||||
if (this.entity && this._isParentEntityAddedToScene)
|
||||
Physics.updateCollider(this);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置BoxCollider的宽度
|
||||
* @param width
|
||||
*/
|
||||
public setWidth(width: number): BoxCollider{
|
||||
this._colliderRequiresAutoSizing = false;
|
||||
let box = this.shape as Box;
|
||||
if (width != box.width){
|
||||
// 更新框,改变边界,如果我们需要更新物理系统中的边界
|
||||
box.updateBox(width, box.height);
|
||||
if (this.entity && this._isParentEntityAddedToScene)
|
||||
Physics.updateCollider(this);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置BoxCollider的高度
|
||||
* @param height
|
||||
*/
|
||||
public setHeight(height: number){
|
||||
this._colliderRequiresAutoSizing = false;
|
||||
let box = this.shape as Box;
|
||||
if (height != box.height){
|
||||
// 更新框,改变边界,如果我们需要更新物理系统中的边界
|
||||
box.updateBox(box.width, height);
|
||||
if (this.entity && this._isParentEntityAddedToScene)
|
||||
Physics.updateCollider(this);
|
||||
}
|
||||
}
|
||||
|
||||
public toString(){
|
||||
return `[BoxCollider: bounds: ${this.bounds}]`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +1,48 @@
|
||||
class CircleCollider extends Collider {
|
||||
public get radius(): number{
|
||||
return (this.shape as Circle).radius;
|
||||
}
|
||||
public set radius(value: number){
|
||||
this.setRadius(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个有半径的圆
|
||||
*
|
||||
* @param radius
|
||||
*/
|
||||
constructor(radius?: number){
|
||||
super();
|
||||
|
||||
if (radius)
|
||||
this._colliderRequiresAutoSizing = true;
|
||||
// 我们在这里插入一个1px的圆圈作为占位符
|
||||
// 直到碰撞器被添加到实体并可以获得更精确的自动调整大小数据的下一帧
|
||||
this.shape = new Circle(radius ? radius : 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置圆的半径
|
||||
* @param radius
|
||||
*/
|
||||
public setRadius(radius: number): CircleCollider{
|
||||
this._colliderRequiresAutoSizing = false;
|
||||
let circle = this.shape as Circle;
|
||||
if (radius != circle.radius){
|
||||
circle.radius = radius;
|
||||
circle._originalRadius = radius;
|
||||
|
||||
if (this.entity && this._isParentEntityAddedToScene)
|
||||
Physics.updateCollider(this);
|
||||
module es {
|
||||
export class CircleCollider extends Collider {
|
||||
public get radius(): number {
|
||||
return (this.shape as Circle).radius;
|
||||
}
|
||||
|
||||
return this;
|
||||
public set radius(value: number) {
|
||||
this.setRadius(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个有半径的圆
|
||||
*
|
||||
* @param radius
|
||||
*/
|
||||
constructor(radius?: number) {
|
||||
super();
|
||||
|
||||
if (radius)
|
||||
this._colliderRequiresAutoSizing = true;
|
||||
// 我们在这里插入一个1px的圆圈作为占位符
|
||||
// 直到碰撞器被添加到实体并可以获得更精确的自动调整大小数据的下一帧
|
||||
this.shape = new Circle(radius ? radius : 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置圆的半径
|
||||
* @param radius
|
||||
*/
|
||||
public setRadius(radius: number): CircleCollider {
|
||||
this._colliderRequiresAutoSizing = false;
|
||||
let circle = this.shape as Circle;
|
||||
if (radius != circle.radius) {
|
||||
circle.radius = radius;
|
||||
circle._originalRadius = radius;
|
||||
|
||||
if (this.entity && this._isParentEntityAddedToScene)
|
||||
Physics.updateCollider(this);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public toString() {
|
||||
return `[CircleCollider: bounds: ${this.bounds}, radius: ${(this.shape as Circle).radius}]`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,26 @@
|
||||
/**
|
||||
* 多边形应该以顺时针方式定义
|
||||
*/
|
||||
class PolygonCollider extends Collider {
|
||||
module es {
|
||||
/**
|
||||
* 如果这些点没有居中,它们将以localOffset的差异为居中。
|
||||
* @param points
|
||||
* 多边形应该以顺时针方式定义
|
||||
*/
|
||||
constructor(points: Vector2[]){
|
||||
super();
|
||||
export class PolygonCollider extends Collider {
|
||||
/**
|
||||
* 如果这些点没有居中,它们将以localOffset的差异为居中。
|
||||
* @param points
|
||||
*/
|
||||
constructor(points: Vector2[]) {
|
||||
super();
|
||||
|
||||
// 第一点和最后一点决不能相同。我们想要一个开放的多边形
|
||||
let isPolygonClosed = points[0] == points[points.length - 1];
|
||||
// 第一点和最后一点决不能相同。我们想要一个开放的多边形
|
||||
let isPolygonClosed = points[0] == points[points.length - 1];
|
||||
|
||||
// 最后一个移除
|
||||
if (isPolygonClosed)
|
||||
points.splice(points.length - 1, 1);
|
||||
// 最后一个移除
|
||||
if (isPolygonClosed)
|
||||
points.splice(points.length - 1, 1);
|
||||
|
||||
Polygon.recenterPolygonVerts(points);
|
||||
this.shape = new Polygon(points);
|
||||
let center = Polygon.findPolygonCenter(points);
|
||||
this.setLocalOffset(center);
|
||||
Polygon.recenterPolygonVerts(points);
|
||||
this.shape = new Polygon(points);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,23 @@
|
||||
interface ITriggerListener {
|
||||
onTriggerEnter(other: Collider, local: Collider);
|
||||
onTriggerExit(other: Collider, local: Collider);
|
||||
}
|
||||
module es{
|
||||
/**
|
||||
* 当添加到组件时,每当实体上的冲突器与另一个组件重叠/退出时,将调用这些方法。
|
||||
* ITriggerListener方法将在实现接口的触发器实体上的任何组件上调用。
|
||||
* 注意,这个接口只与Mover类一起工作
|
||||
*/
|
||||
export interface ITriggerListener {
|
||||
/**
|
||||
* 当碰撞器与触发碰撞器相交时调用。这是在触发碰撞器和触发碰撞器上调用的。
|
||||
* 移动必须由Mover/ProjectileMover方法处理,以使其自动工作。
|
||||
* @param other
|
||||
* @param local
|
||||
*/
|
||||
onTriggerEnter(other: Collider, local: Collider);
|
||||
|
||||
/**
|
||||
* 当另一个碰撞器离开触发碰撞器时调用
|
||||
* @param other
|
||||
* @param local
|
||||
*/
|
||||
onTriggerExit(other: Collider, local: Collider);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,93 +1,95 @@
|
||||
/**
|
||||
* 辅助类说明了一种处理移动的方法,它考虑了包括触发器在内的所有冲突。
|
||||
* ITriggerListener接口用于管理对移动过程中违反的任何触发器的回调。
|
||||
* 一个物体只能通过移动器移动。要正确报告触发器的move方法。
|
||||
*
|
||||
* 请注意,多个移动者相互交互将多次调用ITriggerListener。
|
||||
*/
|
||||
class Mover extends Component {
|
||||
private _triggerHelper: ColliderTriggerHelper;
|
||||
|
||||
public onAddedToEntity(){
|
||||
this._triggerHelper = new ColliderTriggerHelper(this.entity);
|
||||
}
|
||||
|
||||
module es {
|
||||
/**
|
||||
* 计算修改运动矢量的运动,以考虑移动时可能发生的碰撞
|
||||
* @param motion
|
||||
* 辅助类说明了一种处理移动的方法,它考虑了包括触发器在内的所有冲突。
|
||||
* ITriggerListener接口用于管理对移动过程中违反的任何触发器的回调。
|
||||
* 一个物体只能通过移动器移动。要正确报告触发器的move方法。
|
||||
*
|
||||
* 请注意,多个移动者相互交互将多次调用ITriggerListener。
|
||||
*/
|
||||
public calculateMovement(motion: Vector2){
|
||||
let collisionResult = new CollisionResult();
|
||||
export class Mover extends Component {
|
||||
private _triggerHelper: ColliderTriggerHelper;
|
||||
|
||||
if (!this.entity.getComponent(Collider) || !this._triggerHelper){
|
||||
return null;
|
||||
public onAddedToEntity(){
|
||||
this._triggerHelper = new ColliderTriggerHelper(this.entity);
|
||||
}
|
||||
|
||||
// 移动所有的非触发碰撞器并获得最近的碰撞
|
||||
let colliders: Collider[] = this.entity.getComponents(Collider);
|
||||
for (let i = 0; i < colliders.length; i ++){
|
||||
let collider = colliders[i];
|
||||
/**
|
||||
* 计算修改运动矢量的运动,以考虑移动时可能发生的碰撞
|
||||
* @param motion
|
||||
*/
|
||||
public calculateMovement(motion: Vector2){
|
||||
let collisionResult = new CollisionResult();
|
||||
|
||||
// 不检测触发器 在我们移动后会重新访问它
|
||||
if (collider.isTrigger)
|
||||
continue;
|
||||
if (!this.entity.getComponent(Collider) || !this._triggerHelper){
|
||||
return null;
|
||||
}
|
||||
|
||||
// 获取我们在新位置可能发生碰撞的任何东西
|
||||
let bounds = collider.bounds;
|
||||
bounds.x += motion.x;
|
||||
bounds.y += motion.y;
|
||||
let boxcastResult = Physics.boxcastBroadphaseExcludingSelf(collider, bounds, collider.collidesWithLayers);
|
||||
bounds = boxcastResult.bounds;
|
||||
let neighbors = boxcastResult.tempHashSet;
|
||||
// 移动所有的非触发碰撞器并获得最近的碰撞
|
||||
let colliders: Collider[] = this.entity.getComponents(Collider);
|
||||
for (let i = 0; i < colliders.length; i ++){
|
||||
let collider = colliders[i];
|
||||
|
||||
for (let j = 0; j < neighbors.length; j ++){
|
||||
let neighbor = neighbors[j];
|
||||
// 不检测触发器
|
||||
if (neighbor.isTrigger)
|
||||
// 不检测触发器 在我们移动后会重新访问它
|
||||
if (collider.isTrigger)
|
||||
continue;
|
||||
|
||||
let _internalcollisionResult = collider.collidesWith(neighbor, motion);
|
||||
if (_internalcollisionResult){
|
||||
// 如果碰撞 则退回之前的移动量
|
||||
motion = Vector2.subtract(motion, _internalcollisionResult.minimumTranslationVector);
|
||||
// 获取我们在新位置可能发生碰撞的任何东西
|
||||
let bounds = collider.bounds;
|
||||
bounds.x += motion.x;
|
||||
bounds.y += motion.y;
|
||||
let boxcastResult = Physics.boxcastBroadphaseExcludingSelf(collider, bounds, collider.collidesWithLayers);
|
||||
bounds = boxcastResult.bounds;
|
||||
let neighbors = boxcastResult.tempHashSet;
|
||||
|
||||
// 如果我们碰到多个对象,为了简单起见,只取第一个。
|
||||
if (_internalcollisionResult.collider){
|
||||
collisionResult = _internalcollisionResult;
|
||||
for (let j = 0; j < neighbors.length; j ++){
|
||||
let neighbor = neighbors[j];
|
||||
// 不检测触发器
|
||||
if (neighbor.isTrigger)
|
||||
continue;
|
||||
|
||||
let _internalcollisionResult = collider.collidesWith(neighbor, motion);
|
||||
if (_internalcollisionResult){
|
||||
// 如果碰撞 则退回之前的移动量
|
||||
motion = Vector2.subtract(motion, _internalcollisionResult.minimumTranslationVector);
|
||||
|
||||
// 如果我们碰到多个对象,为了简单起见,只取第一个。
|
||||
if (_internalcollisionResult.collider){
|
||||
collisionResult = _internalcollisionResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListPool.free(colliders);
|
||||
|
||||
return {collisionResult: collisionResult, motion: motion};
|
||||
}
|
||||
|
||||
ListPool.free(colliders);
|
||||
/**
|
||||
* 将calculatemomovement应用到实体并更新triggerHelper
|
||||
* @param motion
|
||||
*/
|
||||
public applyMovement(motion: Vector2){
|
||||
// 移动实体到它的新位置,如果我们有一个碰撞,否则移动全部数量。当碰撞发生时,运动被更新
|
||||
this.entity.position = Vector2.add(this.entity.position, motion);
|
||||
|
||||
return {collisionResult: collisionResult, motion: motion};
|
||||
// 对所有是触发器的碰撞器与所有宽相位碰撞器进行重叠检查。任何重叠都会导致触发事件。
|
||||
if (this._triggerHelper)
|
||||
this._triggerHelper.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过调用calculateMovement和applyMovement来移动考虑碰撞的实体;
|
||||
* @param motion
|
||||
*/
|
||||
public move(motion: Vector2){
|
||||
let movementResult = this.calculateMovement(motion);
|
||||
let collisionResult = movementResult.collisionResult;
|
||||
motion = movementResult.motion;
|
||||
|
||||
this.applyMovement(motion);
|
||||
|
||||
return collisionResult;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将calculatemomovement应用到实体并更新triggerHelper
|
||||
* @param motion
|
||||
*/
|
||||
public applyMovement(motion: Vector2){
|
||||
// 移动实体到它的新位置,如果我们有一个碰撞,否则移动全部数量。当碰撞发生时,运动被更新
|
||||
this.entity.position = Vector2.add(this.entity.position, motion);
|
||||
|
||||
// 对所有是触发器的碰撞器与所有宽相位碰撞器进行重叠检查。任何重叠都会导致触发事件。
|
||||
if (this._triggerHelper)
|
||||
this._triggerHelper.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过调用calculateMovement和applyMovement来移动考虑碰撞的实体;
|
||||
* @param motion
|
||||
*/
|
||||
public move(motion: Vector2){
|
||||
let movementResult = this.calculateMovement(motion);
|
||||
let collisionResult = movementResult.collisionResult;
|
||||
motion = movementResult.motion;
|
||||
|
||||
this.applyMovement(motion);
|
||||
|
||||
return collisionResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +1,58 @@
|
||||
/**
|
||||
* 只向itriggerlistener报告冲突的移动器
|
||||
* 该对象将始终移动完整的距离
|
||||
*/
|
||||
class ProjectileMover extends Component {
|
||||
private _tempTriggerList: ITriggerListener[] = [];
|
||||
private _collider: Collider;
|
||||
|
||||
public onAddedToEntity(){
|
||||
this._collider = this.entity.getComponent<Collider>(Collider);
|
||||
if (!this._collider)
|
||||
console.warn("ProjectileMover has no Collider. ProjectilMover requires a Collider!");
|
||||
}
|
||||
|
||||
module es {
|
||||
/**
|
||||
* 移动考虑碰撞的实体
|
||||
* @param motion
|
||||
* 只向itriggerlistener报告冲突的移动器
|
||||
* 该对象将始终移动完整的距离
|
||||
*/
|
||||
public move(motion: Vector2): boolean{
|
||||
if (!this._collider)
|
||||
return false;
|
||||
export class ProjectileMover extends Component {
|
||||
private _tempTriggerList: ITriggerListener[] = [];
|
||||
private _collider: Collider;
|
||||
|
||||
let didCollide = false;
|
||||
public onAddedToEntity(){
|
||||
this._collider = this.entity.getComponent<Collider>(Collider);
|
||||
if (!this._collider)
|
||||
console.warn("ProjectileMover has no Collider. ProjectilMover requires a Collider!");
|
||||
}
|
||||
|
||||
// 获取我们在新位置可能发生碰撞的任何东西
|
||||
this.entity.position = Vector2.add(this.entity.position, motion);
|
||||
/**
|
||||
* 移动考虑碰撞的实体
|
||||
* @param motion
|
||||
*/
|
||||
public move(motion: Vector2): boolean{
|
||||
if (!this._collider)
|
||||
return false;
|
||||
|
||||
// 获取任何可能在新位置发生碰撞的东西
|
||||
let neighbors = Physics.boxcastBroadphase(this._collider.bounds, this._collider.collidesWithLayers);
|
||||
for (let i = 0; i < neighbors.colliders.length; i ++){
|
||||
let neighbor = neighbors.colliders[i];
|
||||
if (this._collider.overlaps(neighbor) && neighbor.enabled){
|
||||
didCollide = true;
|
||||
this.notifyTriggerListeners(this._collider, neighbor);
|
||||
let didCollide = false;
|
||||
|
||||
// 获取我们在新位置可能发生碰撞的任何东西
|
||||
this.entity.position = Vector2.add(this.entity.position, motion);
|
||||
|
||||
// 获取任何可能在新位置发生碰撞的东西
|
||||
let neighbors = Physics.boxcastBroadphase(this._collider.bounds, this._collider.collidesWithLayers);
|
||||
for (let i = 0; i < neighbors.colliders.length; i ++){
|
||||
let neighbor = neighbors.colliders[i];
|
||||
if (this._collider.overlaps(neighbor) && neighbor.enabled){
|
||||
didCollide = true;
|
||||
this.notifyTriggerListeners(this._collider, neighbor);
|
||||
}
|
||||
}
|
||||
|
||||
return didCollide;
|
||||
}
|
||||
|
||||
return didCollide;
|
||||
private notifyTriggerListeners(self: Collider, other: Collider){
|
||||
// 通知我们重叠的碰撞器实体上的任何侦听器
|
||||
other.entity.getComponents("ITriggerListener", this._tempTriggerList);
|
||||
for (let i = 0; i < this._tempTriggerList.length; i ++){
|
||||
this._tempTriggerList[i].onTriggerEnter(self, other);
|
||||
}
|
||||
this._tempTriggerList.length = 0;
|
||||
|
||||
// 通知此实体上的任何侦听器
|
||||
this.entity.getComponents("ITriggerListener", this._tempTriggerList);
|
||||
for (let i = 0; i < this._tempTriggerList.length; i ++){
|
||||
this._tempTriggerList[i].onTriggerEnter(other, self);
|
||||
}
|
||||
this._tempTriggerList.length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private notifyTriggerListeners(self: Collider, other: Collider){
|
||||
// 通知我们重叠的碰撞器实体上的任何侦听器
|
||||
other.entity.getComponents("ITriggerListener", this._tempTriggerList);
|
||||
for (let i = 0; i < this._tempTriggerList.length; i ++){
|
||||
this._tempTriggerList[i].onTriggerEnter(self, other);
|
||||
}
|
||||
this._tempTriggerList.length = 0;
|
||||
|
||||
// 通知此实体上的任何侦听器
|
||||
this.entity.getComponents("ITriggerListener", this._tempTriggerList);
|
||||
for (let i = 0; i < this._tempTriggerList.length; i ++){
|
||||
this._tempTriggerList[i].onTriggerEnter(other, self);
|
||||
}
|
||||
this._tempTriggerList.length = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user