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! // Animate!
for { for {
spring.Update(&sprite.x, &sprite.xVelocity, targetX) sprite.x, sprite.xVelocity = spring.Update(&sprite.x, &sprite.xVelocity, targetX)
spring.Update(&sprite.y, &sprite.yVelocity, targetY) sprite.y, sprite.yVelocity = spring.Update(&sprite.y, &sprite.yVelocity, targetY)
time.Sleep(time.Second/60) time.Sleep(time.Second/60)
} }
``` ```

View File

@ -255,9 +255,9 @@ func (s *Sprite) Update() {
} }
// Calculate positions based on our spring // Calculate positions based on our spring
s.spring.Update(&s.X, &s.xVel, s.TargetX) s.X, s.xVel = s.spring.Update(s.X, s.xVel, s.TargetX)
s.spring.Update(&s.Y, &s.yVel, s.TargetY) s.Y, s.yVel = s.spring.Update(s.Y, s.yVel, s.TargetY)
s.spring.Update(&s.radius, &s.radiusVel, s.TargetRadius) s.radius, s.radiusVel = s.spring.Update(s.radius, s.radiusVel, s.TargetRadius)
} }
func (s Sprite) Draw(ctx *gg.Context) { 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 const targetX = 60
// Update x position (and velocity) with our spring. // 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. // Quit when we're basically at the target position.
if math.Abs(m.x-targetX) < 0.01 { if math.Abs(m.x-targetX) < 0.01 {

View File

@ -9,10 +9,10 @@
// //
// // Update on every frame. // // Update on every frame.
// pos := 0.0 // pos := 0.0
// targetPos := 100.0
// velocity := 0.0 // velocity := 0.0
// targetPos := 100.0
// someUpdateLoop(func() { // someUpdateLoop(func() {
// spring.Update(&pos, &velocity, targetPos) // pos, velocity = spring.Update(pos, velocity, targetPos)
// }) // })
// //
// For background on the algorithm see: // For background on the algorithm see:
@ -61,7 +61,7 @@ import (
// //
// Example: // Example:
// //
// spring := NewSpring(FPS(60), 0.8, 0.98) // spring := NewSpring(FPS(60), 5.0, 0.2)
// //
func FPS(n int) float64 { func FPS(n int) float64 {
return (time.Second / time.Duration(n)).Seconds() return (time.Second / time.Duration(n)).Seconds()
@ -92,13 +92,13 @@ var epsilon = math.Nextafter(1, 2) - 1
// Example: // Example:
// //
// // First precompute spring coefficients based on your settings: // // First precompute spring coefficients based on your settings:
// var x, xVel, y, yVel float // var x, xVel, y, yVel float64
// deltaTime := FPS(60) // deltaTime := FPS(60)
// s := NewSpring(deltaTime, 5.0, 0.2) // s := NewSpring(deltaTime, 5.0, 0.2)
// //
// // Then, in your update loop: // // Then, in your update loop:
// s.Update(&x, &xVel, 10) // update the X position // x, xVel = s.Update(x, xVel, 10) // update the X position
// s.Update(&y, &yVel, 20) // update the Y position // y, yVel = s.Update(y, yVel, 20) // update the Y position
// //
type Spring struct { type Spring struct {
posPosCoef, posVelCoef float64 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. // Update updates position and velocity values against a given target value.
// Call this after calling NewSpring to update values. // Call this after calling NewSpring to update values.
func (s Spring) Update(pos *float64, vel *float64, equilibriumPos float64) { func (s Spring) Update(pos, vel float64, equilibriumPos float64) (newPos, newVel float64) {
oldPos := *pos - equilibriumPos // update in equilibrium relative space oldPos := pos - equilibriumPos // update in equilibrium relative space
oldVel := *vel oldVel := vel
*pos = oldPos*s.posPosCoef + oldVel*s.posVelCoef + equilibriumPos newPos = oldPos*s.posPosCoef + oldVel*s.posVelCoef + equilibriumPos
*vel = oldPos*s.velPosCoef + oldVel*s.velVelCoef newVel = oldPos*s.velPosCoef + oldVel*s.velVelCoef
return newPos, newVel
} }