Browse Source

Allow registering update callback

Getty Ritter 4 years ago
parent
commit
fb8a28257d
2 changed files with 48 additions and 25 deletions
  1. 32 1
      carpet/src/lib.rs
  2. 16 24
      ch2/src/main.rs

+ 32 - 1
carpet/src/lib.rs

@@ -213,18 +213,25 @@ impl Board<CP437> {
     }
 }
 
-
+type Updater = Box<dyn FnMut(&mut specs::World)>;
 pub struct World<Idx> {
     pub world: specs::World,
+    updater: Updater,
     idx: std::marker::PhantomData<Idx>,
 }
 
+fn do_nothing() -> Updater {
+    Box::new(|_| {})
+}
+
 impl <Idx: Tile + 'static> World<Idx> {
     pub fn new(board: Board<Idx>) -> World<Idx> {
         let mut world = specs::World::new();
         world.insert(board);
+        let updater = do_nothing();
         World {
             world,
+            updater,
             idx: std::marker::PhantomData,
         }
     }
@@ -246,6 +253,10 @@ impl <Idx: Tile + 'static> World<Idx> {
     pub fn get(&self, at: impl Into<Coord>) -> Idx {
         self.world.fetch::<Board<Idx>>().get(at)
     }
+
+    pub fn on_update(&mut self, update: impl FnMut(&mut specs::World) + 'static) {
+        self.updater = Box::new(update) as Updater;
+    }
 }
 
 impl World<CP437> {
@@ -262,6 +273,10 @@ impl<Idx: 'static + Tile> ggez::event::EventHandler for World<Idx> {
     }
 
     fn update(&mut self, _ctx: &mut Context) -> Result<(), ggez::GameError> {
+        let mut updater = do_nothing();
+        std::mem::swap(&mut updater, &mut self.updater);
+        updater(&mut self.world);
+        std::mem::swap(&mut updater, &mut self.updater);
         Ok(())
     }
 }
@@ -285,10 +300,26 @@ impl<Idx: Tile + 'static> Game<Idx> {
         })
     }
 
+    pub fn register<C>(&mut self)
+        where C: specs::Component, <C as specs::Component>::Storage: std::default::Default
+    {
+        self.world.world.register::<C>();
+    }
+
+    pub fn insert(&mut self, r: impl specs::prelude::Resource) {
+        self.world.world.insert(r);
+    }
+
     pub fn run(self) -> ggez::GameResult<()> {
         let Game { mut world, mut ctx, mut evloop } = self;
         ggez::event::run(&mut ctx, &mut evloop, &mut world)
     }
+
+    pub fn run_with_systems(self, update: impl FnMut(&mut specs::World) + 'static) -> ggez::GameResult<()> {
+        let Game { mut world, mut ctx, mut evloop } = self;
+        world.on_update(update);
+        ggez::event::run(&mut ctx, &mut evloop, &mut world)
+    }
 }
 
 

+ 16 - 24
ch2/src/main.rs

@@ -59,35 +59,29 @@ impl EventHandler for State {
     }
 
     fn update(&mut self, _ctx: &mut Context) -> Result<(), GameError> {
-        Draw.run_now(&mut self.world);
-        Leftward.run_now(&mut self.world);
         Ok(())
     }
 }
 
 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 mut world = World::new();
-    world.register::<Pos>();
-    world.register::<Renderable>();
-    world.register::<MoveLeft>();
-    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!");
+    game.register::<Pos>();
+    game.register::<Renderable>();
+    game.register::<MoveLeft>();
+    game.world.print([1, 1], "Hello, world!");
 
-    world
+    game.world.world
         .create_entity()
         .with(Pos { x: 40, y: 25 })
         .with(Renderable {
@@ -97,7 +91,7 @@ fn main() -> Result<(), GameError> {
         .build();
 
     for i in 0..10 {
-        world
+        game.world.world
             .create_entity()
             .with(Pos { x: i * 7, y: 20 })
             .with(Renderable {
@@ -107,13 +101,11 @@ fn main() -> Result<(), GameError> {
             .with(MoveLeft)
             .build();
     }
-
-    world.insert(board);
-
-    let mut state = State { world };
-    ggez::event::run(&mut ctx, &mut evloop, &mut state)
+    game.run_with_systems(|world| {
+        Draw.run_now(&world);
+        Leftward.run_now(&world);
+    })
 }
-
 // Local Variables:
 // cargo-process--command-build: "build --release"
 // cargo-process--command-run: "run --release --bin ch2"