sines/sines.rs
1//! Cool looking animated sine waves.
2//!
3//! ```text
4//! ⠀⠀i:⠀107⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀Fixed⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
5//! ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
6//! ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
7//! ⠉⠉⠢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠊⠉⠉⠢⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠔⠉⠉⠑⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠔⠉⠉⠑⢄⠀
8//! ⠀⠀⠀⠘⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⠁⠀⠀⠀⠀⠀⢣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠎⠀⠀⠀⠀⠀⢣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠊⠀⠀⠀⠀⠀⢣
9//! ⠀⠀⠀⠀⢘⡔⠉⠉⠉⠉⠢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⠁⠀⠀⠀⠀⠀⠀⠀⣣⠊⠉⠉⠉⠢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠃⠀⠀⠀⠀⠀⠀⠀⣣⠊⠉⠉⠉⠢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠃⠀⠀⠀⠀⠀⠀⠀
10//! ⠀⠀⠀⡔⠁⠘⡄⠀⠀⠀⠀⠈⣢⡔⠒⠒⠒⠒⢄⡀⡰⠁⠀⠀⠀⠀⠀⠀⡠⠊⠀⢣⠀⠀⠀⠀⠈⣢⡔⠒⠒⠒⠒⢄⡀⢀⠎⠀⠀⠀⠀⠀⠀⡠⠊⠀⢣⠀⠀⠀⠀⠈⡢⡔⠒⠒⠒⠒⢄⡀⢀⠎⠀⠀⠀⠀⠀⢀⠔⠉
11//! ⠀⢠⠊⠀⠀⠀⠱⡀⠀⠀⡠⠊⠀⠘⢄⠀⠀⠀⠀⢸⠣⡀⠀⠀⠀⠀⠀⡔⠁⠀⠀⠈⢆⠀⠀⡠⠊⠀⠘⢄⠀⠀⠀⠀⠈⡮⡀⠀⠀⠀⠀⠀⡔⠁⠀⠀⠈⢆⠀⢀⡠⠊⠀⠑⢄⠀⠀⠀⠀⠈⡮⡀⠀⠀⠀⠀⢠⠊⠀⠀
12//! ⡰⠁⠀⠀⠀⠀⠀⢣⠔⠉⠀⠀⠀⠀⠈⢢⠀⠀⢠⠃⠀⠈⠑⢄⠀⢀⠎⠀⠀⠀⠀⠀⢘⡔⠉⠀⠀⠀⠀⠈⢢⠀⠀⠀⡜⠀⠈⠒⢄⠀⢠⠊⠀⠀⠀⠀⠀⢘⡔⠁⠀⠀⠀⠀⠈⢢⠀⠀⠀⡜⠀⠈⠒⢄⠀⡔⠁⠀⠀⠀
13//! ⠣⣀⣀⣀⣀⡠⠒⠁⢣⠀⠀⠀⠀⠀⠀⠀⠑⢄⠎⠀⠀⠀⠀⢀⠕⠣⣀⣀⢀⣀⡠⠒⠁⠘⡄⠀⠀⠀⠀⠀⠀⠑⢄⡰⠁⠀⠀⠀⢀⠕⠥⣀⣀⣀⣀⡠⠒⠁⠘⡄⠀⠀⠀⠀⠀⠀⠑⢄⡸⠀⠀⠀⠀⡠⠛⠤⣀⣀⣀⣀
14//! ⠀⠀⠀⠀⠀⠀⠀⠀⠀⢣⠀⠀⠀⠀⠀⠀⢀⠎⠑⠤⢄⠤⠔⠁⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠘⡄⠀⠀⠀⠀⠀⠀⡰⠑⠤⠤⠤⠔⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠱⡀⠀⠀⠀⠀⠀⠀⡰⠑⠤⠤⠤⠊⠀⠀⠀⠀⠀⠀⠀
15//! ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢣⠀⠀⠀⠀⢀⠎⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⡄⠀⠀⠀⠀⡰⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⡄⠀⠀⠀⠀⡰⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
16//! ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⠤⠤⠔⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢⢄⠤⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢⠤⠤⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
17//! ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
18//! ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
19//! ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
20//! ```
21//!
22//! ```text
23//! ⠀Δt:⠀0.003731337⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀Variable⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
24//! acc:⠀122.2455052⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
25//! ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
26//! ⠀⢀⠔⠉⠉⠑⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠔⠉⠉⠑⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠖⠋⠉⠑⠢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⠉⠉
27//! ⢠⠃⠀⠀⠀⠀⠈⢢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠃⠀⠀⠀⠀⠈⢲⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⠀⠑⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡜⠀⠀⠀
28//! ⢇⠀⠀⠀⠀⠀⠀⠀⢣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠊⠉⠉⠉⢲⢧⠀⠀⠀⠀⠀⠀⠀⢱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠎⠉⠉⠉⢱⠣⡀⠀⠀⠀⠀⠀⠀⠸⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠔⠉⠉⠉⠑⡾⡀⠀⠀⠀
29//! ⠀⠱⡀⣀⠤⠔⠒⠒⠚⢦⢄⠀⠀⠀⠀⠀⠀⢀⠎⠀⠀⠀⠀⢠⠃⠀⠹⡀⣀⠤⠒⠒⠒⠒⢣⢄⠀⠀⠀⠀⠀⠀⢀⠎⠀⠀⠀⠀⢀⠇⠀⠈⢆⢀⡠⠒⠒⠒⠒⠳⣄⠀⠀⠀⠀⠀⠀⠀⡔⠁⠀⠀⠀⠀⡜⠀⠘⢄⢀⡠
30//! ⠀⢀⠜⢇⠀⠀⠀⠀⠀⠘⡄⠑⠢⡀⠀⠀⡰⠁⠀⠀⠀⠀⢀⠎⠀⠀⢠⠊⢆⠀⠀⠀⠀⠀⠘⡄⠑⠤⡀⠀⠀⡰⠁⠀⠀⠀⠀⢀⠎⠀⠀⢀⠔⠱⡀⠀⠀⠀⠀⠀⢣⠑⠤⡀⠀⠀⢀⠎⠀⠀⠀⠀⠀⡸⠀⠀⢀⠔⠣⡀
31//! ⠔⠁⠀⠀⠣⡀⠀⠀⠀⠀⠘⡄⠀⠑⢄⠜⠀⠀⠀⠀⠀⠀⡎⠀⣀⠔⠁⠀⠀⠣⡀⠀⠀⠀⠀⠘⡄⠀⠈⢢⡔⠁⠀⠀⠀⠀⠀⡎⠀⡠⠔⠁⠀⠀⠘⢄⠀⠀⠀⠀⠀⢇⠀⠈⠢⡠⠃⠀⠀⠀⠀⠀⢰⠁⡠⠔⠁⠀⠀⠘
32//! ⠀⠀⠀⠀⠀⠘⢄⠀⠀⠀⠀⠱⡀⡠⠃⠑⠒⠤⣀⣀⣀⣜⠤⠊⠀⠀⠀⠀⠀⠀⠘⢄⠀⠀⠀⠀⠱⡀⡠⠇⠈⠒⠤⣀⣀⣀⣔⠥⠊⠀⠀⠀⠀⠀⠀⠈⠢⡀⠀⠀⠀⠈⢆⢀⠎⠈⠒⢄⣀⡀⣀⣠⠧⠊⠀⠀⠀⠀⠀⠀
33//! ⠀⠀⠀⠀⠀⠀⠀⠑⠢⠤⠤⠔⠻⡀⠀⠀⠀⠀⠀⠀⡰⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠢⠤⠤⠔⠻⡀⠀⠀⠀⠀⠀⠀⡸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢⠤⡠⠤⠚⢇⠀⠀⠀⠀⠀⠈⢀⠇⠀⠀⠀⠀⠀⠀⠀⠀
34//! ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠱⡀⠀⠀⠀⠀⡔⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⡄⠀⠀⠀⠀⡔⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢆⠀⠀⠀⠀⢠⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀
35//! ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢⢄⠤⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠢⠤⠤⠎⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠓⠤⠤⠔⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
36//! ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
37//! ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
38//! ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
39//! ```
40
41use std::time;
42
43use textcanvas::TextCanvas;
44use textcanvas::charts::Plot;
45use textcanvas::utils::GameLoop;
46
47fn main() {
48 for _ in 0..3 {
49 with_fixed_time_step();
50 with_variable_time_step();
51 }
52}
53
54/// Will loop at a predefined rate.
55fn with_fixed_time_step() {
56 let mut canvas = TextCanvas::new(80, 16);
57
58 let mut big_sine = TextCanvas::new(80, 10);
59 let mut medium_sine = TextCanvas::new(80, 6);
60 let mut small_sine = TextCanvas::new(80, 4);
61
62 let f = |x: f64| x.sin();
63
64 let mut i = 0;
65 #[rustfmt::skip]
66 GameLoop::loop_fixed(time::Duration::from_millis(30), &mut || {
67 if i == 108 {
68 // Break out of the loop.
69 return None;
70 }
71
72 let big_offset = f64::from(i) / 350.0 * 37.0;
73 let medium_offset = f64::from(i) / 250.0 * 37.0;
74 let small_offset = f64::from(i) / 150.0 * 37.0;
75
76 canvas.clear();
77
78 big_sine.clear();
79 medium_sine.clear();
80 small_sine.clear();
81
82 Plot::function(&mut big_sine, -10.0 + big_offset, 10.0 + big_offset, &f);
83 Plot::function(&mut medium_sine, -10.0 + medium_offset, 10.0 + medium_offset, &f);
84 Plot::function(&mut small_sine, -10.0 + small_offset, 10.0 + small_offset, &f);
85
86 canvas.merge_canvas(&big_sine, 0, 12);
87 canvas.merge_canvas(&medium_sine, 0, 20);
88 canvas.merge_canvas(&small_sine, 0, 25);
89
90 canvas.draw_text(&format!(" i: {i}"), 0, 0);
91 canvas.draw_text("Fixed", 37, 0);
92
93 i += 1;
94
95 Some(canvas.to_string())
96 });
97}
98
99/// Will loop as fast as possible.
100fn with_variable_time_step() {
101 let mut canvas = TextCanvas::new(80, 16);
102
103 let mut big_sine = TextCanvas::new(80, 10);
104 let mut medium_sine = TextCanvas::new(80, 6);
105 let mut small_sine = TextCanvas::new(80, 4);
106
107 let f = |x: f64| x.sin();
108
109 let mut accumulator = 0.0;
110 #[rustfmt::skip]
111 GameLoop::loop_variable(&mut |delta_time| {
112 if accumulator >= 333.33 {
113 // Break out of the loop.
114 return None;
115 }
116
117 let big_offset = accumulator / 350.0 * 12.0;
118 let medium_offset = accumulator / 250.0 * 12.0;
119 let small_offset = accumulator / 150.0 * 12.0;
120
121 canvas.clear();
122
123 big_sine.clear();
124 medium_sine.clear();
125 small_sine.clear();
126
127 Plot::function(&mut big_sine, -10.0 + big_offset, 10.0 + big_offset, &f);
128 Plot::function(&mut medium_sine, -10.0 + medium_offset, 10.0 + medium_offset, &f);
129 Plot::function(&mut small_sine, -10.0 + small_offset, 10.0 + small_offset, &f);
130
131 canvas.merge_canvas(&big_sine, 0, 12);
132 canvas.merge_canvas(&medium_sine, 0, 20);
133 canvas.merge_canvas(&small_sine, 0, 25);
134
135 canvas.draw_text(&format!(" Δt: {delta_time:.9}"), 0, 0);
136 canvas.draw_text(&format!("acc: {accumulator:>11.7}"), 0, 1);
137 canvas.draw_text("Variable", 36, 0);
138
139 accumulator += 100.0 * delta_time;
140
141 Some(canvas.to_string())
142 });
143}