create a rotating ascii cube in rust

To create a rotating ASCII cube in Rust, we need to use a combination of 3D graphics and animation techniques. Here's how we can do it step-by-step:

  1. First, we need to create a 3D model of a cube. We can do this by defining the cube's vertices and their respective connections to each other. We can store this data in arrays or vectors:
main.rs
let vertices = [
    [-1.0, -1.0, 1.0], // front bottom left
    [-1.0, 1.0, 1.0],  // front top left
    [1.0, 1.0, 1.0],   // front top right
    [1.0, -1.0, 1.0],  // front bottom right
    [-1.0, -1.0, -1.0],// back bottom left
    [-1.0, 1.0, -1.0], // back top left
    [1.0, 1.0, -1.0],  // back top right
    [1.0, -1.0, -1.0], // back bottom right
];

let connections = [
    [0, 1],
    [1, 2],
    [2, 3],
    [3, 0],
    [4, 5],
    [5, 6],
    [6, 7],
    [7, 4],
    [0, 4],
    [1, 5],
    [2, 6],
    [3, 7],
];
528 chars
26 lines
  1. Then, we need to create a function to draw the model to the console using ASCII characters. We can use the console crate for this:
main.rs
use console::{style, Term};

fn draw_cube(vertices: &[[f32; 3]], connections: &[[usize; 2]]) {
    let term = Term::stdout();

    for connection in connections {
        let start = vertices[connection[0]];
        let end = vertices[connection[1]];
        let x1 = start[0] as i32;
        let y1 = start[1] as i32;
        let x2 = end[0] as i32;
        let y2 = end[1] as i32;
        let dx = x2 - x1;
        let dy = y2 - y1;
        let steps = dx.abs().max(dy.abs());
        let x_inc = dx as f32 / steps as f32;
        let y_inc = dy as f32 / steps as f32;
        let mut x = x1 as f32;
        let mut y = y1 as f32;

        for _ in 0..steps {
            term.move_cursor_to(y as usize, x as usize);
            term.write_str(&style("█").blue().on_white().to_string()).unwrap();

            x += x_inc;
            y += y_inc;
        }
    }
}
866 chars
30 lines
  1. Next, we need to create a loop that rotates the model around its center using trigonometric functions. We can also add some delay between frames to create the illusion of motion:
main.rs
const DELAY: u64 = 100;
const ROTATION_SPEED: f32 = 0.05;

let center = [
    (vertices[0][0] + vertices[6][0]) / 2.0,
    (vertices[0][1] + vertices[6][1]) / 2.0,
    (vertices[0][2] + vertices[6][2]) / 2.0,
];

let mut angle = 0.0;

loop {
    let rotated_vertices = vertices
        .iter()
        .map(|v| {
            let x = v[0] - center[0];
            let y = v[1] - center[1];
            let z = v[2] - center[2];

            let (sin_a, cos_a) = angle.sin_cos();
            let (sin_b, cos_b) = (-angle).sin_cos();

            [
                cos_a * x - sin_a * sin_b * y - sin_a * cos_b * z,
                cos_b * y + sin_b * z,
                sin_a * x + cos_a * sin_b * y + cos_a * cos_b * z,
            ]
        })
        .collect::<Vec<_>>();

    draw_cube(&rotated_vertices, &connections);
    std::thread::sleep(std::time::Duration::from_millis(DELAY));

    angle += ROTATION_SPEED;
}
920 chars
36 lines

And that's it! With these steps, we can create a simple but effective rotating ASCII cube animation in Rust.

gistlibby LogSnag