Browse Source

Rename Board to GameBoard and add a generic 2d board type

Getty Ritter 4 years ago
parent
commit
0f25ba8be4
2 changed files with 103 additions and 14 deletions
  1. 102 13
      carpet/src/lib.rs
  2. 1 1
      ch2/src/main.rs

+ 102 - 13
carpet/src/lib.rs

@@ -76,7 +76,7 @@ impl Tile for CP437 {
     }
 }
 
-pub struct Board<Idx: Tile> {
+pub struct GameBoard<Idx: Tile> {
     size: Size,
     contents: Vec<(Idx, SpriteIdx)>,
     tileset: Tileset<Idx>,
@@ -138,8 +138,8 @@ impl From<[usize; 2]> for Coord {
     }
 }
 
-impl<Idx: Tile> Board<Idx> {
-    pub fn new(size: impl Into<Size>, mut tileset: Tileset<Idx>) -> Board<Idx> {
+impl<Idx: Tile> GameBoard<Idx> {
+    pub fn new(size: impl Into<Size>, mut tileset: Tileset<Idx>) -> GameBoard<Idx> {
         let size = size.into();
         let mut contents = Vec::new();
         for y in 0..size.height {
@@ -151,7 +151,7 @@ impl<Idx: Tile> Board<Idx> {
                 contents.push((Idx::blank(), idx));
             }
         }
-        Board {
+        GameBoard {
             size,
             contents,
             tileset,
@@ -205,7 +205,7 @@ impl<Idx: Tile> Board<Idx> {
     }
 }
 
-impl Board<CP437> {
+impl GameBoard<CP437> {
     pub fn print(&mut self, at: impl Into<Coord>, msg: &str) {
         let Coord { x, y } = at.into();
         for (idx, ch) in msg.chars().enumerate() {
@@ -229,7 +229,7 @@ fn do_nothing() -> Updater {
 }
 
 impl<Idx: Tile + 'static> World<Idx> {
-    pub fn new(board: Board<Idx>) -> World<Idx> {
+    pub fn new(board: GameBoard<Idx>) -> World<Idx> {
         let mut world = specs::World::new();
         world.insert(board);
         let updater = do_nothing();
@@ -242,7 +242,7 @@ impl<Idx: Tile + 'static> World<Idx> {
         }
     }
     pub fn set(&mut self, at: impl Into<Coord>, ch: Idx) {
-        self.world.fetch_mut::<Board<Idx>>().set(at, ch)
+        self.world.fetch_mut::<GameBoard<Idx>>().set(at, ch)
     }
 
     pub fn set_with_color(
@@ -252,12 +252,12 @@ impl<Idx: Tile + 'static> World<Idx> {
         color: impl Into<ggez::graphics::Color>,
     ) {
         self.world
-            .fetch_mut::<Board<Idx>>()
+            .fetch_mut::<GameBoard<Idx>>()
             .set_with_color(at, ch, color)
     }
 
     pub fn get(&self, at: impl Into<Coord>) -> Idx {
-        self.world.fetch::<Board<Idx>>().get(at)
+        self.world.fetch::<GameBoard<Idx>>().get(at)
     }
 
     pub fn on_update(&mut self, update: impl FnMut(&mut specs::World) + 'static) {
@@ -271,14 +271,14 @@ impl<Idx: Tile + 'static> World<Idx> {
 
 impl World<CP437> {
     pub fn print(&mut self, at: impl Into<Coord>, msg: &str) {
-        self.world.fetch_mut::<Board<CP437>>().print(at, msg)
+        self.world.fetch_mut::<GameBoard<CP437>>().print(at, msg)
     }
 }
 
 impl<Idx: 'static + Tile> ggez::event::EventHandler for World<Idx> {
     fn draw(&mut self, ctx: &mut Context) -> Result<(), ggez::GameError> {
         ggez::graphics::clear(ctx, ggez::graphics::BLACK);
-        self.world.fetch::<Board<Idx>>().draw(ctx)?;
+        self.world.fetch::<GameBoard<Idx>>().draw(ctx)?;
         ggez::graphics::present(ctx)
     }
 
@@ -316,7 +316,7 @@ pub struct Game<Idx> {
 
 impl<Idx: Tile + 'static> Game<Idx> {
     pub fn create(
-        board: Board<Idx>,
+        board: GameBoard<Idx>,
         ctx: ggez::Context,
         evloop: ggez::event::EventsLoop,
     ) -> Result<Game<Idx>, ggez::GameError> {
@@ -447,7 +447,96 @@ impl<Idx: Tile + 'static> GameBuilder<Idx> {
             })
             .build()?;
         let tileset = Tileset::from_file(&mut ctx, tile_size, tile_path)?;
-        let board = Board::new(map_size, tileset);
+        let board = GameBoard::new(map_size, tileset);
         Game::create(board, ctx, evloop)
     }
 }
+
+
+pub struct Board<T> {
+    width: usize,
+    height: usize,
+    storage: Vec<T>,
+}
+
+impl<T> Board<T> {
+    pub fn new_from(width: usize, height: usize, func: impl Fn(usize, usize) -> T) -> Board<T> {
+        let mut storage = Vec::with_capacity(width * height);
+        for y in 0..height {
+            for x in 0..width {
+                storage.push(func(x, y))
+            }
+        }
+        Board { width, height, storage }
+    }
+
+    pub fn get(&self, x: usize, y: usize) -> Option<&T> {
+        let idx = x + self.width * y;
+        self.storage.get(idx)
+    }
+
+    pub fn get_mut(&mut self, x: usize, y: usize) -> Option<&mut T> {
+        let idx = x + self.width * y;
+        self.storage.get_mut(idx)
+    }
+
+    pub fn set(&mut self, x: usize, y: usize, val: T) {
+        let idx = x + self.width * y;
+        self.storage[idx] = val;
+    }
+
+    pub fn width(&self) -> usize {
+        self.width
+    }
+
+    pub fn height(&self) -> usize {
+        self.height
+    }
+
+    pub fn contains(&self, pos: impl Into<Coord>) -> bool {
+        let pos = pos.into();
+        pos.x < self.width && pos.y < self.height
+    }
+}
+
+impl<T> std::ops::Index<Coord> for Board<T> {
+    type Output = T;
+
+    fn index(&self, pos: Coord) -> &Self::Output {
+        self.get(pos.x, pos.y).unwrap_or_else(|| panic!("Coordinate {:?} out of range", pos))
+    }
+}
+
+impl<T> std::ops::Index<(usize, usize)> for Board<T> {
+    type Output = T;
+
+    fn index(&self, (x, y): (usize, usize)) -> &Self::Output {
+        self.get(x, y).unwrap_or_else(|| panic!("Coordinate {:?} out of range", (x, y)))
+    }
+}
+
+impl<T> std::ops::Index<[usize;2]> for Board<T> {
+    type Output = T;
+
+    fn index(&self, [x, y]: [usize;2]) -> &Self::Output {
+        self.get(x, y).unwrap_or_else(|| panic!("Coordinate {:?} out of range", (x, y)))
+    }
+}
+
+impl<T> std::ops::IndexMut<Coord> for Board<T> {
+    fn index_mut(&mut self, pos: Coord) -> &mut Self::Output {
+        self.get_mut(pos.x, pos.y).unwrap_or_else(|| panic!("Coordinate {:?} out of range", pos))
+    }
+}
+
+impl<T> std::ops::IndexMut<(usize, usize)> for Board<T> {
+    fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Self::Output {
+        self.get_mut(x, y).unwrap_or_else(|| panic!("Coordinate {:?} out of range", (x, y)))
+    }
+}
+
+impl<T> std::ops::IndexMut<[usize;2]> for Board<T> {
+    fn index_mut(&mut self, [x, y]: [usize;2]) -> &mut Self::Output {
+        self.get_mut(x, y).unwrap_or_else(|| panic!("Coordinate {:?} out of range", (x, y)))
+    }
+}

+ 1 - 1
ch2/src/main.rs

@@ -46,7 +46,7 @@ impl Motion {
 
 system_impl! {
     Draw(
-        resource mut board: carpet::Board<carpet::CP437>,
+        resource mut board: carpet::GameBoard<carpet::CP437>,
         renderable: Renderable,
         pos: Pos,
     ) {