Skip to main content

Spring

Struct Spring 

Source
pub struct Spring { /* private fields */ }
Expand description

Precomputed spring motion parameters for efficient animation updates.

A Spring contains cached coefficients that can be used to efficiently update multiple springs using the same time step, angular frequency, and damping ratio.

§Creating a Spring

Use Spring::new with the time delta (animation frame length), angular frequency, and damping ratio:

use harmonica::{fps, Spring};

// Precompute spring coefficients
let spring = Spring::new(fps(60), 5.0, 0.2);

§Damping Ratios

The damping ratio determines how the spring behaves:

  • Over-damped (ζ > 1): No oscillation, slow approach to equilibrium
  • Critically-damped (ζ = 1): Fastest approach without oscillation
  • Under-damped (ζ < 1): Oscillates around equilibrium with decay

§Example

use harmonica::{fps, Spring};

// Create spring for X and Y positions
let mut x = 0.0;
let mut x_vel = 0.0;
let mut y = 0.0;
let mut y_vel = 0.0;

let spring = Spring::new(fps(60), 5.0, 0.2);

// In your update loop:
(x, x_vel) = spring.update(x, x_vel, 10.0);  // Move X toward 10
(y, y_vel) = spring.update(y, y_vel, 20.0);  // Move Y toward 20

Implementations§

Source§

impl Spring

Source

pub fn new(delta_time: f64, angular_frequency: f64, damping_ratio: f64) -> Self

Creates a new spring, computing the parameters needed to simulate a damped spring over a given period of time.

§Arguments
  • delta_time - The time step to advance (essentially the framerate). Use fps to compute this from a frame rate.
  • angular_frequency - The angular frequency of motion, which affects the speed. Higher values make the spring move faster.
  • damping_ratio - The damping ratio, which determines oscillation:
    • > 1.0: Over-damped (no oscillation, slow return)
    • = 1.0: Critically-damped (fastest without oscillation)
    • < 1.0: Under-damped (oscillates with decay)
§Example
use harmonica::{fps, Spring};

// Create an under-damped spring (will oscillate)
let bouncy = Spring::new(fps(60), 6.0, 0.2);

// Create a critically-damped spring (no oscillation)
let smooth = Spring::new(fps(60), 6.0, 1.0);

// Create an over-damped spring (very slow, no oscillation)
let sluggish = Spring::new(fps(60), 6.0, 2.0);
Source

pub fn update(&self, pos: f64, vel: f64, equilibrium_pos: f64) -> (f64, f64)

Updates position and velocity values against a given target value.

Call this after creating a spring to update values each frame.

§Arguments
  • pos - Current position
  • vel - Current velocity
  • equilibrium_pos - Target position to move toward
§Returns

A tuple of (new_position, new_velocity).

§Example
use harmonica::{fps, Spring};

let spring = Spring::new(fps(60), 5.0, 0.2);
let mut pos = 0.0;
let mut vel = 0.0;
let target = 100.0;

// Simulate 60 frames (1 second at 60 FPS)
for _ in 0..60 {
    (pos, vel) = spring.update(pos, vel, target);
}

println!("Position: {pos}, Velocity: {vel}");

Trait Implementations§

Source§

impl Clone for Spring

Source§

fn clone(&self) -> Spring

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Spring

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Spring

Source§

fn default() -> Spring

Returns the “default value” for a type. Read more
Source§

impl PartialEq for Spring

Source§

fn eq(&self, other: &Spring) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for Spring

Source§

impl StructuralPartialEq for Spring

Auto Trait Implementations§

§

impl Freeze for Spring

§

impl RefUnwindSafe for Spring

§

impl Send for Spring

§

impl Sync for Spring

§

impl Unpin for Spring

§

impl UnwindSafe for Spring

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.