新增box复合体 修复vector2运算问题
This commit is contained in:
85
demo/libs/framework/framework.d.ts
vendored
85
demo/libs/framework/framework.d.ts
vendored
@@ -135,6 +135,10 @@ declare class WeightedPathfinder {
|
|||||||
private static getKey;
|
private static getKey;
|
||||||
static recontructPath<T>(cameFrom: Map<T, T>, start: T, goal: T): T[];
|
static recontructPath<T>(cameFrom: Map<T, T>, start: T, goal: T): T[];
|
||||||
}
|
}
|
||||||
|
declare class DebugDefaults {
|
||||||
|
static verletParticle: number;
|
||||||
|
static verletConstraintEdge: number;
|
||||||
|
}
|
||||||
declare abstract class Component {
|
declare abstract class Component {
|
||||||
entity: Entity;
|
entity: Entity;
|
||||||
private _enabled;
|
private _enabled;
|
||||||
@@ -358,6 +362,9 @@ declare abstract class RenderableComponent extends Component {
|
|||||||
readonly height: number;
|
readonly height: number;
|
||||||
isVisible: boolean;
|
isVisible: boolean;
|
||||||
readonly bounds: Rectangle;
|
readonly bounds: Rectangle;
|
||||||
|
protected getWidth(): number;
|
||||||
|
protected getHeight(): number;
|
||||||
|
protected getBounds(): Rectangle;
|
||||||
protected onBecameVisible(): void;
|
protected onBecameVisible(): void;
|
||||||
protected onBecameInvisible(): void;
|
protected onBecameInvisible(): void;
|
||||||
isVisibleFromCamera(camera: Camera): boolean;
|
isVisibleFromCamera(camera: Camera): boolean;
|
||||||
@@ -484,6 +491,7 @@ declare class Time {
|
|||||||
static unscaledDeltaTime: any;
|
static unscaledDeltaTime: any;
|
||||||
static deltaTime: number;
|
static deltaTime: number;
|
||||||
static timeScale: number;
|
static timeScale: number;
|
||||||
|
static frameCount: number;
|
||||||
private static _lastTime;
|
private static _lastTime;
|
||||||
static update(currentTime: number): void;
|
static update(currentTime: number): void;
|
||||||
}
|
}
|
||||||
@@ -538,19 +546,17 @@ declare class Rectangle {
|
|||||||
declare class Vector2 {
|
declare class Vector2 {
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
private static readonly zeroVector;
|
|
||||||
private static readonly unitVector;
|
|
||||||
static readonly One: Vector2;
|
|
||||||
static readonly Zero: Vector2;
|
|
||||||
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;
|
||||||
static subtract(value1: Vector2, value2: Vector2): Vector2;
|
static subtract(value1: Vector2, value2: Vector2): Vector2;
|
||||||
normalize(): void;
|
normalize(): void;
|
||||||
|
length(): number;
|
||||||
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 transform(position: Vector2, matrix: Matrix2D): Vector2;
|
static transform(position: Vector2, matrix: Matrix2D): Vector2;
|
||||||
|
static distance(value1: Vector2, value2: Vector2): number;
|
||||||
}
|
}
|
||||||
declare enum PointSectors {
|
declare enum PointSectors {
|
||||||
center = 0,
|
center = 0,
|
||||||
@@ -575,6 +581,77 @@ declare class Collisions {
|
|||||||
static isRectToPoint(rX: number, rY: number, rW: number, rH: number, point: Vector2): boolean;
|
static isRectToPoint(rX: number, rY: number, rW: number, rH: number, point: Vector2): boolean;
|
||||||
static getSector(rX: number, rY: number, rW: number, rH: number, point: Vector2): PointSectors;
|
static getSector(rX: number, rY: number, rW: number, rH: number, point: Vector2): PointSectors;
|
||||||
}
|
}
|
||||||
|
declare class Physics {
|
||||||
|
private static _spatialHash;
|
||||||
|
static overlapCircleAll(center: Vector2, randius: number, results: any[], layerMask?: number): number;
|
||||||
|
}
|
||||||
|
declare class Particle {
|
||||||
|
position: Vector2;
|
||||||
|
lastPosition: Vector2;
|
||||||
|
isPinned: boolean;
|
||||||
|
pinnedPosition: any;
|
||||||
|
acceleration: Vector2;
|
||||||
|
mass: number;
|
||||||
|
radius: number;
|
||||||
|
collidesWithColliders: boolean;
|
||||||
|
constructor(position: Vector2);
|
||||||
|
applyForce(force: Vector2): void;
|
||||||
|
}
|
||||||
|
declare class SpatialHash {
|
||||||
|
overlapCircle(circleCenter: Vector2, radius: number, results: any[], layerMask: any): number;
|
||||||
|
}
|
||||||
|
declare class VerletWorld {
|
||||||
|
gravity: Vector2;
|
||||||
|
maximumStepIterations: number;
|
||||||
|
constraintIterations: number;
|
||||||
|
simulationBounds: Rectangle;
|
||||||
|
private _leftOverTime;
|
||||||
|
private _iterationSteps;
|
||||||
|
private _fixedDeltaTime;
|
||||||
|
private _composites;
|
||||||
|
private _fixedDeltaTimeSq;
|
||||||
|
private static _colliders;
|
||||||
|
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[];
|
||||||
|
solveConstraints(): void;
|
||||||
|
addParticle(particle: Particle): Particle;
|
||||||
|
addConstraint<T extends Constraint>(constraint: T): T;
|
||||||
|
removeConstraint(constraint: Constraint): void;
|
||||||
|
updateParticles(deltaTimeSquared: number, gravity: Vector2): 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;
|
||||||
|
debugRender(graphics: egret.Graphics): void;
|
||||||
|
}
|
||||||
|
declare class DistanceConstraint extends Constraint {
|
||||||
|
stiffness: number;
|
||||||
|
restingDistance: number;
|
||||||
|
tearSensitivity: number;
|
||||||
|
private _particleOne;
|
||||||
|
private _particleTwo;
|
||||||
|
constructor(first: Particle, second: Particle, stiffness: number, distance?: number);
|
||||||
|
setCollidesWithColliders(collidesWithColliders: boolean): this;
|
||||||
|
solve(): void;
|
||||||
|
debugRender(graphics: egret.Graphics): void;
|
||||||
|
}
|
||||||
declare class Triangulator {
|
declare class Triangulator {
|
||||||
triangleIndices: number[];
|
triangleIndices: number[];
|
||||||
private _triPrev;
|
private _triPrev;
|
||||||
|
|||||||
@@ -730,6 +730,13 @@ var WeightedPathfinder = (function () {
|
|||||||
};
|
};
|
||||||
return WeightedPathfinder;
|
return WeightedPathfinder;
|
||||||
}());
|
}());
|
||||||
|
var DebugDefaults = (function () {
|
||||||
|
function DebugDefaults() {
|
||||||
|
}
|
||||||
|
DebugDefaults.verletParticle = 0xDC345E;
|
||||||
|
DebugDefaults.verletConstraintEdge = 0x433E36;
|
||||||
|
return DebugDefaults;
|
||||||
|
}());
|
||||||
var Component = (function () {
|
var Component = (function () {
|
||||||
function Component() {
|
function Component() {
|
||||||
this._enabled = true;
|
this._enabled = true;
|
||||||
@@ -1171,7 +1178,7 @@ var Transform = (function () {
|
|||||||
this._worldInverseTransform = Matrix2D.identity;
|
this._worldInverseTransform = Matrix2D.identity;
|
||||||
this._rotation = 0;
|
this._rotation = 0;
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
this._scale = this._localScale = Vector2.One;
|
this._scale = this._localScale = new Vector2(0, 0);
|
||||||
this._children = [];
|
this._children = [];
|
||||||
}
|
}
|
||||||
Object.defineProperty(Transform.prototype, "childCount", {
|
Object.defineProperty(Transform.prototype, "childCount", {
|
||||||
@@ -1695,14 +1702,14 @@ var RenderableComponent = (function (_super) {
|
|||||||
}
|
}
|
||||||
Object.defineProperty(RenderableComponent.prototype, "width", {
|
Object.defineProperty(RenderableComponent.prototype, "width", {
|
||||||
get: function () {
|
get: function () {
|
||||||
return this.bounds.width;
|
return this.getWidth();
|
||||||
},
|
},
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true
|
configurable: true
|
||||||
});
|
});
|
||||||
Object.defineProperty(RenderableComponent.prototype, "height", {
|
Object.defineProperty(RenderableComponent.prototype, "height", {
|
||||||
get: function () {
|
get: function () {
|
||||||
return this.bounds.height;
|
return this.getHeight();
|
||||||
},
|
},
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true
|
configurable: true
|
||||||
@@ -1723,15 +1730,24 @@ var RenderableComponent = (function (_super) {
|
|||||||
});
|
});
|
||||||
Object.defineProperty(RenderableComponent.prototype, "bounds", {
|
Object.defineProperty(RenderableComponent.prototype, "bounds", {
|
||||||
get: function () {
|
get: function () {
|
||||||
if (this._areBoundsDirty) {
|
return this.getBounds();
|
||||||
this._bounds.calculateBounds(this.entity.transform.position, this._localOffset, Vector2.Zero, this.entity.transform.scale, this.entity.transform.rotation, this.width, this.height);
|
|
||||||
this._areBoundsDirty = false;
|
|
||||||
}
|
|
||||||
return this._bounds;
|
|
||||||
},
|
},
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true
|
configurable: true
|
||||||
});
|
});
|
||||||
|
RenderableComponent.prototype.getWidth = function () {
|
||||||
|
return this.bounds.width;
|
||||||
|
};
|
||||||
|
RenderableComponent.prototype.getHeight = function () {
|
||||||
|
return this.bounds.height;
|
||||||
|
};
|
||||||
|
RenderableComponent.prototype.getBounds = function () {
|
||||||
|
if (this._areBoundsDirty) {
|
||||||
|
this._bounds.calculateBounds(this.entity.transform.position, this._localOffset, new Vector2(0, 0), this.entity.transform.scale, this.entity.transform.rotation, this.width, this.height);
|
||||||
|
this._areBoundsDirty = false;
|
||||||
|
}
|
||||||
|
return this._bounds;
|
||||||
|
};
|
||||||
RenderableComponent.prototype.onBecameVisible = function () { };
|
RenderableComponent.prototype.onBecameVisible = function () { };
|
||||||
RenderableComponent.prototype.onBecameInvisible = function () { };
|
RenderableComponent.prototype.onBecameInvisible = function () { };
|
||||||
RenderableComponent.prototype.isVisibleFromCamera = function (camera) {
|
RenderableComponent.prototype.isVisibleFromCamera = function (camera) {
|
||||||
@@ -2058,6 +2074,11 @@ var ComponentList = (function () {
|
|||||||
};
|
};
|
||||||
ComponentList.prototype.update = function () {
|
ComponentList.prototype.update = function () {
|
||||||
this.updateLists();
|
this.updateLists();
|
||||||
|
for (var i = 0; i < this._components.length; i++) {
|
||||||
|
var component = this._components[i];
|
||||||
|
if (component.enabled && (component.updateInterval == 1 || Time.frameCount % component.updateInterval == 0))
|
||||||
|
component.update();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
ComponentList.prototype.onEntityTransformChanged = function (comp) {
|
ComponentList.prototype.onEntityTransformChanged = function (comp) {
|
||||||
for (var i = 0; i < this._components.length; i++) {
|
for (var i = 0; i < this._components.length; i++) {
|
||||||
@@ -2285,13 +2306,17 @@ var Matcher = (function () {
|
|||||||
var Time = (function () {
|
var Time = (function () {
|
||||||
function Time() {
|
function Time() {
|
||||||
}
|
}
|
||||||
|
;
|
||||||
Time.update = function (currentTime) {
|
Time.update = function (currentTime) {
|
||||||
var dt = (currentTime - this._lastTime) / 1000;
|
var dt = (currentTime - this._lastTime) / 1000;
|
||||||
this.deltaTime = dt * this.timeScale;
|
this.deltaTime = dt * this.timeScale;
|
||||||
this.unscaledDeltaTime = dt;
|
this.unscaledDeltaTime = dt;
|
||||||
|
this.frameCount++;
|
||||||
this._lastTime = currentTime;
|
this._lastTime = currentTime;
|
||||||
};
|
};
|
||||||
|
Time.deltaTime = 0;
|
||||||
Time.timeScale = 1;
|
Time.timeScale = 1;
|
||||||
|
Time.frameCount = 0;
|
||||||
Time._lastTime = 0;
|
Time._lastTime = 0;
|
||||||
return Time;
|
return Time;
|
||||||
}());
|
}());
|
||||||
@@ -2570,38 +2595,28 @@ var Vector2 = (function () {
|
|||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
}
|
}
|
||||||
Object.defineProperty(Vector2, "One", {
|
|
||||||
get: function () {
|
|
||||||
return this.unitVector;
|
|
||||||
},
|
|
||||||
enumerable: true,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
Object.defineProperty(Vector2, "Zero", {
|
|
||||||
get: function () {
|
|
||||||
return this.zeroVector;
|
|
||||||
},
|
|
||||||
enumerable: true,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
Vector2.add = function (value1, value2) {
|
Vector2.add = function (value1, value2) {
|
||||||
value1.x += value2.x;
|
var result = new Vector2(0, 0);
|
||||||
value1.y += value2.y;
|
result.x = value1.x + value2.x;
|
||||||
return value1;
|
result.y = value1.y + value2.y;
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
Vector2.divide = function (value1, value2) {
|
Vector2.divide = function (value1, value2) {
|
||||||
value1.x /= value2.x;
|
var result = new Vector2(0, 0);
|
||||||
value1.y /= value2.y;
|
result.x = value1.x / value2.x;
|
||||||
|
result.y = value1.y / value2.y;
|
||||||
return value1;
|
return value1;
|
||||||
};
|
};
|
||||||
Vector2.multiply = function (value1, value2) {
|
Vector2.multiply = function (value1, value2) {
|
||||||
value1.x *= value2.x;
|
var result = new Vector2(0, 0);
|
||||||
value1.y *= value2.y;
|
result.x = value1.x * value2.x;
|
||||||
return value1;
|
result.y = value1.y * value2.y;
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
Vector2.subtract = function (value1, value2) {
|
Vector2.subtract = function (value1, value2) {
|
||||||
value1.x -= value2.x;
|
var result = new Vector2(0, 0);
|
||||||
value1.y -= value2.y;
|
result.x = value1.x - value2.x;
|
||||||
|
result.y = value1.y - value2.y;
|
||||||
return value1;
|
return value1;
|
||||||
};
|
};
|
||||||
Vector2.prototype.normalize = function () {
|
Vector2.prototype.normalize = function () {
|
||||||
@@ -2609,6 +2624,9 @@ var Vector2 = (function () {
|
|||||||
this.x *= val;
|
this.x *= val;
|
||||||
this.y *= val;
|
this.y *= val;
|
||||||
};
|
};
|
||||||
|
Vector2.prototype.length = function () {
|
||||||
|
return Math.sqrt((this.x * this.x) + (this.y * this.y));
|
||||||
|
};
|
||||||
Vector2.dot = function (value1, value2) {
|
Vector2.dot = function (value1, value2) {
|
||||||
return (value1.x * value2.x) + (value1.y * value2.y);
|
return (value1.x * value2.x) + (value1.y * value2.y);
|
||||||
};
|
};
|
||||||
@@ -2619,8 +2637,10 @@ var Vector2 = (function () {
|
|||||||
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));
|
||||||
};
|
};
|
||||||
Vector2.zeroVector = new Vector2(0, 0);
|
Vector2.distance = function (value1, value2) {
|
||||||
Vector2.unitVector = new Vector2(1, 1);
|
var v1 = value1.x - value2.x, v2 = value1.y - value2.y;
|
||||||
|
return Math.sqrt((v1 * v1) + (v2 * v2));
|
||||||
|
};
|
||||||
return Vector2;
|
return Vector2;
|
||||||
}());
|
}());
|
||||||
var PointSectors;
|
var PointSectors;
|
||||||
@@ -2654,7 +2674,7 @@ var Collisions = (function () {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
Collisions.lineToLineIntersection = function (a1, a2, b1, b2) {
|
Collisions.lineToLineIntersection = function (a1, a2, b1, b2) {
|
||||||
var intersection = Vector2.Zero;
|
var intersection = new Vector2(0, 0);
|
||||||
var b = Vector2.subtract(a2, a1);
|
var b = Vector2.subtract(a2, a1);
|
||||||
var d = Vector2.subtract(b2, b1);
|
var d = Vector2.subtract(b2, b1);
|
||||||
var bDotDPerp = b.x * d.y - b.y * d.x;
|
var bDotDPerp = b.x * d.y - b.y * d.x;
|
||||||
@@ -2775,6 +2795,258 @@ var Collisions = (function () {
|
|||||||
};
|
};
|
||||||
return Collisions;
|
return Collisions;
|
||||||
}());
|
}());
|
||||||
|
var Physics = (function () {
|
||||||
|
function Physics() {
|
||||||
|
}
|
||||||
|
Physics.overlapCircleAll = function (center, randius, results, layerMask) {
|
||||||
|
if (layerMask === void 0) { layerMask = -1; }
|
||||||
|
return this._spatialHash.overlapCircle(center, randius, results, layerMask);
|
||||||
|
};
|
||||||
|
return Physics;
|
||||||
|
}());
|
||||||
|
var Particle = (function () {
|
||||||
|
function Particle(position) {
|
||||||
|
this.position = new Vector2(0, 0);
|
||||||
|
this.lastPosition = new Vector2(0, 0);
|
||||||
|
this.acceleration = new Vector2(0, 0);
|
||||||
|
this.mass = 1;
|
||||||
|
this.radius = 0;
|
||||||
|
this.collidesWithColliders = true;
|
||||||
|
this.position = position;
|
||||||
|
this.lastPosition = position;
|
||||||
|
}
|
||||||
|
Particle.prototype.applyForce = function (force) {
|
||||||
|
this.acceleration = Vector2.add(this.acceleration, new Vector2(force.x / this.mass, force.y / this.mass));
|
||||||
|
};
|
||||||
|
return Particle;
|
||||||
|
}());
|
||||||
|
var SpatialHash = (function () {
|
||||||
|
function SpatialHash() {
|
||||||
|
}
|
||||||
|
SpatialHash.prototype.overlapCircle = function (circleCenter, radius, results, layerMask) {
|
||||||
|
var resultCounter = 0;
|
||||||
|
return resultCounter;
|
||||||
|
};
|
||||||
|
return SpatialHash;
|
||||||
|
}());
|
||||||
|
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.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);
|
||||||
|
for (var j = 0; j < composite.particles.length; j++) {
|
||||||
|
var p = composite.particles[j];
|
||||||
|
if (this.simulationBounds) {
|
||||||
|
this.constrainParticleToBounds(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
VerletWorld.prototype.handleCollisions = function (p, collidesWithLayers) {
|
||||||
|
var collidedCount = Physics.overlapCircleAll(p.position, p.radius, VerletWorld._colliders, collidesWithLayers);
|
||||||
|
};
|
||||||
|
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 = [];
|
||||||
|
}
|
||||||
|
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.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.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.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();
|
||||||
|
};
|
||||||
|
return DistanceConstraint;
|
||||||
|
}(Constraint));
|
||||||
var Triangulator = (function () {
|
var Triangulator = (function () {
|
||||||
function Triangulator() {
|
function Triangulator() {
|
||||||
this.triangleIndices = [];
|
this.triangleIndices = [];
|
||||||
|
|||||||
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
@@ -17,6 +17,7 @@
|
|||||||
"bin-debug/ThemeAdapter.js",
|
"bin-debug/ThemeAdapter.js",
|
||||||
"bin-debug/game/MainScene.js",
|
"bin-debug/game/MainScene.js",
|
||||||
"bin-debug/game/SpawnerComponent.js",
|
"bin-debug/game/SpawnerComponent.js",
|
||||||
"bin-debug/game/SpawnerSystem.js"
|
"bin-debug/game/SpawnerSystem.js",
|
||||||
|
"bin-debug/game/VerletDemo.js"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -98,6 +98,7 @@ class Main extends eui.UILayer {
|
|||||||
new Vector2(10, 10),
|
new Vector2(10, 10),
|
||||||
new Vector2(0, 10),
|
new Vector2(0, 10),
|
||||||
new Vector2(0, 0)]));
|
new Vector2(0, 0)]));
|
||||||
|
player.addComponent(new VerletDemo());
|
||||||
player.addComponent(new SpawnComponent(EnemyType.worm));
|
player.addComponent(new SpawnComponent(EnemyType.worm));
|
||||||
// console.log(player.transform.position);
|
// console.log(player.transform.position);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ class MainScene extends Scene {
|
|||||||
constructor(displayContent: egret.DisplayObject){
|
constructor(displayContent: egret.DisplayObject){
|
||||||
super(displayContent);
|
super(displayContent);
|
||||||
|
|
||||||
this.addEntityProcessor(new SpawnerSystem(new Matcher()));
|
// this.addEntityProcessor(new SpawnerSystem(new Matcher()));
|
||||||
this.astarTest();
|
this.astarTest();
|
||||||
this.dijkstraTest();
|
this.dijkstraTest();
|
||||||
this.breadthfirstTest();
|
this.breadthfirstTest();
|
||||||
|
|||||||
27
demo/src/game/VerletDemo.ts
Normal file
27
demo/src/game/VerletDemo.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
class VerletDemo extends RenderableComponent {
|
||||||
|
private _world: VerletWorld;
|
||||||
|
|
||||||
|
protected getWidth(){
|
||||||
|
return 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getHeight(){
|
||||||
|
return 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
public onAddedToEntity(){
|
||||||
|
this._world = new VerletWorld(new Rectangle(0, 0, 800, 600));
|
||||||
|
|
||||||
|
this._world.addComposite(new Box(new Vector2(100, 100), 50, 20));
|
||||||
|
this._world.addComposite(new Box(new Vector2(10, 10), 200, 100));
|
||||||
|
this._world.debugRender(this.entity.scene.stage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public update(){
|
||||||
|
this._world.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
85
source/bin/framework.d.ts
vendored
85
source/bin/framework.d.ts
vendored
@@ -135,6 +135,10 @@ declare class WeightedPathfinder {
|
|||||||
private static getKey;
|
private static getKey;
|
||||||
static recontructPath<T>(cameFrom: Map<T, T>, start: T, goal: T): T[];
|
static recontructPath<T>(cameFrom: Map<T, T>, start: T, goal: T): T[];
|
||||||
}
|
}
|
||||||
|
declare class DebugDefaults {
|
||||||
|
static verletParticle: number;
|
||||||
|
static verletConstraintEdge: number;
|
||||||
|
}
|
||||||
declare abstract class Component {
|
declare abstract class Component {
|
||||||
entity: Entity;
|
entity: Entity;
|
||||||
private _enabled;
|
private _enabled;
|
||||||
@@ -358,6 +362,9 @@ declare abstract class RenderableComponent extends Component {
|
|||||||
readonly height: number;
|
readonly height: number;
|
||||||
isVisible: boolean;
|
isVisible: boolean;
|
||||||
readonly bounds: Rectangle;
|
readonly bounds: Rectangle;
|
||||||
|
protected getWidth(): number;
|
||||||
|
protected getHeight(): number;
|
||||||
|
protected getBounds(): Rectangle;
|
||||||
protected onBecameVisible(): void;
|
protected onBecameVisible(): void;
|
||||||
protected onBecameInvisible(): void;
|
protected onBecameInvisible(): void;
|
||||||
isVisibleFromCamera(camera: Camera): boolean;
|
isVisibleFromCamera(camera: Camera): boolean;
|
||||||
@@ -484,6 +491,7 @@ declare class Time {
|
|||||||
static unscaledDeltaTime: any;
|
static unscaledDeltaTime: any;
|
||||||
static deltaTime: number;
|
static deltaTime: number;
|
||||||
static timeScale: number;
|
static timeScale: number;
|
||||||
|
static frameCount: number;
|
||||||
private static _lastTime;
|
private static _lastTime;
|
||||||
static update(currentTime: number): void;
|
static update(currentTime: number): void;
|
||||||
}
|
}
|
||||||
@@ -538,19 +546,17 @@ declare class Rectangle {
|
|||||||
declare class Vector2 {
|
declare class Vector2 {
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
private static readonly zeroVector;
|
|
||||||
private static readonly unitVector;
|
|
||||||
static readonly One: Vector2;
|
|
||||||
static readonly Zero: Vector2;
|
|
||||||
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;
|
||||||
static subtract(value1: Vector2, value2: Vector2): Vector2;
|
static subtract(value1: Vector2, value2: Vector2): Vector2;
|
||||||
normalize(): void;
|
normalize(): void;
|
||||||
|
length(): number;
|
||||||
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 transform(position: Vector2, matrix: Matrix2D): Vector2;
|
static transform(position: Vector2, matrix: Matrix2D): Vector2;
|
||||||
|
static distance(value1: Vector2, value2: Vector2): number;
|
||||||
}
|
}
|
||||||
declare enum PointSectors {
|
declare enum PointSectors {
|
||||||
center = 0,
|
center = 0,
|
||||||
@@ -575,6 +581,77 @@ declare class Collisions {
|
|||||||
static isRectToPoint(rX: number, rY: number, rW: number, rH: number, point: Vector2): boolean;
|
static isRectToPoint(rX: number, rY: number, rW: number, rH: number, point: Vector2): boolean;
|
||||||
static getSector(rX: number, rY: number, rW: number, rH: number, point: Vector2): PointSectors;
|
static getSector(rX: number, rY: number, rW: number, rH: number, point: Vector2): PointSectors;
|
||||||
}
|
}
|
||||||
|
declare class Physics {
|
||||||
|
private static _spatialHash;
|
||||||
|
static overlapCircleAll(center: Vector2, randius: number, results: any[], layerMask?: number): number;
|
||||||
|
}
|
||||||
|
declare class Particle {
|
||||||
|
position: Vector2;
|
||||||
|
lastPosition: Vector2;
|
||||||
|
isPinned: boolean;
|
||||||
|
pinnedPosition: any;
|
||||||
|
acceleration: Vector2;
|
||||||
|
mass: number;
|
||||||
|
radius: number;
|
||||||
|
collidesWithColliders: boolean;
|
||||||
|
constructor(position: Vector2);
|
||||||
|
applyForce(force: Vector2): void;
|
||||||
|
}
|
||||||
|
declare class SpatialHash {
|
||||||
|
overlapCircle(circleCenter: Vector2, radius: number, results: any[], layerMask: any): number;
|
||||||
|
}
|
||||||
|
declare class VerletWorld {
|
||||||
|
gravity: Vector2;
|
||||||
|
maximumStepIterations: number;
|
||||||
|
constraintIterations: number;
|
||||||
|
simulationBounds: Rectangle;
|
||||||
|
private _leftOverTime;
|
||||||
|
private _iterationSteps;
|
||||||
|
private _fixedDeltaTime;
|
||||||
|
private _composites;
|
||||||
|
private _fixedDeltaTimeSq;
|
||||||
|
private static _colliders;
|
||||||
|
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[];
|
||||||
|
solveConstraints(): void;
|
||||||
|
addParticle(particle: Particle): Particle;
|
||||||
|
addConstraint<T extends Constraint>(constraint: T): T;
|
||||||
|
removeConstraint(constraint: Constraint): void;
|
||||||
|
updateParticles(deltaTimeSquared: number, gravity: Vector2): 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;
|
||||||
|
debugRender(graphics: egret.Graphics): void;
|
||||||
|
}
|
||||||
|
declare class DistanceConstraint extends Constraint {
|
||||||
|
stiffness: number;
|
||||||
|
restingDistance: number;
|
||||||
|
tearSensitivity: number;
|
||||||
|
private _particleOne;
|
||||||
|
private _particleTwo;
|
||||||
|
constructor(first: Particle, second: Particle, stiffness: number, distance?: number);
|
||||||
|
setCollidesWithColliders(collidesWithColliders: boolean): this;
|
||||||
|
solve(): void;
|
||||||
|
debugRender(graphics: egret.Graphics): void;
|
||||||
|
}
|
||||||
declare class Triangulator {
|
declare class Triangulator {
|
||||||
triangleIndices: number[];
|
triangleIndices: number[];
|
||||||
private _triPrev;
|
private _triPrev;
|
||||||
|
|||||||
@@ -730,6 +730,13 @@ var WeightedPathfinder = (function () {
|
|||||||
};
|
};
|
||||||
return WeightedPathfinder;
|
return WeightedPathfinder;
|
||||||
}());
|
}());
|
||||||
|
var DebugDefaults = (function () {
|
||||||
|
function DebugDefaults() {
|
||||||
|
}
|
||||||
|
DebugDefaults.verletParticle = 0xDC345E;
|
||||||
|
DebugDefaults.verletConstraintEdge = 0x433E36;
|
||||||
|
return DebugDefaults;
|
||||||
|
}());
|
||||||
var Component = (function () {
|
var Component = (function () {
|
||||||
function Component() {
|
function Component() {
|
||||||
this._enabled = true;
|
this._enabled = true;
|
||||||
@@ -1171,7 +1178,7 @@ var Transform = (function () {
|
|||||||
this._worldInverseTransform = Matrix2D.identity;
|
this._worldInverseTransform = Matrix2D.identity;
|
||||||
this._rotation = 0;
|
this._rotation = 0;
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
this._scale = this._localScale = Vector2.One;
|
this._scale = this._localScale = new Vector2(0, 0);
|
||||||
this._children = [];
|
this._children = [];
|
||||||
}
|
}
|
||||||
Object.defineProperty(Transform.prototype, "childCount", {
|
Object.defineProperty(Transform.prototype, "childCount", {
|
||||||
@@ -1695,14 +1702,14 @@ var RenderableComponent = (function (_super) {
|
|||||||
}
|
}
|
||||||
Object.defineProperty(RenderableComponent.prototype, "width", {
|
Object.defineProperty(RenderableComponent.prototype, "width", {
|
||||||
get: function () {
|
get: function () {
|
||||||
return this.bounds.width;
|
return this.getWidth();
|
||||||
},
|
},
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true
|
configurable: true
|
||||||
});
|
});
|
||||||
Object.defineProperty(RenderableComponent.prototype, "height", {
|
Object.defineProperty(RenderableComponent.prototype, "height", {
|
||||||
get: function () {
|
get: function () {
|
||||||
return this.bounds.height;
|
return this.getHeight();
|
||||||
},
|
},
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true
|
configurable: true
|
||||||
@@ -1723,15 +1730,24 @@ var RenderableComponent = (function (_super) {
|
|||||||
});
|
});
|
||||||
Object.defineProperty(RenderableComponent.prototype, "bounds", {
|
Object.defineProperty(RenderableComponent.prototype, "bounds", {
|
||||||
get: function () {
|
get: function () {
|
||||||
if (this._areBoundsDirty) {
|
return this.getBounds();
|
||||||
this._bounds.calculateBounds(this.entity.transform.position, this._localOffset, Vector2.Zero, this.entity.transform.scale, this.entity.transform.rotation, this.width, this.height);
|
|
||||||
this._areBoundsDirty = false;
|
|
||||||
}
|
|
||||||
return this._bounds;
|
|
||||||
},
|
},
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true
|
configurable: true
|
||||||
});
|
});
|
||||||
|
RenderableComponent.prototype.getWidth = function () {
|
||||||
|
return this.bounds.width;
|
||||||
|
};
|
||||||
|
RenderableComponent.prototype.getHeight = function () {
|
||||||
|
return this.bounds.height;
|
||||||
|
};
|
||||||
|
RenderableComponent.prototype.getBounds = function () {
|
||||||
|
if (this._areBoundsDirty) {
|
||||||
|
this._bounds.calculateBounds(this.entity.transform.position, this._localOffset, new Vector2(0, 0), this.entity.transform.scale, this.entity.transform.rotation, this.width, this.height);
|
||||||
|
this._areBoundsDirty = false;
|
||||||
|
}
|
||||||
|
return this._bounds;
|
||||||
|
};
|
||||||
RenderableComponent.prototype.onBecameVisible = function () { };
|
RenderableComponent.prototype.onBecameVisible = function () { };
|
||||||
RenderableComponent.prototype.onBecameInvisible = function () { };
|
RenderableComponent.prototype.onBecameInvisible = function () { };
|
||||||
RenderableComponent.prototype.isVisibleFromCamera = function (camera) {
|
RenderableComponent.prototype.isVisibleFromCamera = function (camera) {
|
||||||
@@ -2058,6 +2074,11 @@ var ComponentList = (function () {
|
|||||||
};
|
};
|
||||||
ComponentList.prototype.update = function () {
|
ComponentList.prototype.update = function () {
|
||||||
this.updateLists();
|
this.updateLists();
|
||||||
|
for (var i = 0; i < this._components.length; i++) {
|
||||||
|
var component = this._components[i];
|
||||||
|
if (component.enabled && (component.updateInterval == 1 || Time.frameCount % component.updateInterval == 0))
|
||||||
|
component.update();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
ComponentList.prototype.onEntityTransformChanged = function (comp) {
|
ComponentList.prototype.onEntityTransformChanged = function (comp) {
|
||||||
for (var i = 0; i < this._components.length; i++) {
|
for (var i = 0; i < this._components.length; i++) {
|
||||||
@@ -2285,13 +2306,17 @@ var Matcher = (function () {
|
|||||||
var Time = (function () {
|
var Time = (function () {
|
||||||
function Time() {
|
function Time() {
|
||||||
}
|
}
|
||||||
|
;
|
||||||
Time.update = function (currentTime) {
|
Time.update = function (currentTime) {
|
||||||
var dt = (currentTime - this._lastTime) / 1000;
|
var dt = (currentTime - this._lastTime) / 1000;
|
||||||
this.deltaTime = dt * this.timeScale;
|
this.deltaTime = dt * this.timeScale;
|
||||||
this.unscaledDeltaTime = dt;
|
this.unscaledDeltaTime = dt;
|
||||||
|
this.frameCount++;
|
||||||
this._lastTime = currentTime;
|
this._lastTime = currentTime;
|
||||||
};
|
};
|
||||||
|
Time.deltaTime = 0;
|
||||||
Time.timeScale = 1;
|
Time.timeScale = 1;
|
||||||
|
Time.frameCount = 0;
|
||||||
Time._lastTime = 0;
|
Time._lastTime = 0;
|
||||||
return Time;
|
return Time;
|
||||||
}());
|
}());
|
||||||
@@ -2570,38 +2595,28 @@ var Vector2 = (function () {
|
|||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
}
|
}
|
||||||
Object.defineProperty(Vector2, "One", {
|
|
||||||
get: function () {
|
|
||||||
return this.unitVector;
|
|
||||||
},
|
|
||||||
enumerable: true,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
Object.defineProperty(Vector2, "Zero", {
|
|
||||||
get: function () {
|
|
||||||
return this.zeroVector;
|
|
||||||
},
|
|
||||||
enumerable: true,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
Vector2.add = function (value1, value2) {
|
Vector2.add = function (value1, value2) {
|
||||||
value1.x += value2.x;
|
var result = new Vector2(0, 0);
|
||||||
value1.y += value2.y;
|
result.x = value1.x + value2.x;
|
||||||
return value1;
|
result.y = value1.y + value2.y;
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
Vector2.divide = function (value1, value2) {
|
Vector2.divide = function (value1, value2) {
|
||||||
value1.x /= value2.x;
|
var result = new Vector2(0, 0);
|
||||||
value1.y /= value2.y;
|
result.x = value1.x / value2.x;
|
||||||
|
result.y = value1.y / value2.y;
|
||||||
return value1;
|
return value1;
|
||||||
};
|
};
|
||||||
Vector2.multiply = function (value1, value2) {
|
Vector2.multiply = function (value1, value2) {
|
||||||
value1.x *= value2.x;
|
var result = new Vector2(0, 0);
|
||||||
value1.y *= value2.y;
|
result.x = value1.x * value2.x;
|
||||||
return value1;
|
result.y = value1.y * value2.y;
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
Vector2.subtract = function (value1, value2) {
|
Vector2.subtract = function (value1, value2) {
|
||||||
value1.x -= value2.x;
|
var result = new Vector2(0, 0);
|
||||||
value1.y -= value2.y;
|
result.x = value1.x - value2.x;
|
||||||
|
result.y = value1.y - value2.y;
|
||||||
return value1;
|
return value1;
|
||||||
};
|
};
|
||||||
Vector2.prototype.normalize = function () {
|
Vector2.prototype.normalize = function () {
|
||||||
@@ -2609,6 +2624,9 @@ var Vector2 = (function () {
|
|||||||
this.x *= val;
|
this.x *= val;
|
||||||
this.y *= val;
|
this.y *= val;
|
||||||
};
|
};
|
||||||
|
Vector2.prototype.length = function () {
|
||||||
|
return Math.sqrt((this.x * this.x) + (this.y * this.y));
|
||||||
|
};
|
||||||
Vector2.dot = function (value1, value2) {
|
Vector2.dot = function (value1, value2) {
|
||||||
return (value1.x * value2.x) + (value1.y * value2.y);
|
return (value1.x * value2.x) + (value1.y * value2.y);
|
||||||
};
|
};
|
||||||
@@ -2619,8 +2637,10 @@ var Vector2 = (function () {
|
|||||||
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));
|
||||||
};
|
};
|
||||||
Vector2.zeroVector = new Vector2(0, 0);
|
Vector2.distance = function (value1, value2) {
|
||||||
Vector2.unitVector = new Vector2(1, 1);
|
var v1 = value1.x - value2.x, v2 = value1.y - value2.y;
|
||||||
|
return Math.sqrt((v1 * v1) + (v2 * v2));
|
||||||
|
};
|
||||||
return Vector2;
|
return Vector2;
|
||||||
}());
|
}());
|
||||||
var PointSectors;
|
var PointSectors;
|
||||||
@@ -2654,7 +2674,7 @@ var Collisions = (function () {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
Collisions.lineToLineIntersection = function (a1, a2, b1, b2) {
|
Collisions.lineToLineIntersection = function (a1, a2, b1, b2) {
|
||||||
var intersection = Vector2.Zero;
|
var intersection = new Vector2(0, 0);
|
||||||
var b = Vector2.subtract(a2, a1);
|
var b = Vector2.subtract(a2, a1);
|
||||||
var d = Vector2.subtract(b2, b1);
|
var d = Vector2.subtract(b2, b1);
|
||||||
var bDotDPerp = b.x * d.y - b.y * d.x;
|
var bDotDPerp = b.x * d.y - b.y * d.x;
|
||||||
@@ -2775,6 +2795,258 @@ var Collisions = (function () {
|
|||||||
};
|
};
|
||||||
return Collisions;
|
return Collisions;
|
||||||
}());
|
}());
|
||||||
|
var Physics = (function () {
|
||||||
|
function Physics() {
|
||||||
|
}
|
||||||
|
Physics.overlapCircleAll = function (center, randius, results, layerMask) {
|
||||||
|
if (layerMask === void 0) { layerMask = -1; }
|
||||||
|
return this._spatialHash.overlapCircle(center, randius, results, layerMask);
|
||||||
|
};
|
||||||
|
return Physics;
|
||||||
|
}());
|
||||||
|
var Particle = (function () {
|
||||||
|
function Particle(position) {
|
||||||
|
this.position = new Vector2(0, 0);
|
||||||
|
this.lastPosition = new Vector2(0, 0);
|
||||||
|
this.acceleration = new Vector2(0, 0);
|
||||||
|
this.mass = 1;
|
||||||
|
this.radius = 0;
|
||||||
|
this.collidesWithColliders = true;
|
||||||
|
this.position = position;
|
||||||
|
this.lastPosition = position;
|
||||||
|
}
|
||||||
|
Particle.prototype.applyForce = function (force) {
|
||||||
|
this.acceleration = Vector2.add(this.acceleration, new Vector2(force.x / this.mass, force.y / this.mass));
|
||||||
|
};
|
||||||
|
return Particle;
|
||||||
|
}());
|
||||||
|
var SpatialHash = (function () {
|
||||||
|
function SpatialHash() {
|
||||||
|
}
|
||||||
|
SpatialHash.prototype.overlapCircle = function (circleCenter, radius, results, layerMask) {
|
||||||
|
var resultCounter = 0;
|
||||||
|
return resultCounter;
|
||||||
|
};
|
||||||
|
return SpatialHash;
|
||||||
|
}());
|
||||||
|
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.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);
|
||||||
|
for (var j = 0; j < composite.particles.length; j++) {
|
||||||
|
var p = composite.particles[j];
|
||||||
|
if (this.simulationBounds) {
|
||||||
|
this.constrainParticleToBounds(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
VerletWorld.prototype.handleCollisions = function (p, collidesWithLayers) {
|
||||||
|
var collidedCount = Physics.overlapCircleAll(p.position, p.radius, VerletWorld._colliders, collidesWithLayers);
|
||||||
|
};
|
||||||
|
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 = [];
|
||||||
|
}
|
||||||
|
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.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.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.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();
|
||||||
|
};
|
||||||
|
return DistanceConstraint;
|
||||||
|
}(Constraint));
|
||||||
var Triangulator = (function () {
|
var Triangulator = (function () {
|
||||||
function Triangulator() {
|
function Triangulator() {
|
||||||
this.triangleIndices = [];
|
this.triangleIndices = [];
|
||||||
|
|||||||
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
4
source/src/Debug/DebugDefaults.ts
Normal file
4
source/src/Debug/DebugDefaults.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
class DebugDefaults {
|
||||||
|
public static verletParticle = 0xDC345E;
|
||||||
|
public static verletConstraintEdge = 0x433E36;
|
||||||
|
}
|
||||||
@@ -8,11 +8,11 @@ abstract class RenderableComponent extends Component {
|
|||||||
private _localOffset: Vector2;
|
private _localOffset: Vector2;
|
||||||
|
|
||||||
public get width(){
|
public get width(){
|
||||||
return this.bounds.width;
|
return this.getWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
public get height(){
|
public get height(){
|
||||||
return this.bounds.height;
|
return this.getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
public get isVisible(){
|
public get isVisible(){
|
||||||
@@ -29,8 +29,20 @@ abstract class RenderableComponent extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get bounds(): Rectangle{
|
public get bounds(): Rectangle{
|
||||||
|
return this.getBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getWidth(){
|
||||||
|
return this.bounds.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getHeight(){
|
||||||
|
return this.bounds.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getBounds(){
|
||||||
if (this._areBoundsDirty){
|
if (this._areBoundsDirty){
|
||||||
this._bounds.calculateBounds(this.entity.transform.position, this._localOffset, Vector2.Zero,
|
this._bounds.calculateBounds(this.entity.transform.position, this._localOffset, new Vector2(0, 0),
|
||||||
this.entity.transform.scale, this.entity.transform.rotation, this.width, this.height);
|
this.entity.transform.scale, this.entity.transform.rotation, this.width, this.height);
|
||||||
this._areBoundsDirty = false;
|
this._areBoundsDirty = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class Transform {
|
|||||||
|
|
||||||
constructor(entity: Entity){
|
constructor(entity: Entity){
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
this._scale = this._localScale = Vector2.One;
|
this._scale = this._localScale = new Vector2(0, 0);
|
||||||
this._children = [];
|
this._children = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,11 @@ class ComponentList {
|
|||||||
|
|
||||||
public update(){
|
public update(){
|
||||||
this.updateLists();
|
this.updateLists();
|
||||||
|
for (let i = 0; i < this._components.length; i ++){
|
||||||
|
let component = this._components[i];
|
||||||
|
if (component.enabled && (component.updateInterval == 1 || Time.frameCount % component.updateInterval == 0))
|
||||||
|
component.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public onEntityTransformChanged(comp){
|
public onEntityTransformChanged(comp){
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
class Time {
|
class Time {
|
||||||
public static unscaledDeltaTime;
|
public static unscaledDeltaTime;
|
||||||
public static deltaTime: number;
|
public static deltaTime: number = 0;
|
||||||
public static timeScale = 1;
|
public static timeScale = 1;
|
||||||
|
public static frameCount = 0;;
|
||||||
|
|
||||||
private static _lastTime = 0;
|
private static _lastTime = 0;
|
||||||
|
|
||||||
@@ -9,6 +10,7 @@ class Time {
|
|||||||
let dt = (currentTime - this._lastTime) / 1000;
|
let dt = (currentTime - this._lastTime) / 1000;
|
||||||
this.deltaTime = dt * this.timeScale;
|
this.deltaTime = dt * this.timeScale;
|
||||||
this.unscaledDeltaTime = dt;
|
this.unscaledDeltaTime = dt;
|
||||||
|
this.frameCount ++;
|
||||||
|
|
||||||
this._lastTime = currentTime;
|
this._lastTime = currentTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,17 +3,6 @@ class Vector2 {
|
|||||||
public x: number = 0;
|
public x: number = 0;
|
||||||
public y: number = 0;
|
public y: number = 0;
|
||||||
|
|
||||||
private static readonly zeroVector = new Vector2(0, 0);
|
|
||||||
private static readonly unitVector = new Vector2(1, 1);
|
|
||||||
|
|
||||||
public static get One(){
|
|
||||||
return this.unitVector;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static get Zero(){
|
|
||||||
return this.zeroVector;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从两个值构造一个带有X和Y的二维向量。
|
* 从两个值构造一个带有X和Y的二维向量。
|
||||||
* @param x 二维空间中的x坐标
|
* @param x 二维空间中的x坐标
|
||||||
@@ -25,26 +14,30 @@ class Vector2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static add(value1: Vector2, value2: Vector2){
|
public static add(value1: Vector2, value2: Vector2){
|
||||||
value1.x += value2.x;
|
let result: Vector2 = new Vector2(0, 0);
|
||||||
value1.y += value2.y;
|
result.x = value1.x + value2.x;
|
||||||
return value1;
|
result.y = value1.y + value2.y;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static divide(value1: Vector2, value2: Vector2){
|
public static divide(value1: Vector2, value2: Vector2){
|
||||||
value1.x /= value2.x;
|
let result: Vector2 = new Vector2(0, 0);
|
||||||
value1.y /= value2.y;
|
result.x = value1.x / value2.x;
|
||||||
|
result.y = value1.y / value2.y;
|
||||||
return value1;
|
return value1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static multiply(value1: Vector2, value2: Vector2){
|
public static multiply(value1: Vector2, value2: Vector2){
|
||||||
value1.x *= value2.x;
|
let result: Vector2 = new Vector2(0, 0);
|
||||||
value1.y *= value2.y;
|
result.x = value1.x * value2.x;
|
||||||
return value1;
|
result.y = value1.y * value2.y;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static subtract(value1: Vector2, value2: Vector2){
|
public static subtract(value1: Vector2, value2: Vector2){
|
||||||
value1.x -= value2.x;
|
let result: Vector2 = new Vector2(0, 0);
|
||||||
value1.y -= value2.y;
|
result.x = value1.x - value2.x;
|
||||||
|
result.y = value1.y - value2.y;
|
||||||
return value1;
|
return value1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,6 +48,10 @@ class Vector2 {
|
|||||||
this.y *= val;
|
this.y *= val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public length(){
|
||||||
|
return Math.sqrt((this.x * this.x) + (this.y * this.y));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回两个向量的点积
|
* 返回两个向量的点积
|
||||||
* @param value1
|
* @param value1
|
||||||
@@ -77,4 +74,9 @@ class Vector2 {
|
|||||||
public static transform(position: Vector2, matrix: Matrix2D){
|
public static transform(position: Vector2, matrix: Matrix2D){
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static distance(value1: Vector2, value2: Vector2){
|
||||||
|
let v1 = value1.x - value2.x, v2 = value1.y - value2.y;
|
||||||
|
return Math.sqrt((v1 * v1) + (v2 * v2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ class Collisions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static lineToLineIntersection(a1: Vector2, a2: Vector2, b1: Vector2, b2: Vector2): Vector2 {
|
public static lineToLineIntersection(a1: Vector2, a2: Vector2, b1: Vector2, b2: Vector2): Vector2 {
|
||||||
let intersection = Vector2.Zero;
|
let intersection = new Vector2(0, 0);
|
||||||
|
|
||||||
let b = Vector2.subtract(a2, a1);
|
let b = Vector2.subtract(a2, a1);
|
||||||
let d = Vector2.subtract(b2, b1);
|
let d = Vector2.subtract(b2, b1);
|
||||||
|
|||||||
7
source/src/Physics/Physics.ts
Normal file
7
source/src/Physics/Physics.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
class Physics {
|
||||||
|
private static _spatialHash: SpatialHash;
|
||||||
|
|
||||||
|
public static overlapCircleAll(center: Vector2, randius: number, results: any[], layerMask = -1){
|
||||||
|
return this._spatialHash.overlapCircle(center, randius, results, layerMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
source/src/Physics/Verlet/Composites/Box.ts
Normal file
19
source/src/Physics/Verlet/Composites/Box.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
///<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);
|
||||||
|
}
|
||||||
|
}
|
||||||
67
source/src/Physics/Verlet/Composites/Composite.ts
Normal file
67
source/src/Physics/Verlet/Composites/Composite.ts
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
class Composite {
|
||||||
|
private _constraints: Constraint[] = [];
|
||||||
|
|
||||||
|
public friction = new Vector2(0.98, 1);
|
||||||
|
public drawParticles: boolean = true;
|
||||||
|
public drawConstraints: boolean = true;
|
||||||
|
public particles: Particle[] = [];
|
||||||
|
/**
|
||||||
|
* 处理解决所有约束条件
|
||||||
|
*/
|
||||||
|
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 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
source/src/Physics/Verlet/Constraint/Constraint.ts
Normal file
8
source/src/Physics/Verlet/Constraint/Constraint.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
abstract class Constraint {
|
||||||
|
public composite: Composite;
|
||||||
|
public collidesWithColliders = true;
|
||||||
|
|
||||||
|
public abstract solve();
|
||||||
|
|
||||||
|
public debugRender(graphics: egret.Graphics) {}
|
||||||
|
}
|
||||||
54
source/src/Physics/Verlet/Constraint/DistanceConstraint.ts
Normal file
54
source/src/Physics/Verlet/Constraint/DistanceConstraint.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
class DistanceConstraint extends Constraint {
|
||||||
|
public stiffness: number = 0;
|
||||||
|
public restingDistance: number = 0;
|
||||||
|
public tearSensitivity = Number.POSITIVE_INFINITY;
|
||||||
|
|
||||||
|
private _particleOne: Particle;
|
||||||
|
private _particleTwo: Particle;
|
||||||
|
|
||||||
|
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 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,10 +1,12 @@
|
|||||||
class Particle {
|
class Particle {
|
||||||
public position: Vector2;
|
public position: Vector2 = new Vector2(0, 0);
|
||||||
public lastPosition: Vector2;
|
public lastPosition: Vector2 = new Vector2(0, 0);
|
||||||
public isPinned: boolean;
|
public isPinned: boolean;
|
||||||
public pinnedPosition;
|
public pinnedPosition;
|
||||||
public acceleration: Vector2;
|
public acceleration: Vector2 = new Vector2(0, 0);
|
||||||
public mass: number = 1;
|
public mass: number = 1;
|
||||||
|
public radius: number = 0;
|
||||||
|
public collidesWithColliders = true;
|
||||||
|
|
||||||
constructor(position: Vector2){
|
constructor(position: Vector2){
|
||||||
this.position = position;
|
this.position = position;
|
||||||
7
source/src/Physics/Verlet/SpatialHash.ts
Normal file
7
source/src/Physics/Verlet/SpatialHash.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
class SpatialHash {
|
||||||
|
public overlapCircle(circleCenter: Vector2, radius: number, results: any[], layerMask){
|
||||||
|
let resultCounter = 0;
|
||||||
|
|
||||||
|
return resultCounter;
|
||||||
|
}
|
||||||
|
}
|
||||||
113
source/src/Physics/Verlet/VerletWorld.ts
Normal file
113
source/src/Physics/Verlet/VerletWorld.ts
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
/**
|
||||||
|
* 基于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;
|
||||||
|
|
||||||
|
private static _colliders = new Array(4);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleCollisions(p: Particle, collidesWithLayers: number){
|
||||||
|
let collidedCount = Physics.overlapCircleAll(p.position, p.radius, VerletWorld._colliders, collidesWithLayers);
|
||||||
|
// handle
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
class Composite {
|
|
||||||
private _constraints: Constraint[] = [];
|
|
||||||
|
|
||||||
public particles: Particle[] = [];
|
|
||||||
/**
|
|
||||||
* 处理解决所有约束条件
|
|
||||||
*/
|
|
||||||
public solveConstraints(){
|
|
||||||
for (let i = this._constraints.length - 1; i >= 0; i --){
|
|
||||||
this._constraints[i].solve();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
abstract class Constraint {
|
|
||||||
public composite: Composite;
|
|
||||||
|
|
||||||
public abstract solve();
|
|
||||||
}
|
|
||||||
@@ -1,45 +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;
|
|
||||||
private _iterationSteps: number;
|
|
||||||
private _fixedDeltaTime = 1 / 60;
|
|
||||||
private _composites: Composite[] = [];
|
|
||||||
private _fixedDeltaTimeSq: number;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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