UNPKG

blaze-2d

Version:

A fast and simple WebGL 2 2D game engine written in TypeScript

81 lines 3.23 kB
import { vec2 } from "gl-matrix"; import CollisionObject from "../collisionObject"; import Constraint from "./constraint"; /** * Represents a damped spring joint between two {@link CollisionObject}s or * a {@link CollisionObject} and a point. */ export default class SpringConstraint extends Constraint { constructor(a, b, length, stiffness, damping = 0) { if (a instanceof CollisionObject && b instanceof CollisionObject) { // constraint between two bodies super(a, b); this.length = length; this.stiffness = stiffness; this.damping = damping; } else if (a instanceof CollisionObject) { // constraint between body and point super(a, b); this.length = length; this.stiffness = stiffness; this.damping = damping; } else { // constraint from options super(a); this.length = a.length; this.stiffness = a.stiffness; this.damping = a.damping; } } /** * Updates the constraints anchors and prepares for solving. * * @param dt The time since the last update */ preSolve(dt) { this.updateAnchors(); const anchorA = this.anchorA; const anchorB = this.isBodyToPoint() ? this.point : this.anchorB; const anchorAWorld = vec2.add(vec2.create(), this.a.getPosition(), anchorA); const anchorBWorld = this.isBodyToPoint() ? anchorB : vec2.add(vec2.create(), this.b.getPosition(), anchorB); const delta = vec2.sub(vec2.create(), anchorBWorld, anchorAWorld); const length = vec2.len(delta); this.nDelta = vec2.normalize(vec2.create(), delta); const k = this.kScalar(this.nDelta); this.nMass = 1 / k; this.targetVrn = 0; this.vCoef = 1 - Math.exp(-this.damping * dt * k); // apply spring force const fSpring = this.calcForce(length); const jSpring = (this.jAcc = fSpring * dt); this.applyImpulses(jSpring, this.nDelta); } /** * Applies the spring forces to the attached bodies. * * @see [Chipmunk2D Damped Spring](https://github.com/slembcke/Chipmunk2D/blob/master/src/cpDampedSpring.c) * @see [Constraints and Solvers](https://research.ncl.ac.uk/game/mastersdegree/gametechnologies/physicstutorials/8constraintsandsolvers/Physics%20-%20Constraints%20and%20Solvers.pdf) * * @param dt The time since the last update */ solve(dt) { const anchorA = this.anchorA; const anchorB = this.isBodyToPoint() ? this.point : this.anchorB; // compute relative velocity const relVel = this.calculateRelativeVelocity(anchorA, anchorB); const vrn = vec2.dot(relVel, this.nDelta); // compute velocity loss from drag const vDamp = (this.targetVrn - vrn) * this.vCoef; this.targetVrn = vrn + vDamp; const jDamp = vDamp * this.nMass; this.jAcc += jDamp; this.applyImpulses(jDamp, this.nDelta); } postSolve() { } calcForce(length) { return (this.length - length) * this.stiffness; } } //# sourceMappingURL=spring.js.map