diff options
author | Akshay <[email protected]> | 2021-04-07 14:37:46 +0100 |
---|---|---|
committer | Akshay <[email protected]> | 2021-04-07 14:37:46 +0100 |
commit | b90c2c4bc61248d5ea2e894fc70b84bc00582406 (patch) | |
tree | 5e361a095a5745ba4944e55d12d5e73090cdd54c | |
parent | f57f03cd87d205d8304008d08c05f53c34b44435 (diff) |
implement iso grids; lisp primitives to manipulate grids
-rw-r--r-- | src/grid.rs | 107 | ||||
-rw-r--r-- | src/lisp/prelude.rs | 11 |
2 files changed, 118 insertions, 0 deletions
diff --git a/src/grid.rs b/src/grid.rs new file mode 100644 index 0000000..38efaba --- /dev/null +++ b/src/grid.rs | |||
@@ -0,0 +1,107 @@ | |||
1 | // most of this module was written out of frustration | ||
2 | // TODO: make all this less messy | ||
3 | |||
4 | use sdl2::{pixels::Color, rect::Point, render::Canvas, video::Window}; | ||
5 | |||
6 | use crate::{ | ||
7 | consts::{colors::*, ANGLE}, | ||
8 | rect, | ||
9 | }; | ||
10 | |||
11 | #[derive(Debug, Copy, Clone)] | ||
12 | pub enum GridKind { | ||
13 | Rectangle, | ||
14 | Isometric, | ||
15 | } | ||
16 | |||
17 | pub struct Grid { | ||
18 | pub enabled: bool, | ||
19 | pub color: Color, | ||
20 | pub kind: GridKind, | ||
21 | } | ||
22 | |||
23 | impl Grid { | ||
24 | pub fn new() -> Self { | ||
25 | Self { | ||
26 | enabled: true, | ||
27 | color: GRID_COLOR, | ||
28 | kind: GridKind::Rectangle, | ||
29 | } | ||
30 | } | ||
31 | |||
32 | pub fn draw( | ||
33 | &self, | ||
34 | canvas: &mut Canvas<Window>, | ||
35 | zoom: u8, | ||
36 | start: &Point, | ||
37 | width: u32, | ||
38 | height: u32, | ||
39 | ) { | ||
40 | let cs = zoom as u32; | ||
41 | let (x, y) = (start.x(), start.y()); | ||
42 | canvas.set_draw_color(self.color); | ||
43 | |||
44 | match self.kind { | ||
45 | GridKind::Rectangle => { | ||
46 | let mut vertical_tuples = (1..width) | ||
47 | .map(|i| { | ||
48 | let x = (i * cs) as i32; | ||
49 | let y = (height * cs) as i32; | ||
50 | if i % 2 == 0 { | ||
51 | (*start + Point::new(x, 0), *start + Point::new(x, y)) | ||
52 | } else { | ||
53 | (*start + Point::new(x, y), *start + Point::new(x, 0)) | ||
54 | } | ||
55 | }) | ||
56 | .collect::<Vec<_>>(); | ||
57 | |||
58 | // SAFETY | ||
59 | // The mem space occupied by a [(T, T); N] is the same as twice the mem space of a | ||
60 | // [T; 2 * N], where T is not a dynamically sized type. | ||
61 | let verticals: Vec<Point> = unsafe { | ||
62 | vertical_tuples.set_len(vertical_tuples.len() * 2); | ||
63 | std::mem::transmute(vertical_tuples) | ||
64 | }; | ||
65 | |||
66 | let mut horizontal_tuples = (1..height) | ||
67 | .map(|j| { | ||
68 | let x = (width * cs) as i32; | ||
69 | let y = (j * cs) as i32; | ||
70 | if j % 2 == 0 { | ||
71 | (*start + Point::new(0, y), *start + Point::new(x, y)) | ||
72 | } else { | ||
73 | (*start + Point::new(x, y), *start + Point::new(0, y)) | ||
74 | } | ||
75 | }) | ||
76 | .collect::<Vec<_>>(); | ||
77 | let horizontals: Vec<Point> = unsafe { | ||
78 | horizontal_tuples.set_len(horizontal_tuples.len() * 2); | ||
79 | std::mem::transmute(horizontal_tuples) | ||
80 | }; | ||
81 | |||
82 | canvas.draw_lines(&verticals[..]).unwrap(); | ||
83 | canvas.draw_lines(&horizontals[..]).unwrap(); | ||
84 | } | ||
85 | GridKind::Isometric => { | ||
86 | // tan 26.525 ~= 0.5 | ||
87 | canvas.set_clip_rect(Some(rect!(x, y, width * cs, height * cs))); | ||
88 | for i in (0..2 * height + width).step_by(4) { | ||
89 | let begin = Point::from(((i * cs) as i32, 0i32)); | ||
90 | let end = Point::from((0i32, ((i * cs) as f64 * 0.5).floor() as i32)); | ||
91 | canvas.draw_line(*start + begin, *start + end).unwrap(); | ||
92 | } | ||
93 | for j in (0..height + width / 2).step_by(2) { | ||
94 | let idx = (j as i32 - (width as i32 / 2)) * cs as i32; | ||
95 | let begin = Point::from((-100i32, idx)); | ||
96 | let end = Point::from(( | ||
97 | (width * cs) as i32, | ||
98 | (idx as f64 + (width * cs) as f64 * ANGLE.to_radians().tan()).floor() | ||
99 | as i32, | ||
100 | )); | ||
101 | canvas.draw_line(*start + begin, *start + end).unwrap(); | ||
102 | } | ||
103 | canvas.set_clip_rect(None); | ||
104 | } | ||
105 | } | ||
106 | } | ||
107 | } | ||
diff --git a/src/lisp/prelude.rs b/src/lisp/prelude.rs index fee787e..d0667d8 100644 --- a/src/lisp/prelude.rs +++ b/src/lisp/prelude.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | use crate::{ | 1 | use crate::{ |
2 | bitmap::MapPoint, | 2 | bitmap::MapPoint, |
3 | brush::Brush, | 3 | brush::Brush, |
4 | grid::{Grid, GridKind}, | ||
4 | guide::Guide, | 5 | guide::Guide, |
5 | lisp::{ | 6 | lisp::{ |
6 | error::{EvalError, LispError}, | 7 | error::{EvalError, LispError}, |
@@ -257,6 +258,16 @@ pub fn new_env() -> Result<Environment, LispError> { | |||
257 | Ok(LispExpr::Unit) | 258 | Ok(LispExpr::Unit) |
258 | }); | 259 | }); |
259 | 260 | ||
261 | primitive!(env, Arity::Exact(0), "grid-rectangle", |_, app| { | ||
262 | app.grid.kind = GridKind::Rectangle; | ||
263 | Ok(LispExpr::Unit) | ||
264 | }); | ||
265 | |||
266 | primitive!(env, Arity::Exact(0), "grid-isometric", |_, app| { | ||
267 | app.grid.kind = GridKind::Isometric; | ||
268 | Ok(LispExpr::Unit) | ||
269 | }); | ||
270 | |||
260 | primitive!(env, Arity::Exact(0), "brush-fill", |_, app| { | 271 | primitive!(env, Arity::Exact(0), "brush-fill", |_, app| { |
261 | app.brush = Brush::Fill; | 272 | app.brush = Brush::Fill; |
262 | Ok(LispExpr::Unit) | 273 | Ok(LispExpr::Unit) |