From 538008cbdc8ec8a873e62a8b991201fda5762d63 Mon Sep 17 00:00:00 2001 From: Guillaume Pasquet Date: Thu, 21 Nov 2019 19:54:38 +0000 Subject: Fog of war! Inneficient and buggy but works --- src/entities.rs | 27 +++++++++++++++++++++++---- src/main.rs | 6 ++---- src/state.rs | 13 ++++++++++--- src/tiling.rs | 24 ++++++++++++++++++++---- 4 files changed, 55 insertions(+), 15 deletions(-) diff --git a/src/entities.rs b/src/entities.rs index b3cdf34..430e37a 100644 --- a/src/entities.rs +++ b/src/entities.rs @@ -22,6 +22,8 @@ pub trait Entity { fn is_dirty(&self) -> bool; /// Declare the entity clean fn clean(&mut self); + fn visibility(&mut self, visible: bool); + fn is_visible(&self) -> bool; } #[derive(Clone)] @@ -39,12 +41,19 @@ pub struct Character { luck: i32, xp: i32, tile: Tile, + visible: bool, } pub trait Enemy { - fn new(class: String, health: i32, attack: i32, dodge: i32, luck: i32, - location: Point, tile_str: &'static str) - -> Self; + fn new( + class: String, + health: i32, + attack: i32, + dodge: i32, + luck: i32, + location: Point, + tile_str: &'static str, + ) -> Self; fn set_tile(&mut self, tile: Tile); } @@ -103,6 +112,14 @@ impl Entity for Character { fn clean(&mut self) { self.dirty = false; } + + fn visibility(&mut self, visible: bool) { + self.visible = visible; + } + + fn is_visible(&self) -> bool { + self.visible + } } impl Enemy for Character { @@ -129,6 +146,7 @@ impl Enemy for Character { previous_location: location, tile: Tile::from(TileType::Character(tile_str)), dirty: false, + visible: false, } } @@ -160,9 +178,10 @@ impl Player for Character { previous_location: (0, 0), tile: Tile::new( TileType::Player, - true, // player is visible by default + true, // player is visible by default ), dirty: false, + visible: true, } } diff --git a/src/main.rs b/src/main.rs index 5acbbef..e45701a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,15 +42,13 @@ fn main() { let _raw = RawScreen::into_raw_mode(); - state.render_level(); - let input = input(); let mut reader = input.read_sync(); loop { - // update + state.render_player(); + state.render_level(); state.render_entities(); - state.render_player(); state.render_ui(); diff --git a/src/state.rs b/src/state.rs index 9939226..805e9e9 100644 --- a/src/state.rs +++ b/src/state.rs @@ -6,6 +6,8 @@ use crate::entities::{Character, Entity, Player}; use crate::tiling::{tile_to_str, Tile, TileGrid, TileType}; use crate::world::{apply_movement, Dungeon, Generatable, Level, Movement}; +const PLAYER_SIGHT: usize = 5; + pub struct State { pub player: Character, dungeon: Dungeon, @@ -48,7 +50,7 @@ impl State { } fn render_entity(&self, entity: &dyn Entity) { - if !entity.is_dirty() { + if !entity.is_visible() || !entity.is_dirty() { return; } let dirt = entity.previous_location(); @@ -71,8 +73,13 @@ impl State { } } - pub fn render_player(&self) { - self.render_entity(&self.player) + pub fn render_player(&mut self) { + self.render_entity(&self.player); + + self.grid + .as_mut() + .unwrap() + .clear_fog_of_war(self.player.location(), PLAYER_SIGHT); } fn ui_state_position(&self) -> MoveTo { diff --git a/src/tiling.rs b/src/tiling.rs index c79d6ef..b7c2bc6 100644 --- a/src/tiling.rs +++ b/src/tiling.rs @@ -25,15 +25,23 @@ impl Tile { pub fn get_type(&self) -> &TileType { &self.tile_type } + + pub fn is_visible(&self) -> bool { + self.visible + } + + pub fn visibility(&mut self, visible: bool) { + self.visible = visible; + } } impl From for Tile { fn from(tile_type: TileType) -> Self { Tile { tile_type, - visible: true, // <--- TODO: this set the default beaviour - // - true: all tiles of world and entities will be drawn - // - false: only draw tiles visible for the player + visible: false, // <--- TODO: this set the default beaviour + // - true: all tiles of world and entities will be drawn + // - false: only draw tiles visible for the player } } } @@ -94,10 +102,18 @@ impl TileGrid { pub fn ysize(&self) -> usize { self.ysize } + + pub fn clear_fog_of_war(&mut self, center: &(usize, usize), radius: usize) { + for x in 0.max(center.0 - radius)..center.0 + radius { + for y in 0.max(center.1 - radius)..center.1 + radius { + self.grid[y][x].visibility(true) + } + } + } } pub fn tile_to_str(tile: &Tile) -> &str { - if tile.visible { + if tile.is_visible() { match tile.tile_type { TileType::Floor => ".", TileType::Wall => "#", -- cgit v1.2.3