Browse Source

Add map abstraction and draw it

Getty Ritter 4 years ago
parent
commit
077e7dadf0
4 changed files with 75 additions and 37 deletions
  1. 1 0
      Cargo.lock
  2. 30 1
      carpet/src/lib.rs
  3. 2 1
      ch3/Cargo.toml
  4. 42 35
      ch3/src/main.rs

+ 1 - 0
Cargo.lock

@@ -282,6 +282,7 @@ version = "0.1.0"
 dependencies = [
  "carpet 0.1.0",
  "ggez 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "specs 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "specs-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "specs-system-macro 0.1.0 (git+https://git.infinitenegativeutility.com/getty/specs-system-macro.git)",

+ 30 - 1
carpet/src/lib.rs

@@ -460,7 +460,7 @@ pub struct Board<T> {
 }
 
 impl<T> Board<T> {
-    pub fn new_from(width: usize, height: usize, func: impl Fn(usize, usize) -> T) -> Board<T> {
+    pub fn new_from(width: usize, height: usize, mut func: impl FnMut(usize, usize) -> T) -> Board<T> {
         let mut storage = Vec::with_capacity(width * height);
         for y in 0..height {
             for x in 0..width {
@@ -497,6 +497,13 @@ impl<T> Board<T> {
         let pos = pos.into();
         pos.x < self.width && pos.y < self.height
     }
+
+    pub fn iter(&self) -> BoardIter<T> {
+        BoardIter {
+            n: 0,
+            board: &self,
+        }
+    }
 }
 
 impl<T> std::ops::Index<Coord> for Board<T> {
@@ -540,3 +547,25 @@ impl<T> std::ops::IndexMut<[usize;2]> for Board<T> {
         self.get_mut(x, y).unwrap_or_else(|| panic!("Coordinate {:?} out of range", (x, y)))
     }
 }
+
+
+
+pub struct BoardIter<'a, T> {
+    n: usize,
+    board: &'a Board<T>,
+}
+
+impl<'a, T> Iterator for BoardIter<'a, T> {
+    type Item = (usize, usize, &'a T);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.n < self.board.storage.len() {
+            let x = self.n % self.board.width;
+            let y = self.n / self.board.width;
+            self.n += 1;
+            Some((x, y, &self.board.storage[self.n-1]))
+        } else {
+            None
+        }
+    }
+}

+ 2 - 1
ch3/Cargo.toml

@@ -11,4 +11,5 @@ ggez = "*"
 carpet = { path = "../carpet" }
 specs = "*"
 specs-derive = "*"
-specs-system-macro = { git = "https://git.infinitenegativeutility.com/getty/specs-system-macro.git" }
+specs-system-macro = { git = "https://git.infinitenegativeutility.com/getty/specs-system-macro.git" }
+rand = "*"

+ 42 - 35
ch3/src/main.rs

@@ -5,13 +5,43 @@ extern crate specs_system_macro;
 
 use ggez::GameError;
 use specs::prelude::*;
+use rand::Rng;
 
 #[derive(PartialEq, Clone, Copy, Debug)]
-enum TileType {
+pub enum TileType {
     Wall,
     Floor,
 }
 
+impl TileType {
+    fn glyph(&self) -> carpet::CP437 {
+        match self {
+            TileType::Wall => carpet::CP437::from_char('#'),
+            TileType::Floor => carpet::CP437::from_u8(0),
+        }
+    }
+}
+
+pub struct Map {
+    tiles: carpet::Board<TileType>,
+}
+
+impl Map {
+    fn new() -> Map {
+        let mut rng = rand::thread_rng();
+        let tiles = carpet::Board::new_from(80, 50, |x, y| {
+            if x == 0 || x == 79 || y == 0 || y == 49 {
+                TileType::Wall
+            } else if rng.gen::<u8>() % 8 == 0 {
+                TileType::Wall
+            } else {
+                TileType::Floor
+            }
+        });
+        Map { tiles }
+    }
+}
+
 #[derive(Component)]
 pub struct Pos {
     x: usize,
@@ -24,9 +54,6 @@ pub struct Renderable {
     color: carpet::Color,
 }
 
-#[derive(Component)]
-pub struct MoveLeft;
-
 #[derive(Component)]
 pub struct Player;
 
@@ -52,26 +79,17 @@ impl Motion {
 
 system_impl! {
     Draw(
-        resource mut board: carpet::GameBoard<carpet::CP437>,
+        resource mut game_board: carpet::GameBoard<carpet::CP437>,
+        resource map: Map,
         renderable: Renderable,
         pos: Pos,
     ) {
-        board.clear();
-        for (p, r) in (&pos, &renderable).join() {
-            board.set_with_color([p.x, p.y], r.glyph, r.color);
+        game_board.clear();
+        for (x, y, t) in map.tiles.iter() {
+            game_board.set([x, y], t.glyph());
         }
-    }
-}
-
-system! {
-    Leftward (
-        _left: MoveLeft,
-        mut pos: Pos,
-    ) {
-        if pos.x == 0 {
-            pos.x = 79;
-        } else {
-            pos.x -= 1;
+        for (p, r) in (&pos, &renderable).join() {
+            game_board.set_with_color([p.x, p.y], r.glyph, r.color);
         }
     }
 }
@@ -89,7 +107,8 @@ system! {
 }
 
 fn main() -> Result<(), GameError> {
-    let mut game = carpet::GameBuilder::new()
+    let mut game: carpet::Game<carpet::CP437> =
+        carpet::GameBuilder::new()
         .name("game")
         .author("me")
         .resource_path({
@@ -104,10 +123,10 @@ fn main() -> Result<(), GameError> {
 
     game.register::<Pos>();
     game.register::<Renderable>();
-    game.register::<MoveLeft>();
     game.register::<Motion>();
     game.register::<Player>();
-    game.world.print([1, 1], "Hello, world!");
+
+    game.insert(Map::new());
 
     game.create_entity()
         .with(Pos { x: 40, y: 25 })
@@ -118,17 +137,6 @@ fn main() -> Result<(), GameError> {
         })
         .build();
 
-    for i in 0..10 {
-        game.create_entity()
-            .with(Pos { x: i * 7, y: 20 })
-            .with(Renderable {
-                glyph: carpet::CP437::from_char('X'),
-                color: carpet::Color::Red,
-            })
-            .with(MoveLeft)
-            .build();
-    }
-
     game.on_key((carpet::VirtualKeyCode::W, carpet::KeyMods::NONE), |world| {
         Motion::move_player(world, -1, 0);
     });
@@ -147,7 +155,6 @@ fn main() -> Result<(), GameError> {
 
     game.run_with_systems(|world| {
         Draw.run_now(&world);
-        Leftward.run_now(&world);
         Move.run_now(&world);
     })
 }