Browse Source

Chapter 21 working in WASM land.

Herbert Wolverson 4 years ago
parent
commit
ffbb9fee71

+ 2 - 0
Cargo.lock

@@ -384,6 +384,8 @@ dependencies = [
  "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "specs 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "specs-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasm-bindgen 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "web-sys 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]

+ 14 - 3
book/src/chapter_21.md

@@ -26,22 +26,33 @@ We'll introduce a new file, `rex_assets.rs` to store our REX sprites. The file l
 
 ```rust
 use rltk::{rex::XpFile};
-use std::fs::File;
+
+rltk::embedded_resource!(SMALL_DUNGEON, "../../resources/SmallDungeon_80x50.xp");
 
 pub struct RexAssets {
     pub menu : XpFile
 }
 
 impl RexAssets {
+    #[allow(clippy::new_without_default)]
     pub fn new() -> RexAssets {
+        rltk::link_resource!(SMALL_DUNGEON, "../../resources/SmallDungeon_80x50.xp");
+
         RexAssets{
-            menu : XpFile::read(&mut File::open("../resources/SmallDungeon_80x50.xp").unwrap()).unwrap()
+            menu : XpFile::from_resource("../../resources/SmallDungeon_80x50.xp").unwrap()
         }
     }
 }
 ```
 
