From 74cbb4c9fde7a030720fd5609bb943be75572c37 Mon Sep 17 00:00:00 2001 From: yhh <359807859@qq.com> Date: Wed, 10 Jun 2020 20:29:16 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Everletworld?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/Utils/Verlet/Composites/Composite.ts | 25 +++++++++++ .../src/Utils/Verlet/Constraint/Constraint.ts | 5 +++ source/src/Utils/Verlet/Particle.ts | 17 +++++++ source/src/Utils/Verlet/VerletWorld.ts | 45 +++++++++++++++++++ 4 files changed, 92 insertions(+) create mode 100644 source/src/Utils/Verlet/Composites/Composite.ts create mode 100644 source/src/Utils/Verlet/Constraint/Constraint.ts create mode 100644 source/src/Utils/Verlet/Particle.ts create mode 100644 source/src/Utils/Verlet/VerletWorld.ts diff --git a/source/src/Utils/Verlet/Composites/Composite.ts b/source/src/Utils/Verlet/Composites/Composite.ts new file mode 100644 index 00000000..f3caeada --- /dev/null +++ b/source/src/Utils/Verlet/Composites/Composite.ts @@ -0,0 +1,25 @@ +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)); + } + } +} \ No newline at end of file diff --git a/source/src/Utils/Verlet/Constraint/Constraint.ts b/source/src/Utils/Verlet/Constraint/Constraint.ts new file mode 100644 index 00000000..e371f532 --- /dev/null +++ b/source/src/Utils/Verlet/Constraint/Constraint.ts @@ -0,0 +1,5 @@ +abstract class Constraint { + public composite: Composite; + + public abstract solve(); +} \ No newline at end of file diff --git a/source/src/Utils/Verlet/Particle.ts b/source/src/Utils/Verlet/Particle.ts new file mode 100644 index 00000000..511a713d --- /dev/null +++ b/source/src/Utils/Verlet/Particle.ts @@ -0,0 +1,17 @@ +class Particle { + public position: Vector2; + public lastPosition: Vector2; + public isPinned: boolean; + public pinnedPosition; + public acceleration: Vector2; + public mass: number = 1; + + constructor(position: Vector2){ + this.position = position; + this.lastPosition = position; + } + + public applyForce(force: Vector2){ + this.acceleration = Vector2.add(this.acceleration, new Vector2(force.x / this.mass, force.y / this.mass)); + } +} \ No newline at end of file diff --git a/source/src/Utils/Verlet/VerletWorld.ts b/source/src/Utils/Verlet/VerletWorld.ts new file mode 100644 index 00000000..f2be8ff2 --- /dev/null +++ b/source/src/Utils/Verlet/VerletWorld.ts @@ -0,0 +1,45 @@ +/** + * 基于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); + } +} \ No newline at end of file