优化spatialHash与修复ArcadeRigidbody报错

This commit is contained in:
yhh
2020-12-07 14:58:47 +08:00
parent cf492daa93
commit 06b2163aaa
7 changed files with 94 additions and 70 deletions

View File

@@ -760,7 +760,7 @@ declare module es {
_elasticity: number; _elasticity: number;
_friction: number; _friction: number;
_glue: number; _glue: number;
_inverseMass: any; _inverseMass: number;
_collider: Collider; _collider: Collider;
constructor(); constructor();
/** /**
@@ -869,15 +869,15 @@ declare module es {
} }
declare module es { declare module es {
/** /**
* 只向itriggerlistener报告冲突的移动器 * 移动时考虑到碰撞只用于向任何ITriggerListeners报告
* 该对象将始终移动完整的距离 * 物体总是会全量移动,所以如果需要的话,由调用者在撞击时销毁它。
*/ */
class ProjectileMover extends Component { class ProjectileMover extends Component {
private _tempTriggerList; private _tempTriggerList;
private _collider; private _collider;
onAddedToEntity(): void; onAddedToEntity(): void;
/** /**
* 移动考虑碰撞的实体 * 考虑碰撞的情况下移动实体
* @param motion * @param motion
*/ */
move(motion: Vector2): boolean; move(motion: Vector2): boolean;
@@ -2567,7 +2567,7 @@ declare module es {
* 它的主要目的是将int、int x、y坐标散列到单个Uint32键中使用O(1)查找。 * 它的主要目的是将int、int x、y坐标散列到单个Uint32键中使用O(1)查找。
*/ */
class NumberDictionary { class NumberDictionary {
_store: Map<string, Collider[]>; _store: Map<number, Collider[]>;
add(x: number, y: number, list: Collider[]): void; add(x: number, y: number, list: Collider[]): void;
/** /**
* 使用蛮力方法从字典存储列表中移除碰撞器 * 使用蛮力方法从字典存储列表中移除碰撞器
@@ -2575,7 +2575,7 @@ declare module es {
*/ */
remove(obj: Collider): void; remove(obj: Collider): void;
tryGetValue(x: number, y: number): Collider[]; tryGetValue(x: number, y: number): Collider[];
getKey(x: number, y: number): string; getKey(x: number, y: number): number;
/** /**
* 清除字典数据 * 清除字典数据
*/ */

View File

@@ -1604,10 +1604,15 @@ var es;
* 如果为真则每一帧都会考虑到Physics.gravity * 如果为真则每一帧都会考虑到Physics.gravity
*/ */
_this.shouldUseGravity = true; _this.shouldUseGravity = true;
/**
* 该刚体的速度
*/
_this.velocity = new es.Vector2();
_this._mass = 10; _this._mass = 10;
_this._elasticity = 0.5; _this._elasticity = 0.5;
_this._friction = 0.5; _this._friction = 0.5;
_this._glue = 0.01; _this._glue = 0.01;
_this._inverseMass = 0;
_this._inverseMass = 1 / _this._mass; _this._inverseMass = 1 / _this._mass;
return _this; return _this;
} }
@@ -1717,7 +1722,8 @@ var es;
*/ */
ArcadeRigidbody.prototype.addImpulse = function (force) { ArcadeRigidbody.prototype.addImpulse = function (force) {
if (!this.isImmovable) { if (!this.isImmovable) {
this.velocity.add(new es.Vector2(force.x * 100000, force.y * 100000).multiply(new es.Vector2(this._inverseMass * es.Time.deltaTime))); this.velocity = es.Vector2.add(this.velocity, es.Vector2.multiply(force, new es.Vector2(100000))
.multiply(new es.Vector2(this._inverseMass * es.Time.deltaTime)));
} }
}; };
ArcadeRigidbody.prototype.onAddedToEntity = function () { ArcadeRigidbody.prototype.onAddedToEntity = function () {
@@ -1733,8 +1739,8 @@ var es;
return; return;
} }
if (this.shouldUseGravity) if (this.shouldUseGravity)
this.velocity.add(es.Vector2.multiply(es.Physics.gravity, new es.Vector2(es.Time.deltaTime))); this.velocity = es.Vector2.add(this.velocity, es.Vector2.multiply(es.Physics.gravity, new es.Vector2(es.Time.deltaTime)));
this.entity.transform.position.add(es.Vector2.multiply(this.velocity, new es.Vector2(es.Time.deltaTime))); this.entity.transform.position = es.Vector2.add(this.entity.transform.position, es.Vector2.multiply(this.velocity, new es.Vector2(es.Time.deltaTime)));
var collisionResult = new es.CollisionResult(); var collisionResult = new es.CollisionResult();
// 捞取我们在新的位置上可能会碰撞到的任何东西 // 捞取我们在新的位置上可能会碰撞到的任何东西
var neighbors = es.Physics.boxcastBroadphaseExcludingSelfNonRect(this._collider, this._collider.collidesWithLayers.value); var neighbors = es.Physics.boxcastBroadphaseExcludingSelfNonRect(this._collider, this._collider.collidesWithLayers.value);
@@ -1742,7 +1748,7 @@ var es;
for (var neighbors_1 = __values(neighbors), neighbors_1_1 = neighbors_1.next(); !neighbors_1_1.done; neighbors_1_1 = neighbors_1.next()) { for (var neighbors_1 = __values(neighbors), neighbors_1_1 = neighbors_1.next(); !neighbors_1_1.done; neighbors_1_1 = neighbors_1.next()) {
var neighbor = neighbors_1_1.value; var neighbor = neighbors_1_1.value;
// 如果邻近的对撞机是同一个实体,则忽略它 // 如果邻近的对撞机是同一个实体,则忽略它
if (neighbor.entity == this.entity) { if (neighbor.entity.equals(this.entity)) {
continue; continue;
} }
if (this._collider.collidesWithNonMotion(neighbor, collisionResult)) { if (this._collider.collidesWithNonMotion(neighbor, collisionResult)) {
@@ -1754,10 +1760,10 @@ var es;
} }
else { else {
// 没有ArcadeRigidbody所以我们假设它是不动的只移动我们自己的 // 没有ArcadeRigidbody所以我们假设它是不动的只移动我们自己的
this.entity.transform.position.subtract(collisionResult.minimumTranslationVector); this.entity.transform.position = es.Vector2.subtract(this.entity.transform.position, collisionResult.minimumTranslationVector);
var relativeVelocity = this.velocity.clone(); var relativeVelocity = this.velocity.clone();
this.calculateResponseVelocity(relativeVelocity, collisionResult.minimumTranslationVector, relativeVelocity); this.calculateResponseVelocity(relativeVelocity, collisionResult.minimumTranslationVector, relativeVelocity);
this.velocity.add(relativeVelocity); this.velocity = es.Vector2.add(this.velocity, relativeVelocity);
} }
} }
} }
@@ -1777,14 +1783,14 @@ var es;
*/ */
ArcadeRigidbody.prototype.processOverlap = function (other, minimumTranslationVector) { ArcadeRigidbody.prototype.processOverlap = function (other, minimumTranslationVector) {
if (this.isImmovable) { if (this.isImmovable) {
other.entity.transform.position.add(minimumTranslationVector); other.entity.transform.position = es.Vector2.add(other.entity.transform.position, minimumTranslationVector);
} }
else if (other.isImmovable) { else if (other.isImmovable) {
this.entity.transform.position.subtract(minimumTranslationVector); this.entity.transform.position = es.Vector2.subtract(this.entity.transform.position, minimumTranslationVector);
} }
else { else {
this.entity.transform.position.subtract(es.Vector2.multiply(minimumTranslationVector, es.Vector2Ext.halfVector())); this.entity.transform.position = es.Vector2.subtract(this.entity.transform.position, es.Vector2.multiply(minimumTranslationVector, es.Vector2Ext.halfVector()));
other.entity.transform.position.add(es.Vector2.multiply(minimumTranslationVector, es.Vector2Ext.halfVector())); other.entity.transform.position = es.Vector2.add(other.entity.transform.position, es.Vector2.multiply(minimumTranslationVector, es.Vector2Ext.halfVector()));
} }
}; };
/** /**
@@ -1802,8 +1808,8 @@ var es;
var totalinverseMass = this._inverseMass + other._inverseMass; var totalinverseMass = this._inverseMass + other._inverseMass;
var ourResponseFraction = this._inverseMass / totalinverseMass; var ourResponseFraction = this._inverseMass / totalinverseMass;
var otherResponseFraction = other._inverseMass / totalinverseMass; var otherResponseFraction = other._inverseMass / totalinverseMass;
this.velocity.add(es.Vector2.multiply(relativeVelocity, new es.Vector2(ourResponseFraction))); this.velocity = es.Vector2.add(this.velocity, new es.Vector2(relativeVelocity.x * ourResponseFraction, relativeVelocity.y * ourResponseFraction));
other.velocity.subtract(es.Vector2.multiply(relativeVelocity, new es.Vector2(otherResponseFraction))); other.velocity = es.Vector2.subtract(other.velocity, new es.Vector2(relativeVelocity.x * otherResponseFraction, relativeVelocity.y * otherResponseFraction));
}; };
/** /**
* 给定两个物体和MTV之间的相对速度本方法修改相对速度使其成为碰撞响应 * 给定两个物体和MTV之间的相对速度本方法修改相对速度使其成为碰撞响应
@@ -1819,7 +1825,7 @@ var es;
// 速度是沿碰撞法线和碰撞平面分解的。 // 速度是沿碰撞法线和碰撞平面分解的。
// 弹性将影响沿法线的响应(法线速度分量),摩擦力将影响速度的切向分量(切向速度分量) // 弹性将影响沿法线的响应(法线速度分量),摩擦力将影响速度的切向分量(切向速度分量)
var n = es.Vector2.dot(relativeVelocity, normal); var n = es.Vector2.dot(relativeVelocity, normal);
var normalVelocityComponent = es.Vector2.multiply(normal, new es.Vector2(n)); var normalVelocityComponent = new es.Vector2(normal.x * n, normal.y * n);
var tangentialVelocityComponent = es.Vector2.subtract(relativeVelocity, normalVelocityComponent); var tangentialVelocityComponent = es.Vector2.subtract(relativeVelocity, normalVelocityComponent);
if (n > 0) if (n > 0)
normalVelocityComponent = es.Vector2.zero; normalVelocityComponent = es.Vector2.zero;
@@ -1828,7 +1834,11 @@ var es;
if (tangentialVelocityComponent.lengthSquared() < this._glue) if (tangentialVelocityComponent.lengthSquared() < this._glue)
coefficientOfFriction = 1.01; coefficientOfFriction = 1.01;
// 弹性影响速度的法向分量,摩擦力影响速度的切向分量 // 弹性影响速度的法向分量,摩擦力影响速度的切向分量
responseVelocity = es.Vector2.multiply(new es.Vector2(-(1 + this._elasticity)), normalVelocityComponent).subtract(es.Vector2.multiply(new es.Vector2(coefficientOfFriction), tangentialVelocityComponent)); var t = es.Vector2.multiply(new es.Vector2((1 + this._elasticity)), normalVelocityComponent)
.multiply(new es.Vector2(-1))
.subtract(es.Vector2.multiply(new es.Vector2(coefficientOfFriction), tangentialVelocityComponent));
responseVelocity.x = t.x;
relativeVelocity.y = t.y;
}; };
return ArcadeRigidbody; return ArcadeRigidbody;
}(es.Component)); }(es.Component));
@@ -1947,8 +1957,8 @@ var es;
var es; var es;
(function (es) { (function (es) {
/** /**
* 只向itriggerlistener报告冲突的移动器 * 移动时考虑到碰撞只用于向任何ITriggerListeners报告
* 该对象将始终移动完整的距离 * 物体总是会全量移动,所以如果需要的话,由调用者在撞击时销毁它。
*/ */
var ProjectileMover = /** @class */ (function (_super) { var ProjectileMover = /** @class */ (function (_super) {
__extends(ProjectileMover, _super); __extends(ProjectileMover, _super);
@@ -1960,27 +1970,37 @@ var es;
ProjectileMover.prototype.onAddedToEntity = function () { ProjectileMover.prototype.onAddedToEntity = function () {
this._collider = this.entity.getComponent(es.Collider); this._collider = this.entity.getComponent(es.Collider);
if (!this._collider) if (!this._collider)
console.warn("ProjectileMover has no Collider. ProjectilMover requires a Collider!"); console.warn("ProjectileMover没有ColliderProjectilMover需要一个Collider!");
}; };
/** /**
* 移动考虑碰撞的实体 * 考虑碰撞的情况下移动实体
* @param motion * @param motion
*/ */
ProjectileMover.prototype.move = function (motion) { ProjectileMover.prototype.move = function (motion) {
if (!this._collider) var e_2, _a;
if (this._collider == null)
return false; return false;
var didCollide = false; var didCollide = false;
// 获取我们在新位置可能发生碰撞的任何东西 // 获取我们在新位置可能碰撞的任何东西
this.entity.position = es.Vector2.add(this.entity.position, motion); this.entity.position = es.Vector2.add(this.entity.position, motion);
// 获取任何可能在新位置发生碰撞的东西 // 获取任何可能在新位置发生碰撞的东西
var neighbors = es.Physics.boxcastBroadphase(this._collider.bounds, this._collider.collidesWithLayers.value); var neighbors = es.Physics.boxcastBroadphase(this._collider.bounds, this._collider.collidesWithLayers.value);
for (var i = 0; i < neighbors.size; i++) { try {
var neighbor = neighbors[i]; for (var neighbors_2 = __values(neighbors), neighbors_2_1 = neighbors_2.next(); !neighbors_2_1.done; neighbors_2_1 = neighbors_2.next()) {
if (this._collider.overlaps(neighbor) && neighbor.enabled) { var neighbor = neighbors_2_1.value;
didCollide = true; if (this._collider.overlaps(neighbor) && neighbor.enabled) {
this.notifyTriggerListeners(this._collider, neighbor); didCollide = true;
this.notifyTriggerListeners(this._collider, neighbor);
}
} }
} }
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (neighbors_2_1 && !neighbors_2_1.done && (_a = neighbors_2.return)) _a.call(neighbors_2);
}
finally { if (e_2) throw e_2.error; }
}
return didCollide; return didCollide;
}; };
ProjectileMover.prototype.notifyTriggerListeners = function (self, other) { ProjectileMover.prototype.notifyTriggerListeners = function (self, other) {
@@ -3533,19 +3553,19 @@ var es;
* @param array * @param array
*/ */
FastList.prototype.addRange = function (array) { FastList.prototype.addRange = function (array) {
var e_2, _a; var e_3, _a;
try { try {
for (var array_1 = __values(array), array_1_1 = array_1.next(); !array_1_1.done; array_1_1 = array_1.next()) { for (var array_1 = __values(array), array_1_1 = array_1.next(); !array_1_1.done; array_1_1 = array_1.next()) {
var item = array_1_1.value; var item = array_1_1.value;
this.add(item); this.add(item);
} }
} }
catch (e_2_1) { e_2 = { error: e_2_1 }; } catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally { finally {
try { try {
if (array_1_1 && !array_1_1.done && (_a = array_1.return)) _a.call(array_1); if (array_1_1 && !array_1_1.done && (_a = array_1.return)) _a.call(array_1);
} }
finally { if (e_2) throw e_2.error; } finally { if (e_3) throw e_3.error; }
} }
}; };
/** /**
@@ -6025,7 +6045,7 @@ var es;
*/ */
Physics.boxcastBroadphaseExcludingSelfNonRect = function (collider, layerMask) { Physics.boxcastBroadphaseExcludingSelfNonRect = function (collider, layerMask) {
if (layerMask === void 0) { layerMask = this.allLayers; } if (layerMask === void 0) { layerMask = this.allLayers; }
var bounds = collider.bounds; var bounds = collider.bounds.clone();
return this._spatialHash.aabbBroadphase(bounds, collider, layerMask); return this._spatialHash.aabbBroadphase(bounds, collider, layerMask);
}; };
/** /**
@@ -6284,7 +6304,7 @@ var es;
* @param layerMask * @param layerMask
*/ */
SpatialHash.prototype.overlapCircle = function (circleCenter, radius, results, layerMask) { SpatialHash.prototype.overlapCircle = function (circleCenter, radius, results, layerMask) {
var e_3, _a; var e_4, _a;
var bounds = new es.Rectangle(circleCenter.x - radius, circleCenter.y - radius, radius * 2, radius * 2); var bounds = new es.Rectangle(circleCenter.x - radius, circleCenter.y - radius, radius * 2, radius * 2);
this._overlapTestCircle.radius = radius; this._overlapTestCircle.radius = radius;
this._overlapTestCircle.position = circleCenter; this._overlapTestCircle.position = circleCenter;
@@ -6317,12 +6337,12 @@ var es;
return resultCounter; return resultCounter;
} }
} }
catch (e_3_1) { e_3 = { error: e_3_1 }; } catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally { finally {
try { try {
if (potentials_1_1 && !potentials_1_1.done && (_a = potentials_1.return)) _a.call(potentials_1); if (potentials_1_1 && !potentials_1_1.done && (_a = potentials_1.return)) _a.call(potentials_1);
} }
finally { if (e_3) throw e_3.error; } finally { if (e_4) throw e_4.error; }
} }
return resultCounter; return resultCounter;
}; };
@@ -6381,7 +6401,7 @@ var es;
return this._store.get(this.getKey(x, y)); return this._store.get(this.getKey(x, y));
}; };
NumberDictionary.prototype.getKey = function (x, y) { NumberDictionary.prototype.getKey = function (x, y) {
return x + "_" + y; return x << 16 | (y >>> 0);
}; };
/** /**
* 清除字典数据 * 清除字典数据
@@ -9546,7 +9566,7 @@ var linq;
* 创建一个Set从一个Enumerable.List< T>。 * 创建一个Set从一个Enumerable.List< T>。
*/ */
List.prototype.toSet = function () { List.prototype.toSet = function () {
var e_4, _a; var e_5, _a;
var result = new Set(); var result = new Set();
try { try {
for (var _b = __values(this._elements), _c = _b.next(); !_c.done; _c = _b.next()) { for (var _b = __values(this._elements), _c = _b.next(); !_c.done; _c = _b.next()) {
@@ -9554,12 +9574,12 @@ var linq;
result.add(x); result.add(x);
} }
} }
catch (e_4_1) { e_4 = { error: e_4_1 }; } catch (e_5_1) { e_5 = { error: e_5_1 }; }
finally { finally {
try { try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b); if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
} }
finally { if (e_4) throw e_4.error; } finally { if (e_5) throw e_5.error; }
} }
return result; return result;
}; };

