mirror of
https://github.com/ricoriedel/wipe.git
synced 2024-12-23 06:36:42 +00:00
Add rhombus rotation and stripes
This commit is contained in:
parent
8b551c3d1c
commit
d8fdc142e6
@ -1,4 +1,6 @@
|
||||
pub mod circle;
|
||||
pub mod rotation;
|
||||
pub mod rhombus;
|
||||
|
||||
use crate::vec::Vector;
|
||||
|
||||
|
51
src/animation/rhombus.rs
Normal file
51
src/animation/rhombus.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use crate::animation::Animation;
|
||||
use crate::vec::Vector;
|
||||
|
||||
const THICKNESS: f32 = 0.2;
|
||||
const FINAL_DISTANCE: f32 = 1.0 + THICKNESS * 2.0;
|
||||
|
||||
pub struct RhombusAnimation {
|
||||
center: Vector,
|
||||
thickness: f32,
|
||||
final_distance: f32,
|
||||
}
|
||||
|
||||
impl RhombusAnimation {
|
||||
pub fn new(size: Vector) -> Self {
|
||||
let center = size.center();
|
||||
let distance = center.sum();
|
||||
|
||||
Self {
|
||||
center,
|
||||
thickness: distance * THICKNESS,
|
||||
final_distance: distance * FINAL_DISTANCE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Animation for RhombusAnimation {
|
||||
fn sample(&self, step: f32, pos: Vector) -> f32 {
|
||||
let dist = self.final_distance * step - self.thickness;
|
||||
let pos_dist = (self.center - pos).abs().sum();
|
||||
|
||||
(pos_dist - dist) / self.thickness
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn sample() {
|
||||
let anim = RhombusAnimation::new(Vector::new(30.0, 10.0));
|
||||
|
||||
let sample_1 = anim.sample(0.2, Vector::new(5.0, 16.0));
|
||||
let sample_2 = anim.sample(0.7, Vector::new(22.0, 2.0));
|
||||
let sample_3 = anim.sample(0.5, Vector::new(4.0, 7.0));
|
||||
|
||||
assert!(4.8 < sample_1 && sample_1 < 4.9);
|
||||
assert!(-1.5 < sample_2 && sample_2 < -1.4);
|
||||
assert!(0.7 < sample_3 && sample_3 < 0.8);
|
||||
}
|
||||
}
|
46
src/animation/rotation.rs
Normal file
46
src/animation/rotation.rs
Normal file
@ -0,0 +1,46 @@
|
||||
use std::f32::consts::PI;
|
||||
use crate::animation::Animation;
|
||||
use crate::vec::Vector;
|
||||
|
||||
const TWO_PI: f32 = PI * 2.0;
|
||||
const THICKNESS: f32 = TWO_PI * 0.1;
|
||||
const FULL_ROTATION: f32 = TWO_PI + THICKNESS * 2.0;
|
||||
|
||||
pub struct RotationAnimation {
|
||||
center: Vector
|
||||
}
|
||||
|
||||
impl RotationAnimation {
|
||||
pub fn new(size: Vector) -> Self {
|
||||
Self {
|
||||
center: size.center()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Animation for RotationAnimation {
|
||||
fn sample(&self, step: f32, pos: Vector) -> f32 {
|
||||
let angle = FULL_ROTATION * step - PI - THICKNESS;
|
||||
let pos_angle = (pos - self.center).angle();
|
||||
|
||||
(pos_angle - angle) / THICKNESS
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn sample() {
|
||||
let anim = RotationAnimation::new(Vector::new(30.0, 10.0));
|
||||
|
||||
let sample_1 = anim.sample(0.2, Vector::new(5.0, 16.0));
|
||||
let sample_2 = anim.sample(0.7, Vector::new(22.0, 2.0));
|
||||
let sample_3 = anim.sample(0.5, Vector::new(4.0, 7.0));
|
||||
|
||||
assert!(2.4 < sample_1 && sample_1 < 2.5);
|
||||
assert!(0.7 < sample_2 && sample_2 < 0.8);
|
||||
assert!(-2.3 < sample_3 && sample_3 < -2.2);
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
pub mod level;
|
||||
pub mod circle;
|
||||
pub mod stripes;
|
||||
|
||||
use crate::vec::Vector;
|
||||
|
||||
|
35
src/fill/stripes.rs
Normal file
35
src/fill/stripes.rs
Normal file
@ -0,0 +1,35 @@
|
||||
use crate::FillMode;
|
||||
use crate::vec::Vector;
|
||||
|
||||
const INTERVAL: f32 = 4.0;
|
||||
|
||||
pub struct StripesFillMode {
|
||||
interval: f32
|
||||
}
|
||||
|
||||
impl StripesFillMode {
|
||||
pub fn new(size: Vector) -> Self {
|
||||
Self {
|
||||
interval: size.smaller() / INTERVAL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FillMode for StripesFillMode {
|
||||
fn sample(&self, _: f32, pos: Vector) -> f32 {
|
||||
(pos.sum() % self.interval) / self.interval
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn sample() {
|
||||
let mode = StripesFillMode::new(Vector::new(8.0, 4.0));
|
||||
|
||||
assert_eq!(0.25, mode.sample(0.0, Vector::new(1.5, 0.75)));
|
||||
assert_eq!(0.5, mode.sample(0.0, Vector::new(4.0, 2.5)));
|
||||
}
|
||||
}
|
17
src/main.rs
17
src/main.rs
@ -6,12 +6,15 @@ use clap::ArgEnum;
|
||||
use rand::rngs::OsRng;
|
||||
use crate::animation::Animation;
|
||||
use crate::animation::circle::CircleAnimation;
|
||||
use crate::animation::rhombus::RhombusAnimation;
|
||||
use crate::animation::rotation::RotationAnimation;
|
||||
use crate::char::SimpleCharSampler;
|
||||
use crate::choose::{Chooser, Options};
|
||||
use crate::color::{ColorSampler, SimpleColorSampler};
|
||||
use crate::fill::circle::CircleFillMode;
|
||||
use crate::fill::FillMode;
|
||||
use crate::fill::level::LevelFillMode;
|
||||
use crate::fill::stripes::StripesFillMode;
|
||||
use crate::render::{Renderer, SamplerRenderer};
|
||||
use crate::runner::Runner;
|
||||
use crate::sampler::ComposedSampler;
|
||||
@ -34,14 +37,16 @@ mod choose;
|
||||
|
||||
#[derive(Copy, Clone, ArgEnum)]
|
||||
enum AnimationType {
|
||||
Circle
|
||||
Circle,
|
||||
Rhombus,
|
||||
Rotation
|
||||
}
|
||||
|
||||
impl Options for AnimationType {
|
||||
fn all() -> Vec<Self> where Self: Sized {
|
||||
use AnimationType::*;
|
||||
|
||||
vec![Circle]
|
||||
vec![Circle, Rhombus, Rotation]
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,7 +73,8 @@ impl Options for ColorType {
|
||||
#[derive(Copy, Clone, ArgEnum)]
|
||||
enum FillModeType {
|
||||
Circle,
|
||||
Level
|
||||
Level,
|
||||
Stripes
|
||||
}
|
||||
|
||||
impl Options for FillModeType {
|
||||
@ -128,7 +134,9 @@ fn main() -> Result<(), Error> {
|
||||
|
||||
fn create_animation(animation: AnimationType, size: Vector) -> Box<dyn Animation> {
|
||||
match animation {
|
||||
AnimationType::Circle => Box::new(CircleAnimation::new(size))
|
||||
AnimationType::Circle => Box::new(CircleAnimation::new(size)),
|
||||
AnimationType::Rhombus => Box::new(RhombusAnimation::new(size)),
|
||||
AnimationType::Rotation => Box::new(RotationAnimation::new(size)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,6 +144,7 @@ fn create_fill(fill: FillModeType, size: Vector) -> Box<dyn FillMode> {
|
||||
match fill {
|
||||
FillModeType::Circle => Box::new(CircleFillMode::new(size)),
|
||||
FillModeType::Level => Box::new(LevelFillMode::new()),
|
||||
FillModeType::Stripes => Box::new(StripesFillMode::new(size))
|
||||
}
|
||||
}
|
||||
|
||||
|
12
src/vec.rs
12
src/vec.rs
@ -20,10 +20,22 @@ impl Vector {
|
||||
(self.x * self.x + self.y * self.y).sqrt()
|
||||
}
|
||||
|
||||
pub fn angle(self) -> f32 {
|
||||
self.x.atan2(self.y)
|
||||
}
|
||||
|
||||
pub fn smaller(self) -> f32 {
|
||||
self.x.min(self.y)
|
||||
}
|
||||
|
||||
pub fn abs(self) -> Vector {
|
||||
Self::new(self.x.abs(), self.y.abs())
|
||||
}
|
||||
|
||||
pub fn sum(self) -> f32 {
|
||||
self.x + self.y
|
||||
}
|
||||
|
||||
/// Creates a vector with the on screen coordinates based on the terminal coordinates.
|
||||
/// # Arguments
|
||||
/// * `x`: The x axis of the terminal character.
|
||||
|
Loading…
Reference in New Issue
Block a user