Browse Source

Switch to parameterizing by tilesets

Getty Ritter 4 years ago
parent
commit
190c40ece0
3 changed files with 63 additions and 36 deletions
  1. 55 33
      carpet/src/lib.rs
  2. 1 1
      ch1/src/main.rs
  3. 7 2
      ch2/src/main.rs

+ 55 - 33
carpet/src/lib.rs

@@ -3,9 +3,6 @@ use ggez::graphics::{DrawParam, Drawable, Image};
 use ggez::{Context, GameError};
 use std::path::Path;
 
-/// we only care about 16x16 tilesets
-const TILE_SIZE: f32 = 1.0 / 16.0;
-
 #[derive(Eq, PartialEq, Debug, Copy, Clone)]
 pub enum Color {
     Red,
@@ -23,28 +20,51 @@ impl From<Color> for ggez::graphics::Color {
     }
 }
 
-pub struct Board {
+pub struct Board<Idx: Tile> {
     size: Size,
-    contents: Vec<(u8, SpriteIdx)>,
-    tileset: Tileset,
+    contents: Vec<(Idx, SpriteIdx)>,
+    tileset: Tileset<Idx>,
+}
+
+pub trait Tile: Copy {
+    fn to_location(self) -> [f32;4];
+    fn blank() -> Self;
 }
 
-pub struct Tileset {
+impl Tile for u8 {
+    fn to_location(self) -> [f32;4] {
+        const TILE_SIZE: f32 = 1.0 / 16.0;
+        let u = f32::from(self % 16) * TILE_SIZE;
+        let v = f32::from(self / 16) * TILE_SIZE;
+        [u, v, TILE_SIZE, TILE_SIZE]
+    }
+
+    fn blank() -> Self {
+        0
+    }
+}
+
+pub struct Tileset<Idx: Tile> {
     tile_size: Size,
     batch: SpriteBatch,
+    idx: std::marker::PhantomData<Idx>,
 }
 
-impl Tileset {
+impl<Idx: Tile> Tileset<Idx> {
     pub fn from_file(
         ctx: &mut Context,
         tile_size: impl Into<Size>,
         file: impl AsRef<Path>,
-    ) -> Result<Tileset, GameError> {
+    ) -> Result<Tileset<Idx>, GameError> {
         let tile_size = tile_size.into();
         let image = Image::new(ctx, file)?;
         let mut batch = SpriteBatch::new(image);
         batch.set_filter(ggez::graphics::FilterMode::Nearest);
-        Ok(Tileset { tile_size, batch })
+        Ok(Tileset {
+            tile_size,
+            batch,
+            idx: std::marker::PhantomData,
+        })
     }
 
     fn to_screen(&self, coord: impl Into<Coord>) -> [f32; 2] {
@@ -80,17 +100,17 @@ impl From<[usize; 2]> for Coord {
     }
 }
 
-impl Board {
-    pub fn new(size: impl Into<Size>, mut tileset: Tileset) -> Board {
+impl<Idx: Tile> Board<Idx> {
+    pub fn new(size: impl Into<Size>, mut tileset: Tileset<Idx>) -> Board<Idx> {
         let size = size.into();
         let mut contents = Vec::new();
         for y in 0..size.height {
             for x in 0..size.width {
                 let param = DrawParam::new()
-                    .src(Board::sprite_location(0u8).into())
+                    .src(Idx::blank().to_location().into())
                     .dest(tileset.to_screen([x, y]));
                 let idx = tileset.batch.add(param);
-                contents.push((0u8, idx));
+                contents.push((Idx::blank(), idx));
             }
         }
         Board {
@@ -100,21 +120,21 @@ impl Board {
         }
     }
 
-    fn sprite_location(ch: u8) -> [f32; 4] {
-        let u = f32::from(ch % 16) * TILE_SIZE;
-        let v = f32::from(ch / 16) * TILE_SIZE;
-        [u, v, TILE_SIZE, TILE_SIZE]
-    }
+    // fn sprite_location(ch: u8) -> [f32; 4] {
+    //     let u = f32::from(ch % 16) * TILE_SIZE;
+    //     let v = f32::from(ch / 16) * TILE_SIZE;
+    //     [u, v, TILE_SIZE, TILE_SIZE]
+    // }
 
     pub fn draw(&self, ctx: &mut Context) -> Result<(), ggez::GameError> {
         self.tileset.batch.draw(ctx, DrawParam::new())
     }
 
-    pub fn set(&mut self, at: impl Into<Coord>, ch: u8) {
+    pub fn set(&mut self, at: impl Into<Coord>, ch: Idx) {
         let at = at.into();
         let idx = at.x + at.y * self.size.width;
         let param = DrawParam::new()
-            .src(Board::sprite_location(ch).into())
+            .src(ch.to_location().into())
             .dest(self.tileset.to_screen(at));
         self.tileset.batch.set(self.contents[idx].1, param).unwrap();
     }
@@ -122,40 +142,42 @@ impl Board {
     pub fn set_with_color(
         &mut self,
         at: impl Into<Coord>,
-        ch: u8,
+        ch: Idx,
         color: impl Into<ggez::graphics::Color>,
     ) {
         let at = at.into();
         let idx = at.x + at.y * self.size.width;
         let param = DrawParam::new()
-            .src(Board::sprite_location(ch).into())
+            .src(ch.to_location().into())
             .dest(self.tileset.to_screen(at))
             .color(color.into());
         self.tileset.batch.set(self.contents[idx].1, param).unwrap();
     }
 
-    pub fn get(&mut self, at: impl Into<Coord>) -> u8 {
+    pub fn get(&mut self, at: impl Into<Coord>) -> Idx {
         let at = at.into();
         let idx = at.x + at.y * self.size.width;
         self.contents[idx].0
     }
 
-    pub fn print(&mut self, at: impl Into<Coord>, msg: &str) {
-        let Coord { x, y } = at.into();
-        for (idx, ch) in msg.chars().enumerate() {
-            self.set([idx + x, y], ch as u8);
-        }
-    }
-
     pub fn clear(&mut self) {
         for (n, contents) in self.contents.iter_mut().enumerate() {
             let x = n % self.size.width;
             let y = n / self.size.width;
             let param = DrawParam::new()
-                .src(Board::sprite_location(0).into())
+                .src(Idx::blank().to_location().into())
                 .dest(self.tileset.to_screen([x, y]));
-            contents.0 = 0;
+            contents.0 = Idx::blank();
             self.tileset.batch.set(contents.1, param).unwrap();
         }
     }
 }
+
+impl Board<u8> {
+    pub fn print(&mut self, at: impl Into<Coord>, msg: &str) {
+        let Coord { x, y } = at.into();
+        for (idx, ch) in msg.chars().enumerate() {
+            self.set([idx + x, y], ch as u8);
+        }
+    }
+}

+ 1 - 1
ch1/src/main.rs

@@ -1,7 +1,7 @@
 use ggez::{event::EventHandler, Context, GameError};
 
 struct State {
-    board: carpet::Board,
+    board: carpet::Board<u8>,
 }
 
 impl EventHandler for State {

+ 7 - 2
ch2/src/main.rs

@@ -20,7 +20,7 @@ pub struct Renderable {
 
 system_impl! {
     Draw(
-        resource mut board: carpet::Board,
+        resource mut board: carpet::Board<u8>,
         renderable: Renderable,
         pos: Pos,
     ) {
@@ -54,7 +54,7 @@ struct State {
 impl EventHandler for State {
     fn draw(&mut self, ctx: &mut Context) -> Result<(), GameError> {
         ggez::graphics::clear(ctx, ggez::graphics::BLACK);
-        self.world.fetch::<carpet::Board>().draw(ctx)?;
+        self.world.fetch::<carpet::Board<u8>>().draw(ctx)?;
         ggez::graphics::present(ctx)
     }
 
@@ -113,3 +113,8 @@ fn main() -> Result<(), GameError> {
     let mut state = State { world };
     ggez::event::run(&mut ctx, &mut evloop, &mut state)
 }
+
+// Local Variables:
+// cargo-process--command-build: "build --release"
+// cargo-process--command-run: "run --release --bin ch2"
+// End: