移除物理引擎 移动到新库
This commit is contained in:
135
demo/libs/framework/framework.d.ts
vendored
135
demo/libs/framework/framework.d.ts
vendored
@@ -380,7 +380,16 @@ declare abstract class Collider extends Component {
|
|||||||
shape: Shape;
|
shape: Shape;
|
||||||
physicsLayer: number;
|
physicsLayer: number;
|
||||||
isTrigger: boolean;
|
isTrigger: boolean;
|
||||||
|
registeredPhysicsBounds: Rectangle;
|
||||||
|
protected _isParentEntityAddedToScene: any;
|
||||||
|
protected _isPositionDirty: boolean;
|
||||||
|
protected _colliderRequiresAutoSizing: any;
|
||||||
readonly bounds: Rectangle;
|
readonly bounds: Rectangle;
|
||||||
|
initialize(): void;
|
||||||
|
}
|
||||||
|
declare class BoxCollider extends Collider {
|
||||||
|
width: number;
|
||||||
|
setWidth(width: number): BoxCollider;
|
||||||
}
|
}
|
||||||
declare class EntitySystem {
|
declare class EntitySystem {
|
||||||
private _scene;
|
private _scene;
|
||||||
@@ -513,6 +522,7 @@ declare class MathHelper {
|
|||||||
static toDegrees(radians: number): number;
|
static toDegrees(radians: number): number;
|
||||||
static toRadians(degrees: number): number;
|
static toRadians(degrees: number): number;
|
||||||
static map(value: number, leftMin: number, leftMax: number, rightMin: number, rightMax: number): number;
|
static map(value: number, leftMin: number, leftMax: number, rightMin: number, rightMax: number): number;
|
||||||
|
static lerp(value1: number, value2: number, amount: number): number;
|
||||||
static clamp(value: number, min: number, max: number): number;
|
static clamp(value: number, min: number, max: number): number;
|
||||||
static minOf(a: number, b: number, c: number, d: number): number;
|
static minOf(a: number, b: number, c: number, d: number): number;
|
||||||
static maxOf(a: number, b: number, c: number, d: number): number;
|
static maxOf(a: number, b: number, c: number, d: number): number;
|
||||||
@@ -553,7 +563,7 @@ declare class Rectangle {
|
|||||||
readonly top: number;
|
readonly top: number;
|
||||||
readonly bottom: number;
|
readonly bottom: number;
|
||||||
location: Vector2;
|
location: Vector2;
|
||||||
constructor(x: number, y: number, width: number, height: number);
|
constructor(x?: number, y?: number, width?: number, height?: number);
|
||||||
intersects(value: Rectangle): boolean;
|
intersects(value: Rectangle): boolean;
|
||||||
contains(value: Vector2): boolean;
|
contains(value: Vector2): boolean;
|
||||||
static fromMinMax(minX: number, minY: number, maxX: number, maxY: number): Rectangle;
|
static fromMinMax(minX: number, minY: number, maxX: number, maxY: number): Rectangle;
|
||||||
@@ -566,7 +576,7 @@ declare class Rectangle {
|
|||||||
declare class Vector2 {
|
declare class Vector2 {
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
constructor(x: number, y: number);
|
constructor(x: number, y?: number);
|
||||||
static add(value1: Vector2, value2: Vector2): Vector2;
|
static add(value1: Vector2, value2: Vector2): Vector2;
|
||||||
static divide(value1: Vector2, value2: Vector2): Vector2;
|
static divide(value1: Vector2, value2: Vector2): Vector2;
|
||||||
static multiply(value1: Vector2, value2: Vector2): Vector2;
|
static multiply(value1: Vector2, value2: Vector2): Vector2;
|
||||||
@@ -576,6 +586,7 @@ declare class Vector2 {
|
|||||||
static normalize(value: Vector2): Vector2;
|
static normalize(value: Vector2): Vector2;
|
||||||
static dot(value1: Vector2, value2: Vector2): number;
|
static dot(value1: Vector2, value2: Vector2): number;
|
||||||
static distanceSquared(value1: Vector2, value2: Vector2): number;
|
static distanceSquared(value1: Vector2, value2: Vector2): number;
|
||||||
|
static lerp(value1: Vector2, value2: Vector2, amount: number): Vector2;
|
||||||
static transform(position: Vector2, matrix: Matrix2D): Vector2;
|
static transform(position: Vector2, matrix: Matrix2D): Vector2;
|
||||||
static distance(value1: Vector2, value2: Vector2): number;
|
static distance(value1: Vector2, value2: Vector2): number;
|
||||||
}
|
}
|
||||||
@@ -606,12 +617,44 @@ declare class Physics {
|
|||||||
private static _spatialHash;
|
private static _spatialHash;
|
||||||
static readonly allLayers: number;
|
static readonly allLayers: number;
|
||||||
static overlapCircleAll(center: Vector2, randius: number, results: any[], layerMask?: number): number;
|
static overlapCircleAll(center: Vector2, randius: number, results: any[], layerMask?: number): number;
|
||||||
|
static boxcastBroadphase(rect: Rectangle, layerMask?: number): Collider[];
|
||||||
|
static updateCollider(collider: Collider): void;
|
||||||
}
|
}
|
||||||
declare abstract class Shape {
|
declare abstract class Shape {
|
||||||
bounds: Rectangle;
|
bounds: Rectangle;
|
||||||
position: Vector2;
|
position: Vector2;
|
||||||
abstract pointCollidesWithShape(point: Vector2): CollisionResult;
|
abstract pointCollidesWithShape(point: Vector2): CollisionResult;
|
||||||
}
|
}
|
||||||
|
declare class Polygon extends Shape {
|
||||||
|
points: Vector2[];
|
||||||
|
isUnrotated: boolean;
|
||||||
|
private _polygonCenter;
|
||||||
|
private _areEdgeNormalsDirty;
|
||||||
|
protected _originalPoints: Vector2[];
|
||||||
|
_edgeNormals: Vector2[];
|
||||||
|
readonly edgeNormals: Vector2[];
|
||||||
|
isBox: boolean;
|
||||||
|
constructor(vertCount: number, radius: number);
|
||||||
|
private buildEdgeNormals;
|
||||||
|
setPoints(points: Vector2[]): void;
|
||||||
|
collidesWithShape(other: Shape): void;
|
||||||
|
recalculateCenterAndEdgeNormals(): void;
|
||||||
|
static findPolygonCenter(points: Vector2[]): Vector2;
|
||||||
|
static getClosestPointOnPolygonToPoint(points: Vector2[], point: Vector2): {
|
||||||
|
closestPoint: any;
|
||||||
|
distanceSquared: any;
|
||||||
|
edgeNormal: any;
|
||||||
|
};
|
||||||
|
pointCollidesWithShape(point: Vector2): CollisionResult;
|
||||||
|
containsPoint(point: Vector2): boolean;
|
||||||
|
static buildSymmertricalPolygon(vertCount: number, radius: number): any;
|
||||||
|
}
|
||||||
|
declare class Box extends Polygon {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
updateBox(width: number, height: number): void;
|
||||||
|
containsPoint(point: Vector2): boolean;
|
||||||
|
}
|
||||||
declare class Circle extends Shape {
|
declare class Circle extends Shape {
|
||||||
radius: number;
|
radius: number;
|
||||||
private _originalRadius;
|
private _originalRadius;
|
||||||
@@ -624,30 +667,10 @@ declare class CollisionResult {
|
|||||||
normal: Vector2;
|
normal: Vector2;
|
||||||
point: Vector2;
|
point: Vector2;
|
||||||
}
|
}
|
||||||
declare class Polygon extends Shape {
|
|
||||||
points: Vector2[];
|
|
||||||
isUnrotated: boolean;
|
|
||||||
private _polygonCenter;
|
|
||||||
private _areEdgeNormalsDirty;
|
|
||||||
private _originalPoint;
|
|
||||||
constructor(vertCount: number, radius: number);
|
|
||||||
setPoints(points: Vector2[]): void;
|
|
||||||
recalculateCenterAndEdgeNormals(): void;
|
|
||||||
static findPolygonCenter(points: Vector2[]): Vector2;
|
|
||||||
static getClosestPointOnPolygonToPoint(points: Vector2[], point: Vector2): {
|
|
||||||
closestPoint: any;
|
|
||||||
distanceSquared: any;
|
|
||||||
edgeNormal: any;
|
|
||||||
};
|
|
||||||
pointCollidesWithShape(point: Vector2): CollisionResult;
|
|
||||||
containsPoint(point: Vector2): boolean;
|
|
||||||
static buildSymmertricalPolygon(vertCount: number, radius: number): any;
|
|
||||||
}
|
|
||||||
declare class Rect extends Polygon {
|
|
||||||
containsPoint(point: Vector2): boolean;
|
|
||||||
}
|
|
||||||
declare class ShapeCollisions {
|
declare class ShapeCollisions {
|
||||||
static circleToRect(circle: Circle, box: Rect): CollisionResult;
|
static polygonToPolygon(first: Polygon, second: Polygon): void;
|
||||||
|
static circleToPolygon(circle: Circle, polygon: Polygon): CollisionResult;
|
||||||
|
static circleToRect(circle: Circle, box: Box): CollisionResult;
|
||||||
static pointToCicle(point: Vector2, circle: Circle): CollisionResult;
|
static pointToCicle(point: Vector2, circle: Circle): CollisionResult;
|
||||||
static closestPointOnLine(lineA: Vector2, lineB: Vector2, closestTo: Vector2): Vector2;
|
static closestPointOnLine(lineA: Vector2, lineB: Vector2, closestTo: Vector2): Vector2;
|
||||||
static pointToPoly(point: Vector2, poly: Polygon): CollisionResult;
|
static pointToPoly(point: Vector2, poly: Polygon): CollisionResult;
|
||||||
@@ -665,6 +688,7 @@ declare class Particle {
|
|||||||
applyForce(force: Vector2): void;
|
applyForce(force: Vector2): void;
|
||||||
}
|
}
|
||||||
declare class SpatialHash {
|
declare class SpatialHash {
|
||||||
|
gridBounds: Rectangle;
|
||||||
private _raycastParser;
|
private _raycastParser;
|
||||||
private _cellSize;
|
private _cellSize;
|
||||||
private _inverseCellSize;
|
private _inverseCellSize;
|
||||||
@@ -672,6 +696,8 @@ declare class SpatialHash {
|
|||||||
private _tempHashSet;
|
private _tempHashSet;
|
||||||
private _cellDict;
|
private _cellDict;
|
||||||
constructor(cellSize?: number);
|
constructor(cellSize?: number);
|
||||||
|
remove(collider: Collider): void;
|
||||||
|
register(collider: Collider): void;
|
||||||
overlapCircle(circleCenter: Vector2, radius: number, results: Collider[], layerMask: any): number;
|
overlapCircle(circleCenter: Vector2, radius: number, results: Collider[], layerMask: any): number;
|
||||||
aabbBroadphase(bounds: Rectangle, excludeCollider: Collider, layerMask: number): Collider[];
|
aabbBroadphase(bounds: Rectangle, excludeCollider: Collider, layerMask: number): Collider[];
|
||||||
private cellAtPosition;
|
private cellAtPosition;
|
||||||
@@ -688,64 +714,6 @@ declare class NumberDictionary {
|
|||||||
getAllObjects(): Collider[];
|
getAllObjects(): Collider[];
|
||||||
clear(): void;
|
clear(): void;
|
||||||
}
|
}
|
||||||
declare class VerletWorld {
|
|
||||||
gravity: Vector2;
|
|
||||||
maximumStepIterations: number;
|
|
||||||
constraintIterations: number;
|
|
||||||
simulationBounds: Rectangle;
|
|
||||||
private _leftOverTime;
|
|
||||||
private _iterationSteps;
|
|
||||||
private _fixedDeltaTime;
|
|
||||||
private _composites;
|
|
||||||
private _fixedDeltaTimeSq;
|
|
||||||
private static _colliders;
|
|
||||||
private _tempCircle;
|
|
||||||
constructor(simulationBounds?: Rectangle);
|
|
||||||
update(): void;
|
|
||||||
private handleCollisions;
|
|
||||||
private constrainParticleToBounds;
|
|
||||||
debugRender(displayObject: egret.DisplayObject): void;
|
|
||||||
addComposite<T extends Composite>(composite: T): T;
|
|
||||||
private updateTiming;
|
|
||||||
}
|
|
||||||
declare class Composite {
|
|
||||||
private _constraints;
|
|
||||||
friction: Vector2;
|
|
||||||
drawParticles: boolean;
|
|
||||||
drawConstraints: boolean;
|
|
||||||
particles: Particle[];
|
|
||||||
collidesWithLayers: number;
|
|
||||||
solveConstraints(): void;
|
|
||||||
addParticle(particle: Particle): Particle;
|
|
||||||
addConstraint<T extends Constraint>(constraint: T): T;
|
|
||||||
removeConstraint(constraint: Constraint): void;
|
|
||||||
updateParticles(deltaTimeSquared: number, gravity: Vector2): void;
|
|
||||||
handleConstraintCollisions(): void;
|
|
||||||
debugRender(graphics: egret.Graphics): void;
|
|
||||||
}
|
|
||||||
declare class Box extends Composite {
|
|
||||||
constructor(center: Vector2, width: number, height: number, borderStiffness?: number, diagonalStiffness?: number);
|
|
||||||
}
|
|
||||||
declare abstract class Constraint {
|
|
||||||
composite: Composite;
|
|
||||||
collidesWithColliders: boolean;
|
|
||||||
abstract solve(): any;
|
|
||||||
handleCollisions(collidesWithLayers: number): void;
|
|
||||||
debugRender(graphics: egret.Graphics): void;
|
|
||||||
}
|
|
||||||
declare class DistanceConstraint extends Constraint {
|
|
||||||
stiffness: number;
|
|
||||||
restingDistance: number;
|
|
||||||
tearSensitivity: number;
|
|
||||||
private _particleOne;
|
|
||||||
private _particleTwo;
|
|
||||||
private static _polygon;
|
|
||||||
constructor(first: Particle, second: Particle, stiffness: number, distance?: number);
|
|
||||||
setCollidesWithColliders(collidesWithColliders: boolean): this;
|
|
||||||
handleCollisions(collidersWithLayers: any): void;
|
|
||||||
solve(): void;
|
|
||||||
debugRender(graphics: egret.Graphics): void;
|
|
||||||
}
|
|
||||||
declare class Triangulator {
|
declare class Triangulator {
|
||||||
triangleIndices: number[];
|
triangleIndices: number[];
|
||||||
private _triPrev;
|
private _triPrev;
|
||||||
@@ -757,6 +725,7 @@ declare class Triangulator {
|
|||||||
declare class Vector2Ext {
|
declare class Vector2Ext {
|
||||||
static isTriangleCCW(a: Vector2, center: Vector2, c: Vector2): boolean;
|
static isTriangleCCW(a: Vector2, center: Vector2, c: Vector2): boolean;
|
||||||
static cross(u: Vector2, v: Vector2): number;
|
static cross(u: Vector2, v: Vector2): number;
|
||||||
|
static perpendicular(first: Vector2, second: Vector2): Vector2;
|
||||||
}
|
}
|
||||||
declare class WebGLUtils {
|
declare class WebGLUtils {
|
||||||
static getWebGL(): WebGLRenderingContext;
|
static getWebGL(): WebGLRenderingContext;
|
||||||
|
|||||||
@@ -1786,6 +1786,7 @@ var Collider = (function (_super) {
|
|||||||
function Collider() {
|
function Collider() {
|
||||||
var _this = _super !== null && _super.apply(this, arguments) || this;
|
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||||
_this.physicsLayer = 1 << 0;
|
_this.physicsLayer = 1 << 0;
|
||||||
|
_this._isPositionDirty = true;
|
||||||
return _this;
|
return _this;
|
||||||
}
|
}
|
||||||
Object.defineProperty(Collider.prototype, "bounds", {
|
Object.defineProperty(Collider.prototype, "bounds", {
|
||||||
@@ -1795,8 +1796,38 @@ var Collider = (function (_super) {
|
|||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true
|
configurable: true
|
||||||
});
|
});
|
||||||
|
Collider.prototype.initialize = function () {
|
||||||
|
};
|
||||||
return Collider;
|
return Collider;
|
||||||
}(Component));
|
}(Component));
|
||||||
|
var BoxCollider = (function (_super) {
|
||||||
|
__extends(BoxCollider, _super);
|
||||||
|
function BoxCollider() {
|
||||||
|
return _super !== null && _super.apply(this, arguments) || this;
|
||||||
|
}
|
||||||
|
Object.defineProperty(BoxCollider.prototype, "width", {
|
||||||
|
get: function () {
|
||||||
|
return this.shape.width;
|
||||||
|
},
|
||||||
|
set: function (value) {
|
||||||
|
this.setWidth(value);
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
BoxCollider.prototype.setWidth = function (width) {
|
||||||
|
this._colliderRequiresAutoSizing = false;
|
||||||
|
var box = this.shape;
|
||||||
|
if (width != box.width) {
|
||||||
|
box.updateBox(width, box.height);
|
||||||
|
this._isPositionDirty = true;
|
||||||
|
if (this.entity && this._isParentEntityAddedToScene)
|
||||||
|
Physics.updateCollider(this);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
return BoxCollider;
|
||||||
|
}(Collider));
|
||||||
var EntitySystem = (function () {
|
var EntitySystem = (function () {
|
||||||
function EntitySystem(matcher) {
|
function EntitySystem(matcher) {
|
||||||
this._entities = [];
|
this._entities = [];
|
||||||
@@ -2373,6 +2404,9 @@ var MathHelper = (function () {
|
|||||||
MathHelper.map = function (value, leftMin, leftMax, rightMin, rightMax) {
|
MathHelper.map = function (value, leftMin, leftMax, rightMin, rightMax) {
|
||||||
return rightMin + (value - leftMin) * (rightMax - rightMin) / (leftMax - leftMin);
|
return rightMin + (value - leftMin) * (rightMax - rightMin) / (leftMax - leftMin);
|
||||||
};
|
};
|
||||||
|
MathHelper.lerp = function (value1, value2, amount) {
|
||||||
|
return value1 + (value2 - value1) * amount;
|
||||||
|
};
|
||||||
MathHelper.clamp = function (value, min, max) {
|
MathHelper.clamp = function (value, min, max) {
|
||||||
if (value < min)
|
if (value < min)
|
||||||
return min;
|
return min;
|
||||||
@@ -2543,10 +2577,10 @@ var Matrix2D = (function () {
|
|||||||
}());
|
}());
|
||||||
var Rectangle = (function () {
|
var Rectangle = (function () {
|
||||||
function Rectangle(x, y, width, height) {
|
function Rectangle(x, y, width, height) {
|
||||||
this.x = x;
|
this.x = x ? x : 0;
|
||||||
this.y = y;
|
this.y = y ? y : 0;
|
||||||
this.width = width;
|
this.width = width ? width : 0;
|
||||||
this.height = height;
|
this.height = height ? height : 0;
|
||||||
}
|
}
|
||||||
Object.defineProperty(Rectangle.prototype, "left", {
|
Object.defineProperty(Rectangle.prototype, "left", {
|
||||||
get: function () {
|
get: function () {
|
||||||
@@ -2686,7 +2720,7 @@ var Vector2 = (function () {
|
|||||||
this.x = 0;
|
this.x = 0;
|
||||||
this.y = 0;
|
this.y = 0;
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y ? y : x;
|
||||||
}
|
}
|
||||||
Vector2.add = function (value1, value2) {
|
Vector2.add = function (value1, value2) {
|
||||||
var result = new Vector2(0, 0);
|
var result = new Vector2(0, 0);
|
||||||
@@ -2733,6 +2767,9 @@ var Vector2 = (function () {
|
|||||||
var v1 = value1.x - value2.x, v2 = value1.y - value2.y;
|
var v1 = value1.x - value2.x, v2 = value1.y - value2.y;
|
||||||
return (v1 * v1) + (v2 * v2);
|
return (v1 * v1) + (v2 * v2);
|
||||||
};
|
};
|
||||||
|
Vector2.lerp = function (value1, value2, amount) {
|
||||||
|
return new Vector2(MathHelper.lerp(value1.x, value2.x, amount), MathHelper.lerp(value1.y, value2.y, amount));
|
||||||
|
};
|
||||||
Vector2.transform = function (position, matrix) {
|
Vector2.transform = function (position, matrix) {
|
||||||
return new Vector2((position.x * matrix.m11) + (position.y * matrix.m21), (position.x * matrix.m12) + (position.y * matrix.m22));
|
return new Vector2((position.x * matrix.m11) + (position.y * matrix.m21), (position.x * matrix.m12) + (position.y * matrix.m22));
|
||||||
};
|
};
|
||||||
@@ -2876,6 +2913,14 @@ var Physics = (function () {
|
|||||||
if (layerMask === void 0) { layerMask = -1; }
|
if (layerMask === void 0) { layerMask = -1; }
|
||||||
return this._spatialHash.overlapCircle(center, randius, results, layerMask);
|
return this._spatialHash.overlapCircle(center, randius, results, layerMask);
|
||||||
};
|
};
|
||||||
|
Physics.boxcastBroadphase = function (rect, layerMask) {
|
||||||
|
if (layerMask === void 0) { layerMask = this.allLayers; }
|
||||||
|
return this._spatialHash.aabbBroadphase(rect, null, layerMask);
|
||||||
|
};
|
||||||
|
Physics.updateCollider = function (collider) {
|
||||||
|
this._spatialHash.remove(collider);
|
||||||
|
this._spatialHash.register(collider);
|
||||||
|
};
|
||||||
Physics.allLayers = -1;
|
Physics.allLayers = -1;
|
||||||
return Physics;
|
return Physics;
|
||||||
}());
|
}());
|
||||||
@@ -2884,30 +2929,6 @@ var Shape = (function () {
|
|||||||
}
|
}
|
||||||
return Shape;
|
return Shape;
|
||||||
}());
|
}());
|
||||||
var Circle = (function (_super) {
|
|
||||||
__extends(Circle, _super);
|
|
||||||
function Circle(radius) {
|
|
||||||
var _this = _super.call(this) || this;
|
|
||||||
_this.radius = radius;
|
|
||||||
_this._originalRadius = radius;
|
|
||||||
return _this;
|
|
||||||
}
|
|
||||||
Circle.prototype.pointCollidesWithShape = function (point) {
|
|
||||||
return ShapeCollisions.pointToCicle(point, this);
|
|
||||||
};
|
|
||||||
Circle.prototype.collidesWithShape = function (other) {
|
|
||||||
if (other instanceof Rect && other.isUnrotated) {
|
|
||||||
return ShapeCollisions.circleToRect(this, other);
|
|
||||||
}
|
|
||||||
throw new Error("Collisions of Circle to " + other + " are not supported");
|
|
||||||
};
|
|
||||||
return Circle;
|
|
||||||
}(Shape));
|
|
||||||
var CollisionResult = (function () {
|
|
||||||
function CollisionResult() {
|
|
||||||
}
|
|
||||||
return CollisionResult;
|
|
||||||
}());
|
|
||||||
var Polygon = (function (_super) {
|
var Polygon = (function (_super) {
|
||||||
__extends(Polygon, _super);
|
__extends(Polygon, _super);
|
||||||
function Polygon(vertCount, radius) {
|
function Polygon(vertCount, radius) {
|
||||||
@@ -2917,11 +2938,40 @@ var Polygon = (function (_super) {
|
|||||||
_this.setPoints(Polygon.buildSymmertricalPolygon(vertCount, radius));
|
_this.setPoints(Polygon.buildSymmertricalPolygon(vertCount, radius));
|
||||||
return _this;
|
return _this;
|
||||||
}
|
}
|
||||||
|
Object.defineProperty(Polygon.prototype, "edgeNormals", {
|
||||||
|
get: function () {
|
||||||
|
if (this._areEdgeNormalsDirty)
|
||||||
|
this.buildEdgeNormals();
|
||||||
|
return this._edgeNormals;
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
Polygon.prototype.buildEdgeNormals = function () {
|
||||||
|
var totalEdges = this.isBox ? 2 : this.points.length;
|
||||||
|
if (this._edgeNormals == null || this._edgeNormals.length != totalEdges)
|
||||||
|
this._edgeNormals = new Vector2[totalEdges];
|
||||||
|
var p2;
|
||||||
|
for (var i = 0; i < totalEdges; i++) {
|
||||||
|
var p1 = this.points[i];
|
||||||
|
if (i + 1 >= this.points.length)
|
||||||
|
p2 = this.points[0];
|
||||||
|
else
|
||||||
|
p2 = this.points[i + 1];
|
||||||
|
var perp = Vector2Ext.perpendicular(p1, p2);
|
||||||
|
perp = Vector2.normalize(perp);
|
||||||
|
this._edgeNormals[i] = perp;
|
||||||
|
}
|
||||||
|
};
|
||||||
Polygon.prototype.setPoints = function (points) {
|
Polygon.prototype.setPoints = function (points) {
|
||||||
this.points = points;
|
this.points = points;
|
||||||
this.recalculateCenterAndEdgeNormals();
|
this.recalculateCenterAndEdgeNormals();
|
||||||
this._originalPoint = new Vector2[points.length];
|
this._originalPoints = new Vector2[points.length];
|
||||||
this._originalPoint = points;
|
this._originalPoints = points;
|
||||||
|
};
|
||||||
|
Polygon.prototype.collidesWithShape = function (other) {
|
||||||
|
if (other instanceof Polygon)
|
||||||
|
return ShapeCollisions.polygonToPolygon(this, other);
|
||||||
};
|
};
|
||||||
Polygon.prototype.recalculateCenterAndEdgeNormals = function () {
|
Polygon.prototype.recalculateCenterAndEdgeNormals = function () {
|
||||||
this._polygonCenter = Polygon.findPolygonCenter(this.points);
|
this._polygonCenter = Polygon.findPolygonCenter(this.points);
|
||||||
@@ -2982,21 +3032,84 @@ var Polygon = (function (_super) {
|
|||||||
};
|
};
|
||||||
return Polygon;
|
return Polygon;
|
||||||
}(Shape));
|
}(Shape));
|
||||||
var Rect = (function (_super) {
|
var Box = (function (_super) {
|
||||||
__extends(Rect, _super);
|
__extends(Box, _super);
|
||||||
function Rect() {
|
function Box() {
|
||||||
return _super !== null && _super.apply(this, arguments) || this;
|
return _super !== null && _super.apply(this, arguments) || this;
|
||||||
}
|
}
|
||||||
Rect.prototype.containsPoint = function (point) {
|
Box.prototype.updateBox = function (width, height) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
var halfWidth = width / 2;
|
||||||
|
var halfHeight = height / 2;
|
||||||
|
this.points[0] = new Vector2(-halfWidth, -halfHeight);
|
||||||
|
this.points[1] = new Vector2(halfWidth, -halfHeight);
|
||||||
|
this.points[2] = new Vector2(halfWidth, halfHeight);
|
||||||
|
this.points[3] = new Vector2(-halfWidth, halfHeight);
|
||||||
|
for (var i = 0; i < this.points.length; i++)
|
||||||
|
this._originalPoints[i] = this.points[i];
|
||||||
|
};
|
||||||
|
Box.prototype.containsPoint = function (point) {
|
||||||
if (this.isUnrotated)
|
if (this.isUnrotated)
|
||||||
return this.bounds.contains(point);
|
return this.bounds.contains(point);
|
||||||
return _super.prototype.containsPoint.call(this, point);
|
return _super.prototype.containsPoint.call(this, point);
|
||||||
};
|
};
|
||||||
return Rect;
|
return Box;
|
||||||
}(Polygon));
|
}(Polygon));
|
||||||
|
var Circle = (function (_super) {
|
||||||
|
__extends(Circle, _super);
|
||||||
|
function Circle(radius) {
|
||||||
|
var _this = _super.call(this) || this;
|
||||||
|
_this.radius = radius;
|
||||||
|
_this._originalRadius = radius;
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
Circle.prototype.pointCollidesWithShape = function (point) {
|
||||||
|
return ShapeCollisions.pointToCicle(point, this);
|
||||||
|
};
|
||||||
|
Circle.prototype.collidesWithShape = function (other) {
|
||||||
|
if (other instanceof Box && other.isUnrotated) {
|
||||||
|
return ShapeCollisions.circleToRect(this, other);
|
||||||
|
}
|
||||||
|
throw new Error("Collisions of Circle to " + other + " are not supported");
|
||||||
|
};
|
||||||
|
return Circle;
|
||||||
|
}(Shape));
|
||||||
|
var CollisionResult = (function () {
|
||||||
|
function CollisionResult() {
|
||||||
|
}
|
||||||
|
return CollisionResult;
|
||||||
|
}());
|
||||||
var ShapeCollisions = (function () {
|
var ShapeCollisions = (function () {
|
||||||
function ShapeCollisions() {
|
function ShapeCollisions() {
|
||||||
}
|
}
|
||||||
|
ShapeCollisions.polygonToPolygon = function (first, second) {
|
||||||
|
var result = new CollisionResult();
|
||||||
|
var isIntersecting = true;
|
||||||
|
};
|
||||||
|
ShapeCollisions.circleToPolygon = function (circle, polygon) {
|
||||||
|
var result = new CollisionResult();
|
||||||
|
var poly2Circle = Vector2.subtract(circle.position, polygon.position);
|
||||||
|
var gpp = Polygon.getClosestPointOnPolygonToPoint(polygon.points, poly2Circle);
|
||||||
|
var closestPoint = gpp.closestPoint;
|
||||||
|
var distanceSquared = gpp.distanceSquared;
|
||||||
|
result.normal = gpp.edgeNormal;
|
||||||
|
var circleCenterInsidePoly = polygon.containsPoint(circle.position);
|
||||||
|
if (distanceSquared > circle.radius * circle.radius && !circleCenterInsidePoly)
|
||||||
|
return result;
|
||||||
|
var mtv;
|
||||||
|
if (circleCenterInsidePoly) {
|
||||||
|
mtv = Vector2.multiply(result.normal, new Vector2(Math.sqrt(distanceSquared) - circle.radius, Math.sqrt(distanceSquared) - circle.radius));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (distanceSquared == 0) {
|
||||||
|
mtv = Vector2.multiply(result.normal, new Vector2(circle.radius, circle.radius));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var distance = Math.sqrt(distanceSquared);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
ShapeCollisions.circleToRect = function (circle, box) {
|
ShapeCollisions.circleToRect = function (circle, box) {
|
||||||
var result = new CollisionResult();
|
var result = new CollisionResult();
|
||||||
var closestPointOnBounds = box.bounds.getClosestPointOnRectangleBorderToPoint(circle.position).res;
|
var closestPointOnBounds = box.bounds.getClosestPointOnRectangleBorderToPoint(circle.position).res;
|
||||||
@@ -3062,12 +3175,33 @@ var Particle = (function () {
|
|||||||
var SpatialHash = (function () {
|
var SpatialHash = (function () {
|
||||||
function SpatialHash(cellSize) {
|
function SpatialHash(cellSize) {
|
||||||
if (cellSize === void 0) { cellSize = 100; }
|
if (cellSize === void 0) { cellSize = 100; }
|
||||||
|
this.gridBounds = new Rectangle();
|
||||||
this._tempHashSet = [];
|
this._tempHashSet = [];
|
||||||
this._cellDict = new NumberDictionary();
|
this._cellDict = new NumberDictionary();
|
||||||
this._cellSize = cellSize;
|
this._cellSize = cellSize;
|
||||||
this._inverseCellSize = 1 / this._cellSize;
|
this._inverseCellSize = 1 / this._cellSize;
|
||||||
this._raycastParser = new RaycastResultParser();
|
this._raycastParser = new RaycastResultParser();
|
||||||
}
|
}
|
||||||
|
SpatialHash.prototype.remove = function (collider) {
|
||||||
|
var bounds = collider.registeredPhysicsBounds;
|
||||||
|
var p1 = this.cellCoords(bounds.x, bounds.y);
|
||||||
|
var p2 = this.cellCoords(bounds.right, bounds.bottom);
|
||||||
|
for (var x = p1.x; x <= p2.x; x++) {
|
||||||
|
for (var y = p1.y; y <= p2.y; y++) {
|
||||||
|
var cell = this.cellAtPosition(x, y);
|
||||||
|
if (!cell)
|
||||||
|
console.error("removing Collider [" + collider + "] from a cell that it is not present in");
|
||||||
|
else
|
||||||
|
cell.remove(collider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SpatialHash.prototype.register = function (collider) {
|
||||||
|
var bounds = collider.bounds;
|
||||||
|
collider.registeredPhysicsBounds = bounds;
|
||||||
|
var p1 = this.cellCoords(bounds.x, bounds.y);
|
||||||
|
var p2 = this.cellCoords(bounds.right, bounds.bottom);
|
||||||
|
};
|
||||||
SpatialHash.prototype.overlapCircle = function (circleCenter, radius, results, layerMask) {
|
SpatialHash.prototype.overlapCircle = function (circleCenter, radius, results, layerMask) {
|
||||||
var bounds = new Rectangle(circleCenter.x - radius, circleCenter.y - radius, radius * 2, radius * 2);
|
var bounds = new Rectangle(circleCenter.x - radius, circleCenter.y - radius, radius * 2, radius * 2);
|
||||||
this._overlapTestCircle.radius = radius;
|
this._overlapTestCircle.radius = radius;
|
||||||
@@ -3150,263 +3284,6 @@ var NumberDictionary = (function () {
|
|||||||
};
|
};
|
||||||
return NumberDictionary;
|
return NumberDictionary;
|
||||||
}());
|
}());
|
||||||
var VerletWorld = (function () {
|
|
||||||
function VerletWorld(simulationBounds) {
|
|
||||||
this.gravity = new Vector2(0, 980);
|
|
||||||
this.maximumStepIterations = 5;
|
|
||||||
this.constraintIterations = 3;
|
|
||||||
this._leftOverTime = 0;
|
|
||||||
this._iterationSteps = 0;
|
|
||||||
this._fixedDeltaTime = 1 / 60;
|
|
||||||
this._composites = [];
|
|
||||||
this._tempCircle = new Circle(1);
|
|
||||||
this.simulationBounds = simulationBounds;
|
|
||||||
this._fixedDeltaTimeSq = Math.pow(this._fixedDeltaTime, 2);
|
|
||||||
}
|
|
||||||
VerletWorld.prototype.update = function () {
|
|
||||||
this.updateTiming();
|
|
||||||
for (var iteration = 1; iteration <= this._iterationSteps; iteration++) {
|
|
||||||
for (var i = this._composites.length - 1; i >= 0; i--) {
|
|
||||||
var composite = this._composites[i];
|
|
||||||
for (var s = 0; s < this.constraintIterations; s++) {
|
|
||||||
composite.solveConstraints();
|
|
||||||
}
|
|
||||||
composite.updateParticles(this._fixedDeltaTimeSq, this.gravity);
|
|
||||||
composite.handleConstraintCollisions();
|
|
||||||
for (var j = 0; j < composite.particles.length; j++) {
|
|
||||||
var p = composite.particles[j];
|
|
||||||
if (this.simulationBounds) {
|
|
||||||
this.constrainParticleToBounds(p);
|
|
||||||
}
|
|
||||||
if (p.collidesWithColliders)
|
|
||||||
this.handleCollisions(p, composite.collidesWithLayers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
VerletWorld.prototype.handleCollisions = function (p, collidesWithLayers) {
|
|
||||||
var collidedCount = Physics.overlapCircleAll(p.position, p.radius, VerletWorld._colliders, collidesWithLayers);
|
|
||||||
for (var i = 0; i < collidedCount; i++) {
|
|
||||||
var collider = VerletWorld._colliders[i];
|
|
||||||
if (collider.isTrigger)
|
|
||||||
continue;
|
|
||||||
if (p.radius < 2) {
|
|
||||||
var collisionResult = collider.shape.pointCollidesWithShape(p.position);
|
|
||||||
if (collisionResult) {
|
|
||||||
p.position = Vector2.subtract(p.position, collisionResult.minimumTranslationVector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this._tempCircle.radius = p.radius;
|
|
||||||
this._tempCircle.position = p.position;
|
|
||||||
var collisionResult = this._tempCircle.collidesWithShape(collider.shape);
|
|
||||||
if (collisionResult) {
|
|
||||||
p.position = Vector2.subtract(p.position, collisionResult.minimumTranslationVector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
VerletWorld.prototype.constrainParticleToBounds = function (p) {
|
|
||||||
var tempPos = p.position;
|
|
||||||
var bounds = this.simulationBounds;
|
|
||||||
if (p.radius == 0) {
|
|
||||||
if (tempPos.y > bounds.height) {
|
|
||||||
tempPos.y = bounds.height;
|
|
||||||
}
|
|
||||||
else if (tempPos.y < bounds.y) {
|
|
||||||
tempPos.y = bounds.y;
|
|
||||||
}
|
|
||||||
if (tempPos.x < bounds.x) {
|
|
||||||
tempPos.x = bounds.x;
|
|
||||||
}
|
|
||||||
else if (tempPos.x > bounds.width) {
|
|
||||||
tempPos.x = bounds.width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (tempPos.y < bounds.y + p.radius) {
|
|
||||||
tempPos.y = 2 * (bounds.y + p.radius) - tempPos.y;
|
|
||||||
}
|
|
||||||
if (tempPos.y > bounds.height - p.radius) {
|
|
||||||
tempPos.y = 2 * (bounds.height - p.radius) - tempPos.y;
|
|
||||||
}
|
|
||||||
if (tempPos.x > bounds.width - p.radius) {
|
|
||||||
tempPos.x = 2 * (bounds.width - p.radius) - tempPos.x;
|
|
||||||
}
|
|
||||||
if (tempPos.x < bounds.x + p.radius)
|
|
||||||
tempPos.x = 2 * (bounds.x + p.radius) - tempPos.x;
|
|
||||||
}
|
|
||||||
p.position = tempPos;
|
|
||||||
};
|
|
||||||
VerletWorld.prototype.debugRender = function (displayObject) {
|
|
||||||
if (!displayObject)
|
|
||||||
return;
|
|
||||||
displayObject.stage.removeChildren();
|
|
||||||
for (var i = 0; i < this._composites.length; i++) {
|
|
||||||
var shape = new egret.Shape();
|
|
||||||
this._composites[i].debugRender(shape.graphics);
|
|
||||||
displayObject.stage.addChild(shape);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
VerletWorld.prototype.addComposite = function (composite) {
|
|
||||||
this._composites.push(composite);
|
|
||||||
return composite;
|
|
||||||
};
|
|
||||||
VerletWorld.prototype.updateTiming = function () {
|
|
||||||
this._leftOverTime += Time.deltaTime;
|
|
||||||
this._iterationSteps = Math.trunc(this._leftOverTime / this._fixedDeltaTime);
|
|
||||||
this._leftOverTime -= this._iterationSteps * this._fixedDeltaTime;
|
|
||||||
this._iterationSteps = Math.min(this._iterationSteps, this.maximumStepIterations);
|
|
||||||
};
|
|
||||||
VerletWorld._colliders = new Array(4);
|
|
||||||
return VerletWorld;
|
|
||||||
}());
|
|
||||||
var Composite = (function () {
|
|
||||||
function Composite() {
|
|
||||||
this._constraints = [];
|
|
||||||
this.friction = new Vector2(0.98, 1);
|
|
||||||
this.drawParticles = true;
|
|
||||||
this.drawConstraints = true;
|
|
||||||
this.particles = [];
|
|
||||||
this.collidesWithLayers = Physics.allLayers;
|
|
||||||
}
|
|
||||||
Composite.prototype.solveConstraints = function () {
|
|
||||||
for (var i = this._constraints.length - 1; i >= 0; i--) {
|
|
||||||
this._constraints[i].solve();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Composite.prototype.addParticle = function (particle) {
|
|
||||||
this.particles.push(particle);
|
|
||||||
return particle;
|
|
||||||
};
|
|
||||||
Composite.prototype.addConstraint = function (constraint) {
|
|
||||||
this._constraints.push(constraint);
|
|
||||||
constraint.composite = this;
|
|
||||||
return constraint;
|
|
||||||
};
|
|
||||||
Composite.prototype.removeConstraint = function (constraint) {
|
|
||||||
this._constraints.remove(constraint);
|
|
||||||
};
|
|
||||||
Composite.prototype.updateParticles = function (deltaTimeSquared, gravity) {
|
|
||||||
for (var j = 0; j < this.particles.length; j++) {
|
|
||||||
var p = this.particles[j];
|
|
||||||
if (p.isPinned) {
|
|
||||||
p.position = p.pinnedPosition;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
p.applyForce(Vector2.multiply(new Vector2(p.mass, p.mass), gravity));
|
|
||||||
var vel = Vector2.multiply(Vector2.subtract(p.position, p.lastPosition), this.friction);
|
|
||||||
var nextPos = Vector2.add(Vector2.add(p.position, vel), Vector2.multiply(p.acceleration, new Vector2(0.5 * deltaTimeSquared, 0.5 * deltaTimeSquared)));
|
|
||||||
p.lastPosition = p.position;
|
|
||||||
p.position = nextPos;
|
|
||||||
p.acceleration.x = p.acceleration.y = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Composite.prototype.handleConstraintCollisions = function () {
|
|
||||||
for (var i = this._constraints.length - 1; i >= 0; i--) {
|
|
||||||
if (this._constraints[i].collidesWithColliders)
|
|
||||||
this._constraints[i].handleCollisions(this.collidesWithLayers);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Composite.prototype.debugRender = function (graphics) {
|
|
||||||
if (this.drawConstraints) {
|
|
||||||
for (var i = 0; i < this._constraints.length; i++) {
|
|
||||||
this._constraints[i].debugRender(graphics);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.drawParticles) {
|
|
||||||
for (var i = 0; i < this.particles.length; i++) {
|
|
||||||
var size = this.particles[i].radius ? this.particles[i].radius : 4;
|
|
||||||
graphics.lineStyle(4, DebugDefaults.verletParticle);
|
|
||||||
graphics.drawRect(this.particles[i].position.x, this.particles[i].position.y, size, size);
|
|
||||||
graphics.endFill();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return Composite;
|
|
||||||
}());
|
|
||||||
var Box = (function (_super) {
|
|
||||||
__extends(Box, _super);
|
|
||||||
function Box(center, width, height, borderStiffness, diagonalStiffness) {
|
|
||||||
if (borderStiffness === void 0) { borderStiffness = 0.2; }
|
|
||||||
if (diagonalStiffness === void 0) { diagonalStiffness = 0.5; }
|
|
||||||
var _this = _super.call(this) || this;
|
|
||||||
var tl = _this.addParticle(new Particle(Vector2.add(center, new Vector2(-width / 2, -height / 2))));
|
|
||||||
var tr = _this.addParticle(new Particle(Vector2.add(center, new Vector2(width / 2, -height / 2))));
|
|
||||||
var br = _this.addParticle(new Particle(Vector2.add(center, new Vector2(width / 2, height / 2))));
|
|
||||||
var bl = _this.addParticle(new Particle(Vector2.add(center, new Vector2(-width / 2, height / 2))));
|
|
||||||
_this.addConstraint(new DistanceConstraint(tl, tr, borderStiffness));
|
|
||||||
_this.addConstraint(new DistanceConstraint(tr, br, borderStiffness));
|
|
||||||
_this.addConstraint(new DistanceConstraint(br, bl, borderStiffness));
|
|
||||||
_this.addConstraint(new DistanceConstraint(bl, tl, borderStiffness));
|
|
||||||
_this.addConstraint(new DistanceConstraint(tl, br, diagonalStiffness)).setCollidesWithColliders(false);
|
|
||||||
_this.addConstraint(new DistanceConstraint(bl, tr, diagonalStiffness)).setCollidesWithColliders(false);
|
|
||||||
return _this;
|
|
||||||
}
|
|
||||||
return Box;
|
|
||||||
}(Composite));
|
|
||||||
var Constraint = (function () {
|
|
||||||
function Constraint() {
|
|
||||||
this.collidesWithColliders = true;
|
|
||||||
}
|
|
||||||
Constraint.prototype.handleCollisions = function (collidesWithLayers) {
|
|
||||||
};
|
|
||||||
Constraint.prototype.debugRender = function (graphics) { };
|
|
||||||
return Constraint;
|
|
||||||
}());
|
|
||||||
var DistanceConstraint = (function (_super) {
|
|
||||||
__extends(DistanceConstraint, _super);
|
|
||||||
function DistanceConstraint(first, second, stiffness, distance) {
|
|
||||||
if (distance === void 0) { distance = -1; }
|
|
||||||
var _this = _super.call(this) || this;
|
|
||||||
_this.stiffness = 0;
|
|
||||||
_this.restingDistance = 0;
|
|
||||||
_this.tearSensitivity = Number.POSITIVE_INFINITY;
|
|
||||||
_this._particleOne = first;
|
|
||||||
_this._particleTwo = second;
|
|
||||||
_this.stiffness = stiffness;
|
|
||||||
if (distance > -1) {
|
|
||||||
_this.restingDistance = distance;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_this.restingDistance = Vector2.distance(first.position, second.position);
|
|
||||||
}
|
|
||||||
return _this;
|
|
||||||
}
|
|
||||||
DistanceConstraint.prototype.setCollidesWithColliders = function (collidesWithColliders) {
|
|
||||||
this.collidesWithColliders = collidesWithColliders;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
DistanceConstraint.prototype.handleCollisions = function (collidersWithLayers) {
|
|
||||||
var minX = Math.min(this._particleOne.position.x, this._particleTwo.position.x);
|
|
||||||
var maxX = Math.max(this._particleOne.position.x, this._particleTwo.position.x);
|
|
||||||
var minY = Math.min(this._particleOne.position.y, this._particleTwo.position.y);
|
|
||||||
var maxY = Math.max(this._particleOne.position.y, this._particleTwo.position.y);
|
|
||||||
};
|
|
||||||
DistanceConstraint.prototype.solve = function () {
|
|
||||||
var diff = Vector2.subtract(this._particleOne.position, this._particleTwo.position);
|
|
||||||
var d = diff.length();
|
|
||||||
var difference = (this.restingDistance - d) / d;
|
|
||||||
if (d / this.restingDistance > this.tearSensitivity) {
|
|
||||||
this.composite.removeConstraint(this);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var im1 = 1 / this._particleOne.mass;
|
|
||||||
var im2 = 1 / this._particleTwo.mass;
|
|
||||||
var scalarP1 = (im1 / (im1 + im2)) * this.stiffness;
|
|
||||||
var scalarP2 = this.stiffness - scalarP1;
|
|
||||||
this._particleOne.position = Vector2.add(this._particleOne.position, Vector2.multiply(diff, new Vector2(scalarP1 * difference, scalarP1 * difference)));
|
|
||||||
this._particleTwo.position = Vector2.subtract(this._particleTwo.position, Vector2.multiply(diff, new Vector2(scalarP2 * difference, scalarP2 * difference)));
|
|
||||||
};
|
|
||||||
DistanceConstraint.prototype.debugRender = function (graphics) {
|
|
||||||
graphics.lineStyle(1, DebugDefaults.verletConstraintEdge);
|
|
||||||
graphics.lineTo(this._particleOne.position.x, this._particleOne.position.y);
|
|
||||||
graphics.lineTo(this._particleTwo.position.x, this._particleTwo.position.y);
|
|
||||||
graphics.endFill();
|
|
||||||
};
|
|
||||||
DistanceConstraint._polygon = new Polygon(2, 1);
|
|
||||||
return DistanceConstraint;
|
|
||||||
}(Constraint));
|
|
||||||
var Triangulator = (function () {
|
var Triangulator = (function () {
|
||||||
function Triangulator() {
|
function Triangulator() {
|
||||||
this.triangleIndices = [];
|
this.triangleIndices = [];
|
||||||
@@ -3494,6 +3371,9 @@ var Vector2Ext = (function () {
|
|||||||
Vector2Ext.cross = function (u, v) {
|
Vector2Ext.cross = function (u, v) {
|
||||||
return u.y * v.x - u.x * v.y;
|
return u.y * v.x - u.x * v.y;
|
||||||
};
|
};
|
||||||
|
Vector2Ext.perpendicular = function (first, second) {
|
||||||
|
return new Vector2(-1 * (second.y - first.y), second.x - first.x);
|
||||||
|
};
|
||||||
return Vector2Ext;
|
return Vector2Ext;
|
||||||
}());
|
}());
|
||||||
var WebGLUtils = (function () {
|
var WebGLUtils = (function () {
|
||||||
|
|||||||
2
demo/libs/framework/framework.min.js
vendored
2
demo/libs/framework/framework.min.js
vendored
File diff suppressed because one or more lines are too long
135
source/bin/framework.d.ts
vendored
135
source/bin/framework.d.ts
vendored
@@ -380,7 +380,16 @@ declare abstract class Collider extends Component {
|
|||||||
shape: Shape;
|
shape: Shape;
|
||||||
physicsLayer: number;
|
physicsLayer: number;
|
||||||
isTrigger: boolean;
|
isTrigger: boolean;
|
||||||
|
registeredPhysicsBounds: Rectangle;
|
||||||
|
protected _isParentEntityAddedToScene: any;
|
||||||
|
protected _isPositionDirty: boolean;
|
||||||
|
protected _colliderRequiresAutoSizing: any;
|
||||||
readonly bounds: Rectangle;
|
readonly bounds: Rectangle;
|
||||||
|
initialize(): void;
|
||||||
|
}
|
||||||
|
declare class BoxCollider extends Collider {
|
||||||
|
width: number;
|
||||||
|
setWidth(width: number): BoxCollider;
|
||||||
}
|
}
|
||||||
declare class EntitySystem {
|
declare class EntitySystem {
|
||||||
private _scene;
|
private _scene;
|
||||||
@@ -513,6 +522,7 @@ declare class MathHelper {
|
|||||||
static toDegrees(radians: number): number;
|
static toDegrees(radians: number): number;
|
||||||
static toRadians(degrees: number): number;
|
static toRadians(degrees: number): number;
|
||||||
static map(value: number, leftMin: number, leftMax: number, rightMin: number, rightMax: number): number;
|
static map(value: number, leftMin: number, leftMax: number, rightMin: number, rightMax: number): number;
|
||||||
|
static lerp(value1: number, value2: number, amount: number): number;
|
||||||
static clamp(value: number, min: number, max: number): number;
|
static clamp(value: number, min: number, max: number): number;
|
||||||
static minOf(a: number, b: number, c: number, d: number): number;
|
static minOf(a: number, b: number, c: number, d: number): number;
|
||||||
static maxOf(a: number, b: number, c: number, d: number): number;
|
static maxOf(a: number, b: number, c: number, d: number): number;
|
||||||
@@ -553,7 +563,7 @@ declare class Rectangle {
|
|||||||
readonly top: number;
|
readonly top: number;
|
||||||
readonly bottom: number;
|
readonly bottom: number;
|
||||||
location: Vector2;
|
location: Vector2;
|
||||||
constructor(x: number, y: number, width: number, height: number);
|
constructor(x?: number, y?: number, width?: number, height?: number);
|
||||||
intersects(value: Rectangle): boolean;
|
intersects(value: Rectangle): boolean;
|
||||||
contains(value: Vector2): boolean;
|
contains(value: Vector2): boolean;
|
||||||
static fromMinMax(minX: number, minY: number, maxX: number, maxY: number): Rectangle;
|
static fromMinMax(minX: number, minY: number, maxX: number, maxY: number): Rectangle;
|
||||||
@@ -566,7 +576,7 @@ declare class Rectangle {
|
|||||||
declare class Vector2 {
|
declare class Vector2 {
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
constructor(x: number, y: number);
|
constructor(x: number, y?: number);
|
||||||
static add(value1: Vector2, value2: Vector2): Vector2;
|
static add(value1: Vector2, value2: Vector2): Vector2;
|
||||||
static divide(value1: Vector2, value2: Vector2): Vector2;
|
static divide(value1: Vector2, value2: Vector2): Vector2;
|
||||||
static multiply(value1: Vector2, value2: Vector2): Vector2;
|
static multiply(value1: Vector2, value2: Vector2): Vector2;
|
||||||
@@ -576,6 +586,7 @@ declare class Vector2 {
|
|||||||
static normalize(value: Vector2): Vector2;
|
static normalize(value: Vector2): Vector2;
|
||||||
static dot(value1: Vector2, value2: Vector2): number;
|
static dot(value1: Vector2, value2: Vector2): number;
|
||||||
static distanceSquared(value1: Vector2, value2: Vector2): number;
|
static distanceSquared(value1: Vector2, value2: Vector2): number;
|
||||||
|
static lerp(value1: Vector2, value2: Vector2, amount: number): Vector2;
|
||||||
static transform(position: Vector2, matrix: Matrix2D): Vector2;
|
static transform(position: Vector2, matrix: Matrix2D): Vector2;
|
||||||
static distance(value1: Vector2, value2: Vector2): number;
|
static distance(value1: Vector2, value2: Vector2): number;
|
||||||
}
|
}
|
||||||
@@ -606,12 +617,44 @@ declare class Physics {
|
|||||||
private static _spatialHash;
|
private static _spatialHash;
|
||||||
static readonly allLayers: number;
|
static readonly allLayers: number;
|
||||||
static overlapCircleAll(center: Vector2, randius: number, results: any[], layerMask?: number): number;
|
static overlapCircleAll(center: Vector2, randius: number, results: any[], layerMask?: number): number;
|
||||||
|
static boxcastBroadphase(rect: Rectangle, layerMask?: number): Collider[];
|
||||||
|
static updateCollider(collider: Collider): void;
|
||||||
}
|
}
|
||||||
declare abstract class Shape {
|
declare abstract class Shape {
|
||||||
bounds: Rectangle;
|
bounds: Rectangle;
|
||||||
position: Vector2;
|
position: Vector2;
|
||||||
abstract pointCollidesWithShape(point: Vector2): CollisionResult;
|
abstract pointCollidesWithShape(point: Vector2): CollisionResult;
|
||||||
}
|
}
|
||||||
|
declare class Polygon extends Shape {
|
||||||
|
points: Vector2[];
|
||||||
|
isUnrotated: boolean;
|
||||||
|
private _polygonCenter;
|
||||||
|
private _areEdgeNormalsDirty;
|
||||||
|
protected _originalPoints: Vector2[];
|
||||||
|
_edgeNormals: Vector2[];
|
||||||
|
readonly edgeNormals: Vector2[];
|
||||||
|
isBox: boolean;
|
||||||
|
constructor(vertCount: number, radius: number);
|
||||||
|
private buildEdgeNormals;
|
||||||
|
setPoints(points: Vector2[]): void;
|
||||||
|
collidesWithShape(other: Shape): void;
|
||||||
|
recalculateCenterAndEdgeNormals(): void;
|
||||||
|
static findPolygonCenter(points: Vector2[]): Vector2;
|
||||||
|
static getClosestPointOnPolygonToPoint(points: Vector2[], point: Vector2): {
|
||||||
|
closestPoint: any;
|
||||||
|
distanceSquared: any;
|
||||||
|
edgeNormal: any;
|
||||||
|
};
|
||||||
|
pointCollidesWithShape(point: Vector2): CollisionResult;
|
||||||
|
containsPoint(point: Vector2): boolean;
|
||||||
|
static buildSymmertricalPolygon(vertCount: number, radius: number): any;
|
||||||
|
}
|
||||||
|
declare class Box extends Polygon {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
updateBox(width: number, height: number): void;
|
||||||
|
containsPoint(point: Vector2): boolean;
|
||||||
|
}
|
||||||
declare class Circle extends Shape {
|
declare class Circle extends Shape {
|
||||||
radius: number;
|
radius: number;
|
||||||
private _originalRadius;
|
private _originalRadius;
|
||||||
@@ -624,30 +667,10 @@ declare class CollisionResult {
|
|||||||
normal: Vector2;
|
normal: Vector2;
|
||||||
point: Vector2;
|
point: Vector2;
|
||||||
}
|
}
|
||||||
declare class Polygon extends Shape {
|
|
||||||
points: Vector2[];
|
|
||||||
isUnrotated: boolean;
|
|
||||||
private _polygonCenter;
|
|
||||||
private _areEdgeNormalsDirty;
|
|
||||||
private _originalPoint;
|
|
||||||
constructor(vertCount: number, radius: number);
|
|
||||||
setPoints(points: Vector2[]): void;
|
|
||||||
recalculateCenterAndEdgeNormals(): void;
|
|
||||||
static findPolygonCenter(points: Vector2[]): Vector2;
|
|
||||||
static getClosestPointOnPolygonToPoint(points: Vector2[], point: Vector2): {
|
|
||||||
closestPoint: any;
|
|
||||||
distanceSquared: any;
|
|
||||||
edgeNormal: any;
|
|
||||||
};
|
|
||||||
pointCollidesWithShape(point: Vector2): CollisionResult;
|
|
||||||
containsPoint(point: Vector2): boolean;
|
|
||||||
static buildSymmertricalPolygon(vertCount: number, radius: number): any;
|
|
||||||
}
|
|
||||||
declare class Rect extends Polygon {
|
|
||||||
containsPoint(point: Vector2): boolean;
|
|
||||||
}
|
|
||||||
declare class ShapeCollisions {
|
declare class ShapeCollisions {
|
||||||
static circleToRect(circle: Circle, box: Rect): CollisionResult;
|
static polygonToPolygon(first: Polygon, second: Polygon): void;
|
||||||
|
static circleToPolygon(circle: Circle, polygon: Polygon): CollisionResult;
|
||||||
|
static circleToRect(circle: Circle, box: Box): CollisionResult;
|
||||||
static pointToCicle(point: Vector2, circle: Circle): CollisionResult;
|
static pointToCicle(point: Vector2, circle: Circle): CollisionResult;
|
||||||
static closestPointOnLine(lineA: Vector2, lineB: Vector2, closestTo: Vector2): Vector2;
|
static closestPointOnLine(lineA: Vector2, lineB: Vector2, closestTo: Vector2): Vector2;
|
||||||
static pointToPoly(point: Vector2, poly: Polygon): CollisionResult;
|
static pointToPoly(point: Vector2, poly: Polygon): CollisionResult;
|
||||||
@@ -665,6 +688,7 @@ declare class Particle {
|
|||||||
applyForce(force: Vector2): void;
|
applyForce(force: Vector2): void;
|
||||||
}
|
}
|
||||||
declare class SpatialHash {
|
declare class SpatialHash {
|
||||||
|
gridBounds: Rectangle;
|
||||||
private _raycastParser;
|
private _raycastParser;
|
||||||
private _cellSize;
|
private _cellSize;
|
||||||
private _inverseCellSize;
|
private _inverseCellSize;
|
||||||
@@ -672,6 +696,8 @@ declare class SpatialHash {
|
|||||||
private _tempHashSet;
|
private _tempHashSet;
|
||||||
private _cellDict;
|
private _cellDict;
|
||||||
constructor(cellSize?: number);
|
constructor(cellSize?: number);
|
||||||
|
remove(collider: Collider): void;
|
||||||
|
register(collider: Collider): void;
|
||||||
overlapCircle(circleCenter: Vector2, radius: number, results: Collider[], layerMask: any): number;
|
overlapCircle(circleCenter: Vector2, radius: number, results: Collider[], layerMask: any): number;
|
||||||
aabbBroadphase(bounds: Rectangle, excludeCollider: Collider, layerMask: number): Collider[];
|
aabbBroadphase(bounds: Rectangle, excludeCollider: Collider, layerMask: number): Collider[];
|
||||||
private cellAtPosition;
|
private cellAtPosition;
|
||||||
@@ -688,64 +714,6 @@ declare class NumberDictionary {
|
|||||||
getAllObjects(): Collider[];
|
getAllObjects(): Collider[];
|
||||||
clear(): void;
|
clear(): void;
|
||||||
}
|
}
|
||||||
declare class VerletWorld {
|
|
||||||
gravity: Vector2;
|
|
||||||
maximumStepIterations: number;
|
|
||||||
constraintIterations: number;
|
|
||||||
simulationBounds: Rectangle;
|
|
||||||
private _leftOverTime;
|
|
||||||
private _iterationSteps;
|
|
||||||
private _fixedDeltaTime;
|
|
||||||
private _composites;
|
|
||||||
private _fixedDeltaTimeSq;
|
|
||||||
private static _colliders;
|
|
||||||
private _tempCircle;
|
|
||||||
constructor(simulationBounds?: Rectangle);
|
|
||||||
update(): void;
|
|
||||||
private handleCollisions;
|
|
||||||
private constrainParticleToBounds;
|
|
||||||
debugRender(displayObject: egret.DisplayObject): void;
|
|
||||||
addComposite<T extends Composite>(composite: T): T;
|
|
||||||
private updateTiming;
|
|
||||||
}
|
|
||||||
declare class Composite {
|
|
||||||
private _constraints;
|
|
||||||
friction: Vector2;
|
|
||||||
drawParticles: boolean;
|
|
||||||
drawConstraints: boolean;
|
|
||||||
particles: Particle[];
|
|
||||||
collidesWithLayers: number;
|
|
||||||
solveConstraints(): void;
|
|
||||||
addParticle(particle: Particle): Particle;
|
|
||||||
addConstraint<T extends Constraint>(constraint: T): T;
|
|
||||||
removeConstraint(constraint: Constraint): void;
|
|
||||||
updateParticles(deltaTimeSquared: number, gravity: Vector2): void;
|
|
||||||
handleConstraintCollisions(): void;
|
|
||||||
debugRender(graphics: egret.Graphics): void;
|
|
||||||
}
|
|
||||||
declare class Box extends Composite {
|
|
||||||
constructor(center: Vector2, width: number, height: number, borderStiffness?: number, diagonalStiffness?: number);
|
|
||||||
}
|
|
||||||
declare abstract class Constraint {
|
|
||||||
composite: Composite;
|
|
||||||
collidesWithColliders: boolean;
|
|
||||||
abstract solve(): any;
|
|
||||||
handleCollisions(collidesWithLayers: number): void;
|
|
||||||
debugRender(graphics: egret.Graphics): void;
|
|
||||||
}
|
|
||||||
declare class DistanceConstraint extends Constraint {
|
|
||||||
stiffness: number;
|
|
||||||
restingDistance: number;
|
|
||||||
tearSensitivity: number;
|
|
||||||
private _particleOne;
|
|
||||||
private _particleTwo;
|
|
||||||
private static _polygon;
|
|
||||||
constructor(first: Particle, second: Particle, stiffness: number, distance?: number);
|
|
||||||
setCollidesWithColliders(collidesWithColliders: boolean): this;
|
|
||||||
handleCollisions(collidersWithLayers: any): void;
|
|
||||||
solve(): void;
|
|
||||||
debugRender(graphics: egret.Graphics): void;
|
|
||||||
}
|
|
||||||
declare class Triangulator {
|
declare class Triangulator {
|
||||||
triangleIndices: number[];
|
triangleIndices: number[];
|
||||||
private _triPrev;
|
private _triPrev;
|
||||||
@@ -757,6 +725,7 @@ declare class Triangulator {
|
|||||||
declare class Vector2Ext {
|
declare class Vector2Ext {
|
||||||
static isTriangleCCW(a: Vector2, center: Vector2, c: Vector2): boolean;
|
static isTriangleCCW(a: Vector2, center: Vector2, c: Vector2): boolean;
|
||||||
static cross(u: Vector2, v: Vector2): number;
|
static cross(u: Vector2, v: Vector2): number;
|
||||||
|
static perpendicular(first: Vector2, second: Vector2): Vector2;
|
||||||
}
|
}
|
||||||
declare class WebGLUtils {
|
declare class WebGLUtils {
|
||||||
static getWebGL(): WebGLRenderingContext;
|
static getWebGL(): WebGLRenderingContext;
|
||||||
|
|||||||
@@ -1786,6 +1786,7 @@ var Collider = (function (_super) {
|
|||||||
function Collider() {
|
function Collider() {
|
||||||
var _this = _super !== null && _super.apply(this, arguments) || this;
|
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||||
_this.physicsLayer = 1 << 0;
|
_this.physicsLayer = 1 << 0;
|
||||||
|
_this._isPositionDirty = true;
|
||||||
return _this;
|
return _this;
|
||||||
}
|
}
|
||||||
Object.defineProperty(Collider.prototype, "bounds", {
|
Object.defineProperty(Collider.prototype, "bounds", {
|
||||||
@@ -1795,8 +1796,38 @@ var Collider = (function (_super) {
|
|||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true
|
configurable: true
|
||||||
});
|
});
|
||||||
|
Collider.prototype.initialize = function () {
|
||||||
|
};
|
||||||
return Collider;
|
return Collider;
|
||||||
}(Component));
|
}(Component));
|
||||||
|
var BoxCollider = (function (_super) {
|
||||||
|
__extends(BoxCollider, _super);
|
||||||
|
function BoxCollider() {
|
||||||
|
return _super !== null && _super.apply(this, arguments) || this;
|
||||||
|
}
|
||||||
|
Object.defineProperty(BoxCollider.prototype, "width", {
|
||||||
|
get: function () {
|
||||||
|
return this.shape.width;
|
||||||
|
},
|
||||||
|
set: function (value) {
|
||||||
|
this.setWidth(value);
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
BoxCollider.prototype.setWidth = function (width) {
|
||||||
|
this._colliderRequiresAutoSizing = false;
|
||||||
|
var box = this.shape;
|
||||||
|
if (width != box.width) {
|
||||||
|
box.updateBox(width, box.height);
|
||||||
|
this._isPositionDirty = true;
|
||||||
|
if (this.entity && this._isParentEntityAddedToScene)
|
||||||
|
Physics.updateCollider(this);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
return BoxCollider;
|
||||||
|
}(Collider));
|
||||||
var EntitySystem = (function () {
|
var EntitySystem = (function () {
|
||||||
function EntitySystem(matcher) {
|
function EntitySystem(matcher) {
|
||||||
this._entities = [];
|
this._entities = [];
|
||||||
@@ -2373,6 +2404,9 @@ var MathHelper = (function () {
|
|||||||
MathHelper.map = function (value, leftMin, leftMax, rightMin, rightMax) {
|
MathHelper.map = function (value, leftMin, leftMax, rightMin, rightMax) {
|
||||||
return rightMin + (value - leftMin) * (rightMax - rightMin) / (leftMax - leftMin);
|
return rightMin + (value - leftMin) * (rightMax - rightMin) / (leftMax - leftMin);
|
||||||
};
|
};
|
||||||
|
MathHelper.lerp = function (value1, value2, amount) {
|
||||||
|
return value1 + (value2 - value1) * amount;
|
||||||
|
};
|
||||||
MathHelper.clamp = function (value, min, max) {
|
MathHelper.clamp = function (value, min, max) {
|
||||||
if (value < min)
|
if (value < min)
|
||||||
return min;
|
return min;
|
||||||
@@ -2543,10 +2577,10 @@ var Matrix2D = (function () {
|
|||||||
}());
|
}());
|
||||||
var Rectangle = (function () {
|
var Rectangle = (function () {
|
||||||
function Rectangle(x, y, width, height) {
|
function Rectangle(x, y, width, height) {
|
||||||
this.x = x;
|
this.x = x ? x : 0;
|
||||||
this.y = y;
|
this.y = y ? y : 0;
|
||||||
this.width = width;
|
this.width = width ? width : 0;
|
||||||
this.height = height;
|
this.height = height ? height : 0;
|
||||||
}
|
}
|
||||||
Object.defineProperty(Rectangle.prototype, "left", {
|
Object.defineProperty(Rectangle.prototype, "left", {
|
||||||
get: function () {
|
get: function () {
|
||||||
@@ -2686,7 +2720,7 @@ var Vector2 = (function () {
|
|||||||
this.x = 0;
|
this.x = 0;
|
||||||
this.y = 0;
|
this.y = 0;
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y ? y : x;
|
||||||
}
|
}
|
||||||
Vector2.add = function (value1, value2) {
|
Vector2.add = function (value1, value2) {
|
||||||
var result = new Vector2(0, 0);
|
var result = new Vector2(0, 0);
|
||||||
@@ -2733,6 +2767,9 @@ var Vector2 = (function () {
|
|||||||
var v1 = value1.x - value2.x, v2 = value1.y - value2.y;
|
var v1 = value1.x - value2.x, v2 = value1.y - value2.y;
|
||||||
return (v1 * v1) + (v2 * v2);
|
return (v1 * v1) + (v2 * v2);
|
||||||
};
|
};
|
||||||
|
Vector2.lerp = function (value1, value2, amount) {
|
||||||
|
return new Vector2(MathHelper.lerp(value1.x, value2.x, amount), MathHelper.lerp(value1.y, value2.y, amount));
|
||||||
|
};
|
||||||
Vector2.transform = function (position, matrix) {
|
Vector2.transform = function (position, matrix) {
|
||||||
return new Vector2((position.x * matrix.m11) + (position.y * matrix.m21), (position.x * matrix.m12) + (position.y * matrix.m22));
|
return new Vector2((position.x * matrix.m11) + (position.y * matrix.m21), (position.x * matrix.m12) + (position.y * matrix.m22));
|
||||||
};
|
};
|
||||||
@@ -2876,6 +2913,14 @@ var Physics = (function () {
|
|||||||
if (layerMask === void 0) { layerMask = -1; }
|
if (layerMask === void 0) { layerMask = -1; }
|
||||||
return this._spatialHash.overlapCircle(center, randius, results, layerMask);
|
return this._spatialHash.overlapCircle(center, randius, results, layerMask);
|
||||||
};
|
};
|
||||||
|
Physics.boxcastBroadphase = function (rect, layerMask) {
|
||||||
|
if (layerMask === void 0) { layerMask = this.allLayers; }
|
||||||
|
return this._spatialHash.aabbBroadphase(rect, null, layerMask);
|
||||||
|
};
|
||||||
|
Physics.updateCollider = function (collider) {
|
||||||
|
this._spatialHash.remove(collider);
|
||||||
|
this._spatialHash.register(collider);
|
||||||
|
};
|
||||||
Physics.allLayers = -1;
|
Physics.allLayers = -1;
|
||||||
return Physics;
|
return Physics;
|
||||||
}());
|
}());
|
||||||
@@ -2884,30 +2929,6 @@ var Shape = (function () {
|
|||||||
}
|
}
|
||||||
return Shape;
|
return Shape;
|
||||||
}());
|
}());
|
||||||
var Circle = (function (_super) {
|
|
||||||
__extends(Circle, _super);
|
|
||||||
function Circle(radius) {
|
|
||||||
var _this = _super.call(this) || this;
|
|
||||||
_this.radius = radius;
|
|
||||||
_this._originalRadius = radius;
|
|
||||||
return _this;
|
|
||||||
}
|
|
||||||
Circle.prototype.pointCollidesWithShape = function (point) {
|
|
||||||
return ShapeCollisions.pointToCicle(point, this);
|
|
||||||
};
|
|
||||||
Circle.prototype.collidesWithShape = function (other) {
|
|
||||||
if (other instanceof Rect && other.isUnrotated) {
|
|
||||||
return ShapeCollisions.circleToRect(this, other);
|
|
||||||
}
|
|
||||||
throw new Error("Collisions of Circle to " + other + " are not supported");
|
|
||||||
};
|
|
||||||
return Circle;
|
|
||||||
}(Shape));
|
|
||||||
var CollisionResult = (function () {
|
|
||||||
function CollisionResult() {
|
|
||||||
}
|
|
||||||
return CollisionResult;
|
|
||||||
}());
|
|
||||||
var Polygon = (function (_super) {
|
var Polygon = (function (_super) {
|
||||||
__extends(Polygon, _super);
|
__extends(Polygon, _super);
|
||||||
function Polygon(vertCount, radius) {
|
function Polygon(vertCount, radius) {
|
||||||
@@ -2917,11 +2938,40 @@ var Polygon = (function (_super) {
|
|||||||
_this.setPoints(Polygon.buildSymmertricalPolygon(vertCount, radius));
|
_this.setPoints(Polygon.buildSymmertricalPolygon(vertCount, radius));
|
||||||
return _this;
|
return _this;
|
||||||
}
|
}
|
||||||
|
Object.defineProperty(Polygon.prototype, "edgeNormals", {
|
||||||
|
get: function () {
|
||||||
|
if (this._areEdgeNormalsDirty)
|
||||||
|
this.buildEdgeNormals();
|
||||||
|
return this._edgeNormals;
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
Polygon.prototype.buildEdgeNormals = function () {
|
||||||
|
var totalEdges = this.isBox ? 2 : this.points.length;
|
||||||
|
if (this._edgeNormals == null || this._edgeNormals.length != totalEdges)
|
||||||
|
this._edgeNormals = new Vector2[totalEdges];
|
||||||
|
var p2;
|
||||||
|
for (var i = 0; i < totalEdges; i++) {
|
||||||
|
var p1 = this.points[i];
|
||||||
|
if (i + 1 >= this.points.length)
|
||||||
|
p2 = this.points[0];
|
||||||
|
else
|
||||||
|
p2 = this.points[i + 1];
|
||||||
|
var perp = Vector2Ext.perpendicular(p1, p2);
|
||||||
|
perp = Vector2.normalize(perp);
|
||||||
|
this._edgeNormals[i] = perp;
|
||||||
|
}
|
||||||
|
};
|
||||||
Polygon.prototype.setPoints = function (points) {
|
Polygon.prototype.setPoints = function (points) {
|
||||||
this.points = points;
|
this.points = points;
|
||||||
this.recalculateCenterAndEdgeNormals();
|
this.recalculateCenterAndEdgeNormals();
|
||||||
this._originalPoint = new Vector2[points.length];
|
this._originalPoints = new Vector2[points.length];
|
||||||
this._originalPoint = points;
|
this._originalPoints = points;
|
||||||
|
};
|
||||||
|
Polygon.prototype.collidesWithShape = function (other) {
|
||||||
|
if (other instanceof Polygon)
|
||||||
|
return ShapeCollisions.polygonToPolygon(this, other);
|
||||||
};
|
};
|
||||||
Polygon.prototype.recalculateCenterAndEdgeNormals = function () {
|
Polygon.prototype.recalculateCenterAndEdgeNormals = function () {
|
||||||
this._polygonCenter = Polygon.findPolygonCenter(this.points);
|
this._polygonCenter = Polygon.findPolygonCenter(this.points);
|
||||||
@@ -2982,21 +3032,84 @@ var Polygon = (function (_super) {
|
|||||||
};
|
};
|
||||||
return Polygon;
|
return Polygon;
|
||||||
}(Shape));
|
}(Shape));
|
||||||
var Rect = (function (_super) {
|
var Box = (function (_super) {
|
||||||
__extends(Rect, _super);
|
__extends(Box, _super);
|
||||||
function Rect() {
|
function Box() {
|
||||||
return _super !== null && _super.apply(this, arguments) || this;
|
return _super !== null && _super.apply(this, arguments) || this;
|
||||||
}
|
}
|
||||||
Rect.prototype.containsPoint = function (point) {
|
Box.prototype.updateBox = function (width, height) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
var halfWidth = width / 2;
|
||||||
|
var halfHeight = height / 2;
|
||||||
|
this.points[0] = new Vector2(-halfWidth, -halfHeight);
|
||||||
|
this.points[1] = new Vector2(halfWidth, -halfHeight);
|
||||||
|
this.points[2] = new Vector2(halfWidth, halfHeight);
|
||||||
|
this.points[3] = new Vector2(-halfWidth, halfHeight);
|
||||||
|
for (var i = 0; i < this.points.length; i++)
|
||||||
|
this._originalPoints[i] = this.points[i];
|
||||||
|
};
|
||||||
|
Box.prototype.containsPoint = function (point) {
|
||||||
if (this.isUnrotated)
|
if (this.isUnrotated)
|
||||||
return this.bounds.contains(point);
|
return this.bounds.contains(point);
|
||||||
return _super.prototype.containsPoint.call(this, point);
|
return _super.prototype.containsPoint.call(this, point);
|
||||||
};
|
};
|
||||||
return Rect;
|
return Box;
|
||||||
}(Polygon));
|
}(Polygon));
|
||||||
|
var Circle = (function (_super) {
|
||||||
|
__extends(Circle, _super);
|
||||||
|
function Circle(radius) {
|
||||||
|
var _this = _super.call(this) || this;
|
||||||
|
_this.radius = radius;
|
||||||
|
_this._originalRadius = radius;
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
Circle.prototype.pointCollidesWithShape = function (point) {
|
||||||
|
return ShapeCollisions.pointToCicle(point, this);
|
||||||
|
};
|
||||||
|
Circle.prototype.collidesWithShape = function (other) {
|
||||||
|
if (other instanceof Box && other.isUnrotated) {
|
||||||
|
return ShapeCollisions.circleToRect(this, other);
|
||||||
|
}
|
||||||
|
throw new Error("Collisions of Circle to " + other + " are not supported");
|
||||||
|
};
|
||||||
|
return Circle;
|
||||||
|
}(Shape));
|
||||||
|
var CollisionResult = (function () {
|
||||||
|
function CollisionResult() {
|
||||||
|
}
|
||||||
|
return CollisionResult;
|
||||||
|
}());
|
||||||
var ShapeCollisions = (function () {
|
var ShapeCollisions = (function () {
|
||||||
function ShapeCollisions() {
|
function ShapeCollisions() {
|
||||||
}
|
}
|
||||||
|
ShapeCollisions.polygonToPolygon = function (first, second) {
|
||||||
|
var result = new CollisionResult();
|
||||||
|
var isIntersecting = true;
|
||||||
|
};
|
||||||
|
ShapeCollisions.circleToPolygon = function (circle, polygon) {
|
||||||
|
var result = new CollisionResult();
|
||||||
|
var poly2Circle = Vector2.subtract(circle.position, polygon.position);
|
||||||
|
var gpp = Polygon.getClosestPointOnPolygonToPoint(polygon.points, poly2Circle);
|
||||||
|
var closestPoint = gpp.closestPoint;
|
||||||
|
var distanceSquared = gpp.distanceSquared;
|
||||||
|
result.normal = gpp.edgeNormal;
|
||||||
|
var circleCenterInsidePoly = polygon.containsPoint(circle.position);
|
||||||
|
if (distanceSquared > circle.radius * circle.radius && !circleCenterInsidePoly)
|
||||||
|
return result;
|
||||||
|
var mtv;
|
||||||
|
if (circleCenterInsidePoly) {
|
||||||
|
mtv = Vector2.multiply(result.normal, new Vector2(Math.sqrt(distanceSquared) - circle.radius, Math.sqrt(distanceSquared) - circle.radius));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (distanceSquared == 0) {
|
||||||
|
mtv = Vector2.multiply(result.normal, new Vector2(circle.radius, circle.radius));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var distance = Math.sqrt(distanceSquared);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
ShapeCollisions.circleToRect = function (circle, box) {
|
ShapeCollisions.circleToRect = function (circle, box) {
|
||||||
var result = new CollisionResult();
|
var result = new CollisionResult();
|
||||||
var closestPointOnBounds = box.bounds.getClosestPointOnRectangleBorderToPoint(circle.position).res;
|
var closestPointOnBounds = box.bounds.getClosestPointOnRectangleBorderToPoint(circle.position).res;
|
||||||
@@ -3062,12 +3175,33 @@ var Particle = (function () {
|
|||||||
var SpatialHash = (function () {
|
var SpatialHash = (function () {
|
||||||
function SpatialHash(cellSize) {
|
function SpatialHash(cellSize) {
|
||||||
if (cellSize === void 0) { cellSize = 100; }
|
if (cellSize === void 0) { cellSize = 100; }
|
||||||
|
this.gridBounds = new Rectangle();
|
||||||
this._tempHashSet = [];
|
this._tempHashSet = [];
|
||||||
this._cellDict = new NumberDictionary();
|
this._cellDict = new NumberDictionary();
|
||||||
this._cellSize = cellSize;
|
this._cellSize = cellSize;
|
||||||
this._inverseCellSize = 1 / this._cellSize;
|
this._inverseCellSize = 1 / this._cellSize;
|
||||||
this._raycastParser = new RaycastResultParser();
|
this._raycastParser = new RaycastResultParser();
|
||||||
}
|
}
|
||||||
|
SpatialHash.prototype.remove = function (collider) {
|
||||||
|
var bounds = collider.registeredPhysicsBounds;
|
||||||
|
var p1 = this.cellCoords(bounds.x, bounds.y);
|
||||||
|
var p2 = this.cellCoords(bounds.right, bounds.bottom);
|
||||||
|
for (var x = p1.x; x <= p2.x; x++) {
|
||||||
|
for (var y = p1.y; y <= p2.y; y++) {
|
||||||
|
var cell = this.cellAtPosition(x, y);
|
||||||
|
if (!cell)
|
||||||
|
console.error("removing Collider [" + collider + "] from a cell that it is not present in");
|
||||||
|
else
|
||||||
|
cell.remove(collider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SpatialHash.prototype.register = function (collider) {
|
||||||
|
var bounds = collider.bounds;
|
||||||
|
collider.registeredPhysicsBounds = bounds;
|
||||||
|
var p1 = this.cellCoords(bounds.x, bounds.y);
|
||||||
|
var p2 = this.cellCoords(bounds.right, bounds.bottom);
|
||||||
|
};
|
||||||
SpatialHash.prototype.overlapCircle = function (circleCenter, radius, results, layerMask) {
|
SpatialHash.prototype.overlapCircle = function (circleCenter, radius, results, layerMask) {
|
||||||
var bounds = new Rectangle(circleCenter.x - radius, circleCenter.y - radius, radius * 2, radius * 2);
|
var bounds = new Rectangle(circleCenter.x - radius, circleCenter.y - radius, radius * 2, radius * 2);
|
||||||
this._overlapTestCircle.radius = radius;
|
this._overlapTestCircle.radius = radius;
|
||||||
@@ -3150,263 +3284,6 @@ var NumberDictionary = (function () {
|
|||||||
};
|
};
|
||||||
return NumberDictionary;
|
return NumberDictionary;
|
||||||
}());
|
}());
|
||||||
var VerletWorld = (function () {
|
|
||||||
function VerletWorld(simulationBounds) {
|
|
||||||
this.gravity = new Vector2(0, 980);
|
|
||||||
this.maximumStepIterations = 5;
|
|
||||||
this.constraintIterations = 3;
|
|
||||||
this._leftOverTime = 0;
|
|
||||||
this._iterationSteps = 0;
|
|
||||||
this._fixedDeltaTime = 1 / 60;
|
|
||||||
this._composites = [];
|
|
||||||
this._tempCircle = new Circle(1);
|
|
||||||
this.simulationBounds = simulationBounds;
|
|
||||||
this._fixedDeltaTimeSq = Math.pow(this._fixedDeltaTime, 2);
|
|
||||||
}
|
|
||||||
VerletWorld.prototype.update = function () {
|
|
||||||
this.updateTiming();
|
|
||||||
for (var iteration = 1; iteration <= this._iterationSteps; iteration++) {
|
|
||||||
for (var i = this._composites.length - 1; i >= 0; i--) {
|
|
||||||
var composite = this._composites[i];
|
|
||||||
for (var s = 0; s < this.constraintIterations; s++) {
|
|
||||||
composite.solveConstraints();
|
|
||||||
}
|
|
||||||
composite.updateParticles(this._fixedDeltaTimeSq, this.gravity);
|
|
||||||
composite.handleConstraintCollisions();
|
|
||||||
for (var j = 0; j < composite.particles.length; j++) {
|
|
||||||
var p = composite.particles[j];
|
|
||||||
if (this.simulationBounds) {
|
|
||||||
this.constrainParticleToBounds(p);
|
|
||||||
}
|
|
||||||
if (p.collidesWithColliders)
|
|
||||||
this.handleCollisions(p, composite.collidesWithLayers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
VerletWorld.prototype.handleCollisions = function (p, collidesWithLayers) {
|
|
||||||
var collidedCount = Physics.overlapCircleAll(p.position, p.radius, VerletWorld._colliders, collidesWithLayers);
|
|
||||||
for (var i = 0; i < collidedCount; i++) {
|
|
||||||
var collider = VerletWorld._colliders[i];
|
|
||||||
if (collider.isTrigger)
|
|
||||||
continue;
|
|
||||||
if (p.radius < 2) {
|
|
||||||
var collisionResult = collider.shape.pointCollidesWithShape(p.position);
|
|
||||||
if (collisionResult) {
|
|
||||||
p.position = Vector2.subtract(p.position, collisionResult.minimumTranslationVector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this._tempCircle.radius = p.radius;
|
|
||||||
this._tempCircle.position = p.position;
|
|
||||||
var collisionResult = this._tempCircle.collidesWithShape(collider.shape);
|
|
||||||
if (collisionResult) {
|
|
||||||
p.position = Vector2.subtract(p.position, collisionResult.minimumTranslationVector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
VerletWorld.prototype.constrainParticleToBounds = function (p) {
|
|
||||||
var tempPos = p.position;
|
|
||||||
var bounds = this.simulationBounds;
|
|
||||||
if (p.radius == 0) {
|
|
||||||
if (tempPos.y > bounds.height) {
|
|
||||||
tempPos.y = bounds.height;
|
|
||||||
}
|
|
||||||
else if (tempPos.y < bounds.y) {
|
|
||||||
tempPos.y = bounds.y;
|
|
||||||
}
|
|
||||||
if (tempPos.x < bounds.x) {
|
|
||||||
tempPos.x = bounds.x;
|
|
||||||
}
|
|
||||||
else if (tempPos.x > bounds.width) {
|
|
||||||
tempPos.x = bounds.width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (tempPos.y < bounds.y + p.radius) {
|
|
||||||
tempPos.y = 2 * (bounds.y + p.radius) - tempPos.y;
|
|
||||||
}
|
|
||||||
if (tempPos.y > bounds.height - p.radius) {
|
|
||||||
tempPos.y = 2 * (bounds.height - p.radius) - tempPos.y;
|
|
||||||
}
|
|
||||||
if (tempPos.x > bounds.width - p.radius) {
|
|
||||||
tempPos.x = 2 * (bounds.width - p.radius) - tempPos.x;
|
|
||||||
}
|
|
||||||
if (tempPos.x < bounds.x + p.radius)
|
|
||||||
tempPos.x = 2 * (bounds.x + p.radius) - tempPos.x;
|
|
||||||
}
|
|
||||||
p.position = tempPos;
|
|
||||||
};
|
|
||||||
VerletWorld.prototype.debugRender = function (displayObject) {
|
|
||||||
if (!displayObject)
|
|
||||||
return;
|
|
||||||
displayObject.stage.removeChildren();
|
|
||||||
for (var i = 0; i < this._composites.length; i++) {
|
|
||||||
var shape = new egret.Shape();
|
|
||||||
this._composites[i].debugRender(shape.graphics);
|
|
||||||
displayObject.stage.addChild(shape);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
VerletWorld.prototype.addComposite = function (composite) {
|
|
||||||
this._composites.push(composite);
|
|
||||||
return composite;
|
|
||||||
};
|
|
||||||
VerletWorld.prototype.updateTiming = function () {
|
|
||||||
this._leftOverTime += Time.deltaTime;
|
|
||||||
this._iterationSteps = Math.trunc(this._leftOverTime / this._fixedDeltaTime);
|
|
||||||
this._leftOverTime -= this._iterationSteps * this._fixedDeltaTime;
|
|
||||||
this._iterationSteps = Math.min(this._iterationSteps, this.maximumStepIterations);
|
|
||||||
};
|
|
||||||
VerletWorld._colliders = new Array(4);
|
|
||||||
return VerletWorld;
|
|
||||||
}());
|
|
||||||
var Composite = (function () {
|
|
||||||
function Composite() {
|
|
||||||
this._constraints = [];
|
|
||||||
this.friction = new Vector2(0.98, 1);
|
|
||||||
this.drawParticles = true;
|
|
||||||
this.drawConstraints = true;
|
|
||||||
this.particles = [];
|
|
||||||
this.collidesWithLayers = Physics.allLayers;
|
|
||||||
}
|
|
||||||
Composite.prototype.solveConstraints = function () {
|
|
||||||
for (var i = this._constraints.length - 1; i >= 0; i--) {
|
|
||||||
this._constraints[i].solve();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Composite.prototype.addParticle = function (particle) {
|
|
||||||
this.particles.push(particle);
|
|
||||||
return particle;
|
|
||||||
};
|
|
||||||
Composite.prototype.addConstraint = function (constraint) {
|
|
||||||
this._constraints.push(constraint);
|
|
||||||
constraint.composite = this;
|
|
||||||
return constraint;
|
|
||||||
};
|
|
||||||
Composite.prototype.removeConstraint = function (constraint) {
|
|
||||||
this._constraints.remove(constraint);
|
|
||||||
};
|
|
||||||
Composite.prototype.updateParticles = function (deltaTimeSquared, gravity) {
|
|
||||||
for (var j = 0; j < this.particles.length; j++) {
|
|
||||||
var p = this.particles[j];
|
|
||||||
if (p.isPinned) {
|
|
||||||
p.position = p.pinnedPosition;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
p.applyForce(Vector2.multiply(new Vector2(p.mass, p.mass), gravity));
|
|
||||||
var vel = Vector2.multiply(Vector2.subtract(p.position, p.lastPosition), this.friction);
|
|
||||||
var nextPos = Vector2.add(Vector2.add(p.position, vel), Vector2.multiply(p.acceleration, new Vector2(0.5 * deltaTimeSquared, 0.5 * deltaTimeSquared)));
|
|
||||||
p.lastPosition = p.position;
|
|
||||||
p.position = nextPos;
|
|
||||||
p.acceleration.x = p.acceleration.y = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Composite.prototype.handleConstraintCollisions = function () {
|
|
||||||
for (var i = this._constraints.length - 1; i >= 0; i--) {
|
|
||||||
if (this._constraints[i].collidesWithColliders)
|
|
||||||
this._constraints[i].handleCollisions(this.collidesWithLayers);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Composite.prototype.debugRender = function (graphics) {
|
|
||||||
if (this.drawConstraints) {
|
|
||||||
for (var i = 0; i < this._constraints.length; i++) {
|
|
||||||
this._constraints[i].debugRender(graphics);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.drawParticles) {
|
|
||||||
for (var i = 0; i < this.particles.length; i++) {
|
|
||||||
var size = this.particles[i].radius ? this.particles[i].radius : 4;
|
|
||||||
graphics.lineStyle(4, DebugDefaults.verletParticle);
|
|
||||||
graphics.drawRect(this.particles[i].position.x, this.particles[i].position.y, size, size);
|
|
||||||
graphics.endFill();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return Composite;
|
|
||||||
}());
|
|
||||||
var Box = (function (_super) {
|
|
||||||
__extends(Box, _super);
|
|
||||||
function Box(center, width, height, borderStiffness, diagonalStiffness) {
|
|
||||||
if (borderStiffness === void 0) { borderStiffness = 0.2; }
|
|
||||||
if (diagonalStiffness === void 0) { diagonalStiffness = 0.5; }
|
|
||||||
var _this = _super.call(this) || this;
|
|
||||||
var tl = _this.addParticle(new Particle(Vector2.add(center, new Vector2(-width / 2, -height / 2))));
|
|
||||||
var tr = _this.addParticle(new Particle(Vector2.add(center, new Vector2(width / 2, -height / 2))));
|
|
||||||
var br = _this.addParticle(new Particle(Vector2.add(center, new Vector2(width / 2, height / 2))));
|
|
||||||
var bl = _this.addParticle(new Particle(Vector2.add(center, new Vector2(-width / 2, height / 2))));
|
|
||||||
_this.addConstraint(new DistanceConstraint(tl, tr, borderStiffness));
|
|
||||||
_this.addConstraint(new DistanceConstraint(tr, br, borderStiffness));
|
|
||||||
_this.addConstraint(new DistanceConstraint(br, bl, borderStiffness));
|
|
||||||
_this.addConstraint(new DistanceConstraint(bl, tl, borderStiffness));
|
|
||||||
_this.addConstraint(new DistanceConstraint(tl, br, diagonalStiffness)).setCollidesWithColliders(false);
|
|
||||||
_this.addConstraint(new DistanceConstraint(bl, tr, diagonalStiffness)).setCollidesWithColliders(false);
|
|
||||||
return _this;
|
|
||||||
}
|
|
||||||
return Box;
|
|
||||||
}(Composite));
|
|
||||||
var Constraint = (function () {
|
|
||||||
function Constraint() {
|
|
||||||
this.collidesWithColliders = true;
|
|
||||||
}
|
|
||||||
Constraint.prototype.handleCollisions = function (collidesWithLayers) {
|
|
||||||
};
|
|
||||||
Constraint.prototype.debugRender = function (graphics) { };
|
|
||||||
return Constraint;
|
|
||||||
}());
|
|
||||||
var DistanceConstraint = (function (_super) {
|
|
||||||
__extends(DistanceConstraint, _super);
|
|
||||||
function DistanceConstraint(first, second, stiffness, distance) {
|
|
||||||
if (distance === void 0) { distance = -1; }
|
|
||||||
var _this = _super.call(this) || this;
|
|
||||||
_this.stiffness = 0;
|
|
||||||
_this.restingDistance = 0;
|
|
||||||
_this.tearSensitivity = Number.POSITIVE_INFINITY;
|
|
||||||
_this._particleOne = first;
|
|
||||||
_this._particleTwo = second;
|
|
||||||
_this.stiffness = stiffness;
|
|
||||||
if (distance > -1) {
|
|
||||||
_this.restingDistance = distance;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_this.restingDistance = Vector2.distance(first.position, second.position);
|
|
||||||
}
|
|
||||||
return _this;
|
|
||||||
}
|
|
||||||
DistanceConstraint.prototype.setCollidesWithColliders = function (collidesWithColliders) {
|
|
||||||
this.collidesWithColliders = collidesWithColliders;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
DistanceConstraint.prototype.handleCollisions = function (collidersWithLayers) {
|
|
||||||
var minX = Math.min(this._particleOne.position.x, this._particleTwo.position.x);
|
|
||||||
var maxX = Math.max(this._particleOne.position.x, this._particleTwo.position.x);
|
|
||||||
var minY = Math.min(this._particleOne.position.y, this._particleTwo.position.y);
|
|
||||||
var maxY = Math.max(this._particleOne.position.y, this._particleTwo.position.y);
|
|
||||||
};
|
|
||||||
DistanceConstraint.prototype.solve = function () {
|
|
||||||
var diff = Vector2.subtract(this._particleOne.position, this._particleTwo.position);
|
|
||||||
var d = diff.length();
|
|
||||||
var difference = (this.restingDistance - d) / d;
|
|
||||||
if (d / this.restingDistance > this.tearSensitivity) {
|
|
||||||
this.composite.removeConstraint(this);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var im1 = 1 / this._particleOne.mass;
|
|
||||||
var im2 = 1 / this._particleTwo.mass;
|
|
||||||
var scalarP1 = (im1 / (im1 + im2)) * this.stiffness;
|
|
||||||
var scalarP2 = this.stiffness - scalarP1;
|
|
||||||
this._particleOne.position = Vector2.add(this._particleOne.position, Vector2.multiply(diff, new Vector2(scalarP1 * difference, scalarP1 * difference)));
|
|
||||||
this._particleTwo.position = Vector2.subtract(this._particleTwo.position, Vector2.multiply(diff, new Vector2(scalarP2 * difference, scalarP2 * difference)));
|
|
||||||
};
|
|
||||||
DistanceConstraint.prototype.debugRender = function (graphics) {
|
|
||||||
graphics.lineStyle(1, DebugDefaults.verletConstraintEdge);
|
|
||||||
graphics.lineTo(this._particleOne.position.x, this._particleOne.position.y);
|
|
||||||
graphics.lineTo(this._particleTwo.position.x, this._particleTwo.position.y);
|
|
||||||
graphics.endFill();
|
|
||||||
};
|
|
||||||
DistanceConstraint._polygon = new Polygon(2, 1);
|
|
||||||
return DistanceConstraint;
|
|
||||||
}(Constraint));
|
|
||||||
var Triangulator = (function () {
|
var Triangulator = (function () {
|
||||||
function Triangulator() {
|
function Triangulator() {
|
||||||
this.triangleIndices = [];
|
this.triangleIndices = [];
|
||||||
@@ -3494,6 +3371,9 @@ var Vector2Ext = (function () {
|
|||||||
Vector2Ext.cross = function (u, v) {
|
Vector2Ext.cross = function (u, v) {
|
||||||
return u.y * v.x - u.x * v.y;
|
return u.y * v.x - u.x * v.y;
|
||||||
};
|
};
|
||||||
|
Vector2Ext.perpendicular = function (first, second) {
|
||||||
|
return new Vector2(-1 * (second.y - first.y), second.x - first.x);
|
||||||
|
};
|
||||||
return Vector2Ext;
|
return Vector2Ext;
|
||||||
}());
|
}());
|
||||||
var WebGLUtils = (function () {
|
var WebGLUtils = (function () {
|
||||||
|
|||||||
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
24
source/src/ECS/Components/Physics/Colliders/BoxCollider.ts
Normal file
24
source/src/ECS/Components/Physics/Colliders/BoxCollider.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
///<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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setWidth(width: number): BoxCollider{
|
||||||
|
this._colliderRequiresAutoSizing = false;
|
||||||
|
let box = this.shape as Box;
|
||||||
|
if (width != box.width){
|
||||||
|
box.updateBox(width, box.height);
|
||||||
|
this._isPositionDirty = true;
|
||||||
|
if (this.entity && this._isParentEntityAddedToScene)
|
||||||
|
Physics.updateCollider(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,8 +2,16 @@ abstract class Collider extends Component{
|
|||||||
public shape: Shape;
|
public shape: Shape;
|
||||||
public physicsLayer = 1 << 0;
|
public physicsLayer = 1 << 0;
|
||||||
public isTrigger: boolean;
|
public isTrigger: boolean;
|
||||||
|
public registeredPhysicsBounds: Rectangle;
|
||||||
|
|
||||||
|
protected _isParentEntityAddedToScene;
|
||||||
|
protected _isPositionDirty = true;
|
||||||
|
protected _colliderRequiresAutoSizing;
|
||||||
|
|
||||||
public get bounds(): Rectangle {
|
public get bounds(): Rectangle {
|
||||||
return this.shape.bounds;
|
return this.shape.bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public initialize() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -32,11 +32,11 @@ class Rectangle {
|
|||||||
this.y = value.y;
|
this.y = value.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(x: number, y: number, width: number, height: number) {
|
constructor(x?: number, y?: number, width?: number, height?: number) {
|
||||||
this.x = x;
|
this.x = x ? x : 0;
|
||||||
this.y = y;
|
this.y = y ? y : 0;
|
||||||
this.width = width;
|
this.width = width ? width : 0;
|
||||||
this.height = height;
|
this.height = height ? height : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public intersects(value: Rectangle) {
|
public intersects(value: Rectangle) {
|
||||||
|
|||||||
@@ -10,4 +10,9 @@ class Physics {
|
|||||||
public static boxcastBroadphase(rect: Rectangle, layerMask: number = this.allLayers){
|
public static boxcastBroadphase(rect: Rectangle, layerMask: number = this.allLayers){
|
||||||
return this._spatialHash.aabbBroadphase(rect, null, layerMask);
|
return this._spatialHash.aabbBroadphase(rect, null, layerMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static updateCollider(collider: Collider){
|
||||||
|
this._spatialHash.remove(collider);
|
||||||
|
this._spatialHash.register(collider);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
28
source/src/Physics/Shapes/Box.ts
Normal file
28
source/src/Physics/Shapes/Box.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
///<reference path="./Polygon.ts" />
|
||||||
|
class Box extends Polygon {
|
||||||
|
public width: number;
|
||||||
|
public height: number;
|
||||||
|
|
||||||
|
public updateBox(width: number, height: number){
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
|
||||||
|
let halfWidth = width / 2;
|
||||||
|
let halfHeight = height / 2;
|
||||||
|
|
||||||
|
this.points[0] = new Vector2(-halfWidth, -halfHeight);
|
||||||
|
this.points[1] = new Vector2(halfWidth, -halfHeight);
|
||||||
|
this.points[2] = new Vector2(halfWidth, halfHeight);
|
||||||
|
this.points[3] = new Vector2(-halfWidth, halfHeight);
|
||||||
|
|
||||||
|
for (let i = 0; i < this.points.length; i ++)
|
||||||
|
this._originalPoints[i] = this.points[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
public containsPoint(point: Vector2){
|
||||||
|
if (this.isUnrotated)
|
||||||
|
return this.bounds.contains(point);
|
||||||
|
|
||||||
|
return super.containsPoint(point);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,8 +14,8 @@ class Circle extends Shape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public collidesWithShape(other: Shape): CollisionResult{
|
public collidesWithShape(other: Shape): CollisionResult{
|
||||||
if (other instanceof Rect && (other as Rect).isUnrotated){
|
if (other instanceof Box && (other as Box).isUnrotated){
|
||||||
return ShapeCollisions.circleToRect(this, other as Rect);
|
return ShapeCollisions.circleToRect(this, other as Box);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(`Collisions of Circle to ${other} are not supported`);
|
throw new Error(`Collisions of Circle to ${other} are not supported`);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ class Polygon extends Shape {
|
|||||||
public isUnrotated: boolean = true;
|
public isUnrotated: boolean = true;
|
||||||
private _polygonCenter: Vector2;
|
private _polygonCenter: Vector2;
|
||||||
private _areEdgeNormalsDirty = true;
|
private _areEdgeNormalsDirty = true;
|
||||||
private _originalPoint: Vector2[];
|
protected _originalPoints: Vector2[];
|
||||||
|
|
||||||
public _edgeNormals: Vector2[];
|
public _edgeNormals: Vector2[];
|
||||||
public get edgeNormals(){
|
public get edgeNormals(){
|
||||||
@@ -42,8 +42,8 @@ class Polygon extends Shape {
|
|||||||
this.points = points;
|
this.points = points;
|
||||||
this.recalculateCenterAndEdgeNormals();
|
this.recalculateCenterAndEdgeNormals();
|
||||||
|
|
||||||
this._originalPoint = new Vector2[points.length];
|
this._originalPoints = new Vector2[points.length];
|
||||||
this._originalPoint = points;
|
this._originalPoints = points;
|
||||||
}
|
}
|
||||||
|
|
||||||
public collidesWithShape(other: Shape){
|
public collidesWithShape(other: Shape){
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
class Rect extends Polygon {
|
|
||||||
public containsPoint(point: Vector2){
|
|
||||||
if (this.isUnrotated)
|
|
||||||
return this.bounds.contains(point);
|
|
||||||
|
|
||||||
return super.containsPoint(point);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -32,7 +32,7 @@ class ShapeCollisions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static circleToRect(circle: Circle, box: Rect): CollisionResult{
|
public static circleToRect(circle: Circle, box: Box): CollisionResult{
|
||||||
let result = new CollisionResult();
|
let result = new CollisionResult();
|
||||||
let closestPointOnBounds = box.bounds.getClosestPointOnRectangleBorderToPoint(circle.position).res;
|
let closestPointOnBounds = box.bounds.getClosestPointOnRectangleBorderToPoint(circle.position).res;
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
///<reference path="./Composite.ts"/>
|
|
||||||
class Box extends Composite{
|
|
||||||
constructor(center: Vector2, width: number, height: number, borderStiffness = 0.2, diagonalStiffness = 0.5){
|
|
||||||
super();
|
|
||||||
|
|
||||||
let tl = this.addParticle(new Particle(Vector2.add(center, new Vector2(-width / 2, -height / 2))));
|
|
||||||
let tr = this.addParticle(new Particle(Vector2.add(center, new Vector2(width / 2, -height / 2))));
|
|
||||||
let br = this.addParticle(new Particle(Vector2.add(center, new Vector2(width / 2, height / 2))));
|
|
||||||
let bl = this.addParticle(new Particle(Vector2.add(center, new Vector2(-width / 2, height / 2))));
|
|
||||||
|
|
||||||
this.addConstraint(new DistanceConstraint(tl, tr, borderStiffness));
|
|
||||||
this.addConstraint(new DistanceConstraint(tr, br, borderStiffness));
|
|
||||||
this.addConstraint(new DistanceConstraint(br, bl, borderStiffness));
|
|
||||||
this.addConstraint(new DistanceConstraint(bl, tl, borderStiffness));
|
|
||||||
|
|
||||||
this.addConstraint(new DistanceConstraint(tl, br, diagonalStiffness)).setCollidesWithColliders(false);
|
|
||||||
this.addConstraint(new DistanceConstraint(bl, tr, diagonalStiffness)).setCollidesWithColliders(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
class Composite {
|
|
||||||
private _constraints: Constraint[] = [];
|
|
||||||
|
|
||||||
public friction = new Vector2(0.98, 1);
|
|
||||||
public drawParticles: boolean = true;
|
|
||||||
public drawConstraints: boolean = true;
|
|
||||||
public particles: Particle[] = [];
|
|
||||||
public collidesWithLayers = Physics.allLayers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理解决所有约束条件
|
|
||||||
*/
|
|
||||||
public solveConstraints(){
|
|
||||||
for (let i = this._constraints.length - 1; i >= 0; i --){
|
|
||||||
this._constraints[i].solve();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public addParticle(particle: Particle){
|
|
||||||
this.particles.push(particle);
|
|
||||||
return particle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public addConstraint<T extends Constraint>(constraint: T): T{
|
|
||||||
this._constraints.push(constraint);
|
|
||||||
constraint.composite = this;
|
|
||||||
return constraint;
|
|
||||||
}
|
|
||||||
|
|
||||||
public removeConstraint(constraint: Constraint){
|
|
||||||
this._constraints.remove(constraint);
|
|
||||||
}
|
|
||||||
|
|
||||||
public updateParticles(deltaTimeSquared: number, gravity: Vector2){
|
|
||||||
for (let j = 0; j < this.particles.length; j ++){
|
|
||||||
let p = this.particles[j];
|
|
||||||
if (p.isPinned){
|
|
||||||
p.position = p.pinnedPosition;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.applyForce(Vector2.multiply(new Vector2(p.mass, p.mass), gravity));
|
|
||||||
|
|
||||||
let vel = Vector2.multiply(Vector2.subtract(p.position, p.lastPosition), this.friction);
|
|
||||||
let nextPos = Vector2.add(Vector2.add(p.position, vel), Vector2.multiply(p.acceleration, new Vector2(0.5 * deltaTimeSquared, 0.5 * deltaTimeSquared)));
|
|
||||||
|
|
||||||
p.lastPosition = p.position;
|
|
||||||
p.position = nextPos;
|
|
||||||
p.acceleration.x = p.acceleration.y = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public handleConstraintCollisions(){
|
|
||||||
for (let i = this._constraints.length - 1; i >= 0; i --){
|
|
||||||
if (this._constraints[i].collidesWithColliders)
|
|
||||||
this._constraints[i].handleCollisions(this.collidesWithLayers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public debugRender(graphics: egret.Graphics){
|
|
||||||
if (this.drawConstraints){
|
|
||||||
for (let i = 0; i < this._constraints.length; i ++){
|
|
||||||
this._constraints[i].debugRender(graphics);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.drawParticles){
|
|
||||||
for (let i = 0; i < this.particles.length; i ++){
|
|
||||||
let size = this.particles[i].radius ? this.particles[i].radius : 4;
|
|
||||||
graphics.lineStyle(4, DebugDefaults.verletParticle);
|
|
||||||
graphics.drawRect(this.particles[i].position.x, this.particles[i].position.y, size, size);
|
|
||||||
graphics.endFill();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
abstract class Constraint {
|
|
||||||
public composite: Composite;
|
|
||||||
public collidesWithColliders = true;
|
|
||||||
|
|
||||||
public abstract solve();
|
|
||||||
|
|
||||||
public handleCollisions(collidesWithLayers: number){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public debugRender(graphics: egret.Graphics) {}
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
///<reference path="../../Shapes/Polygon.ts"/>
|
|
||||||
class DistanceConstraint extends Constraint {
|
|
||||||
public stiffness: number = 0;
|
|
||||||
public restingDistance: number = 0;
|
|
||||||
public tearSensitivity = Number.POSITIVE_INFINITY;
|
|
||||||
public shouldApproximateCollisionWithPoints: boolean;
|
|
||||||
public totalPointsToApproximateCollisionsWith = 5;
|
|
||||||
|
|
||||||
private _particleOne: Particle;
|
|
||||||
private _particleTwo: Particle;
|
|
||||||
private static _polygon = new Polygon(2, 1);
|
|
||||||
|
|
||||||
constructor(first: Particle, second: Particle, stiffness: number, distance = -1){
|
|
||||||
super();
|
|
||||||
|
|
||||||
this._particleOne = first;
|
|
||||||
this._particleTwo = second;
|
|
||||||
this.stiffness = stiffness;
|
|
||||||
|
|
||||||
if (distance > -1){
|
|
||||||
this.restingDistance = distance;
|
|
||||||
}else{
|
|
||||||
this.restingDistance = Vector2.distance(first.position, second.position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public setCollidesWithColliders(collidesWithColliders: boolean){
|
|
||||||
this.collidesWithColliders = collidesWithColliders;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public handleCollisions(collidersWithLayers){
|
|
||||||
if (this.shouldApproximateCollisionWithPoints){
|
|
||||||
this.approximateCollisionWithPoints(collidersWithLayers)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let minX = Math.min(this._particleOne.position.x, this._particleTwo.position.x);
|
|
||||||
let maxX = Math.max(this._particleOne.position.x, this._particleTwo.position.x);
|
|
||||||
let minY = Math.min(this._particleOne.position.y, this._particleTwo.position.y);
|
|
||||||
let maxY = Math.max(this._particleOne.position.y, this._particleTwo.position.y);
|
|
||||||
DistanceConstraint._polygon.bounds = Rectangle.fromMinMax(minX, minY, maxX, maxY);
|
|
||||||
|
|
||||||
let midPoint: Vector2 = this.preparePolygonForCollisionChecks();
|
|
||||||
let colliders = Physics.boxcastBroadphase(DistanceConstraint._polygon.bounds, collidersWithLayers);
|
|
||||||
colliders.forEach(collider => {
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private preparePolygonForCollisionChecks(){
|
|
||||||
let midPoint = Vector2.lerp(this._particleOne.position, this._particleTwo.position, 0.5);
|
|
||||||
DistanceConstraint._polygon.position = midPoint;
|
|
||||||
DistanceConstraint._polygon.points[0] = Vector2.subtract(this._particleOne.position, DistanceConstraint._polygon.position);
|
|
||||||
DistanceConstraint._polygon.points[1] = Vector2.subtract(this._particleTwo.position, DistanceConstraint._polygon.position);
|
|
||||||
DistanceConstraint._polygon.recalculateCenterAndEdgeNormals();
|
|
||||||
|
|
||||||
return midPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
private approximateCollisionWithPoints(collidersWithLayers: number){
|
|
||||||
let pt;
|
|
||||||
for (let j = 0; j < this.totalPointsToApproximateCollisionsWith - 1; j ++){
|
|
||||||
pt = Vector2.lerp(this._particleOne.position, this._particleTwo.position, (j + 1) / this.totalPointsToApproximateCollisionsWith);
|
|
||||||
let collidedCount = Physics.overlapCircleAll(pt, 3, VerletWorld.colliders, collidersWithLayers);
|
|
||||||
for (let i = 0; i < collidedCount; i ++){
|
|
||||||
let collider = VerletWorld.colliders[i];
|
|
||||||
let collisionResult: CollisionResult = collider.shape.pointCollidesWithShape(pt);
|
|
||||||
if (collisionResult){
|
|
||||||
this._particleOne.position = Vector2.subtract(this._particleOne.position, collisionResult.minimumTranslationVector);
|
|
||||||
this._particleTwo.position = Vector2.subtract(this._particleTwo.position, collisionResult.minimumTranslationVector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public solve() {
|
|
||||||
let diff = Vector2.subtract(this._particleOne.position, this._particleTwo.position);
|
|
||||||
let d = diff.length();
|
|
||||||
|
|
||||||
let difference = (this.restingDistance - d) / d;
|
|
||||||
|
|
||||||
if (d / this.restingDistance > this.tearSensitivity){
|
|
||||||
this.composite.removeConstraint(this);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let im1 = 1 / this._particleOne.mass;
|
|
||||||
let im2 = 1 / this._particleTwo.mass;
|
|
||||||
let scalarP1 = (im1 / (im1 + im2)) * this.stiffness;
|
|
||||||
let scalarP2 = this.stiffness - scalarP1;
|
|
||||||
|
|
||||||
this._particleOne.position = Vector2.add(this._particleOne.position, Vector2.multiply(diff, new Vector2(scalarP1 * difference, scalarP1 * difference)));
|
|
||||||
this._particleTwo.position = Vector2.subtract(this._particleTwo.position, Vector2.multiply(diff, new Vector2(scalarP2 * difference, scalarP2 * difference)))
|
|
||||||
}
|
|
||||||
|
|
||||||
public debugRender(graphics: egret.Graphics){
|
|
||||||
graphics.lineStyle(1, DebugDefaults.verletConstraintEdge);
|
|
||||||
graphics.lineTo(this._particleOne.position.x, this._particleOne.position.y);
|
|
||||||
graphics.lineTo(this._particleTwo.position.x, this._particleTwo.position.y);
|
|
||||||
graphics.endFill();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
class SpatialHash {
|
class SpatialHash {
|
||||||
|
public gridBounds: Rectangle = new Rectangle();
|
||||||
|
|
||||||
private _raycastParser: RaycastResultParser;
|
private _raycastParser: RaycastResultParser;
|
||||||
private _cellSize: number;
|
private _cellSize: number;
|
||||||
private _inverseCellSize: number;
|
private _inverseCellSize: number;
|
||||||
@@ -12,6 +14,29 @@ class SpatialHash {
|
|||||||
this._raycastParser = new RaycastResultParser();
|
this._raycastParser = new RaycastResultParser();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public remove(collider: Collider){
|
||||||
|
let bounds = collider.registeredPhysicsBounds;
|
||||||
|
let p1 = this.cellCoords(bounds.x, bounds.y);
|
||||||
|
let p2 = this.cellCoords(bounds.right, bounds.bottom);
|
||||||
|
|
||||||
|
for (let x = p1.x; x <= p2.x; x ++){
|
||||||
|
for (let y = p1.y; y <= p2.y; y ++){
|
||||||
|
let cell = this.cellAtPosition(x, y);
|
||||||
|
if (!cell)
|
||||||
|
console.error(`removing Collider [${collider}] from a cell that it is not present in`);
|
||||||
|
else
|
||||||
|
cell.remove(collider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public register(collider: Collider){
|
||||||
|
let bounds = collider.bounds;
|
||||||
|
collider.registeredPhysicsBounds = bounds;
|
||||||
|
let p1 = this.cellCoords(bounds.x, bounds.y);
|
||||||
|
let p2 = this.cellCoords(bounds.right, bounds.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
public overlapCircle(circleCenter: Vector2, radius: number, results: Collider[], layerMask){
|
public overlapCircle(circleCenter: Vector2, radius: number, results: Collider[], layerMask){
|
||||||
let bounds = new Rectangle(circleCenter.x - radius, circleCenter.y - radius, radius * 2, radius * 2);
|
let bounds = new Rectangle(circleCenter.x - radius, circleCenter.y - radius, radius * 2, radius * 2);
|
||||||
|
|
||||||
|
|||||||
@@ -1,135 +0,0 @@
|
|||||||
/**
|
|
||||||
* 基于verlet进行改造的物理引擎 ts重写
|
|
||||||
* https://github.com/subprotocol/verlet-js
|
|
||||||
*/
|
|
||||||
class VerletWorld {
|
|
||||||
public gravity: Vector2 = new Vector2(0, 980);
|
|
||||||
public maximumStepIterations = 5;
|
|
||||||
public constraintIterations = 3;
|
|
||||||
public simulationBounds: Rectangle;
|
|
||||||
|
|
||||||
private _leftOverTime: number = 0;
|
|
||||||
private _iterationSteps: number = 0;
|
|
||||||
private _fixedDeltaTime = 1 / 60;
|
|
||||||
private _composites: Composite[] = [];
|
|
||||||
private _fixedDeltaTimeSq: number;
|
|
||||||
|
|
||||||
public static colliders: Collider[] = new Array(4);
|
|
||||||
private _tempCircle: Circle = new Circle(1);
|
|
||||||
|
|
||||||
constructor(simulationBounds?: Rectangle){
|
|
||||||
this.simulationBounds = simulationBounds;
|
|
||||||
this._fixedDeltaTimeSq = Math.pow(this._fixedDeltaTime, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public update(){
|
|
||||||
this.updateTiming();
|
|
||||||
|
|
||||||
for (let iteration = 1; iteration <= this._iterationSteps; iteration ++){
|
|
||||||
for (let i = this._composites.length - 1; i >= 0; i --){
|
|
||||||
let composite = this._composites[i];
|
|
||||||
|
|
||||||
for (let s = 0; s < this.constraintIterations; s++){
|
|
||||||
composite.solveConstraints();
|
|
||||||
}
|
|
||||||
|
|
||||||
composite.updateParticles(this._fixedDeltaTimeSq, this.gravity);
|
|
||||||
|
|
||||||
composite.handleConstraintCollisions();
|
|
||||||
|
|
||||||
for (let j = 0; j < composite.particles.length; j ++){
|
|
||||||
let p = composite.particles[j];
|
|
||||||
|
|
||||||
if (this.simulationBounds){
|
|
||||||
this.constrainParticleToBounds(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p.collidesWithColliders)
|
|
||||||
this.handleCollisions(p, composite.collidesWithLayers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleCollisions(p: Particle, collidesWithLayers: number){
|
|
||||||
let collidedCount = Physics.overlapCircleAll(p.position, p.radius, VerletWorld.colliders, collidesWithLayers);
|
|
||||||
for (let i = 0; i < collidedCount; i ++){
|
|
||||||
let collider = VerletWorld.colliders[i];
|
|
||||||
if (collider.isTrigger)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (p.radius < 2){
|
|
||||||
let collisionResult = collider.shape.pointCollidesWithShape(p.position);
|
|
||||||
if (collisionResult){
|
|
||||||
p.position = Vector2.subtract(p.position, collisionResult.minimumTranslationVector);
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
this._tempCircle.radius = p.radius;
|
|
||||||
this._tempCircle.position = p.position;
|
|
||||||
|
|
||||||
let collisionResult = this._tempCircle.collidesWithShape(collider.shape);
|
|
||||||
if (collisionResult){
|
|
||||||
p.position = Vector2.subtract(p.position, collisionResult.minimumTranslationVector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private constrainParticleToBounds(p: Particle){
|
|
||||||
let tempPos = p.position;
|
|
||||||
let bounds = this.simulationBounds;
|
|
||||||
|
|
||||||
if (p.radius == 0){
|
|
||||||
if (tempPos.y > bounds.height){
|
|
||||||
tempPos.y = bounds.height;
|
|
||||||
} else if(tempPos.y < bounds.y){
|
|
||||||
tempPos.y = bounds.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tempPos.x < bounds.x){
|
|
||||||
tempPos.x = bounds.x;
|
|
||||||
}else if(tempPos.x > bounds.width){
|
|
||||||
tempPos.x = bounds.width;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
if (tempPos.y < bounds.y + p.radius){
|
|
||||||
tempPos.y = 2 * (bounds.y + p.radius) - tempPos.y;
|
|
||||||
}
|
|
||||||
if (tempPos.y > bounds.height - p.radius){
|
|
||||||
tempPos.y = 2 * (bounds.height - p.radius) - tempPos.y;
|
|
||||||
}
|
|
||||||
if (tempPos.x > bounds.width - p.radius){
|
|
||||||
tempPos.x = 2 * (bounds.width - p.radius) - tempPos.x;
|
|
||||||
}
|
|
||||||
if (tempPos.x < bounds.x + p.radius)
|
|
||||||
tempPos.x = 2 * (bounds.x + p.radius) - tempPos.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.position = tempPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public debugRender(displayObject: egret.DisplayObject){
|
|
||||||
if (!displayObject)
|
|
||||||
return;
|
|
||||||
|
|
||||||
displayObject.stage.removeChildren();
|
|
||||||
for (let i = 0; i < this._composites.length; i ++){
|
|
||||||
let shape = new egret.Shape();
|
|
||||||
this._composites[i].debugRender(shape.graphics);
|
|
||||||
displayObject.stage.addChild(shape);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public addComposite<T extends Composite>(composite: T): T{
|
|
||||||
this._composites.push(composite);
|
|
||||||
return composite;
|
|
||||||
}
|
|
||||||
|
|
||||||
private updateTiming(){
|
|
||||||
this._leftOverTime += Time.deltaTime;
|
|
||||||
this._iterationSteps = Math.trunc(this._leftOverTime / this._fixedDeltaTime);
|
|
||||||
this._leftOverTime -= this._iterationSteps * this._fixedDeltaTime;
|
|
||||||
|
|
||||||
this._iterationSteps = Math.min(this._iterationSteps, this.maximumStepIterations);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user