diff --git a/src/animation/circle.rs b/src/animation/circle.rs new file mode 100644 index 0000000..7e9eff8 --- /dev/null +++ b/src/animation/circle.rs @@ -0,0 +1,51 @@ +use crate::animation::Animation; +use crate::vec::Vector; + +const THICKNESS: f32 = 0.2; +const FINAL_RADIUS: f32 = 1.0 + THICKNESS * 2.0; + +pub struct CircleAnimation { + center: Vector, + thickness: f32, + final_radius: f32, +} + +impl CircleAnimation { + pub fn new(size: Vector) -> Self { + let center = size.center(); + let distance = center.length(); + + Self { + center, + thickness: distance * THICKNESS, + final_radius: distance * FINAL_RADIUS, + } + } +} + +impl Animation for CircleAnimation { + fn sample(&self, step: f32, pos: Vector) -> f32 { + let radius = self.final_radius * step - self.thickness; + let distance = (pos - self.center).length(); + + (distance - radius) / self.thickness + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn sample() { + let anim = CircleAnimation::new(Vector::new(10.0, 20.0)); + + let sample_1 = anim.sample(0.5, Vector::new(17.0, 5.0)); + let sample_2 = anim.sample(0.8, Vector::new(11.0, 8.0)); + let sample_3 = anim.sample(0.2, Vector::new(7.0, 10.0)); + + assert!(3.3 < sample_1 && sample_1 < 3.4); + assert!(-1.8 < sample_2 && sample_2 < -1.7); + assert!(0.4 < sample_3 && sample_3 < 0.5); + } +} \ No newline at end of file diff --git a/src/animation/mod.rs b/src/animation/mod.rs new file mode 100644 index 0000000..9eb03a3 --- /dev/null +++ b/src/animation/mod.rs @@ -0,0 +1,7 @@ +mod circle; + +use crate::vec::Vector; + +pub trait Animation { + fn sample(&self, step: f32, pos: Vector) -> f32; +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index fe65078..46cbf89 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ mod fill; mod vec; mod array; mod surface; +mod animation; #[derive(Parser)] #[clap(author = "Rico Riedel", version = "0.1.0", about = "Wipe your terminal with a random animation.")] diff --git a/src/vec.rs b/src/vec.rs index 90ce8d4..4aa6ada 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -1,3 +1,5 @@ +use std::ops::Sub; + /// A vector with a x and y axis. #[derive(Copy, Clone)] pub struct Vector { @@ -12,6 +14,14 @@ impl Vector { Self { x, y } } + pub fn center(self) -> Self { + Self::new(self.x / 2.0, self.y / 2.0) + } + + pub fn length(self) -> f32 { + (self.x * self.x + self.y * self.y).sqrt() + } + /// Creates a vector with the on screen coordinates based on the terminal coordinates. /// # Arguments /// * `x`: The x axis of the terminal character. @@ -21,6 +31,14 @@ impl Vector { } } +impl Sub for Vector { + type Output = Vector; + + fn sub(self, rhs: Self) -> Self::Output { + Vector::new(self.x - rhs.x, self.y - rhs.y) + } +} + #[cfg(test)] mod test { use super::*;