diff --git a/src/components.rs b/src/components.rs index a1f72ec..4feca6f 100644 --- a/src/components.rs +++ b/src/components.rs @@ -22,4 +22,5 @@ pub struct Player {} pub struct Viewshed { pub visible_tiles: Vec, pub range: i32, + pub dirty: bool, } diff --git a/src/main.rs b/src/main.rs index 37ae6be..a4971b3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -78,6 +78,7 @@ fn main() -> rltk::BError { .with(Viewshed { visible_tiles: Vec::new(), range: 8, + dirty: true, }) .build(); diff --git a/src/map.rs b/src/map.rs index 94ad4e7..67ca173 100644 --- a/src/map.rs +++ b/src/map.rs @@ -15,6 +15,7 @@ pub struct Map { pub width: i32, pub height: i32, pub revealed_tiles: Vec, + pub visible_tiles: Vec, } impl Map { @@ -60,6 +61,7 @@ impl Map { width: 80, height: 50, revealed_tiles: vec![false; 80 * 50], + visible_tiles: vec![false; 80 * 50], }; const MAX_ROOMS: i32 = 30; @@ -128,26 +130,25 @@ pub fn draw_map(ecs: &World, ctx: &mut Rltk) { for (idx, tile) in map.tiles.iter().enumerate() { // Render a tile depending on the tile type if map.revealed_tiles[idx] { + let glyph; + let mut fg; + match tile { TileType::Floor => { - ctx.set( - x, - y, - RGB::from_f32(0.5, 0.5, 0.5), - RGB::from_f32(0., 0., 0.), - rltk::to_cp437('.'), - ); + glyph = rltk::to_cp437('.'); + fg = RGB::from_f32(0., 0.5, 0.5); } TileType::Wall => { - ctx.set( - x, - y, - RGB::from_f32(0.0, 1.0, 0.0), - RGB::from_f32(0., 0., 0.), - rltk::to_cp437('#'), - ); + glyph = rltk::to_cp437('#'); + fg = RGB::from_f32(0., 1.0, 0.); } } + + if !map.visible_tiles[idx] { + fg = fg.to_greyscale(); + } + + ctx.set(x, y, fg, RGB::from_f32(0., 0., 0.), glyph); } // Move to the next set of coordinates diff --git a/src/player.rs b/src/player.rs index 0c80922..9f33f8e 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,4 +1,4 @@ -use super::{Map, Player, Position, State, TileType}; +use super::{Map, Player, Position, State, TileType, Viewshed}; use rltk::{Rltk, VirtualKeyCode}; use specs::prelude::*; use std::cmp::{max, min}; @@ -6,13 +6,16 @@ use std::cmp::{max, min}; pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) { let mut positions = ecs.write_storage::(); let mut players = ecs.write_storage::(); + let mut viewsheds = ecs.write_storage::(); let map = ecs.fetch::(); - for (_player, pos) in (&mut players, &mut positions).join() { + for (_player, pos, viewshed) in (&mut players, &mut positions, &mut viewsheds).join() { let destination_idx = map.xy_idx(pos.x + delta_x, pos.y + delta_y); if map.tiles[destination_idx] != TileType::Wall { pos.x = min(79, max(0, pos.x + delta_x)); pos.y = min(49, max(0, pos.y + delta_y)); + + viewshed.dirty = true; } } } diff --git a/src/visibility_system.rs b/src/visibility_system.rs index eb10745..4adf1b2 100644 --- a/src/visibility_system.rs +++ b/src/visibility_system.rs @@ -17,18 +17,26 @@ impl<'a> System<'a> for VisibilitySystem { let (mut map, entities, mut viewshed, pos, player) = data; for (ent, viewshed, pos) in (&entities, &mut viewshed, &pos).join() { - viewshed.visible_tiles.clear(); - viewshed.visible_tiles = field_of_view(Point::new(pos.x, pos.y), viewshed.range, &*map); - viewshed - .visible_tiles - .retain(|p| p.x >= 0 && p.x < map.width && p.y >= 0 && p.y < map.height); + if viewshed.dirty { + viewshed.dirty = false; + viewshed.visible_tiles.clear(); + viewshed.visible_tiles = + field_of_view(Point::new(pos.x, pos.y), viewshed.range, &*map); + viewshed + .visible_tiles + .retain(|p| p.x >= 0 && p.x < map.width && p.y >= 0 && p.y < map.height); - // if this is the player, reveal what they can see - let p: Option<&Player> = player.get(ent); - if let Some(p) = p { - for vis in viewshed.visible_tiles.iter() { - let idx = map.xy_idx(vis.x, vis.y); - map.revealed_tiles[idx] = true; + // if this is the player, reveal what they can see + let _p: Option<&Player> = player.get(ent); + if let Some(_p) = _p { + for t in map.visible_tiles.iter_mut() { + *t = false + } + for vis in viewshed.visible_tiles.iter() { + let idx = map.xy_idx(vis.x, vis.y); + map.revealed_tiles[idx] = true; + map.visible_tiles[idx] = true; + } } } }