Return back to the "Tweak Ferris" Page
/* main.rs */ mod convert_to_vec; mod display; mod get_options; mod images; use convert_to_vec::str_to_vecvecstring; use display::draw_frame; use get_options::get_opts; use ncurses::*; use std::{thread::sleep, time::Duration}; // For a sleep/delay between image frames. fn main() { // Get image data; put it in "model_vecvecstring". let (model_string, fly, oops, interruptible) = get_opts(); let model_vecvecstring = str_to_vecvecstring(&model_string); // ncurses housekeeping stuff. initscr(); // Start ncurses, initializing the screen. noecho(); // Turn off keyboard echo to the screen. curs_set(CURSOR_VISIBILITY::CURSOR_INVISIBLE); // Turn off the display of the cursor. let mut screen_height = 0; // How high... let mut screen_width = 0; // ... and wide ... getmaxyx(stdscr(), &mut screen_height, &mut screen_width); // ... is the screen? // This will be our delay, in milliseconds, between frame images. let delay = 100; let delay_between_frames = Duration::from_millis(delay); // How many frames in the image? let num_of_frames = model_vecvecstring.len() as i32; // How tall is the image? (How many lines are in the first inner vector?) let image_height = model_vecvecstring[0].len() as i32; // Normally type usize, but we need i32 for the "let row..." below. // How wide is the image (in characters/screen columns)? let image_width = model_vecvecstring[0][0].len() as i32; let row: i32 = screen_height - image_height; for col in (-image_width..screen_width).rev() { // Distance to travel is width of screen plus the width of the image. let frame_num = (col % num_of_frames) as usize; // The remainder of this math tells us which frame to display, in descending order. let frame = &model_vecvecstring[frame_num]; // Get the first frame of the image... draw_frame(frame, row, col, screen_width, screen_height); // ... and draw it. sleep(delay_between_frames); } endwin(); // Exit ncurses and restore screen to normal. } // end of main()
/* display.rs */ use ncurses::*; pub fn draw_frame(frame: &Vec<String>, mut row: i32, col: i32, screen_width: i32, screen_height: i32) { for each_line in frame { my_mvaddstr(row, col, each_line, screen_width, screen_height); row += 1; } refresh(); } // end of draw_frame() fn my_mvaddstr(row: i32, mut col: i32, frame_line: &str, screen_width: i32, screen_height: i32) { /* This function recieves one line of an ASCII-art image, and trims away any of that line that would otherwise be displayed off-screen; then it displays the remaining portion of the line at the designated row,col coordinates. */ let mut line = frame_line.to_string(); // A &str is immutable by nature; we need a mutable string. Could also have used "String::from()" or "to_owned()". // Trim from left side as image moves off left edge if col < 0 { // If we've moved left of the left-edge, for _ in 0..col.abs() { // then for each column beyond edge, line.remove(0); // trim the first char off the string, repeatedly. } // "line" should now have front end trimmed off. col = 0; } // Trim from right side if it extends off right edge if col + (line.len() as i32) > screen_width { let amt_to_trim = (col + (line.len() as i32)) - screen_width; for _ in 0..amt_to_trim { line.pop(); } } if (row >= 0) && (row < screen_height) { // We're on-screen, so it's okay to print this line. mvaddstr(row, col, &line); } } // end of my_mvaddstr()
/* get_options.rs */ pub fn get_opts() -> (String, bool, bool, bool) { use crate::images::*; use clap::Parser; // Use c[ommand] l[ine] a[rgument] p[arser] to get command-line arguments. // Set up program-argument possibilities. #[derive(Parser)] struct Arguments { /// Which model should be used? #[arg(long,short, default_value_t = String::from("D51"))] model: String, /// Should the model fly? #[arg(long, short, default_value_t = false)] fly: bool, /// Accident? #[arg(long, short, default_value_t = false)] oops: bool, /// Is the program-run interruptible? #[arg(long, short, default_value_t = false)] interruptible: bool, } // end of Arguments struct definition // Get arguments from command-line, if any. let args: Arguments = Arguments::parse(); // Process "model" option. let image_str = match args.model.to_uppercase().as_str() { "P" | "PLANE" => PLANE, "D" | "D51" => D51, "C" | "C51" => C51, "L" | "LITTLE" => LITTLE, "B" | "BOAT" => BOAT, "T" | "TWIN" | "TWINENGINE" => TWINENGINE, "M" | "MOTOR" | "MOTORCYCLE" | "CYCLE" => MOTORCYCLE, "J" | "JACK" => JACK, "F" | "FERRIS" | "MASCOT" => FERRIS, _ => D51, }; // Process "fly" option. let mut fly: bool = false; if args.fly { fly = true; } else { fly = false; } // Process Accident ("oops") option. let mut oops: bool = false; if args.oops { oops = true; } else { oops = false; } // Process "interruptible" option. let mut interruptible: bool = false; if args.interruptible { interruptible = true; } else { interruptible = false; } return (image_str.to_string(), fly, oops, interruptible); } // end of get_options()
/* convert_to_vec.rs */ pub fn str_to_vecvecstring(incoming_str: &str) -> Vec<Vec<String>> { //The first character in the original const, after the 'r"', is a newline; lose it. let image_str: &str = &incoming_str[1..]; // Create new empty vector of vectors of Strings. let mut outer_vec: Vec<Vec<String>> = Vec::new(); // This keeps track of which frame/inner vector we're processing. let mut inner_vec_num: usize = 0; // We'll start with the first one. // Create a first new inner vector into the outer vector. outer_vec.push(Vec::new()); for mut each_line in image_str.lines() { // Cycle through each line of the image_str image. if each_line == "" { // If the line is a blank line ... // ... we're starting a new frame, so create a new inner vector... outer_vec.push(Vec::new()); // ... and increase the count of vectors by one. inner_vec_num += 1; } else { // The line is not blank, so process it as part of the current frame. if &each_line[each_line.len() - 1..] == "'" { // If end of line is a single-quote ... each_line = &each_line[0..each_line.len() - 1]; // ... remove it. } // Add an erasing space to the end of each line (converting it to a String from a &str). let each_line = format!("{} ", each_line); // Now add the non-blank line to the current inner vector. outer_vec[inner_vec_num].push(each_line); } // Then move on to the next loop/line. } // Return the finished vector of String vectors. outer_vec } // end of str_to_vecvecstring()
/* images.rs */ /* Feel free to add your own images, and modify the rest of the program code accordingly. - Ideally all the lines of all the frames of a particular image should be of the same length. But if not, the first line of the first frame should be the longest, as that's the line the program uses to determine an image's length. - If there are multiple frames/cels of the image, a blank line must separate the frames. - The single quotes at the end of the lines are optional; they merely serve as a visual indicator of the end of the line. Some of the image lines have the single quote; some do not. The program will strip them out if they are included here. - The "r" before the string tells the compiler to read the string in "raw" mode, so that backslashes are not interpreted as escape characters. - If a hash/splat ("#") is used in an image, the "r" must be modified to be "r#", and the end of the string must be closed with a "#". You can see this in both the TWINENGINE and MOTORCYCLE declarations. Original Copyright Notice from "sl.h" in the "sl" package of Debian Bookworm: /*======================================== * sl.h: SL version 5.02 * Copyright 1993,2002,2014 * Toyoda Masashi * (mtoyoda@acm.org) * Last Modified: 2014/06/03 *======================================== */ This Rust re-write by: Kent West - kent.west@gmail.com June 2023 */ pub const D51: &str = r" ==== ________ ___________' _D _| |_______/ \__I_I_____===__|_________|' |(_)--- | H\________/ | | =|___ ___| ' / | | H | | | | ||_| |_|| ' | | | H |__--------------------| [___] | ' | ________|___H__/__|_____/[][]~\_______| | ' |/ | |-----------I_____I [][] [] D |=======|__' __/ =| o |=-~~\ /~~\ /~~\ /~~\ ____Y___________|__' |/-=|___|= || || || |_____/~\___/ ' \_/ \O=====O=====O=====O_/ \_/ ' ==== ________ ___________ _D _| |_______/ \__I_I_____===__|_________| |(_)--- | H\________/ | | =|___ ___| / | | H | | | | ||_| |_|| | | | H |__--------------------| [___] | | ________|___H__/__|_____/[][]~\_______| | |/ | |-----------I_____I [][] [] D |=======|__ __/ =| o |=-~~\ /~~\ /~~\ /~~\ ____Y___________|__ |/-=|___|=O=====O=====O=====O |_____/~\___/ \_/ \__/ \__/ \__/ \__/ \_/ ==== ________ ___________' _D _| |_______/ \__I_I_____===__|_________|' |(_)--- | H\________/ | | =|___ ___| ' / | | H | | | | ||_| |_|| ' | | | H |__--------------------| [___] | ' | ________|___H__/__|_____/[][]~\_______| | ' |/ | |-----------I_____I [][] [] D |=======|__' __/ =| o |=-O=====O=====O=====O \ ____Y___________|__' |/-=|___|= || || || |_____/~\___/ ' \_/ \__/ \__/ \__/ \__/ \_/ ' ==== ________ ___________ _D _| |_______/ \__I_I_____===__|_________| |(_)--- | H\________/ | | =|___ ___| / | | H | | | | ||_| |_|| | | | H |__--------------------| [___] | | ________|___H__/__|_____/[][]~\_______| | |/ | |-----------I_____I [][] [] D |=======|__ __/ =| o |=-~O=====O=====O=====O\ ____Y___________|__ |/-=|___|= || || || |_____/~\___/ \_/ \__/ \__/ \__/ \__/ \_/ ==== ________ ___________' _D _| |_______/ \__I_I_____===__|_________|' |(_)--- | H\________/ | | =|___ ___| ' / | | H | | | | ||_| |_|| ' | | | H |__--------------------| [___] | ' | ________|___H__/__|_____/[][]~\_______| | ' |/ | |-----------I_____I [][] [] D |=======|__' __/ =| o |=-~~\ /~~\ /~~\ /~~\ ____Y___________|__' |/-=|___|= O=====O=====O=====O|_____/~\___/ ' \_/ \__/ \__/ \__/ \__/ \_/ ' ==== ________ ___________ _D _| |_______/ \__I_I_____===__|_________| |(_)--- | H\________/ | | =|___ ___| / | | H | | | | ||_| |_|| | | | H |__--------------------| [___] | | ________|___H__/__|_____/[][]~\_______| | |/ | |-----------I_____I [][] [] D |=======|__ __/ =| o |=-~~\ /~~\ /~~\ /~~\ ____Y___________|__ |/-=|___|= || || || |_____/~\___/ \_/ \_O=====O=====O=====O/ \_/ "; pub const LITTLE: &str = r" ++ +------ ____ ____________________ ' || |+-+ | | \@@@@@@@@@@@ | ___ ___ ___ ___ | ' /---------|| | | | \@@@@@@@@@@@@@_ | |_| |_| |_| |_| | ' + ======== +-+ | | | |__________________| ' _|--O========O~\-+ |__________________| |__________________| ' //// \_/ \_/ (O) (O) (O) (O) ' ++ +------ ____ ____________________ ' || |+-+ | | \@@@@@@@@@@@ | ___ ___ ___ ___ | ' /---------|| | | | \@@@@@@@@@@@@@_ | |_| |_| |_| |_| | ' + ======== +-+ | | | |__________________| ' _|--/O========O\-+ |__________________| |__________________| ' //// \_/ \_/ (O) (O) (O) (O) ' ++ +------ ____ ____________________ ' || |+-+ | | \@@@@@@@@@@@ | ___ ___ ___ ___ | ' /---------|| | | | \@@@@@@@@@@@@@_ | |_| |_| |_| |_| | ' + ======== +-+ | | | |__________________| ' _|--/~O========O-+ |__________________| |__________________| ' //// \_/ \_/ (O) (O) (O) (O) ' ++ +------ ____ ____________________ ' || |+-+ | | \@@@@@@@@@@@ | ___ ___ ___ ___ | ' /---------|| | | | \@@@@@@@@@@@@@_ | |_| |_| |_| |_| | ' + ======== +-+ | | | |__________________| ' _|--/~\------/~\-+ |__________________| |__________________| ' //// \_O========O (O) (O) (O) (O) ' ++ +------ ____ ____________________ ' || |+-+ | | \@@@@@@@@@@@ | ___ ___ ___ ___ | ' /---------|| | | | \@@@@@@@@@@@@@_ | |_| |_| |_| |_| | ' + ======== +-+ | | | |__________________| ' _|--/~\------/~\-+ |__________________| |__________________| ' //// \O========O/ (O) (O) (O) (O) ' ++ +------ ____ ____________________ ' || |+-+ | | \@@@@@@@@@@@ | ___ ___ ___ ___ | ' /---------|| | | | \@@@@@@@@@@@@@_ | |_| |_| |_| |_| | ' + ======== +-+ | | | |__________________| ' _|--/~\------/~\-+ |__________________| |__________________| ' //// O========O_/ (O) (O) (O) (O) ' "; // end of LITTLE pub const C51: &str = r" ___ ' _|_|_ _ __ __ ___________' D__/ \_(_)___| |__H__| |_____I_Ii_()|_________|' | `---' |:: `--' H `--' | |___ ___| ' +|~~~~~~~~++::~~~~~~~H~~+=====+~~~~~~|~~||_| |_|| ' || | :: H +=====+ | |:: ...| ' | | _______|_::-----------------[][]-----| | ' | /~~ || |-----/~~~~\ /[I_____I][][] --|||_______|__' ------'|oOo|===[]- || || | ||=======_|__' /~\____|___|/~\_| O=======O=======O |__|+-/~\_| ' \_/ \_/ \____/ \____/ \____/ \_/ ' ___ ' _|_|_ _ __ __ ___________' D__/ \_(_)___| |__H__| |_____I_Ii_()|_________|' | `---' |:: `--' H `--' | |___ ___| ' +|~~~~~~~~++::~~~~~~~H~~+=====+~~~~~~|~~||_| |_|| ' || | :: H +=====+ | |:: ...| ' | | _______|_::-----------------[][]-----| | ' | /~~ || |-----/~~~~\ /[I_____I][][] --|||_______|__' ------'|oOo|==[]=- || || | ||=======_|__' /~\____|___|/~\_| || || |__|+-/~\_| ' \_/ \_/ \_O=======O=======O__/ \_/ ' ___ ' _|_|_ _ __ __ ___________' D__/ \_(_)___| |__H__| |_____I_Ii_()|_________|' | `---' |:: `--' H `--' | |___ ___| ' +|~~~~~~~~++::~~~~~~~H~~+=====+~~~~~~|~~||_| |_|| ' || | :: H +=====+ | |:: ...| ' | | _______|_::-----------------[][]-----| | ' | /~~ || |-----/~~~~\ /[I_____I][][] --|||_______|__' ------'|oOo|=[]==- || || | ||=======_|__' /~\____|___|/~\_| || || |__|+-/~\_| ' \_/ \_/ O=======O=======O____/ \_/ ' ___ ' _|_|_ _ __ __ ___________' D__/ \_(_)___| |__H__| |_____I_Ii_()|_________|' | `---' |:: `--' H `--' | |___ ___| ' +|~~~~~~~~++::~~~~~~~H~~+=====+~~~~~~|~~||_| |_|| ' || | :: H +=====+ | |:: ...| ' | | _______|_::-----------------[][]-----| | ' | /~~ || |-----/~~~~\ /[I_____I][][] --|||_______|__' ------'|oOo|[]===- || || | ||=======_|__' /~\____|___|/~\_|O=======O=======O |__|+-/~\_| ' \_/ \_/ \____/ \____/ \____/ \_/ ' ___ ' _|_|_ _ __ __ ___________' D__/ \_(_)___| |__H__| |_____I_Ii_()|_________|' | `---' |:: `--' H `--' | |___ ___| ' +|~~~~~~~~++::~~~~~~~H~~+=====+~~~~~~|~~||_| |_|| ' || | :: H +=====+ | |:: ...| ' | | _______|_::-----------------[][]-----| | ' | /~~ || |-----/~~~~\ /[I_____I][][] --|||_______|__' ------'|oOo|=[]==-O=======O=======O | ||=======_|__' /~\____|___|/~\_| || || |__|+-/~\_| ' \_/ \_/ \____/ \____/ \____/ \_/ ' ___ ' _|_|_ _ __ __ ___________' D__/ \_(_)___| |__H__| |_____I_Ii_()|_________|' | `---' |:: `--' H `--' | |___ ___| ' +|~~~~~~~~++::~~~~~~~H~~+=====+~~~~~~|~~||_| |_|| ' || | :: H +=====+ | |:: ...| ' | | _______|_::-----------------[][]-----| | ' | /~~ || |-----/~~~~\ /[I_____I][][] --|||_______|__' ------'|oOo|==[]=- O=======O=======O | ||=======_|__' /~\____|___|/~\_| || || |__|+-/~\_| ' \_/ \_/ \____/ \____/ \____/ \_/ ' "; // end of C51 pub const BOAT: &str = r" |\ ' | \ ' | \ ' |___\ ' \--|----/ ' \_____/ ' "; // end of BOAT pub const TWINENGINE: &str = r#" .____ __ _ __o__ _______ _ _ _ / / \ ~\ / / \ '\ ..../ .' . ' ' . ~\ ' / / . | . ~ \ .+~\~ ~ ' ' " " ' ' ~ - - - - - -''_ / . <# . - - -/' . ' \ __ '~ - \ .. - ~-.._ / |__| ( ) ( ) ( ) 0 o _ _ ~ . .-' .- ~ '-. -. < . ~ ' ' . . - ~ ~ -.__~_. _ _ ~- . N121PP . / . . . . ,- ~ ' ~ - - - - =. <#> . \.._ . ~ ____ _ .. .. .- . . / ' ~ -. ~ -. ' . . ' ~ - . ~-. ~ - . ~ . ~ -...0..~. ____ .____ __ _ __o__ _______ _ _ _ / / \ ~\ / / \ '\ ..../ .' . ' ' . ~\ ' / / . _ . ~ \ .+~\~ ~ ' ' " " ' ' ~ - - - - - -''_ / . <# -. - - -/' . ' \ __ '~ - \ .. - ~-.._ / |__| ( ) ( ) ( ) 0 o _ _ ~ . .-' .- ~ '-. -. < . ~ ' ' . . - ~ ~ -.__~_. _ _ ~- . N121PP . . . . . ,- ~ ' ~ - - - - =. - <#> - . \.._ . ~ ____ _ .. .. .- . . ' ~ -. ~ -. ' . . ' ~ - . ~-. ~ - . ~ . ~ -...0..~. ____ .____ __ _ __o__ _______ _ _ _ / / \ ~\ / / \ '\ ..../ .' . ' ' . ~\ ' / / . / . ~ \ .+~\~ ~ ' ' " " ' ' ~ - - - - - -''_ / . -<# . - - -/' . ' \ __ '~ - \ .. - ~-.._ / |__| ( ) ( ) ( ) 0 o _ _ ~ . .-' .- ~ '-. -. < . ~ ' ' . . - ~ ~ -.__~_. _ _ ~- . N121PP . \ . . . . ,- ~ ' ~ - - - - =. <#> . \.._ . ~ ____ _ .. .. .- . . \ ' ~ -. ~ -. ' . . ' ~ - . ~-. ~ - . ~ . ~ -...0..~. ____ .____ __ _ __o__ _______ _ _ _ / / \ ~\ / / \ '\ ..../ .' . ' ' . ~\ ' / / . _ . ~ \ .+~\~ ~ ' ' " " ' ' ~ - - - - - -''_ / . <# -. - - -/' . ' \ __ '~ - \ .. - ~-.._ / |__| ( ) ( ) ( ) 0 o _ _ ~ . .-' .- ~ '-. -. < . ~ ' ' . . - ~ ~ -.__~_. _ _ ~- . N121PP . . . . . ,- ~ ' ~ - - - - =. - <#> - . \.._ . ~ ____ _ .. .. .- . . ' ~ -. ~ -. ' . . ' ~ - . ~-. ~ - . ~ . ~ -...0..~. ____ "#; // end of TWINENGINE pub const PLANE: &str = r" ____ _ ' | __\_\_o____/_| ' <[___\_\_-----< ' | o' ' ' ' ____ _ ' / __\_\_o____/_| ' <[___\_\_-----< ' \ o' ' ' ' ____ _ ' | __\_\_o____/_| ' <[___\_\_-----< ' | o' ' ' ' ____ _ ' \ __\_\_o____/_| ' <[___\_\_-----< ' / o' ' ' ' "; // end of PLANE pub const MOTORCYCLE: &str = r#" _ ' ,S/ .e.##ee ' ,SS/_ /#####"" ' ,SSSSSS`|##| ' ,'|SSSSSS/%##| ' | ;SSSSS/%%%/ .-""-._ __..ooo._.sSSSSSSSSS"7. ' |/SSSSS/%%%/.' `._ __ _.od888888888888"' '"SSSSS" ' ___ `"SSS/%%%/"-.,sSSs._ 8888o._ __.o888888888""SS"" `-._ `7Sb ' _.sssSSSSSSSSSSS/`%%/ ,sSSSSSSSSS-.888888888888888888888"'.S" ,SSS"" `7b ' ,+"" ```""SS/%%./,sSSSSSSSS". `"888888888888888"'.sSS" ,SS"' `S.' /%%%/sSSSSSSSS" `s. `"88888888"'.sSSSS" ,S"' 7' /%%%/ `SSSSSSS$$,..sSS`-. `"88'.sSSSSSSSS._ ,-' ' /%%%/ `SSSS$$$$SSS",\\\`-. `"SSSSSS" 8"""7.-' ' /`%/ `SS$$$SSS,dP,s.\\//`-. `SS" ,'`8 ,ee888888ee. ' ,oo8888oo/ / `"""",d88Pd8888./,-'/`. `,-._`d' ,d88888888888888b. ' ,d888888888/ /8b. d8888Pd8888888bd88b`. :_._`8 ,888888"' '""88888. ' ,888P' / /"888b. d88888`8888888Pd8888 : :_`-.( ,d8888.__ 7888b. ' d88P / / `788b (88888:. `8888Pd88888 ; ; `-._ 8888P_Z_.>-""--.._ `8888 ' d88' ,--/ / `88b `88888b`. `8P 78888"; ; `"*88_," s88s. `888b ' d88' ,',$/ /$$$$. `88b `8888b `. `"'88"_/_,'`-._ `-.d8"88"8P. `888.' 888 ; ,$$$$$$$$$' 888 `"8' `---------------`-.._ 8888888888 888'' 888 : `$$$$$$$': 888 '888b`-._8s888888"P .888'' 788. ` `$$$$' ; 88P 8888. "8878888P' d888 ' 88b `. `"' ,' d88' '888b '88s8"' .d888' ' `88b. `-..-' d88' '888b. .dd888' ' 788b. ,888' 7888b._ _.d8888P ' `7888oo..__..oo888' `"8888888888888888"' ' `"7888888888P"' `"788 mGk 8P"' ' "#; // end of MOTORCYCLE pub const JACK: &str = r" \ 0 / ' \|/ ' | ' / \ ' _/ \_ ' ' __0__ ' / | \ ' / \ ' _\ /_ ' ' o ' /\ /\ ' |/ \| ' _\ /_ ' ' __0__ ' / | \ ' / \ ' _\ /_ ' "; // end of JACK pub const COALCAR: &str = r" _________________ _| \_____A =| | -| | __|________________________|_ |__________________________|_ |_D__D__D_| |_D__D__D_| \_/ \_/ \_/ \_/ "; // end of COALCAR pub const FERRIS: &str = r" _~^~^~_ ' \) / o o \ (/' \'_ - _'/ ' | '-----' | ' "; // end of FERRIS
Return back to the "Move Image Off Left-Edge of Screen" Page