Browse Source

some cleanup

Getty Ritter 1 year ago
parent
commit
fcc12f3735
5 changed files with 69 additions and 25 deletions
  1. 12 0
      Cargo.lock
  2. 1 0
      Cargo.toml
  3. 46 23
      carpet/src/vis.rs
  4. 2 1
      ch5/src/main.rs
  5. 8 1
      ch5/src/map.rs

+ 12 - 0
Cargo.lock

@@ -373,6 +373,18 @@ dependencies = [
  "specs-system-macro",
 ]
 
+[[package]]
+name = "ch6"
+version = "0.1.0"
+dependencies = [
+ "carpet",
+ "ggez",
+ "rand",
+ "specs",
+ "specs-derive",
+ "specs-system-macro",
+]
+
 [[package]]
 name = "clang-sys"
 version = "1.3.3"

+ 1 - 0
Cargo.toml

@@ -7,4 +7,5 @@ members = [
   "ch3",
   "ch4",
   "ch5",
+  "ch6",
 ]

+ 46 - 23
carpet/src/vis.rs

@@ -91,16 +91,11 @@ impl ShadowLine {
     }
 
     fn add(&mut self, other: Shadow) {
-        let index = {
-            let mut index = 0;
-            while index < self.shadows.len() {
-                if self.shadows[index].start >= other.start {
-                    break;
-                }
-                index += 1;
-            }
-            index
-        };
+        let index = self
+            .shadows
+            .iter()
+            .position(|sh| sh.start >= other.start)
+            .unwrap_or(self.shadows.len());
 
         // find whether there's an overlapping previous and next
         // shadow segment
@@ -114,27 +109,42 @@ impl ShadowLine {
                 .get(index - 1)
                 .filter(|sh| sh.end > other.start)
         };
-        let next = if index == self.shadows.len() {
-            None
-        } else {
-            self.shadows.get(index).filter(|sh| sh.start < other.end)
-        };
+        let next = self.shadows.get(index).filter(|sh| sh.start < other.end);
 
         match (previous, next) {
-            // two overlapping segments: join them together
+            // 1 2 3 4 5 6 7      1 2 3 4 5 6 7
+            // [prev] [next]  =>  [prev.......]
+            //    [other]
+            //
+            // two overlapping segments: join them together,
+            // specifically extending the previous one and deleting
+            // the second
             (Some(_), Some(n)) => {
                 self.shadows[index - 1].end = n.end;
                 self.shadows.remove(index);
             }
-            // just one overlapping segment: extend the segment in the
-            // appropriate direction
+            // 1 2 3 4 5 6 7 8 9      1 2 3 4 5 6 7 8 9
+            // [prev]     [next]  =>  [prev]  [next...]
+            //         [other]
+            //
+            // just overlapping a later segment: pull the later
+            // segment's start point earlier
             (None, Some(_)) => {
                 self.shadows[index].start = other.start;
             }
+            // 1 2 3 4 5 6 7 8 9      1 2 3 4 5 6 7 8 9
+            // [prev]     [next]  =>  [prev...]  [next]
+            //   [other]
+            //
+            // just overlapping an earlier segment: pull the earlier
+            // segment's end point later
             (Some(_), None) => {
                 self.shadows[index - 1].end = other.end;
             }
-            // no overlapping segments: add this one
+            // 1 2 3 4 5 6 7 8    1 2 3 4 5 6 7 8
+            // [p]         [n] => [p] [other] [n]
+            //     [other]
+            // no overlapping segments: just add this one in between
             (None, None) => {
                 self.shadows.insert(index, other);
             }
@@ -145,13 +155,19 @@ impl ShadowLine {
 pub struct Viewshed<T> {
     pub vis: Board<bool>,
     blocking: Box<fn(&T) -> bool>,
+    pub range: Option<usize>,
 }
 
 impl<T> Viewshed<T> {
     pub fn create(original: &Board<T>, blocking: fn(&T) -> bool) -> Viewshed<T> {
         let vis = Board::new_from(original.width(), original.height(), |_, _| false);
         let blocking = Box::new(blocking);
-        Viewshed { vis, blocking }
+        let range = None;
+        Viewshed {
+            vis,
+            blocking,
+            range,
+        }
     }
 
     pub fn visibility(&self, coord: impl Into<Coord>) -> bool {
@@ -198,9 +214,16 @@ impl<T> Viewshed<T> {
                 let visible = !line.in_shadow(&projection);
                 self.vis[pos] = visible;
 
-                if visible && (self.blocking)(&board[pos]) {
-                    line.add(projection);
-                    full_shadow = line.is_full_shadow();
+                if visible {
+                    let out_of_range = if let Some(r) = self.range {
+                        ((row.pow(2) + col.pow(2)) as f32).sqrt() >= r as f32
+                    } else {
+                        false
+                    };
+                    if out_of_range || (self.blocking)(&board[pos]) {
+                        line.add(projection);
+                        full_shadow = line.is_full_shadow();
+                    }
                 }
             }
         }

+ 2 - 1
ch5/src/main.rs

@@ -38,7 +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::Cell::blocks_view);
+    let mut vs = carpet::Viewshed::create(&map.tiles, map::Cell::blocks_view);
+    vs.range = Some(20);
     game.insert(map::Viewshed { vs, dirty: true });
     game.insert(map);
 

+ 8 - 1
ch5/src/map.rs

@@ -39,7 +39,14 @@ impl Map {
     pub fn new() -> Map {
         let mut rng = rand::thread_rng();
         let mut map = Map {
-            tiles: carpet::Board::new_with_default(80, 50, Cell { tile: TileType::Wall, seen: false }),
+            tiles: carpet::Board::new_with_default(
+                80,
+                50,
+                Cell {
+                    tile: TileType::Wall,
+                    seen: false,
+                },
+            ),
             rooms: Vec::new(),
         };