use std::{cell::RefCell, f32::consts::PI};
use super::{AnimatedFloat, Behavior};
struct SineProps {
pub speed: AnimatedFloat,
pub cycles: f32,
count: f32,
distance: f32,
center: f32,
}
pub struct Sine {
props: RefCell<SineProps>,
}
impl Sine {
pub const HALF_PI: f32 = { 0.5 * PI };
pub fn new(start: f32, end: f32, speed: f32, cycles: f32, offset: f32) -> Self {
let distance = (start - end) * 0.5;
let props = RefCell::new(SineProps {
speed: AnimatedFloat::new(speed, None),
cycles,
count: Self::HALF_PI + offset * (PI / speed), distance,
center: end + distance,
});
Self {
props,
}
}
}
impl Behavior for Sine {
fn update(&self, dt: f32) -> f32 {
let mut props = self.props.borrow_mut();
props.speed.update(dt);
props.count += dt * (PI / props.speed.get());
if self.is_complete() {
return props.center + PI * props.distance;
}
props.center + props.count.sin() * props.distance
}
fn is_complete(&self) -> bool {
let props = self.props.borrow();
props.cycles > 0.0 && ((props.count - Self::HALF_PI) / PI) * 0.5 >= props.cycles
}
}