新增verlet物理引擎(实验性)
This commit is contained in:
9
source/src/Physics/Verlet/Composites/Ball.ts
Normal file
9
source/src/Physics/Verlet/Composites/Ball.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
///<reference path="./Composite.ts" />
|
||||
module es {
|
||||
export class Ball extends Composite {
|
||||
constructor(position: Vector2, radius: number = 10) {
|
||||
super();
|
||||
this.addParticle(new Particle(position)).radius = radius;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
source/src/Physics/Verlet/Composites/Box.ts
Normal file
23
source/src/Physics/Verlet/Composites/Box.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
///<reference path="./Composite.ts" />
|
||||
module es {
|
||||
export class VerletBox extends es.Composite {
|
||||
constructor(center: es.Vector2, width: number, height: number, borderStiffness: number = 0.2, diagonalStiffness: number = 0.5) {
|
||||
super();
|
||||
|
||||
const tl = this.addParticle(new Particle(center.add(new Vector2(-width / 2, -height / 2))));
|
||||
const tr = this.addParticle(new Particle(center.add(new Vector2(width / 2, -height / 2))));
|
||||
const br = this.addParticle(new Particle(center.add(new Vector2(width / 2, height / 2))));
|
||||
const bl = this.addParticle(new Particle(center.add(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
88
source/src/Physics/Verlet/Composites/Composite.ts
Normal file
88
source/src/Physics/Verlet/Composites/Composite.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
module es {
|
||||
export class Composite {
|
||||
public friction: Vector2 = new Vector2(0.98, 1);
|
||||
public drawParticles: boolean = true;
|
||||
public drawConstraints: boolean = true;
|
||||
public collidesWithLayers: number = Physics.allLayers;
|
||||
public particles: Particle[] = [];
|
||||
_constraints: Constraint[] = [];
|
||||
|
||||
public addParticle(particle: Particle): Particle {
|
||||
this.particles.push(particle);
|
||||
return particle;
|
||||
}
|
||||
|
||||
public removeParticle(particle: Particle) {
|
||||
const index = this.particles.indexOf(particle);
|
||||
this.particles.splice(index, 1);
|
||||
}
|
||||
|
||||
public removeAll() {
|
||||
this.particles.length = 0;
|
||||
this._constraints.length = 0;
|
||||
}
|
||||
|
||||
public addConstraint<T extends Constraint>(constraint: T): T {
|
||||
this._constraints.push(constraint);
|
||||
constraint.composite = this;
|
||||
return constraint;
|
||||
}
|
||||
|
||||
public removeConstraint(constraint: Constraint) {
|
||||
const index = this._constraints.indexOf(constraint);
|
||||
this._constraints.splice(index, 1);
|
||||
}
|
||||
|
||||
public applyForce(force: Vector2) {
|
||||
for (let j = 0; j < this.particles.length; j ++)
|
||||
this.particles[j].applyForce(force);
|
||||
}
|
||||
|
||||
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 ++) {
|
||||
const p = this.particles[j];
|
||||
if (p.isPinned) {
|
||||
p.position = p.pinnedPosition;
|
||||
continue;
|
||||
}
|
||||
|
||||
p.applyForce(gravity.scale(p.mass));
|
||||
|
||||
const vel = p.position.sub(p.lastPosition).multiply(this.friction);
|
||||
const nextPos = p.position.add(vel).add(p.acceleration.scale(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(batcher: IBatcher) {
|
||||
if (this.drawConstraints) {
|
||||
for (let i = 0; i < this._constraints.length; i ++)
|
||||
this._constraints[i].debugRender(batcher);
|
||||
}
|
||||
|
||||
if (this.drawParticles) {
|
||||
for (let i = 0; i < this.particles.length; i ++) {
|
||||
if (this.particles[i].radius == 0)
|
||||
batcher.drawPixel(this.particles[i].position, new Color(220, 52, 94), 4);
|
||||
else
|
||||
batcher.drawCircleLow(this.particles[i].position, this.particles[i].radius, new Color(220, 52, 94), 1, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
20
source/src/Physics/Verlet/Composites/LineSegments.ts
Normal file
20
source/src/Physics/Verlet/Composites/LineSegments.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
module es {
|
||||
export class LineSegments extends Composite {
|
||||
constructor(vertices: Vector2[], stiffness: number) {
|
||||
super();
|
||||
|
||||
for (let i = 0; i < vertices.length; i ++) {
|
||||
const p = new Particle(vertices[i]);
|
||||
this.addParticle(p);
|
||||
|
||||
if (i > 0)
|
||||
this.addConstraint(new DistanceConstraint(this.particles[i], this.particles[i - 1], stiffness));
|
||||
}
|
||||
}
|
||||
|
||||
public pinParticleAtIndex(index: number): LineSegments {
|
||||
this.particles[index].pin();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user