Implement fog of dungeon

This commit is contained in:
Joachim Lusiardi 2023-11-20 22:59:19 +01:00
parent d44c0fd53e
commit 1cfe16c4ef
5 changed files with 59 additions and 9 deletions

View File

@ -11,7 +11,7 @@ impl Game {
// check if move is allowed first // check if move is allowed first
let player = &self.player; let player = &self.player;
let player_pos = player.get_position(); 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_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 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) { 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 can_go {
if level.get_element(new_x as i16, new_y as i16).unwrap() == LevelElement::StairDown { if level.get_element(new_x as i16, new_y as i16).unwrap() == LevelElement::StairDown {
self.player.set_position( let start_x = self.levels[(player_pos.get_level() + 1) as usize].start_x;
player_pos.get_level() + 1, let start_y = self.levels[(player_pos.get_level() + 1) as usize].start_y;
self.levels[(player_pos.get_level() + 1) as usize].start_x as u16, 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].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 { } else if level.get_element(new_x as i16, new_y as i16).unwrap() == LevelElement::StairUp {
self.player.set_position( self.player.set_position(
player_pos.get_level() - 1, player_pos.get_level() - 1,
@ -38,6 +37,7 @@ impl Game {
); );
} else { } else {
self.player.change_position(dx, dy); self.player.change_position(dx, dy);
self.levels[player_pos.get_level() as usize].discover(new_x as i16, new_y as i16);
} }
} }
} }

View File

@ -1,3 +1,5 @@
use std::cmp::{max, min};
pub const LEVEL_WIDTH: usize = 50; pub const LEVEL_WIDTH: usize = 50;
pub const LEVEL_HEIGHT: usize = 25; pub const LEVEL_HEIGHT: usize = 25;
@ -7,6 +9,7 @@ pub enum LevelElement {
Floor, Floor,
StairDown, StairDown,
StairUp, StairUp,
Unknown,
} }
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq)]
@ -22,6 +25,7 @@ pub enum RoomType {
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq)]
pub struct Level { pub struct Level {
pub(crate) structure: [[LevelElement; LEVEL_HEIGHT]; LEVEL_WIDTH], pub(crate) structure: [[LevelElement; LEVEL_HEIGHT]; LEVEL_WIDTH],
pub(crate) discovered: [[bool; LEVEL_HEIGHT]; LEVEL_WIDTH],
pub(crate) start_x: usize, pub(crate) start_x: usize,
pub(crate) start_y: usize, pub(crate) start_y: usize,
pub(crate) end_x: usize, pub(crate) end_x: usize,
@ -33,10 +37,11 @@ impl Level {
let s = [[LevelElement::Wall; LEVEL_HEIGHT]; LEVEL_WIDTH]; let s = [[LevelElement::Wall; LEVEL_HEIGHT]; LEVEL_WIDTH];
Level { Level {
structure: s, structure: s,
discovered: [[false; LEVEL_HEIGHT]; LEVEL_WIDTH],
start_x: 1, start_x: 1,
start_y: 1, start_y: 1,
end_x: 1, end_x: 1,
end_y: 1 end_y: 1,
} }
} }
pub fn get_element(&self, x: i16, y: i16) -> Option<LevelElement> { pub fn get_element(&self, x: i16, y: i16) -> Option<LevelElement> {
@ -46,7 +51,48 @@ impl Level {
if x >= LEVEL_WIDTH as i16 || y >= LEVEL_HEIGHT as i16 { if x >= LEVEL_WIDTH as i16 || y >= LEVEL_HEIGHT as i16 {
return None; 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;
}
}
} }
} }

View File

@ -284,6 +284,7 @@ impl LevelGenerator {
} }
Level { Level {
structure: s, structure: s,
discovered: [[false; 1 + ROOMS_HORIZONTAL * ROOM_HEIGHT]; 1 + ROOMS_VERTICAL * ROOM_WIDTH],
start_x, start_x,
start_y, start_y,
end_x, end_x,

View File

@ -101,6 +101,9 @@ impl<'a> Widget for LevelWidget<'a> {
LevelElement::StairUp => { LevelElement::StairUp => {
self.set_cell(buf, x, y, "<", Color::Black, Color::Gray); self.set_cell(buf, x, y, "<", Color::Black, Color::Gray);
} }
LevelElement::Unknown => {
self.set_cell(buf, x, y, "", Color::DarkGray, Color::Gray);
}
} }
} }
} }

View File

@ -36,7 +36,7 @@ fn main() -> Result<()> {
levels, 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)?; stdout().execute(EnterAlternateScreen)?;
enable_raw_mode()?; enable_raw_mode()?;