Initial commit.
This commit is contained in:
commit
4f8f02e146
3 changed files with 92 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
/Cargo.lock
|
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "ttylia"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
authors = ["Rasmus Kaj <kaj@kth.se>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
num-complex = { version = "0.2", default-features = false }
|
82
src/main.rs
Normal file
82
src/main.rs
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue