diff --git a/README.md b/README.md index b23d208..c964a4c 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ const targetX = 50.0 const targetY = 100.0 // Initialize a spring with framerate, angular frequency, and damping values. -spring := harmonica.NewSpring(harmonica.FPS60, 0.8, 0.98) +spring := harmonica.NewSpring(harmonica.FPS(60), 6.0, 0.5) // Animate! for { @@ -38,6 +38,42 @@ For details, see the [examples][examples] and the [docs][docs]. [examples]: https://github.com/charmbracelet/harmonica/tree/master/examples [docs]: https://pkg.go.dev/github.com/charmbracelet/harmonica?tab=doc +## Settings + +`NewSpring` takes three different values on initialization: + +* **Time Delta:** the time step to operate on. Game engines typically provide + a way to determine the time delta, however if that's not available you can + simply set the framerate with the included `FPS(int)` utility function. Make + the framerate you set here matches your actual framerate. +* **Angular Velocity:** this translates roughly to the speed. Higher values are + faster. +* **Damping Ratio:** the springiness of the animation, generally between `0` + and `1`, though it can go higher. Lower values are springier. For details, + see below. + +## Damping Ratios + +The damping ratio affects the motion in one of three different ways depending +on how it's set. + +### Under-Damping + +A spring is under-damped when its damping ratio is less than `1`. An +under-damped spring reaches equilibrium the fastest, but overshoots and will +continue to oscillate as its amplitude decays over time. + +### Critical Damping + +A spring is critically-damped the damping ratio is exactly `1`. A critically +damped spring will reach equilibrium as fast as possible without oscillating. + +### Over-Damping + +A spring is over-damped the damping ratio is greater than `1`. An over-damped +spring will never oscillate, but reaches equilibrium at a slower rate than +a critically damped spring. + ## Acknowledgements This library is a fairly straightforward port of [Ryan Juckett][juckett]’s diff --git a/harmonica.go b/harmonica.go index 42dd9c1..9bcffd1 100644 --- a/harmonica.go +++ b/harmonica.go @@ -5,16 +5,15 @@ // Example usage: // // // Run once to initialize. -// spring := NewSpring(FPS(60), 0.8, 1.0) +// spring := NewSpring(FPS(60), 6.0, 0.2) // // // Update on every frame. // pos := 0.0 -// targetPos := 10.0 +// targetPos := 100.0 // velocity := 0.0 -// spring.Update(&pos, &velocity, targetPos) -// -// // You could also use a custom FPS with the TimeDelta helper: -// fps := TimeDelta(time.Second/24) // 24fps +// someUpdateLoop(func() { +// spring.Update(&pos, &velocity, targetPos) +// }) // // For background on the algorithm see: // https://www.ryanjuckett.com/damped-springs/ @@ -56,7 +55,9 @@ import ( ) // FPS returns a time delta for a given number of frames per second. This -// value can be used as the time delta when initializing a Spring. +// value can be used as the time delta when initializing a Spring. Note that +// game engines often provide the time delta as well, which you should use +// instead of this function, if possible. // // Example: // @@ -66,7 +67,7 @@ func FPS(n int) float64 { return (time.Second / time.Duration(n)).Seconds() } -// In calculus ε is (in vague terms) an arbitrarily small positive number. In +// In calculus ε is, in vague terms, an arbitrarily small positive number. In // the original C++ source ε is represented as such: // // const float epsilon = 0.0001 @@ -90,11 +91,14 @@ var epsilon = math.Nextafter(1, 2) - 1 // // Example: // +// // First precomute spring coefficients based on your settings: // var x, xVel, y, yVel float -// fps := TimeDelta(time.Second/60) // or use a const like FPS60 or FPS30 -// s := NewSping(fps, 0.98, 8.0) -// s.Update(&x, &xVel, 10) // update the X position -// s.Update(&y, &yVel, 20) // update the Y position +// deltaTime := FPS(60) +// s := NewSpring(deltaTime, 5.0, 0.2) +// +// // Then, in your update loop: +// s.Update(&x, &xVel, 10) // update the X position +// s.Update(&y, &yVel, 20) // update the Y position // type Spring struct { posPosCoef, posVelCoef float64