Browse Source

integrate viewshed in badly

Getty Ritter 1 year ago
parent
commit
fbd38938ed
4 changed files with 42 additions and 3 deletions
  1. 4 0
      carpet/src/vis.rs
  2. 3 0
      ch5/src/main.rs
  3. 15 0
      ch5/src/map.rs
  4. 20 3
      ch5/src/systems.rs

+ 4 - 0
carpet/src/vis.rs

@@ -164,6 +164,10 @@ impl<T> Viewshed<T> {
         Viewshed { vis, blocking }
     }
 
+    pub fn visibility(&self, coord: impl Into<Coord>) -> Visibility {
+        self.vis[coord.into()]
+    }
+
     pub fn calculate_from(&mut self, board: &Board<T>, coord: Coord) {
         self.set_visibility(coord, true);
         for octant in ALL_OCTANTS {

+ 3 - 0
ch5/src/main.rs

@@ -38,6 +38,8 @@ fn main() -> Result<(), GameError> {
         .first()
         .map(|r| r.center())
         .unwrap_or_else(|| [40, 25].into());
+    let vs = carpet::Viewshed::create(&map.tiles, map::TileType::blocks_view);
+    game.insert(map::Viewshed { vs, dirty: true });
     game.insert(map);
 
     game.create_entity()
@@ -60,6 +62,7 @@ fn main() -> Result<(), GameError> {
     }
 
     game.run_with_systems(|world| {
+        systems::Visibility.run_now(world);
         systems::Draw.run_now(world);
         systems::Move.run_now(world);
     })

+ 15 - 0
ch5/src/map.rs

@@ -1,5 +1,7 @@
 use rand::Rng;
 
+use specs::prelude::*;
+
 #[derive(PartialEq, Clone, Copy, Debug)]
 pub enum TileType {
     Wall,
@@ -13,6 +15,13 @@ impl TileType {
             TileType::Floor => carpet::CP437::from_u8(0),
         }
     }
+
+    pub fn blocks_view(&self) -> bool {
+        match self {
+            TileType::Wall => true,
+            TileType::Floor => false,
+        }
+    }
 }
 
 pub struct Map {
@@ -74,3 +83,9 @@ impl Map {
         Some(&TileType::Floor) == self.tiles.get(x, y)
     }
 }
+
+#[derive(Component)]
+pub struct Viewshed {
+    pub vs: carpet::Viewshed<TileType>,
+    pub dirty: bool,
+}

+ 20 - 3
ch5/src/systems.rs

@@ -1,16 +1,19 @@
-use crate::components::{Motion, Renderable};
-use crate::map::Map;
+use crate::components::{Motion, Player, Renderable};
+use crate::map::{Map, Viewshed};
 
 system_impl! {
     Draw(
         resource mut game_board: carpet::GameBoard<carpet::CP437>,
         resource map: Map,
+        resource vs: Viewshed,
         renderable: Renderable,
         pos: carpet::Coord,
     ) {
         game_board.clear();
         for (x, y, t) in map.tiles.iter() {
-            game_board.set([x, y], t.glyph());
+            if vs.vs.visibility([x, y]) == carpet::Visibility::Visible {
+                game_board.set([x, y], t.glyph());
+            }
         }
         for (p, r) in (&pos, &renderable).join() {
             game_board.set_with_color([p.x, p.y], r.glyph, r.color);
@@ -34,3 +37,17 @@ system! {
         motion.clear();
     }
 }
+
+system! {
+    Visibility(
+        resource map: Map,
+        resource mut viewshed: Viewshed,
+        pos: carpet::Coord,
+        _player: Player,
+    ) {
+        if viewshed.dirty {
+            viewshed.vs.calculate_from(&map.tiles, *pos);
+            viewshed.dirty = false;
+        }
+    }
+}