[O] Actually draw asciis
This commit is contained in:
+62
-67
@@ -1,16 +1,16 @@
|
|||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
|
|
||||||
use std::io::{stdin, Write};
|
use std::{mem, thread};
|
||||||
use std::{io, mem, thread};
|
|
||||||
use std::borrow::ToOwned;
|
|
||||||
use std::ops::Deref;
|
|
||||||
use std::ptr::null;
|
|
||||||
use std::string::ToString;
|
use std::string::ToString;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use rand::Rng;
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use rand::Rng;
|
||||||
use termion::color::{Fg, Rgb};
|
use termion::color::{Fg, Rgb};
|
||||||
use termion::cursor::Goto;
|
use termion::cursor::Goto;
|
||||||
|
use crate::cowsay::gen_bubble_ascii;
|
||||||
|
|
||||||
|
mod cowsay;
|
||||||
|
|
||||||
const RESET: &str = "\x1b[0m";
|
const RESET: &str = "\x1b[0m";
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ struct SnowParticle {
|
|||||||
|
|
||||||
/// AsciiArt is a struct that holds the ascii art and the credit for the art.
|
/// AsciiArt is a struct that holds the ascii art and the credit for the art.
|
||||||
#[derive(Clone, PartialEq, Eq)]
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
struct AsciiArt {
|
pub struct AsciiArt {
|
||||||
art: String,
|
art: String,
|
||||||
h: u16,
|
h: u16,
|
||||||
w: u16,
|
w: u16,
|
||||||
@@ -96,8 +96,8 @@ struct Consts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct Mutes {
|
struct Mutes {
|
||||||
width: u16,
|
w: u16,
|
||||||
height: u16,
|
h: u16,
|
||||||
x: u16,
|
x: u16,
|
||||||
|
|
||||||
buf: Vec<Vec<Option<Pixel>>>,
|
buf: Vec<Vec<Option<Pixel>>>,
|
||||||
@@ -166,7 +166,8 @@ impl Mutes {
|
|||||||
let snow = create_snow(width, height);
|
let snow = create_snow(width, height);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
width, height, x,
|
w: width,
|
||||||
|
h: height, x,
|
||||||
buf, last_buf,
|
buf, last_buf,
|
||||||
last_update: Instant::now(),
|
last_update: Instant::now(),
|
||||||
snow,
|
snow,
|
||||||
@@ -183,13 +184,13 @@ impl Mutes {
|
|||||||
|
|
||||||
// If the snow particle is out of x bounds, wrap it around
|
// If the snow particle is out of x bounds, wrap it around
|
||||||
if p.x < 0.0 {
|
if p.x < 0.0 {
|
||||||
p.x += self.width as f32;
|
p.x += self.w as f32;
|
||||||
} else if p.x > self.width as f32 {
|
} else if p.x > self.w as f32 {
|
||||||
p.x -= self.width as f32;
|
p.x -= self.w as f32;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the snow particle is out of y bounds, reset it
|
// If the snow particle is out of y bounds, reset it
|
||||||
if p.y > self.height as f32 {
|
if p.y > self.h as f32 {
|
||||||
let (vx, vy) = snow_rand_velocity();
|
let (vx, vy) = snow_rand_velocity();
|
||||||
p.vx = vx;
|
p.vx = vx;
|
||||||
p.vy = vy;
|
p.vy = vy;
|
||||||
@@ -199,7 +200,7 @@ impl Mutes {
|
|||||||
// Draw the snow particle in the buffer
|
// Draw the snow particle in the buffer
|
||||||
let x = p.x.round() as u16;
|
let x = p.x.round() as u16;
|
||||||
let y = p.y.round() as u16;
|
let y = p.y.round() as u16;
|
||||||
if x < self.width && y < self.height {
|
if x < self.w && y < self.h {
|
||||||
self.buf[y as usize][x as usize] = Some(Pixel { color: p.color, char: '*' });
|
self.buf[y as usize][x as usize] = Some(Pixel { color: p.color, char: '*' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,7 +214,7 @@ impl Mutes {
|
|||||||
// Draw the character in the buffer
|
// Draw the character in the buffer
|
||||||
let x = x + j as u16;
|
let x = x + j as u16;
|
||||||
let y = y + i as u16;
|
let y = y + i as u16;
|
||||||
if x < self.width && y < self.height {
|
if x < self.w && y < self.h {
|
||||||
self.buf[y as usize][x as usize] = Some(Pixel { color, char: c });
|
self.buf[y as usize][x as usize] = Some(Pixel { color, char: c });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,7 +224,7 @@ impl Mutes {
|
|||||||
/// Draw the buffer to the screen, diffing it with the last buffer, and only drawing the changed pixels
|
/// Draw the buffer to the screen, diffing it with the last buffer, and only drawing the changed pixels
|
||||||
fn draw_buf(&mut self) -> Result<String> {
|
fn draw_buf(&mut self) -> Result<String> {
|
||||||
// Create a buffer string
|
// Create a buffer string
|
||||||
let mut buf_str = String::with_capacity((self.width * self.height) as usize);
|
let mut buf_str = String::with_capacity((self.w * self.h) as usize);
|
||||||
|
|
||||||
// Keep the last color
|
// Keep the last color
|
||||||
let mut last_color: &str = "";
|
let mut last_color: &str = "";
|
||||||
@@ -238,8 +239,8 @@ impl Mutes {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Loop through all pixels in the buffer
|
// Loop through all pixels in the buffer
|
||||||
for y in 0..self.height {
|
for y in 0..self.h {
|
||||||
for x in 0..self.width {
|
for x in 0..self.w {
|
||||||
// Get the pixel
|
// Get the pixel
|
||||||
let p = &self.buf[y as usize][x as usize];
|
let p = &self.buf[y as usize][x as usize];
|
||||||
|
|
||||||
@@ -282,73 +283,67 @@ impl Mutes {
|
|||||||
buf_str.push_str(RESET);
|
buf_str.push_str(RESET);
|
||||||
|
|
||||||
// Flush the buffer
|
// Flush the buffer
|
||||||
buf_str.push_str(&Goto(1, self.height as u16 + 1).to_string());
|
buf_str.push_str(&Goto(1, self.h as u16 + 1).to_string());
|
||||||
|
|
||||||
Ok(buf_str)
|
Ok(buf_str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Main {
|
fn draw_ascii_frame(mt: &mut Mutes, cn: &Consts) {
|
||||||
fn new() -> Self {
|
// Draw the cat
|
||||||
// Create the mutes object
|
mt.print_ascii(&cn.asc_cat, mt.x, mt.h - cn.asc_cat.h, "\x1b[38;2;255;231;151m");
|
||||||
let consts = Consts::new();
|
|
||||||
let mut mutes = Mutes::new(&consts);
|
|
||||||
|
|
||||||
Self {
|
// Draw the tree
|
||||||
cn: consts,
|
mt.print_ascii(&cn.asc_tree, (mt.w - 2 * cn.asc_tree.w) / 4, mt.h - cn.asc_tree.h,
|
||||||
mt: mutes,
|
"\x1b[38;2;204;255;88m");
|
||||||
}
|
mt.print_ascii(&cn.asc_tree, (mt.w + 2 * cn.asc_tree.w) / 2, mt.h - cn.asc_tree.h,
|
||||||
}
|
"\x1b[38;2;204;255;88m");
|
||||||
|
|
||||||
fn draw_ascii_frame(&mut self) {
|
// Draw the house
|
||||||
// Draw the cat
|
mt.print_ascii(&cn.asc_house, (mt.w + cn.asc_house.w) / 2, mt.h - cn.asc_house.h,
|
||||||
self.mt.print_ascii(&self.cn.asc_cat, self.mt.x, 0, "\x1b[38;2;255;231;151m");
|
"\x1b[38;2;251;194;110m");
|
||||||
|
}
|
||||||
|
|
||||||
// Draw the tree
|
fn start_loop(mt: &mut Mutes, cn: &Consts) {
|
||||||
self.mt.print_ascii(&self.cn.asc_tree, 0, 0, "\x1b[38;2;0;255;0m");
|
// Clear the screen
|
||||||
|
print!("{}", termion::clear::All);
|
||||||
|
print!("{}", termion::cursor::Hide);
|
||||||
|
|
||||||
// Draw the house
|
// Start the loop
|
||||||
self.mt.print_ascii(&self.cn.asc_house, 0, 0, "\x1b[38;2;255;0;0m");
|
loop {
|
||||||
}
|
// Get the current time
|
||||||
|
let now = Instant::now();
|
||||||
|
|
||||||
fn start_loop(&mut self) {
|
// Calculate the delta time
|
||||||
// Clear the screen
|
let dt = (now - mt.last_update).as_secs_f32();
|
||||||
print!("{}", termion::clear::All);
|
mt.last_update = now;
|
||||||
print!("{}", termion::cursor::Hide);
|
|
||||||
|
|
||||||
// Start the loop
|
// Update the snow
|
||||||
loop {
|
mt.update_snow(dt);
|
||||||
// Get the current time
|
draw_ascii_frame(mt, cn);
|
||||||
let now = Instant::now();
|
|
||||||
|
|
||||||
// Calculate the delta time
|
// Draw the buffer, time it, and print it
|
||||||
let dt = (now - self.mt.last_update).as_secs_f32();
|
let start = Instant::now();
|
||||||
self.mt.last_update = now;
|
let txt = mt.draw_buf().unwrap();
|
||||||
|
let end = Instant::now();
|
||||||
|
let draw_time = (end - start).as_secs_f32();
|
||||||
|
print!("\rDraw time: {:.2}ms", draw_time * 1000.0);
|
||||||
|
print!("{}", txt);
|
||||||
|
|
||||||
// Update the snow
|
|
||||||
self.mt.update_snow(dt);
|
|
||||||
|
|
||||||
// Draw the buffer, time it, and print it
|
// Set cursor to the bottom of the screen
|
||||||
let start = Instant::now();
|
print!("\x1b[9999;9999H");
|
||||||
let txt = self.mt.draw_buf().unwrap();
|
|
||||||
let end = Instant::now();
|
|
||||||
let draw_time = (end - start).as_secs_f32();
|
|
||||||
print!("\rDraw time: {:.2}ms", draw_time * 1000.0);
|
|
||||||
print!("{}", txt);
|
|
||||||
|
|
||||||
// Set cursor to the bottom of the screen
|
// Sleep for 1/20th of a second
|
||||||
print!("\x1b[9999;9999H");
|
thread::sleep(Duration::from_millis(1000 / 20));
|
||||||
|
|
||||||
// Sleep for 1/20th of a second
|
|
||||||
thread::sleep(Duration::from_millis(1000 / 20));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
pretty_env_logger::init();
|
pretty_env_logger::init();
|
||||||
|
|
||||||
// Create the Main object
|
let cn = Consts::new();
|
||||||
let mut main = Main::new();
|
let mut mt = Mutes::new(&cn);
|
||||||
main.start_loop();
|
|
||||||
|
start_loop(&mut mt, &cn);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user