Browse Source

Start to introduce a CP437 abstraction instead of using u8

Getty Ritter 4 years ago
parent
commit
4145236364
3 changed files with 55 additions and 19 deletions
  1. 49 13
      carpet/src/lib.rs
  2. 1 1
      ch1/src/main.rs
  3. 5 5
      ch2/src/main.rs

+ 49 - 13
carpet/src/lib.rs

@@ -20,30 +20,66 @@ impl From<Color> for ggez::graphics::Color {
     }
 }
 
-pub struct Board<Idx: Tile> {
-    size: Size,
-    contents: Vec<(Idx, SpriteIdx)>,
-    tileset: Tileset<Idx>,
-}
 
-pub trait Tile: Copy {
+/// The `Tile` trait is used to identify which tile we care about on a
+/// tilesheet, and also to provide a sensible 'blank' tile. The tile
+/// identifiers we care about should at least be `Clone`, but often
+/// they'll be (wrappers over) small identifiers (like a `u8` or a
+/// `u16`) and could probably be `Copy`.
+pub trait Tile: Clone {
     fn to_location(self) -> [f32;4];
     fn blank() -> Self;
 }
 
-impl Tile for u8 {
+/// This represents a character from DOS codepage 437
+#[derive(Debug, Copy, Clone)]
+pub struct CP437(u8);
+
+impl CP437 {
+    pub fn from_u8(ch: u8) -> CP437 {
+        CP437(ch)
+    }
+
+    pub fn from_char(ch: char) -> CP437 {
+        CP437(match ch as u32 {
+            // happy faces
+            0x263A => 1,
+            0x263B => 2,
+            // card suits
+            0x2665 => 3,
+            0x2666 => 4,
+            0x2663 => 5,
+            0x2660 => 6,
+            0x2022 => 7,
+            // fill this in some time later
+            // standard ASCII mappings
+            0x20 ..= 0x7e => ch as u8,
+            0x2302 => 0x7f,
+            _ => panic!("Character {} does not have a CP437 equivalent", ch),
+        })
+    }
+}
+
+impl Tile for CP437 {
     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;
+        let u = f32::from(self.0 % 16) * TILE_SIZE;
+        let v = f32::from(self.0 / 16) * TILE_SIZE;
         [u, v, TILE_SIZE, TILE_SIZE]
     }
 
     fn blank() -> Self {
-        0
+        CP437(0)
     }
 }
 
+
+pub struct Board<Idx: Tile> {
+    size: Size,
+    contents: Vec<(Idx, SpriteIdx)>,
+    tileset: Tileset<Idx>,
+}
+
 pub struct Tileset<Idx: Tile> {
     tile_size: Size,
     batch: SpriteBatch,
@@ -157,7 +193,7 @@ impl<Idx: Tile> Board<Idx> {
     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
+        self.contents[idx].0.clone()
     }
 
     pub fn clear(&mut self) {
@@ -173,11 +209,11 @@ impl<Idx: Tile> Board<Idx> {
     }
 }
 
-impl Board<u8> {
+impl Board<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() {
-            self.set([idx + x, y], ch as u8);
+            self.set([idx + x, y], CP437::from_char(ch));
         }
     }
 }

+ 1 - 1
ch1/src/main.rs

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

+ 5 - 5
ch2/src/main.rs

@@ -14,13 +14,13 @@ pub struct Pos {
 
 #[derive(Component)]
 pub struct Renderable {
-    glyph: u8,
+    glyph: carpet::CP437,
     color: carpet::Color,
 }
 
 system_impl! {
     Draw(
-        resource mut board: carpet::Board<u8>,
+        resource mut board: carpet::Board<carpet::CP437>,
         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<u8>>().draw(ctx)?;
+        self.world.fetch::<carpet::Board<carpet::CP437>>().draw(ctx)?;
         ggez::graphics::present(ctx)
     }
 
@@ -91,7 +91,7 @@ fn main() -> Result<(), GameError> {
         .create_entity()
         .with(Pos { x: 40, y: 25 })
         .with(Renderable {
-            glyph: 'A' as u8,
+            glyph: carpet::CP437::from_char('A'),
             color: carpet::Color::Blue,
         })
         .build();
@@ -101,7 +101,7 @@ fn main() -> Result<(), GameError> {
             .create_entity()
             .with(Pos { x: i * 7, y: 20 })
             .with(Renderable {
-                glyph: 'X' as u8,
+                glyph: carpet::CP437::from_char('X'),
                 color: carpet::Color::Red,
             })
             .with(MoveLeft)