File diff suppressed because one or more lines are too long

View File

@@ -54,7 +54,7 @@ module es {
/** /**
* 该刚体的速度 * 该刚体的速度
*/ */
public velocity: Vector2; public velocity: Vector2 = new Vector2();
/** /**
* 质量为0的刚体被认为是不可移动的。改变速度和碰撞对它们没有影响 * 质量为0的刚体被认为是不可移动的。改变速度和碰撞对它们没有影响
@@ -67,7 +67,7 @@ module es {
public _elasticity = 0.5; public _elasticity = 0.5;
public _friction = 0.5; public _friction = 0.5;
public _glue = 0.01; public _glue = 0.01;
public _inverseMass; public _inverseMass: number = 0;
public _collider: Collider; public _collider: Collider;
constructor(){ constructor(){
@@ -122,7 +122,8 @@ module es {
*/ */
public addImpulse(force: Vector2) { public addImpulse(force: Vector2) {
if (!this.isImmovable) { if (!this.isImmovable) {
this.velocity.add(new Vector2(force.x * 100000, force.y * 100000).multiply(new Vector2(this._inverseMass * Time.deltaTime))); this.velocity = Vector2.add(this.velocity, Vector2.multiply(force, new Vector2(100000))
.multiply(new Vector2(this._inverseMass * Time.deltaTime)));
} }
} }
@@ -140,16 +141,16 @@ module es {
} }
if (this.shouldUseGravity) if (this.shouldUseGravity)
this.velocity.add(Vector2.multiply(Physics.gravity, new Vector2(Time.deltaTime))); this.velocity = Vector2.add(this.velocity, Vector2.multiply(Physics.gravity, new Vector2(Time.deltaTime)));
this.entity.transform.position.add(Vector2.multiply(this.velocity, new Vector2(Time.deltaTime))); this.entity.transform.position = Vector2.add(this.entity.transform.position, Vector2.multiply(this.velocity, new Vector2(Time.deltaTime)));
let collisionResult = new CollisionResult(); let collisionResult = new CollisionResult();
// 捞取我们在新的位置上可能会碰撞到的任何东西 // 捞取我们在新的位置上可能会碰撞到的任何东西
let neighbors = Physics.boxcastBroadphaseExcludingSelfNonRect(this._collider, this._collider.collidesWithLayers.value); let neighbors = Physics.boxcastBroadphaseExcludingSelfNonRect(this._collider, this._collider.collidesWithLayers.value);
for (let neighbor of neighbors) { for (let neighbor of neighbors) {
// 如果邻近的对撞机是同一个实体,则忽略它 // 如果邻近的对撞机是同一个实体,则忽略它
if (neighbor.entity == this.entity) { if (neighbor.entity.equals(this.entity)) {
continue; continue;
} }
@@ -161,10 +162,10 @@ module es {
this.processCollision(neighborRigidbody, collisionResult.minimumTranslationVector); this.processCollision(neighborRigidbody, collisionResult.minimumTranslationVector);
} else { } else {
// 没有ArcadeRigidbody所以我们假设它是不动的只移动我们自己的 // 没有ArcadeRigidbody所以我们假设它是不动的只移动我们自己的
this.entity.transform.position.subtract(collisionResult.minimumTranslationVector); this.entity.transform.position = Vector2.subtract(this.entity.transform.position, collisionResult.minimumTranslationVector);
let relativeVelocity = this.velocity.clone(); let relativeVelocity = this.velocity.clone();
this.calculateResponseVelocity(relativeVelocity, collisionResult.minimumTranslationVector, relativeVelocity); this.calculateResponseVelocity(relativeVelocity, collisionResult.minimumTranslationVector, relativeVelocity);
this.velocity.add(relativeVelocity); this.velocity = Vector2.add(this.velocity, relativeVelocity);
} }
} }
} }
@@ -177,12 +178,12 @@ module es {
*/ */
public processOverlap(other: ArcadeRigidbody, minimumTranslationVector: Vector2) { public processOverlap(other: ArcadeRigidbody, minimumTranslationVector: Vector2) {
if (this.isImmovable) { if (this.isImmovable) {
other.entity.transform.position.add(minimumTranslationVector); other.entity.transform.position = Vector2.add(other.entity.transform.position, minimumTranslationVector);
}else if(other.isImmovable) { }else if(other.isImmovable) {
this.entity.transform.position.subtract(minimumTranslationVector); this.entity.transform.position = Vector2.subtract(this.entity.transform.position, minimumTranslationVector);
} else { } else {
this.entity.transform.position.subtract(Vector2.multiply(minimumTranslationVector, Vector2Ext.halfVector())); this.entity.transform.position = Vector2.subtract(this.entity.transform.position, Vector2.multiply(minimumTranslationVector, Vector2Ext.halfVector()));
other.entity.transform.position.add(Vector2.multiply(minimumTranslationVector, Vector2Ext.halfVector())); other.entity.transform.position = Vector2.add(other.entity.transform.position, Vector2.multiply(minimumTranslationVector, Vector2Ext.halfVector()));
} }
} }
@@ -204,8 +205,8 @@ module es {
let ourResponseFraction = this._inverseMass / totalinverseMass; let ourResponseFraction = this._inverseMass / totalinverseMass;
let otherResponseFraction = other._inverseMass / totalinverseMass; let otherResponseFraction = other._inverseMass / totalinverseMass;
this.velocity.add(Vector2.multiply(relativeVelocity, new Vector2(ourResponseFraction))); this.velocity = Vector2.add(this.velocity, new Vector2(relativeVelocity.x * ourResponseFraction, relativeVelocity.y * ourResponseFraction));
other.velocity.subtract(Vector2.multiply(relativeVelocity, new Vector2(otherResponseFraction))); other.velocity = Vector2.subtract(other.velocity, new Vector2(relativeVelocity.x * otherResponseFraction, relativeVelocity.y * otherResponseFraction));
} }
/** /**
@@ -223,7 +224,7 @@ module es {
// 弹性将影响沿法线的响应(法线速度分量),摩擦力将影响速度的切向分量(切向速度分量) // 弹性将影响沿法线的响应(法线速度分量),摩擦力将影响速度的切向分量(切向速度分量)
let n = Vector2.dot(relativeVelocity, normal); let n = Vector2.dot(relativeVelocity, normal);
let normalVelocityComponent = Vector2.multiply(normal, new Vector2(n)); let normalVelocityComponent = new Vector2(normal.x * n, normal.y * n);
let tangentialVelocityComponent = Vector2.subtract(relativeVelocity, normalVelocityComponent); let tangentialVelocityComponent = Vector2.subtract(relativeVelocity, normalVelocityComponent);
if (n > 0) if (n > 0)
@@ -235,7 +236,11 @@ module es {
coefficientOfFriction = 1.01; coefficientOfFriction = 1.01;
// 弹性影响速度的法向分量,摩擦力影响速度的切向分量 // 弹性影响速度的法向分量,摩擦力影响速度的切向分量
responseVelocity = Vector2.multiply(new Vector2(-(1 + this._elasticity)), normalVelocityComponent).subtract(Vector2.multiply(new Vector2(coefficientOfFriction), tangentialVelocityComponent)); let t = Vector2.multiply(new Vector2((1 + this._elasticity)), normalVelocityComponent)
.multiply(new Vector2(-1))
.subtract(Vector2.multiply(new Vector2(coefficientOfFriction), tangentialVelocityComponent));
responseVelocity.x = t.x;
relativeVelocity.y = t.y;
} }
} }
} }

View File

@@ -1,7 +1,7 @@
module es { module es {
/** /**
* 只向itriggerlistener报告冲突的移动器 * 移动时考虑到碰撞只用于向任何ITriggerListeners报告
* 该对象将始终移动完整的距离 * 物体总是会全量移动,所以如果需要的话,由调用者在撞击时销毁它。
*/ */
export class ProjectileMover extends Component { export class ProjectileMover extends Component {
private _tempTriggerList: ITriggerListener[] = []; private _tempTriggerList: ITriggerListener[] = [];
@@ -10,26 +10,25 @@ module es {
public onAddedToEntity() { public onAddedToEntity() {
this._collider = this.entity.getComponent<Collider>(Collider); this._collider = this.entity.getComponent<Collider>(Collider);
if (!this._collider) if (!this._collider)
console.warn("ProjectileMover has no Collider. ProjectilMover requires a Collider!"); console.warn("ProjectileMover没有ColliderProjectilMover需要一个Collider!");
} }
/** /**
* 移动考虑碰撞的实体 * 考虑碰撞的情况下移动实体
* @param motion * @param motion
*/ */
public move(motion: Vector2): boolean { public move(motion: Vector2): boolean {
if (!this._collider) if (this._collider == null)
return false; return false;
let didCollide = false; let didCollide = false;
// 获取我们在新位置可能发生碰撞的任何东西 // 获取我们在新位置可能碰撞的任何东西
this.entity.position = Vector2.add(this.entity.position, motion); this.entity.position = Vector2.add(this.entity.position, motion);
// 获取任何可能在新位置发生碰撞的东西 // 获取任何可能在新位置发生碰撞的东西
let neighbors = Physics.boxcastBroadphase(this._collider.bounds, this._collider.collidesWithLayers.value); let neighbors = Physics.boxcastBroadphase(this._collider.bounds, this._collider.collidesWithLayers.value);
for (let i = 0; i < neighbors.size; i ++){ for (let neighbor of neighbors){
let neighbor = neighbors[i];
if (this._collider.overlaps(neighbor) && neighbor.enabled){ if (this._collider.overlaps(neighbor) && neighbor.enabled){
didCollide = true; didCollide = true;
this.notifyTriggerListeners(this._collider, neighbor); this.notifyTriggerListeners(this._collider, neighbor);

View File

@@ -76,7 +76,7 @@ module es {
* @param layerMask * @param layerMask
*/ */
public static boxcastBroadphaseExcludingSelfNonRect(collider: Collider, layerMask = this.allLayers) { public static boxcastBroadphaseExcludingSelfNonRect(collider: Collider, layerMask = this.allLayers) {
let bounds = collider.bounds; let bounds = collider.bounds.clone();
return this._spatialHash.aabbBroadphase(bounds, collider, layerMask); return this._spatialHash.aabbBroadphase(bounds, collider, layerMask);
} }

View File

@@ -268,7 +268,7 @@ module es {
* 它的主要目的是将int、int x、y坐标散列到单个Uint32键中使用O(1)查找。 * 它的主要目的是将int、int x、y坐标散列到单个Uint32键中使用O(1)查找。
*/ */
export class NumberDictionary { export class NumberDictionary {
public _store: Map<string, Collider[]> = new Map<string, Collider[]>(); public _store: Map<number, Collider[]> = new Map<number, Collider[]>();
public add(x: number, y: number, list: Collider[]) { public add(x: number, y: number, list: Collider[]) {
this._store.set(this.getKey(x, y), list); this._store.set(this.getKey(x, y), list);
@@ -291,7 +291,7 @@ module es {
} }
public getKey(x: number, y: number){ public getKey(x: number, y: number){
return `${x}_${y}`; return x << 16 | (y >>> 0);
} }
/** /**