diff --git a/src/components.rs b/src/components.rs index 82e174a..082890a 100644 --- a/src/components.rs +++ b/src/components.rs @@ -22,5 +22,9 @@ pub struct Player {} #[derive(Component)] pub struct Viewshed { pub visible_tiles : Vec, - pub range : i32 -} \ No newline at end of file + pub range : i32, + pub dirty : bool +} + +#[derive(Component, Debug)] +pub struct Monster {} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index e6c35eb..94f5e77 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,9 +40,11 @@ impl GameState for State { let positions = self.ecs.read_storage::(); let renderables = self.ecs.read_storage::(); + let map = self.ecs.fetch::(); for (pos, render) in (&positions, &renderables).join() { - ctx.set(pos.x, pos.y, render.fg, render.bg, render.glyph); + let idx = map.xy_idx(pos.x, pos.y); + if map.visible_tiles[idx] {ctx.set(pos.x, pos.y, render.fg, render.bg, render.glyph) } } } } @@ -57,11 +59,11 @@ fn main() -> rltk::BError { gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); + gs.ecs.register::(); let map = Map::new_map_rooms_and_corridors(); let (player_x, player_y) = map.rooms[0].center(); - gs.ecs.insert(map); - + gs.ecs .create_entity() @@ -75,9 +77,33 @@ fn main() -> rltk::BError { bg: RGB::named(rltk::BLACK), }) .with(Player {}) - .with(Viewshed{ visible_tiles : Vec::new(), range : 8}) + .with(Viewshed{ visible_tiles : Vec::new(), range : 8, dirty : true}) .build(); + let mut rng = rltk::RandomNumberGenerator::new(); + for room in map.rooms.iter().skip(1) { + let (x,y) = room.center(); + + let glyph : rltk::FontCharType; + let roll = rng.roll_dice(1, 2); + match roll { + 1 => { glyph = rltk::to_cp437('g') }, + _ => { glyph = rltk::to_cp437('o') } + } + + gs.ecs.create_entity() + .with(Position{ x, y }) + .with(Renderable{ + glyph: glyph, + 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); + // Main loop runner rltk::main_loop(context, gs) } diff --git a/src/map.rs b/src/map.rs index e1ab578..20f9896 100644 --- a/src/map.rs +++ b/src/map.rs @@ -9,12 +9,14 @@ pub enum TileType { Floor, } +#[derive(Default)] pub struct Map { pub tiles : Vec::, pub rooms : Vec::, pub width : i32, pub height : i32, - pub revealed_tiles : Vec + pub revealed_tiles : Vec, + pub visible_tiles : Vec } impl Map { @@ -55,7 +57,8 @@ impl Map { rooms : Vec::new(), width : 80, height : 50, - revealed_tiles : vec![false; 80*50] + revealed_tiles : vec![false; 80*50], + visible_tiles : vec![false; 80*50] }; const MAX_ROOMS: i32 = 30; @@ -148,29 +151,20 @@ pub fn draw_map(ecs: &World, ctx: &mut Rltk) { let mut x = 0; for (idx, tile) in map.tiles.iter().enumerate() { 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, 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); } x += 1; if x > 79 { diff --git a/src/player.rs b/src/player.rs index 61900aa..50e9379 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,18 +1,21 @@ use rltk::{VirtualKeyCode, Rltk}; use specs::prelude::*; -use super::{Position, Player, TileType, Map, State}; +use super::{Position, Player, TileType, Map, State, Viewshed}; use std::cmp::{min, max}; 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 7a8e408..9aa80a0 100644 --- a/src/visibility_system.rs +++ b/src/visibility_system.rs @@ -16,17 +16,23 @@ 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); - - 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 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); + + 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; + } } } + } } } \ No newline at end of file