mirror of
https://github.com/charmbracelet/harmonica.git
synced 2026-07-20 02:29:33 -06:00
Update README and example code
This commit is contained in:
parent
3250234a99
commit
87e1a9dba6
38
README.md
38
README.md
@ -23,7 +23,7 @@ const targetX = 50.0
|
|||||||
const targetY = 100.0
|
const targetY = 100.0
|
||||||
|
|
||||||
// Initialize a spring with framerate, angular frequency, and damping values.
|
// 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!
|
// Animate!
|
||||||
for {
|
for {
|
||||||
@ -38,6 +38,42 @@ For details, see the [examples][examples] and the [docs][docs].
|
|||||||
[examples]: https://github.com/charmbracelet/harmonica/tree/master/examples
|
[examples]: https://github.com/charmbracelet/harmonica/tree/master/examples
|
||||||
[docs]: https://pkg.go.dev/github.com/charmbracelet/harmonica?tab=doc
|
[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
|
## Acknowledgements
|
||||||
|
|
||||||
This library is a fairly straightforward port of [Ryan Juckett][juckett]’s
|
This library is a fairly straightforward port of [Ryan Juckett][juckett]’s
|
||||||
|
|||||||
28
harmonica.go
28
harmonica.go
@ -5,16 +5,15 @@
|
|||||||
// Example usage:
|
// Example usage:
|
||||||
//
|
//
|
||||||
// // Run once to initialize.
|
// // Run once to initialize.
|
||||||
// spring := NewSpring(FPS(60), 0.8, 1.0)
|
// spring := NewSpring(FPS(60), 6.0, 0.2)
|
||||||
//
|
//
|
||||||
// // Update on every frame.
|
// // Update on every frame.
|
||||||
// pos := 0.0
|
// pos := 0.0
|
||||||
// targetPos := 10.0
|
// targetPos := 100.0
|
||||||
// velocity := 0.0
|
// velocity := 0.0
|
||||||
// spring.Update(&pos, &velocity, targetPos)
|
// someUpdateLoop(func() {
|
||||||
//
|
// spring.Update(&pos, &velocity, targetPos)
|
||||||
// // You could also use a custom FPS with the TimeDelta helper:
|
// })
|
||||||
// fps := TimeDelta(time.Second/24) // 24fps
|
|
||||||
//
|
//
|
||||||
// For background on the algorithm see:
|
// For background on the algorithm see:
|
||||||
// https://www.ryanjuckett.com/damped-springs/
|
// 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
|
// 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:
|
// Example:
|
||||||
//
|
//
|
||||||
@ -66,7 +67,7 @@ func FPS(n int) float64 {
|
|||||||
return (time.Second / time.Duration(n)).Seconds()
|
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:
|
// the original C++ source ε is represented as such:
|
||||||
//
|
//
|
||||||
// const float epsilon = 0.0001
|
// const float epsilon = 0.0001
|
||||||
@ -90,11 +91,14 @@ var epsilon = math.Nextafter(1, 2) - 1
|
|||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
//
|
//
|
||||||
|
// // First precomute spring coefficients based on your settings:
|
||||||
// var x, xVel, y, yVel float
|
// var x, xVel, y, yVel float
|
||||||
// fps := TimeDelta(time.Second/60) // or use a const like FPS60 or FPS30
|
// deltaTime := FPS(60)
|
||||||
// s := NewSping(fps, 0.98, 8.0)
|
// s := NewSpring(deltaTime, 5.0, 0.2)
|
||||||
// s.Update(&x, &xVel, 10) // update the X position
|
//
|
||||||
// s.Update(&y, &yVel, 20) // update the Y position
|
// // 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 {
|
type Spring struct {
|
||||||
posPosCoef, posVelCoef float64
|
posPosCoef, posVelCoef float64
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user