From 4f8f02e146b2880fc514912865361d8a7090c150 Mon Sep 17 00:00:00 2001 From: Rasmus Kaj Date: Thu, 5 Oct 2023 20:54:59 +0200 Subject: [PATCH] Initial commit. --- .gitignore | 2 ++ Cargo.toml | 8 ++++++ src/main.rs | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4fffb2f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..331c846 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "ttylia" +version = "0.1.0" +edition = "2021" +authors = ["Rasmus Kaj "] + +[dependencies] +num-complex = { version = "0.2", default-features = false } diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..1d23399 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,82 @@ +use num_complex::Complex32; +use std::{io::{self, Write}, thread::sleep, time::{Duration, Instant}}; + +const CHARS: &[u8; 33] = b"@. .,:;-~+*i=xom\\//11II77OO77MMMM"; + +fn main() { + const WIDTH: u16 = 40; + const HEIGHT: u16 = 24; + const SY: f32 = 3.2 / (HEIGHT as f32); + const SX: f32 = SY / 1.4; + const X0: f32 = ((WIDTH / 2) as f32) * SX; + const Y0: f32 = ((HEIGHT / 2) as f32) * SY; + let frame_time = Duration::from_millis(300 /*1000/30*/); + let max_iter = u8::try_from(CHARS.len()-1).unwrap(); + let mut buffer = [0u8; (WIDTH * HEIGHT) as usize]; + let mut c = Complex32 { re: -0.5, im: 0.5 }; + let mut rotor = Complex32 { re: 1., im: frame_time.as_secs_f32() * 0.2 }; + let mut frame = 0; + let mut out = io::stdout().lock(); + out.write_all(b"\x1B[2J").unwrap(); + loop { + let frame_start = Instant::now(); + c *= rotor; + if c.norm_sqr() > 2. { + rotor *= (1. / rotor.norm_sqr()).sqrt(); + } + frame += 1; + let mut p = 0; + for y in 0..HEIGHT / 2 { + let zy = f32::from(y) * SY - Y0; + for x in 0..WIDTH { + let z = Complex32 { + re: f32::from(x) * SX - X0, + im: zy, + }; + let val = pixel(julia(z, c, max_iter)); + buffer[p] = val; + p += 1; + buffer[buffer.len() - p] = val; + } + } + let status = format!("ttylia | Rasmus Kaj | Rust | {:.3}", c.l1_norm()); + buffer[0..status.len()].clone_from_slice(status.as_bytes()); + //buffer[0] = b't'; + out.write_all(b"\x1B[H").unwrap(); + for y in 0..HEIGHT { + out.write_all(b"\x1B#6").unwrap(); + out.write_all(&buffer[usize::from(y * WIDTH)..usize::from((y + 1) * WIDTH)]).unwrap(); + } + out.write_all(b"\x1B#6").unwrap(); + //out.write_all(b"\r").unwrap(); + //out.write_all(b"\x1B[Httylia | Rasmus Kaj | Rust \n").unwrap(); + //writeln!(out, "| {c:+.5} | {frame:4} ").unwrap(); + out.flush().unwrap(); + if let Some(remains) = frame_time.checked_sub(frame_start.elapsed()) { + //writeln!(out, " {remains:.3?} ").unwrap(); + sleep(remains); + //} else { + // writeln!(out, "Hurry!").unwrap(); + } + } +} + +fn pixel(i: u8) -> u8 { + CHARS[usize::from(i)] + // u32::from_be_bytes([0xff, i * 6, i + i / 2, i.saturating_mul(8)]) +} + +fn julia(z: Complex32, c: Complex32, max_i: u8) -> u8 { + let mut z = z; + for i in 1..max_i { + if z.norm_sqr() > 4.0 { + return i; + } + z = z * z + c; + } + if z.norm_sqr() > 4.0 { + max_i + } else { + 0 + } +}