From 966582e0c278f5075c93340cc2b0da6f6a0f50b7 Mon Sep 17 00:00:00 2001 From: Paul Brinkmeier Date: Sun, 30 Nov 2025 02:38:35 +0100 Subject: [PATCH] Add dash --- src/game.rs | 167 ++++++++++++++++++++++++++++-------------------- src/geometry.rs | 5 +- 2 files changed, 100 insertions(+), 72 deletions(-) diff --git a/src/game.rs b/src/game.rs index ede73a1..135e93e 100644 --- a/src/game.rs +++ b/src/game.rs @@ -17,7 +17,8 @@ pub struct GameModel { pub enum GameEvent { Quit, Nop, - MovePlayer(V2), + PlayerMove(V2), + PlayerDash(V2), } impl GameEvent { @@ -26,14 +27,14 @@ impl GameEvent { use KeyCode::Char; match key_event.code { Char('q') => return GameEvent::Quit, - Char('j') => return GameEvent::MovePlayer(V2::new(0, 1)), - Char('k') => return GameEvent::MovePlayer(V2::new(0, -1)), - Char('h') => return GameEvent::MovePlayer(V2::new(-1, 0)), - Char('l') => return GameEvent::MovePlayer(V2::new(1, 0)), - Char('J') => return GameEvent::MovePlayer(V2::new(0, 2)), - Char('K') => return GameEvent::MovePlayer(V2::new(0, -2)), - Char('H') => return GameEvent::MovePlayer(V2::new(-2, 0)), - Char('L') => return GameEvent::MovePlayer(V2::new(2, 0)), + Char('j') => return GameEvent::PlayerMove(V2::new(0, 1)), + Char('k') => return GameEvent::PlayerMove(V2::new(0, -1)), + Char('h') => return GameEvent::PlayerMove(V2::new(-1, 0)), + Char('l') => return GameEvent::PlayerMove(V2::new(1, 0)), + Char('J') => return GameEvent::PlayerDash(V2::new(0, 1)), + Char('K') => return GameEvent::PlayerDash(V2::new(0, -1)), + Char('H') => return GameEvent::PlayerDash(V2::new(-1, 0)), + Char('L') => return GameEvent::PlayerDash(V2::new(1, 0)), _ => (), } } @@ -43,21 +44,53 @@ impl GameEvent { } struct Room { - size: V2, -} -impl Room { - fn in_bounds(&self, player_pos: P2) -> bool { - (0..self.size.x as isize).contains(&player_pos.x) - && (0..self.size.y as isize).contains(&player_pos.y) - } + tiles: Grid, } +impl Room {} impl GameModel { pub fn new() -> Self { Self { player_pos: P2::new(1, 1), room: Room { - size: V2::new(20, 10), + tiles: { + let w = 30; + let h = 12; + let mut tiles = Grid::from_fn(w, h, |x, y| { + let is_vertical_boundary = [0, w - 1].contains(&x); + let is_horizontal_boundary = [0, h - 1].contains(&y); + + if is_vertical_boundary || is_horizontal_boundary { + Tile::Wall + } else { + Tile::Floor + } + }); + + tiles + .get_mut(P2::new(1, 1)) + .map(|tile| *tile = Tile::Ladder); + + tiles + .get_mut(P2::new(5, 2)) + .map(|tile| *tile = Tile::Amphora); + + tiles.get_mut(P2::new(8, 5)).map(|tile| *tile = Tile::Frog); + + tiles.get_mut(P2::new(7, 6)).map(|tile| *tile = Tile::Water); + tiles.get_mut(P2::new(8, 6)).map(|tile| *tile = Tile::Water); + tiles.get_mut(P2::new(9, 6)).map(|tile| *tile = Tile::Water); + + tiles.get_mut(P2::new(8, 7)).map(|tile| *tile = Tile::Wall); + tiles.get_mut(P2::new(9, 7)).map(|tile| *tile = Tile::Wall); + + tiles.get_mut(P2::new(10, 2)).map(|tile| *tile = Tile::Portal); + tiles.get_mut(P2::new(18, 2)).map(|tile| *tile = Tile::Portal); + tiles.get_mut(P2::new(10, 8)).map(|tile| *tile = Tile::Portal); + tiles.get_mut(P2::new(18, 8)).map(|tile| *tile = Tile::Portal); + + tiles + }, }, } } @@ -66,14 +99,32 @@ impl GameModel { match GameEvent::from_crossterm(event) { GameEvent::Quit => None, GameEvent::Nop => Some(self), - GameEvent::MovePlayer(direction) => { + GameEvent::PlayerMove(direction) => { let player_pos = self.player_pos + direction; - if self.room.in_bounds(player_pos) { + if let Some(target_tile) = self.room.tiles.get(player_pos) + && target_tile.may_enter() + { Some(Self { player_pos, ..self }) } else { Some(self) } } + GameEvent::PlayerDash(direction) => { + let max_dash_tiles = 10; + let mut player_pos = self.player_pos; + for _ in 0..max_dash_tiles { + let next_pos = player_pos + direction; + if let Some(target_tile) = self.room.tiles.get(next_pos) && target_tile.may_enter() { + player_pos = next_pos; + if target_tile.may_interact() { + break + } + } else { + break; + } + } + Some(Self { player_pos, ..self }) + } } } @@ -87,43 +138,7 @@ impl GameModel { } fn render_tiles(&self) -> Grid { - let w = self.room.size.x; - let h = self.room.size.y; - let mut tiles = Grid::from_fn(w, h, |x, y| { - let is_vertical_boundary = [0, w - 1].contains(&x); - let is_horizontal_boundary = [0, h - 1].contains(&y); - let is_corner = is_vertical_boundary && is_horizontal_boundary; - - if is_corner { - Tile::Corner - } else if is_vertical_boundary { - Tile::VerticalWall - } else if is_horizontal_boundary { - Tile::HorizontalWall - } else { - Tile::Floor - } - }); - - tiles - .get_mut(P2::new(1, 1)) - .map(|tile| *tile = Tile::Ladder); - - tiles - .get_mut(P2::new(5, 2)) - .map(|tile| *tile = Tile::Amphora); - - tiles.get_mut(P2::new(8, 5)).map(|tile| *tile = Tile::Frog); - - tiles.get_mut(P2::new(7, 6)).map(|tile| *tile = Tile::Water); - - tiles.get_mut(P2::new(8, 6)).map(|tile| *tile = Tile::Water); - - tiles.get_mut(P2::new(9, 6)).map(|tile| *tile = Tile::Water); - - tiles.get_mut(P2::new(8, 7)).map(|tile| *tile = Tile::Water); - - tiles.get_mut(P2::new(9, 7)).map(|tile| *tile = Tile::Water); + let mut tiles = self.room.tiles.clone(); tiles .get_mut(self.player_pos) @@ -133,6 +148,7 @@ impl GameModel { } } +#[derive(Clone)] enum Tile { Floor, Ladder, @@ -140,17 +156,14 @@ enum Tile { Amphora, Frog, Water, - Corner, - VerticalWall, - HorizontalWall, + Wall, + Portal, } impl Tile { fn render(&self, cell: &mut Cell) { match self { - Tile::Floor => { - cell.set_symbol(" "); - } + Tile::Floor => {} Tile::Ladder => { cell.set_symbol("Ħ"); } @@ -169,15 +182,29 @@ impl Tile { .set_bg(Color::Blue) .set_fg(Color::White); } - Tile::Corner => { - cell.set_symbol("♦"); + Tile::Wall => { + cell.set_bg(Color::DarkGray); } - Tile::VerticalWall => { - cell.set_symbol("║"); - }, - Tile::HorizontalWall => { - cell.set_symbol("═"); - }, + Tile::Portal => { + cell.set_symbol("@").set_fg(Color::LightBlue); + } + } + } + + fn may_enter(&self) -> bool { + match self { + Tile::Wall => false, + _ => true, + } + } + + fn may_interact(&self) -> bool { + match self { + Tile::Amphora => true, + Tile::Frog => true, + Tile::Ladder => true, + Tile::Portal => true, + _ => false, } } } diff --git a/src/geometry.rs b/src/geometry.rs index 1215c35..b97869b 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -44,7 +44,7 @@ impl> Div for P2 { } } -#[derive(Debug)] +#[derive(Clone, Copy, Debug)] pub struct V2 { pub x: T, pub y: T, @@ -64,6 +64,7 @@ impl> Div for V2 { } } +#[derive(Clone)] pub struct Grid { pub dims: V2, elements: Vec, @@ -103,4 +104,4 @@ impl Grid { None } } -} +} \ No newline at end of file