siege/
lib.rs

1extern crate line_drawing;
2
3use line_drawing::{Point, Bresenham, BresenhamCircle};
4
5/// The material that the parts are made of.
6/// This determines how they get rendered and their strength.
7#[derive(Debug, Copy, Clone, Eq, PartialEq)]
8pub enum Material {
9    Wood,
10    Metal,
11    Rope
12}
13
14/// The parts of which a siege engine is build up.
15#[derive(Debug)]
16pub enum Part {
17    Beam(Beam),
18    Wheel(Wheel)
19}
20
21/// A rectangular rod which is a basically a line with a material.
22#[derive(Debug)]
23pub struct Beam {
24    pub start: Point<f64>,
25    pub end: Point<f64>,
26    pub material: Material
27}
28
29impl Beam {
30    pub fn new(start: (i32, i32), end: (i32, i32), material: Material) -> Self {
31        Beam {
32            material,
33
34            start: (start.0 as f64, start.1 as f64),
35            end: (end.0 as f64, end.1 as f64),
36        }
37    }
38
39    pub fn draw(&self, dst: &mut [u32], dst_width: usize, offset: (f64, f64)) {
40        let color = match self.material {
41            Material::Wood => 0x8F563B,
42            Material::Metal => 0x696A6A,
43            Material::Rope => 0xD9A066,
44        };
45
46        let start = ((self.start.0 + offset.0) as i32, (self.start.1 + offset.1) as i32);
47        let end = ((self.end.0 + offset.0) as i32, (self.end.1 + offset.1) as i32);
48        for (x, y) in Bresenham::new(start, end) {
49            dst[x as usize + y as usize * dst_width] = color;
50        }
51    }
52}
53
54/// A rotatable circle which is basically a circle with a material.
55#[derive(Debug)]
56pub struct Wheel {
57    pub pos: Point<f64>,
58    pub radius: f64,
59    pub material: Material
60}
61
62impl Wheel {
63    pub fn new(start: (i32, i32), end: (i32, i32), material: Material) -> Self {
64        let dx = (end.0 - start.0) as f64;
65        let dy = (end.1 - start.1) as f64;
66        Wheel {
67            material,
68
69            pos: (start.0 as f64, start.1 as f64),
70            radius: (dx * dx + dy * dy).sqrt()
71        }
72    }
73
74    pub fn draw(&self, dst: &mut [u32], dst_width: usize, offset: (f64, f64)) {
75        let color = match self.material {
76            Material::Wood => 0x8F563B,
77            Material::Metal => 0x696A6A,
78            Material::Rope => 0xD9A066,
79        };
80
81        let pos = ((self.pos.0 + offset.0) as i32, (self.pos.1 + offset.1) as i32);
82        for (x, y) in BresenhamCircle::new(pos.0, pos.1, self.radius as i32) {
83            dst[x as usize + y as usize * dst_width] = color;
84        }
85    }
86}
87
88/// A instance of a siege engine.
89#[derive(Debug)]
90pub struct Engine {
91    pub pos: Point<f64>,
92    pub parts: Vec<Part>
93}
94
95impl Engine {
96    /// Place a empty siege engine at the given position with no parts.
97    pub fn new(x: f64, y: f64) -> Self {
98        Engine {
99            pos: (x, y),
100            parts: Vec::new()
101        }
102    }
103
104    /// Render the graphics of the siege engine to a buffer.
105    pub fn render_to_buffer(&self, dst: &mut [u32], dst_width: usize) {
106        for part in self.parts.iter() {
107            if let &Part::Beam(ref beam) = part {
108                beam.draw(dst, dst_width, self.pos);
109            }
110            if let &Part::Wheel(ref wheel) = part {
111                wheel.draw(dst, dst_width, self.pos);
112            }
113        }
114    }
115
116    /// Add a beam with the material.
117    pub fn add_beam(&mut self, start: (i32, i32), end: (i32, i32), material: Material) {
118        self.parts.push(Part::Beam(Beam::new(start, end, material)));
119    }
120
121    /// Add a wheel with the material.
122    pub fn add_wheel(&mut self, start: (i32, i32), end: (i32, i32), material: Material) {
123        self.parts.push(Part::Wheel(Wheel::new(start, end, material)));
124    }
125}
126
127#[cfg(test)]
128mod tests {
129    #[test]
130    fn it_works() {
131        assert_eq!(2 + 2, 4);
132    }
133}