Copy values in Update method to avoid data races

This commit is contained in:
Christian Rocha 2021-07-23 13:31:14 -04:00
parent 37ee95df51
commit d45b96278a
No known key found for this signature in database
GPG Key ID: D6CC7A16E5878018
4 changed files with 19 additions and 17 deletions

View File

@ -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)
}
```

View File

@ -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) {

View File

@ -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 {

View File

@ -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
}