From db7a2b24184a2dc0bb86d2e7d039b733d4982abc Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sun, 6 Oct 2024 23:30:59 +0200 Subject: [PATCH] auto resize board when drawing out of bounds --- README.md | 2 +- src/editor.rs | 40 ++++++++++-------- src/marble_engine.rs | 2 +- src/marble_engine/board.rs | 83 ++++++++++++++++++++++++++++++++------ src/solution.rs | 5 +-- 5 files changed, 96 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 4997eb8..3814c9e 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ sim/speed control gui (option) display input as numbers scroll output default i/o text modes specified per level -grow grid automatically while editing +properly center view make marble movement not order-dependent (`>ooo <` does not behave symmetrically) blueprints scroll level list diff --git a/src/editor.rs b/src/editor.rs index 3f222bb..0e8db05 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -186,6 +186,11 @@ impl Editor { } } + fn set_tile(&mut self, pos: Pos, tile: Tile) { + self.source_board.grow_to_include(pos); + self.source_board.set(pos, tile); + } + pub fn update(&mut self, rl: &RaylibHandle) { if rl.is_key_pressed(KeyboardKey::KEY_ESCAPE) { self.sim_state = SimState::Editing; @@ -515,13 +520,6 @@ impl Editor { (1 << self.zoom) as f32, Color::new(255, 180, 20, 255), ); - for n in 0..10 { - if d.is_key_pressed(unsafe { - std::mem::transmute(KeyboardKey::KEY_ZERO as u32 + n) - }) { - self.source_board.set(*pos, Tile::Digit(n as u8)); - } - } if d.is_key_pressed(KeyboardKey::KEY_LEFT) { pos.x -= 1; } @@ -534,6 +532,14 @@ impl Editor { if d.is_key_pressed(KeyboardKey::KEY_DOWN) { pos.y += 1; } + let pos = *pos; + for n in 0..10 { + if d.is_key_pressed(unsafe { + std::mem::transmute(KeyboardKey::KEY_ZERO as u32 + n) + }) { + self.set_tile(pos, Tile::Digit(n as u8)); + } + } } if mouse_pos.y < footer_top && mouse_pos.y > HEADER_HEIGHT as f32 { let tile_pos = (mouse_pos - self.view_offset) / (16 << self.zoom) as f32; @@ -570,25 +576,25 @@ impl Editor { if d.is_mouse_button_down(MouseButton::MOUSE_BUTTON_LEFT) { match self.active_tool { Tool::None => (), - Tool::SetTile(tile) => self.source_board.set(tile_pos.into(), tile), - Tool::Math => self.source_board.set( + Tool::SetTile(tile) => self.set_tile(tile_pos.into(), tile), + Tool::Math => self.set_tile( tile_pos.into(), Tile::Powerable(PTile::Math(self.tool_menu_math), false), ), - Tool::Gate => self.source_board.set( + Tool::Gate => self.set_tile( tile_pos.into(), Tile::Powerable(PTile::Gate(self.tool_menu_gate), false), ), - Tool::Wire => self.source_board.set( + Tool::Wire => self.set_tile( tile_pos.into(), Tile::Powerable(PTile::Wire(self.tool_menu_wire), false), ), - Tool::Arrow => self - .source_board - .set(tile_pos.into(), Tile::Arrow(self.tool_menu_arrow)), - Tool::Mirror => self - .source_board - .set(tile_pos.into(), Tile::Mirror(self.tool_menu_mirror)), + Tool::Arrow => { + self.set_tile(tile_pos.into(), Tile::Arrow(self.tool_menu_arrow)) + } + Tool::Mirror => { + self.set_tile(tile_pos.into(), Tile::Mirror(self.tool_menu_mirror)) + } Tool::Digits(_pos) => { self.active_tool = Tool::Digits(Some(tile_pos.into())); if let Some(tile) = self.source_board.get_mut(tile_pos.into()) { diff --git a/src/marble_engine.rs b/src/marble_engine.rs index 97c4b61..ffd6fc7 100644 --- a/src/marble_engine.rs +++ b/src/marble_engine.rs @@ -121,7 +121,7 @@ impl Machine { continue; }; let next_pos = dir.step(marble_pos); - if !self.board.in_bounds(next_pos) { + if !self.board.pos_in_bounds(next_pos) { continue; } let mut new_tile = None; diff --git a/src/marble_engine/board.rs b/src/marble_engine/board.rs index 9fec522..884d905 100644 --- a/src/marble_engine/board.rs +++ b/src/marble_engine/board.rs @@ -41,6 +41,8 @@ pub struct Board { rows: Vec>, width: usize, height: usize, + offset_x: isize, + offset_y: isize, } impl Board { @@ -80,6 +82,8 @@ impl Board { rows, width, height, + offset_x: 0, + offset_y: 0, } } @@ -88,6 +92,8 @@ impl Board { width: rows[0].len(), height: rows.len(), rows, + offset_x: 0, + offset_y: 0, } } @@ -104,11 +110,24 @@ impl Board { sum } - pub fn in_bounds(&self, p: Pos) -> bool { + fn transform(&self, p: Pos) -> Pos { + Pos { + x: p.x + self.offset_x, + y: p.y + self.offset_y, + } + } + + pub fn pos_in_bounds(&self, p: Pos) -> bool { + let p = self.transform(p); + self.in_bounds(p) + } + + fn in_bounds(&self, p: Pos) -> bool { p.x >= 0 && p.y >= 0 && p.x < self.width as isize && p.y < self.height as isize } pub fn get(&self, p: Pos) -> Option { + let p = self.transform(p); if self.in_bounds(p) { Some(self.rows[p.y as usize][p.x as usize]) } else { @@ -117,6 +136,7 @@ impl Board { } pub fn get_or_blank(&self, p: Pos) -> Tile { + let p = self.transform(p); if self.in_bounds(p) { self.rows[p.y as usize][p.x as usize] } else { @@ -125,6 +145,7 @@ impl Board { } pub fn get_mut(&mut self, p: Pos) -> Option<&mut Tile> { + let p = self.transform(p); if self.in_bounds(p) { Some(&mut self.rows[p.y as usize][p.x as usize]) } else { @@ -133,6 +154,7 @@ impl Board { } pub fn get_blank_mut(&mut self, p: Pos) -> Option<&mut Tile> { + let p = self.transform(p); if self.in_bounds(p) { let tile = &mut self.rows[p.y as usize][p.x as usize]; if tile == &Tile::Blank { @@ -143,11 +165,45 @@ impl Board { } pub fn set(&mut self, p: Pos, tile: Tile) { + let p = self.transform(p); if self.in_bounds(p) { self.rows[p.y as usize][p.x as usize] = tile; } } + pub fn grow_to_include(&mut self, p: Pos) { + let p = self.transform(p); + if p.x < 0 { + let len = p.x.abs() as usize; + for row in &mut self.rows { + let mut new_row = vec![Tile::Blank; len]; + new_row.append(row); + *row = new_row; + } + self.offset_x += len as isize; + self.width += len; + } else if p.x as usize >= self.width { + let new_width = p.x as usize + 1; + for row in &mut self.rows { + row.resize(new_width, Tile::Blank); + } + self.width = new_width; + } + + if p.y < 0 { + let len = p.y.abs() as usize; + let mut new_rows = vec![vec![Tile::Blank; self.width]; len]; + new_rows.append(&mut self.rows); + self.rows = new_rows; + self.offset_y += len as isize; + self.height += len; + } else if p.y as usize > self.height { + let new_height = p.y as usize + 1; + self.rows.resize(new_height, vec![Tile::Blank; self.width]); + self.height = new_height; + } + } + pub fn width(&self) -> usize { self.width } @@ -160,18 +216,19 @@ impl Board { let tile_size = 16 << zoom; for x in 0..self.width { for y in 0..self.height { - if let Some(tile) = self.get((x, y).into()) { - let px = x as i32 * tile_size + offset.x as i32 + tile_size / 2; - let py = y as i32 * tile_size + offset.y as i32 + tile_size / 2; - let texture = textures.get(&tile.texture()); - d.draw_texture_ex( - texture, - Vector2::new((px - tile_size / 2) as f32, (py - tile_size / 2) as f32), - 0.0, - (1 << zoom) as f32, - Color::WHITE, - ); - } + let tile = self.rows[y][x]; + let px = + (x as i32 - self.offset_x as i32) * tile_size + offset.x as i32 + tile_size / 2; + let py = + (y as i32 - self.offset_y as i32) * tile_size + offset.y as i32 + tile_size / 2; + let texture = textures.get(&tile.texture()); + d.draw_texture_ex( + texture, + Vector2::new((px - tile_size / 2) as f32, (py - tile_size / 2) as f32), + 0.0, + (1 << zoom) as f32, + Color::WHITE, + ); } } } diff --git a/src/solution.rs b/src/solution.rs index a4d8b23..a25ebef 100644 --- a/src/solution.rs +++ b/src/solution.rs @@ -30,10 +30,7 @@ impl Solution { solution_id: format!("solution_{number}"), level_id: level.id().to_owned(), name: format!("Unnamed {number}"), - board: level - .init_board() - .unwrap_or_else(|| " \n".repeat(20)), // todo remove when auto resizing is implemented - // score: Some(Score { cycles: 5, tiles: 88, area: 987 }), + board: level.init_board().unwrap_or(String::from(" ")), score: None, } }