mirror of
https://github.com/charmbracelet/harmonica.git
synced 2026-07-19 10:09:33 -06:00
Copy values in Update method to avoid data races
This commit is contained in:
parent
37ee95df51
commit
d45b96278a
@ -43,8 +43,8 @@ spring := harmonica.NewSpring(harmonica.FPS(60), 6.0, 0.5)
|
||||
|
||||
// Animate!
|
||||
for {
|
||||
spring.Update(&sprite.x, &sprite.xVelocity, targetX)
|
||||
spring.Update(&sprite.y, &sprite.yVelocity, targetY)
|
||||
sprite.x, sprite.xVelocity = spring.Update(&sprite.x, &sprite.xVelocity, targetX)
|
||||
sprite.y, sprite.yVelocity = spring.Update(&sprite.y, &sprite.yVelocity, targetY)
|
||||
time.Sleep(time.Second/60)
|
||||
}
|
||||
```
|
||||
|
||||
@ -255,9 +255,9 @@ func (s *Sprite) Update() {
|
||||
}
|
||||
|
||||
// Calculate positions based on our spring
|
||||
s.spring.Update(&s.X, &s.xVel, s.TargetX)
|
||||
s.spring.Update(&s.Y, &s.yVel, s.TargetY)
|
||||
s.spring.Update(&s.radius, &s.radiusVel, s.TargetRadius)
|
||||
s.X, s.xVel = s.spring.Update(s.X, s.xVel, s.TargetX)
|
||||
s.Y, s.yVel = s.spring.Update(s.Y, s.yVel, s.TargetY)
|
||||
s.radius, s.radiusVel = s.spring.Update(s.radius, s.radiusVel, s.TargetRadius)
|
||||
}
|
||||
|
||||
func (s Sprite) Draw(ctx *gg.Context) {
|
||||
|
||||
@ -66,7 +66,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
const targetX = 60
|
||||
|
||||
// Update x position (and velocity) with our spring.
|
||||
m.spring.Update(&m.x, &m.xVel, targetX)
|
||||
m.x, m.xVel = m.spring.Update(m.x, m.xVel, targetX)
|
||||
|
||||
// Quit when we're basically at the target position.
|
||||
if math.Abs(m.x-targetX) < 0.01 {
|
||||
|
||||
24
harmonica.go
24
harmonica.go
@ -9,10 +9,10 @@
|
||||
//
|
||||
// // Update on every frame.
|
||||
// pos := 0.0
|
||||
// targetPos := 100.0
|
||||
// velocity := 0.0
|
||||
// targetPos := 100.0
|
||||
// someUpdateLoop(func() {
|
||||
// spring.Update(&pos, &velocity, targetPos)
|
||||
// pos, velocity = spring.Update(pos, velocity, targetPos)
|
||||
// })
|
||||
//
|
||||
// For background on the algorithm see:
|
||||
@ -61,7 +61,7 @@ import (
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// spring := NewSpring(FPS(60), 0.8, 0.98)
|
||||
// spring := NewSpring(FPS(60), 5.0, 0.2)
|
||||
//
|
||||
func FPS(n int) float64 {
|
||||
return (time.Second / time.Duration(n)).Seconds()
|
||||
@ -92,13 +92,13 @@ var epsilon = math.Nextafter(1, 2) - 1
|
||||
// Example:
|
||||
//
|
||||
// // First precompute spring coefficients based on your settings:
|
||||
// var x, xVel, y, yVel float
|
||||
// var x, xVel, y, yVel float64
|
||||
// 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
|
||||
// x, xVel = s.Update(x, xVel, 10) // update the X position
|
||||
// y, yVel = s.Update(y, yVel, 20) // update the Y position
|
||||
//
|
||||
type Spring struct {
|
||||
posPosCoef, posVelCoef float64
|
||||
@ -212,10 +212,12 @@ func NewSpring(deltaTime, angularFrequency, dampingRatio float64) (s Spring) {
|
||||
|
||||
// Update updates position and velocity values against a given target value.
|
||||
// Call this after calling NewSpring to update values.
|
||||
func (s Spring) Update(pos *float64, vel *float64, equilibriumPos float64) {
|
||||
oldPos := *pos - equilibriumPos // update in equilibrium relative space
|
||||
oldVel := *vel
|
||||
func (s Spring) Update(pos, vel float64, equilibriumPos float64) (newPos, newVel float64) {
|
||||
oldPos := pos - equilibriumPos // update in equilibrium relative space
|
||||
oldVel := vel
|
||||
|
||||
*pos = oldPos*s.posPosCoef + oldVel*s.posVelCoef + equilibriumPos
|
||||
*vel = oldPos*s.velPosCoef + oldVel*s.velVelCoef
|
||||
newPos = oldPos*s.posPosCoef + oldVel*s.posVelCoef + equilibriumPos
|
||||
newVel = oldPos*s.velPosCoef + oldVel*s.velVelCoef
|
||||
|
||||
return newPos, newVel
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user