-Very simple - it defines a structure, and loads the dungeon graphic into it when `new` is called. We'll also insert it into Specs as a resource so we can access our sprites anywhere. In `main.rs`:
+Very simple - it defines a structure, and loads the dungeon graphic into it when `new` is called. We'll also insert it into Specs as a resource so we can access our sprites anywhere. There are some new concepts here:
+
+1. We're using `rltk::embedded_resource!` to include the file in our binary. This gets around having to ship the binary with your executable (and makes life easier in `wasm` land).
+2. `#[allow(clippy::new_without_default)]` tells the linter to stop telling me to write a default implementation, when we don't need one!
+3. `rltk::link_resource!` is the second-half the the embedded resource; the first stores it in memory, this one tells RLTK where to find it.
+4. `menu : XpFile::from_resource("../../resources/SmallDungeon_80x50.xp").unwrap()` loads the Rex paint file from memory.
+
+In `main.rs`:
 
 ```rust
 gs.ecs.insert(rex_assets::RexAssets::new());

+ 4 - 0
chapter-21-rexmenu/Cargo.toml

@@ -12,3 +12,7 @@ specs = { version = "0.15.0", features = ["serde"] }
 specs-derive = "0.4.0"
 serde= { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
+
+[target.'cfg(any(target_arch = "wasm32"))'.dependencies]
+web-sys = { version = "0.3", features=["console"] }
+wasm-bindgen = "0.2"

+ 37 - 20
chapter-21-rexmenu/src/main.rs

@@ -35,6 +35,8 @@ pub mod particle_system;
 pub mod hunger_system;
 pub mod rex_assets;
 
+rltk::add_wasm_support!();
+
 #[derive(PartialEq, Copy, Clone)]
 pub enum RunState { AwaitingInput, 
     PreRun, 
@@ -52,8 +54,36 @@ pub enum RunState { AwaitingInput,
 }
 
 pub struct State {
-    pub ecs: World,
-    pub systems: Dispatcher<'static, 'static>
+    pub ecs: World
+}
+
+impl State {
+    fn run_systems(&mut self) {
+        let mut mapindex = MapIndexingSystem{};
+        mapindex.run_now(&self.ecs);
+        let mut vis = VisibilitySystem{};
+        vis.run_now(&self.ecs);
+        let mut mob = MonsterAI{};
+        mob.run_now(&self.ecs);
+        let mut melee = MeleeCombatSystem{};
+        melee.run_now(&self.ecs);
+        let mut damage = DamageSystem{};
+        damage.run_now(&self.ecs);
+        let mut pickup = ItemCollectionSystem{};
+        pickup.run_now(&self.ecs);
+        let mut itemuse = ItemUseSystem{};
+        itemuse.run_now(&self.ecs);
+        let mut drop_items = ItemDropSystem{};
+        drop_items.run_now(&self.ecs);
+        let mut item_remove = ItemRemoveSystem{};
+        item_remove.run_now(&self.ecs);
+        let mut hunger = hunger_system::HungerSystem{};
+        hunger.run_now(&self.ecs);
+        let mut particles = particle_system::ParticleSpawnSystem{};
+        particles.run_now(&self.ecs);
+
+        self.ecs.maintain();
+    }
 }
 
 impl GameState for State {
@@ -88,7 +118,7 @@ impl GameState for State {
         
         match newrunstate {
             RunState::PreRun => {
-                self.systems.dispatch(&self.ecs);
+                self.run_systems();
                 self.ecs.maintain();
                 newrunstate = RunState::AwaitingInput;
             }
@@ -96,7 +126,7 @@ impl GameState for State {
                 newrunstate = player_input(self, ctx);
             }
             RunState::PlayerTurn => {
-                self.systems.dispatch(&self.ecs);
+                self.run_systems();
                 self.ecs.maintain();
                 match *self.ecs.fetch::<RunState>() {
                     RunState::MagicMapReveal{ .. } => newrunstate = RunState::MagicMapReveal{ row: 0 },
@@ -104,7 +134,7 @@ impl GameState for State {
                 }                
             }
             RunState::MonsterTurn => {
-                self.systems.dispatch(&self.ecs);
+                self.run_systems();
                 self.ecs.maintain();
                 newrunstate = RunState::AwaitingInput;
             }
@@ -361,23 +391,10 @@ impl State {
 }
 
 fn main() {
-    let mut context = Rltk::init_simple8x8(80, 50, "Hello Rust World", "../resources");
+    let mut context = Rltk::init_simple8x8(80, 50, "Hello Rust World", "resources");
     context.with_post_scanlines(true);
     let mut gs = State {
-        ecs: World::new(),
-        systems : DispatcherBuilder::new()
-            .with(MapIndexingSystem{}, "map_indexing_system", &[])
-            .with(VisibilitySystem{}, "visibility_system", &[])
-            .with(MonsterAI{}, "monster_ai", &["visibility_system", "map_indexing_system"])
-            .with(MeleeCombatSystem{}, "melee_combat", &["monster_ai"])
-            .with(DamageSystem{}, "damage", &["melee_combat"])
-            .with(ItemCollectionSystem{}, "pickup", &["melee_combat"])
-            .with(ItemUseSystem{}, "potions", &["melee_combat"])
-            .with(ItemDropSystem{}, "drop_items", &["melee_combat"])
-            .with(ItemRemoveSystem{}, "remove_items", &["melee_combat"])
-            .with(hunger_system::HungerSystem{}, "hunger", &["melee_combat", "potions"])
-            .with(particle_system::ParticleSpawnSystem{}, "spawn_particles", &["potions", "melee_combat"])
-            .build(),
+        ecs: World::new()
     };
     gs.ecs.register::<Position>();
     gs.ecs.register::<Renderable>();

+ 6 - 2
chapter-21-rexmenu/src/rex_assets.rs

@@ -1,14 +1,18 @@
 use rltk::{rex::XpFile};
-use std::fs::File;
+
+rltk::embedded_resource!(SMALL_DUNGEON, "../../resources/SmallDungeon_80x50.xp");
 
 pub struct RexAssets {
     pub menu : XpFile
 }
 
 impl RexAssets {
+    #[allow(clippy::new_without_default)]
     pub fn new() -> RexAssets {
+        rltk::link_resource!(SMALL_DUNGEON, "../../resources/SmallDungeon_80x50.xp");
+
         RexAssets{
-            menu : XpFile::read(&mut File::open("../resources/SmallDungeon_80x50.xp").unwrap()).unwrap()
+            menu : XpFile::from_resource("../../resources/SmallDungeon_80x50.xp").unwrap()
         }
     }
 }

+ 6 - 1
chapter-21-rexmenu/src/saveload_system.rs

@@ -20,6 +20,11 @@ macro_rules! serialize_individually {
     };
 }
 
+#[cfg(target_arch = "wasm32")]
+pub fn save_game(_ecs : &mut World) {
+}
+
+#[cfg(not(target_arch = "wasm32"))]
 pub fn save_game(ecs : &mut World) {
     // Create helper
     let mapcopy = ecs.get_mut::<super::map::Map>().unwrap().clone();
@@ -56,7 +61,7 @@ macro_rules! deserialize_individually {
         $(
         DeserializeComponents::<NoError, _>::deserialize(
             &mut ( &mut $ecs.write_storage::<$type>(), ),
-            &mut $data.0, // entities
+            &$data.0, // entities
             &mut $data.1, // marker
             &mut $data.2, // allocater
             &mut $de,

+ 1 - 0
wasmbuild.bat

@@ -19,6 +19,7 @@ CALL :Stage chapter-17-blood
 CALL :Stage chapter-18-particles
 CALL :Stage chapter-19-food
 CALL :Stage chapter-20-magicmapping
+CALL :Stage chapter-21-rexmenu
 
 REM Publish or perish
 cd book\book\wasm