diff --git a/src/components.rs b/src/components.rs index e94376c..5f17e23 100644 --- a/src/components.rs +++ b/src/components.rs @@ -1,4 +1,4 @@ -use rltk::{RGB,Point}; +use rltk::{Point, RGB}; use specs::prelude::*; @@ -20,6 +20,7 @@ pub struct Player {} #[derive(Component)] pub struct Viewshed { - pub visible_tiles : Vec, - pub range : i32 + pub visible_tiles: Vec, + pub range: i32, + pub dirty: bool, } diff --git a/src/main.rs b/src/main.rs index e28ea87..a49b1a1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,17 +17,19 @@ pub struct State { ecs: World, } -fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) { +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() { - let x = min(79, max(0, pos.x + delta_x)); - let y = min(49, max(0, pos.y + delta_y)); - if map.tile_at(x, y) != TileType::Wall { - pos.x = x; - pos.y = y; + 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; } } } @@ -141,9 +143,28 @@ fn main() { .with(Viewshed { visible_tiles: Vec::new(), range: 8, + dirty: true, }) .build(); + for room in map.rooms.iter().skip(1) { + let (x, y) = room.center(); + gs.ecs + .create_entity() + .with(Position { x, y }) + .with(Renderable { + glyph: rltk::to_cp437('g'), + fg: RGB::named(rltk::RED), + bg: RGB::named(rltk::BLACK), + }) + .with(Viewshed { + visible_tiles: Vec::new(), + range: 8, + dirty: true, + }) + .build(); + } + gs.ecs.insert(map); rltk::main_loop(context, gs); diff --git a/src/visibility_system.rs b/src/visibility_system.rs index 8dcfd7e..89c7d56 100644 --- a/src/visibility_system.rs +++ b/src/visibility_system.rs @@ -19,22 +19,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 - 1 && p.y > 0 && p.y < map.height - 1); + if viewshed.dirty { + 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 - 1 && p.y > 0 && p.y < map.height - 1); + viewshed.dirty = false; - // If this is the player, reveal what they can see - let p: Option<&Player> = player.get(ent); - if let Some(_) = 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; + // If this is the player, reveal what they can see + let p: Option<&Player> = player.get(ent); + if let Some(_) = 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; + } } } }