Skip to content

Instantly share code, notes, and snippets.

@gordonbrander
Last active November 6, 2022 07:34
Show Gist options
  • Select an option

  • Save gordonbrander/8766f52dd13cc3cff4a3 to your computer and use it in GitHub Desktop.

Select an option

Save gordonbrander/8766f52dd13cc3cff4a3 to your computer and use it in GitHub Desktop.
boing.js (second pass)
// Create a spring object.
export const Spring = (curr, prev, dest, stiffness, damping) => ({
curr, // The current position of spring
prev, // The position of spring at previous tick
dest, // The destination of spring
stiffness, // How hard it springs back
damping, // Friction. 1.0 means no bounce.
});
// Given numbers, calculate the next position for a spring.
Spring.next = (curr, prev, dest, stiffness, damping) => {
// Calculate spring force
const fspring = -stiffness * (curr - dest);
// Calculate velocity
const vel = curr - prev;
// Calculate damping force.
const fdamping = -damping * vel;
// Calc acceleration by adjusting spring force to damping force
const acc = fspring + fdamping;
// Calculate new velocity after adding acceleration. Scale to framerate.
const nextv = (vel + acc);
// Calculate next position by integrating velocity. Scale to framerate.
const next = (curr + nextv);
return next;
}
// Some arbitrarily small positive number used as threshold value.
const epsilon = 0.001;
// Given numbers, calcluate if a spring is at rest.
Spring.isResting = (curr, prev, dest) =>
Math.abs(curr - prev) < epsilon && Math.abs(curr - dest) < epsilon;
// Create a new spring at location.
Spring.at = (pos, stiffness, damping) =>
Spring(pos, pos, pos, stiffness, damping);
// Copy a spring
Spring.copy = (spring) => Spring(
spring.curr, spring.prev, spring.dest,
spring.stiffness, spring.damping
);
// Set coords on a spring, mutating spring
Spring.coords = (spring, curr, prev, dest) => {
spring.curr = curr;
spring.prev = prev;
spring.dest = dest;
return spring;
}
// Set the destination of spring A to the current location of spring B.
Spring.connect = (a, b) =>
Spring.coords(a, a.curr, a.prev, b.curr);
Spring.animate = (spring) =>
!Spring.isResting(spring.curr, spring.prev, spring.dest) ?
Spring.coords(
spring,
Spring.next(
spring.curr, spring.prev, spring.dest,
spring.stiffness, spring.damping),
spring.curr, spring.dest) :
Spring.coords(spring, spring.dest, spring.dest, spring.dest);
Spring.animate2d = (spring) =>
(!Spring.isResting(spring.curr[0], spring.prev[0], spring.dest[0]) ||
!Spring.isResting(spring.curr[1], spring.prev[1], spring.dest[1])) ?
Spring.coords(
spring,
[Spring.next(
spring.curr[0], spring.prev[0], spring.dest[0],
spring.stiffness, spring.damping),
Spring.next(
spring.curr[1], spring.prev[1], spring.dest[1],
spring.stiffness, spring.damping)],
spring.curr, spring.dest) :
Spring.coords(spring, spring.dest, spring.dest, spring.dest);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment