voxgen/
turtle_graphics.rs

1use line_drawing::Bresenham;
2
3use crate::voxel_buffer::{ArrayVoxelBuffer, Rgba, VoxelBuffer};
4
5/// The drawing turtle.
6#[derive(Copy, Clone, Debug)]
7pub struct Turtle {
8    x: i32,
9    y: i32,
10    heading: f32,
11    color: Rgba,
12}
13
14/// Draw an `ArrayVoxelBuffer` using LOGO-style turtle graphics commands.
15pub struct TurtleGraphics {
16    buf: ArrayVoxelBuffer<Rgba>,
17    state: Turtle,
18}
19
20impl TurtleGraphics {
21    /// Create a new `TurtleGraphics` object of the given dimensions.
22    ///
23    /// The `ArrayVoxelBuffer` is initially empty, and the turtle is at position (0,
24    /// 0, 0) with a heading of 0.0 radians (facing east).
25    pub fn new(size_x: u32, size_y: u32, size_z: u32) -> TurtleGraphics {
26        TurtleGraphics {
27            buf: ArrayVoxelBuffer::new(size_x, size_y, size_z),
28            state: Turtle {
29                x: 0,
30                y: 0,
31                heading: 0.0,
32                color: Rgba([0, 0, 0, 255])
33            },
34        }
35    }
36
37    /// Move the turtle without drawing a line.
38    pub fn step(&mut self, step_size: f32) {
39        self.state.x = self.state.x + (step_size * self.state.heading.cos()) as i32;
40        self.state.y = self.state.y + (step_size * self.state.heading.sin()) as i32;
41    }
42
43    /// Move the turtle and draw a line along it's path.
44    ///
45    /// The turtle moves `step_size` voxels in the direction of it's current
46    /// `heading`.
47    pub fn draw(&mut self, step_size: f32) {
48        let (x0, y0) = (self.state.x, self.state.y);
49        self.step(step_size);
50        let (x1, y1) = (self.state.x, self.state.y);
51        for (x, y) in Bresenham::new((x0, y0), (x1, y1)) {
52            *self.buf.voxel_mut(x as u32, y as u32, 0) = self.state.color;
53        }
54    }
55
56    /// Set the turtle drawing color to the RGBA value of `color`.
57    pub fn color(&mut self, color: Rgba) {
58        self.state.color = color;
59    }
60
61    /// Rotate the turtle `angle_increment` radians to the left.
62    pub fn right(&mut self, angle_increment: f32) {
63        self.state.heading -= angle_increment;
64    }
65
66    /// Rotate the turtle `angle_increment` radians to the right.
67    pub fn left(&mut self, angle_increment: f32) {
68        self.state.heading += angle_increment;
69    }
70
71    /// Get the current state of the turtle.
72    pub fn state(&mut self) -> Turtle {
73        self.state
74    }
75
76    /// Get the current state of the turtle.
77    pub fn buf(&mut self) -> &ArrayVoxelBuffer<Rgba> {
78        &self.buf
79    }
80}