From 1cfe16c4ef5b34b0d609d7b70361e6d9068f422f Mon Sep 17 00:00:00 2001 From: Joachim Lusiardi Date: Mon, 20 Nov 2023 22:59:19 +0100 Subject: [PATCH] Implement fog of dungeon --- src/game.rs | 12 +++++----- src/level.rs | 50 ++++++++++++++++++++++++++++++++++++++++-- src/level_generator.rs | 1 + src/level_widget.rs | 3 +++ src/main.rs | 2 +- 5 files changed, 59 insertions(+), 9 deletions(-) diff --git a/src/game.rs b/src/game.rs index 7c50f7e..ecc028c 100644 --- a/src/game.rs +++ b/src/game.rs @@ -11,7 +11,7 @@ impl Game { // check if move is allowed first let player = &self.player; let player_pos = player.get_position(); - let level = &self.levels[player_pos.get_level() as usize]; + let mut level = &self.levels[player_pos.get_level() as usize]; let new_x = ((player_pos.get_x() as i16) + dx as i16) as u16; let new_y = ((player_pos.get_y() as i16) + dy as i16) as u16; let can_go: bool = match level.get_element(new_x as i16, new_y as i16) { @@ -25,11 +25,10 @@ impl Game { }; if can_go { if level.get_element(new_x as i16, new_y as i16).unwrap() == LevelElement::StairDown { - self.player.set_position( - player_pos.get_level() + 1, - self.levels[(player_pos.get_level() + 1) as usize].start_x as u16, - self.levels[(player_pos.get_level() + 1) as usize].start_y as u16, - ); + let start_x = self.levels[(player_pos.get_level() + 1) as usize].start_x; + let start_y = self.levels[(player_pos.get_level() + 1) as usize].start_y; + self.player.set_position(player_pos.get_level() + 1, start_x as u16, start_y as u16); + self.levels[(player_pos.get_level() + 1) as usize].discover(start_x as i16, start_y as i16); } else if level.get_element(new_x as i16, new_y as i16).unwrap() == LevelElement::StairUp { self.player.set_position( player_pos.get_level() - 1, @@ -38,6 +37,7 @@ impl Game { ); } else { self.player.change_position(dx, dy); + self.levels[player_pos.get_level() as usize].discover(new_x as i16, new_y as i16); } } } diff --git a/src/level.rs b/src/level.rs index 32f9753..28ca1b2 100644 --- a/src/level.rs +++ b/src/level.rs @@ -1,3 +1,5 @@ +use std::cmp::{max, min}; + pub const LEVEL_WIDTH: usize = 50; pub const LEVEL_HEIGHT: usize = 25; @@ -7,6 +9,7 @@ pub enum LevelElement { Floor, StairDown, StairUp, + Unknown, } #[derive(Copy, Clone, Debug, PartialEq)] @@ -22,6 +25,7 @@ pub enum RoomType { #[derive(Copy, Clone, Debug, PartialEq)] pub struct Level { pub(crate) structure: [[LevelElement; LEVEL_HEIGHT]; LEVEL_WIDTH], + pub(crate) discovered: [[bool; LEVEL_HEIGHT]; LEVEL_WIDTH], pub(crate) start_x: usize, pub(crate) start_y: usize, pub(crate) end_x: usize, @@ -33,10 +37,11 @@ impl Level { let s = [[LevelElement::Wall; LEVEL_HEIGHT]; LEVEL_WIDTH]; Level { structure: s, + discovered: [[false; LEVEL_HEIGHT]; LEVEL_WIDTH], start_x: 1, start_y: 1, end_x: 1, - end_y: 1 + end_y: 1, } } pub fn get_element(&self, x: i16, y: i16) -> Option { @@ -46,7 +51,48 @@ impl Level { if x >= LEVEL_WIDTH as i16 || y >= LEVEL_HEIGHT as i16 { return None; } - Some(self.structure[x as usize][y as usize]) + if self.discovered[x as usize][y as usize] { + return Some(self.structure[x as usize][y as usize]); + } + return Some(LevelElement::Unknown); + } + /// discover the area with in the level around the given position + pub fn discover(&mut self, x: i16, y: i16) { + for x_r in x - 1..=x + 1 { + for y_r in y - 1..=y + 1 { + let tx = min(max(x_r, 0), (LEVEL_WIDTH - 1) as i16) as usize; + let ty = min(max(y_r, 0), (LEVEL_HEIGHT - 1) as i16) as usize; + self.discovered[tx][ty] = true; + } + } + for x_r in x..=x + 2 { + let tx = min(max(x_r, 0), (LEVEL_WIDTH - 1) as i16) as usize; + self.discovered[tx][y as usize] = true; + if self.structure[tx][y as usize] == LevelElement::Wall { + break; + } + } + for y_r in y..=y + 2 { + let ty = min(max(y_r, 0), (LEVEL_HEIGHT - 1) as i16) as usize; + self.discovered[x as usize][ty] = true; + if self.structure[x as usize][ty] == LevelElement::Wall { + break; + } + } + for x_r in (x-2..x).rev() { + let tx = min(max(x_r, 0), (LEVEL_WIDTH - 1) as i16) as usize; + self.discovered[tx][y as usize] = true; + if self.structure[tx][y as usize] == LevelElement::Wall { + break; + } + } + for y_r in (y-2..y).rev() { + let ty = min(max(y_r, 0), (LEVEL_HEIGHT - 1) as i16) as usize; + self.discovered[x as usize][ty] = true; + if self.structure[x as usize][ty] == LevelElement::Wall { + break; + } + } } } diff --git a/src/level_generator.rs b/src/level_generator.rs index 3c560d8..7722508 100644 --- a/src/level_generator.rs +++ b/src/level_generator.rs @@ -284,6 +284,7 @@ impl LevelGenerator { } Level { structure: s, + discovered: [[false; 1 + ROOMS_HORIZONTAL * ROOM_HEIGHT]; 1 + ROOMS_VERTICAL * ROOM_WIDTH], start_x, start_y, end_x, diff --git a/src/level_widget.rs b/src/level_widget.rs index 8570d23..cd37bea 100644 --- a/src/level_widget.rs +++ b/src/level_widget.rs @@ -101,6 +101,9 @@ impl<'a> Widget for LevelWidget<'a> { LevelElement::StairUp => { self.set_cell(buf, x, y, "<", Color::Black, Color::Gray); } + LevelElement::Unknown => { + self.set_cell(buf, x, y, "▒", Color::DarkGray, Color::Gray); + } } } } diff --git a/src/main.rs b/src/main.rs index e0ff4eb..7fe0216 100644 --- a/src/main.rs +++ b/src/main.rs @@ -36,7 +36,7 @@ fn main() -> Result<()> { levels, }; - g.player.change_position((levels[0].start_x) as i8, (levels[0].start_y) as i8); + g.move_player((levels[0].start_x) as i8, (levels[0].start_y) as i8); stdout().execute(EnterAlternateScreen)?; enable_raw_mode()?;