Browse Source

Wrap a full abstraction around ggez

Getty Ritter 4 years ago
parent
commit
519b78d36c
2 changed files with 117 additions and 29 deletions
  1. 109 17
      carpet/src/lib.rs
  2. 8 12
      ch1/src/main.rs

+ 109 - 17
carpet/src/lib.rs

@@ -157,12 +157,6 @@ impl<Idx: Tile> Board<Idx> {
         }
     }
 
-    // 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())
     }
@@ -220,23 +214,20 @@ impl Board<CP437> {
 }
 
 
-
-pub struct Game<Idx> {
+pub struct World<Idx> {
     pub world: specs::World,
     idx: std::marker::PhantomData<Idx>,
 }
 
-
-impl<Idx: Tile + 'static> Game<Idx> {
-    pub fn create(_name: &str, _author: &str, board: Board<Idx>) -> Result<Game<Idx>, ggez::GameError> {
+impl <Idx: Tile + 'static> World<Idx> {
+    pub fn new(board: Board<Idx>) -> World<Idx> {
         let mut world = specs::World::new();
         world.insert(board);
-        Ok(Game {
+        World {
             world,
             idx: std::marker::PhantomData,
-        })
+        }
     }
-
     pub fn set(&mut self, at: impl Into<Coord>, ch: Idx) {
         self.world.fetch_mut::<Board<Idx>>().set(at, ch)
     }
@@ -257,14 +248,13 @@ impl<Idx: Tile + 'static> Game<Idx> {
     }
 }
 
-impl Game<CP437> {
+impl World<CP437> {
     pub fn print(&mut self, at: impl Into<Coord>, msg: &str) {
         self.world.fetch_mut::<Board<CP437>>().print(at, msg)
     }
 }
 
-
-impl<Idx: 'static + Tile> ggez::event::EventHandler for Game<Idx> {
+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)?;
@@ -275,3 +265,105 @@ impl<Idx: 'static + Tile> ggez::event::EventHandler for Game<Idx> {
         Ok(())
     }
 }
+
+//
+
+pub struct Game<Idx> {
+    pub ctx: ggez::Context,
+    pub evloop: ggez::event::EventsLoop,
+    pub world: World<Idx>,
+}
+
+
+impl<Idx: Tile + 'static> Game<Idx> {
+    pub fn create(board: Board<Idx>, ctx: ggez::Context, evloop: ggez::event::EventsLoop) -> Result<Game<Idx>, ggez::GameError> {
+        let world = World::new(board);
+        Ok(Game {
+            world,
+            ctx,
+            evloop,
+        })
+    }
+
+    pub fn run(self) -> ggez::GameResult<()> {
+        let Game { mut world, mut ctx, mut evloop } = self;
+        ggez::event::run(&mut ctx, &mut evloop, &mut world)
+    }
+}
+
+
+// game builder
+use std::path::PathBuf;
+
+pub struct GameBuilder<Idx: Tile> {
+    name: String,
+    author: String,
+    resource_path: Option<PathBuf>,
+    tile_size: Option<[usize;2]>,
+    tile_path: Option<PathBuf>,
+    map_size: Option<[usize;2]>,
+    idx: std::marker::PhantomData<Idx>,
+}
+
+impl<Idx: Tile + 'static> GameBuilder<Idx> {
+    pub fn new() -> GameBuilder<Idx> {
+        GameBuilder {
+            name: "Carpet Game".to_owned(),
+            author: "unknown author".to_owned(),
+            resource_path: None,
+            tile_size: None,
+            tile_path: None,
+            map_size: None,
+            idx: std::marker::PhantomData,
+        }
+    }
+
+    pub fn name(mut self, name: impl Into<String>) -> GameBuilder<Idx> {
+        self.name = name.into();
+        self
+    }
+
+    pub fn author(mut self, author: impl Into<String>) -> GameBuilder<Idx> {
+        self.author = author.into();
+        self
+    }
+
+    pub fn resource_path(mut self, path: impl AsRef<Path>) -> GameBuilder<Idx> {
+        self.resource_path = Some(path.as_ref().to_path_buf());
+        self
+    }
+
+    pub fn tileset(mut self, image: impl AsRef<Path>, size: impl Into<[usize;2]>) -> GameBuilder<Idx> {
+        self.tile_path = Some(image.as_ref().to_path_buf());
+        self.tile_size = Some(size.into());
+        self
+    }
+
+    pub fn map_size(mut self, width: usize, height: usize) -> GameBuilder<Idx> {
+        self.map_size = Some([width, height]);
+        self
+    }
+
+    pub fn build(self) -> ggez::GameResult<Game<Idx>> {
+        use ggez::error::GameError::ResourceLoadError;
+        let resource_path = self.resource_path
+            .ok_or_else(|| ResourceLoadError("No resource path specified".to_owned()))?;
+        let tile_path = self.tile_path
+            .ok_or_else(|| ResourceLoadError("No tile path specified".to_owned()))?;
+        let tile_size = self.tile_size
+            .ok_or_else(|| ResourceLoadError("No tile size specified".to_owned()))?;
+        let map_size = self.map_size
+            .ok_or_else(|| ResourceLoadError("No map size specified".to_owned()))?;
+        let (mut ctx, evloop) = ggez::ContextBuilder::new(&self.name, &self.author)
+            .add_resource_path(resource_path)
+            .window_mode(ggez::conf::WindowMode {
+                width: (tile_size[0] * map_size[0]) as f32,
+                height: (tile_size[1] * map_size[1]) as f32,
+                ..ggez::conf::WindowMode::default()
+            })
+            .build()?;
+        let tileset = Tileset::from_file(&mut ctx, tile_size, tile_path)?;
+        let board = Board::new(map_size, tileset);
+        Game::create(board, ctx, evloop)
+    }
+}

+ 8 - 12
ch1/src/main.rs

@@ -1,22 +1,18 @@
 use ggez::GameError;
 
 fn main() -> Result<(), GameError> {
-    let (mut ctx, mut evloop) = ggez::ContextBuilder::new("game", "me")
-        .add_resource_path({
+    let mut game = carpet::GameBuilder::new()
+        .name("game")
+        .author("me")
+        .resource_path({
             let base = std::env::var("CARGO_MANIFEST_DIR").unwrap();
             let mut path = std::path::PathBuf::from(base);
             path.push("resources");
             path
         })
-        .window_mode(ggez::conf::WindowMode {
-            width: 80.0 * 8.0,
-            height: 50.0 * 8.0,
-            ..ggez::conf::WindowMode::default()
-        })
+        .tileset("/terminal8x8.jpg", [8, 8])
+        .map_size(80, 50)
         .build()?;
-    let tileset = carpet::Tileset::from_file(&mut ctx, [8, 8], "/terminal8x8.jpg")?;
-    let mut board = carpet::Board::new([80, 50], tileset);
-    board.print([1, 1], "Hello, world!");
-    let mut game = carpet::Game::create("game", "me", board)?;
-    ggez::event::run(&mut ctx, &mut evloop, &mut game)
+    game.world.print([1, 1], "Hello, world!");
+    game.run()
 }