diff --git a/src/main.rs b/src/main.rs index d59762d..1396e74 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ use std::io::stdout; +use std::time::Duration; use anyhow::Error; use clap::Parser; use clap::ArgEnum; @@ -11,8 +12,10 @@ use crate::fill::circle::CircleFillMode; use crate::fill::FillMode; use crate::fill::level::LevelFillMode; use crate::render::{Renderer, SamplerRenderer}; +use crate::runner::Runner; use crate::sampler::ComposedSampler; use crate::surface::WriteSurface; +use crate::timer::SimpleTimer; use crate::vec::Vector; mod color; @@ -24,6 +27,8 @@ mod surface; mod animation; mod sampler; mod render; +mod timer; +mod runner; #[derive(Copy, Clone, ArgEnum)] enum AnimationType { @@ -81,12 +86,11 @@ fn main() -> Result<(), Error> { let sampler = Box::new(ComposedSampler::new(animation, fill, color, char)); let surface = Box::new(WriteSurface::new(stdout(), width, height)); - let mut renderer = Box::new(SamplerRenderer::new(surface, sampler)); + let renderer = Box::new(SamplerRenderer::new(surface, sampler)); + let timer = Box::new(SimpleTimer::new(Duration::from_millis(1000 / 60))); + let runner = Runner::new(Duration::from_secs(2), timer, renderer); - renderer.render(0.5); - renderer.present()?; - - Ok(()) + runner.run() } fn create_animation(animation: AnimationType, size: Vector) -> Box { diff --git a/src/runner.rs b/src/runner.rs new file mode 100644 index 0000000..142b010 --- /dev/null +++ b/src/runner.rs @@ -0,0 +1,31 @@ +use std::time::Duration; +use anyhow::Error; +use crate::Renderer; +use crate::timer::Timer; + +pub struct Runner { + timer: Box, + ticks: u128, + renderer: Box, +} + +impl Runner { + pub fn new(duration: Duration, + timer: Box, + renderer: Box) -> Self { + let ticks = duration.as_nanos() / timer.delay().as_nanos(); + + Self { timer, ticks, renderer } + } + + pub fn run(mut self) -> Result<(), Error> { + for i in 0..self.ticks { + let step = i as f32 / self.ticks as f32; + + self.renderer.render(step); + self.renderer.present()?; + self.timer.sleep(); + } + self.renderer.finish() + } +} \ No newline at end of file diff --git a/src/timer.rs b/src/timer.rs new file mode 100644 index 0000000..2c39454 --- /dev/null +++ b/src/timer.rs @@ -0,0 +1,39 @@ +use std::thread::sleep; +use std::time::{Duration, Instant}; +use mockall::automock; + +#[automock] +pub trait Timer { + fn sleep(&mut self); + + fn delay(&self) -> Duration; +} + +pub struct SimpleTimer { + delay: Duration, + last: Instant +} + +impl SimpleTimer { + pub fn new(delay: Duration) -> Self { + Self { + last: Instant::now(), + delay, + } + } +} + +impl Timer for SimpleTimer { + fn sleep(&mut self) { + let now = Instant::now(); + + if self.last + self.delay > now { + sleep(self.delay - (now - self.last)); + } + self.last = Instant::now(); + } + + fn delay(&self) -> Duration { + self.delay + } +} \ No newline at end of file