kaka.farm

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit ba321fa413b820edce1ccd992db373021fc700c8
parent 772fedb8f9952e6fec050d1fdd8c6889318f0ff0
Author: Yuval Langer <yuval.langer@gmail.com>
Date:   Fri, 19 Jan 2024 08:13:39 +0200

Move an historically useful post into the published area.

Diffstat:
Dcommonly-forgotten/content/2019-06-12-making-quicksilver-and-friends-play-nice-with-wasm32.md | 189-------------------------------------------------------------------------------
Aposts/2019-06-12-making-quicksilver-and-friends-play-nice-with-wasm32.md | 186+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 186 insertions(+), 189 deletions(-)

diff --git a/commonly-forgotten/content/2019-06-12-making-quicksilver-and-friends-play-nice-with-wasm32.md b/commonly-forgotten/content/2019-06-12-making-quicksilver-and-friends-play-nice-with-wasm32.md @@ -1,189 +0,0 @@ ---- -title: Making Quicksilver and friends play nice with wasm32. -published_date: "2019-06-12 20:23:48 +0000" -layout: default.liquid -is_draft: false ---- -## Disclaimer: - -This technology is indistinguishable from magic. I am merely recalling which - spells and incantations worked for me. If you have anything to add, you can - reach me on <https://gitgud.io/yuvallanger/kaka.farm/> or - <https://gitlab.com/yuvallanger/kaka.farm/>. - -Several months ago, writing a Flappy Bird clone called [Rectangly -Rect](https://gitgud.io/yuvallanger/rectangly-rect/), I have done a bunch of -asking around and found exactly which parts don't work and how to replace them. -Yesterday, trying to adapt YasamSim to the web, I have re-discovered those -workarounds, and decided to write this down. - -## `println!`! - -First thing, drop all of your `println!`s. For some esoteric reason, this -function throws a wrench into the web's machinery. Same goes for -`std::time::Instance::now()`. For now I just dropped all calls to `now()`, -maybe I could ask the browser manually with whatever function Javascript has, -or maybe there is a more standardized `std` alternative for the web - I don't -know. - -In order to replace `println!`, I had to add to `Cargo.toml` a general -dependency for the crate `log`, an entry for every target that is not wasm32 -for the crate `env_logger`, and an entry for the crate `web_logger` for the -wasm32 target: - -```Cargo.toml -[dependencies] -log = "0.4" - -[target.'cfg(not(wasm32))'.dependencies] -env_logger = "0.6" - -[target.'cfg(wasm32)'.dependencies] -web_logger = "0.1" -``` - -In `src/logging.rs`, conditionally compile a different `init_logger()` function -for each platform, wasm32 and not-wasm32: - -```src/logging.rs -#[cfg(target_arch = "wasm32")] -pub fn init_logger() { - ::web_logger::init(); -} - -#[cfg(not(target_arch = "wasm32"))] -pub fn init_logger() { - ::env_logger::init(); -} -``` - -In `src/main.rs`, call the `init_logger()` defined in the `logging.rs` -sub-module at the head of your `main()` function: - -```src/main.rs -mod logging; - -fn main() { - logging::init_logger(); - … -} -``` - -Now you can call `info!()`, `error!()`, `warn!()`, etc., as described in <https://docs.rs/log/0.4/log/>. - -If you also debug it in your native target, you can also provide the `RUST_LOG` -environment variable, as per <https://docs.rs/env_logger/0.6/env_logger/>'s -documentation, in your command line incantations: - -``` -$ RUST_LOG=DEBUG cargo run -``` - -## Sequentialize SPECS. - -For some more esoteric reasons, probably something to do with threads, I had to -rewrite how I run my `specs::System`s , and -how `specs::System`s written. - -### Dispatching `specs::Dispatcher`. - -One normally builds a dependency graph of `specs::System`s using something -like: - -```src/main.rs -fn make_specs_dispatcher() -> specs::Dispatcher<'static, 'static> { - specs::DispatcherBuilder::new() - .with( - SystemFoo, - "system_foo", - &[], - ) - .with( - SystemBar, - "system_bar", - &["system_foo"], - ) - .build() -} - -struct OurGameState { - specs_world: specs::World, - specs_dispatcher: specs::Dispatcher, -} - - -impl State for OurGameState { - fn new() -> Result<World> { - let specs_world = make_specs_world_and_register_components(); // Implemented elsewhere… - let specs_dispatcher = make_specs_dispatcher(); - - Ok( - OurGameState { - specs_world, - specs_dispatcher, - } - ) - } - - fn update(&mut self, window: &mut Window) -> Result<()> { - let system_foo = SystemFoo; - let system_bar = SystemBar; - - system_foo.run_now(&selfworld.res); - system_bar.run_now(&world.res); - - world.maintain(); - - Ok(()) - } - - [imagine the rest of the quicksilver::lifecycle::State methods implemented here…] -} -``` - -In this example `SystemBar` depends on the state of the `specs::World` left by -`SystemFoo` after it does its thing. - -Instead of using this `Dispatcher` as described in -<https://slide-rs.github.io/specs/03_dispatcher.html>, you do this in your -`quicksilver::lifecycle::State::update()` - -``` -struct OurGameState { - specs_world: specs::World, -} - -impl State for OurGameState { - fn new() -> Result<World> { - let specs_world = make_specs_world_and_register_components(); // Implemented elsewhere… - - Ok( - OurGameState { - specs_world, - } - ) - } - - fn update(&mut self, window: &mut Window) -> Result<()> { - let system_foo = SystemFoo; - let system_bar = SystemBar; - - system_foo.run_now(&selfworld.res); - system_bar.run_now(&world.res); - - world.maintain(); - - Ok(()) - } - - [imagine the rest of the quicksilver::lifecycle::State methods implemented here…] -} -``` - -But in order to sequentialize how you deal with `specs`, you'd need to change one more thing: - -### Lay off `specs::LazyUpdater`. - -If you do anything with `specs::LazyUpdate`, you would have to convert it into -another form, interacting with your `Component` `Storage`s directly with -`WriteStorage` or whatever. diff --git a/posts/2019-06-12-making-quicksilver-and-friends-play-nice-with-wasm32.md b/posts/2019-06-12-making-quicksilver-and-friends-play-nice-with-wasm32.md @@ -0,0 +1,186 @@ +title: Making Quicksilver and friends play nice with wasm32. +date: 2019-06-12 20:23:48 +--- +## Disclaimer: + +This technology is indistinguishable from magic. I am merely recalling which + spells and incantations worked for me. If you have anything to add, you can + reach me on <https://gitgud.io/yuvallanger/kaka.farm/> or + <https://gitlab.com/yuvallanger/kaka.farm/>. + +Several months ago, writing a Flappy Bird clone called [Rectangly +Rect](https://gitgud.io/yuvallanger/rectangly-rect/), I have done a bunch of +asking around and found exactly which parts don't work and how to replace them. +Yesterday, trying to adapt YasamSim to the web, I have re-discovered those +workarounds, and decided to write this down. + +## `println!`! + +First thing, drop all of your `println!`s. For some esoteric reason, this +function throws a wrench into the web's machinery. Same goes for +`std::time::Instance::now()`. For now I just dropped all calls to `now()`, +maybe I could ask the browser manually with whatever function Javascript has, +or maybe there is a more standardized `std` alternative for the web - I don't +know. + +In order to replace `println!`, I had to add to `Cargo.toml` a general +dependency for the crate `log`, an entry for every target that is not wasm32 +for the crate `env_logger`, and an entry for the crate `web_logger` for the +wasm32 target: + +```Cargo.toml +[dependencies] +log = "0.4" + +[target.'cfg(not(wasm32))'.dependencies] +env_logger = "0.6" + +[target.'cfg(wasm32)'.dependencies] +web_logger = "0.1" +``` + +In `src/logging.rs`, conditionally compile a different `init_logger()` function +for each platform, wasm32 and not-wasm32: + +```src/logging.rs +#[cfg(target_arch = "wasm32")] +pub fn init_logger() { + ::web_logger::init(); +} + +#[cfg(not(target_arch = "wasm32"))] +pub fn init_logger() { + ::env_logger::init(); +} +``` + +In `src/main.rs`, call the `init_logger()` defined in the `logging.rs` +sub-module at the head of your `main()` function: + +```src/main.rs +mod logging; + +fn main() { + logging::init_logger(); + … +} +``` + +Now you can call `info!()`, `error!()`, `warn!()`, etc., as described in <https://docs.rs/log/0.4/log/>. + +If you also debug it in your native target, you can also provide the `RUST_LOG` +environment variable, as per <https://docs.rs/env_logger/0.6/env_logger/>'s +documentation, in your command line incantations: + +``` +$ RUST_LOG=DEBUG cargo run +``` + +## Sequentialize SPECS. + +For some more esoteric reasons, probably something to do with threads, I had to +rewrite how I run my `specs::System`s , and +how `specs::System`s written. + +### Dispatching `specs::Dispatcher`. + +One normally builds a dependency graph of `specs::System`s using something +like: + +```src/main.rs +fn make_specs_dispatcher() -> specs::Dispatcher<'static, 'static> { + specs::DispatcherBuilder::new() + .with( + SystemFoo, + "system_foo", + &[], + ) + .with( + SystemBar, + "system_bar", + &["system_foo"], + ) + .build() +} + +struct OurGameState { + specs_world: specs::World, + specs_dispatcher: specs::Dispatcher, +} + + +impl State for OurGameState { + fn new() -> Result<World> { + let specs_world = make_specs_world_and_register_components(); // Implemented elsewhere… + let specs_dispatcher = make_specs_dispatcher(); + + Ok( + OurGameState { + specs_world, + specs_dispatcher, + } + ) + } + + fn update(&mut self, window: &mut Window) -> Result<()> { + let system_foo = SystemFoo; + let system_bar = SystemBar; + + system_foo.run_now(&selfworld.res); + system_bar.run_now(&world.res); + + world.maintain(); + + Ok(()) + } + + [imagine the rest of the quicksilver::lifecycle::State methods implemented here…] +} +``` + +In this example `SystemBar` depends on the state of the `specs::World` left by +`SystemFoo` after it does its thing. + +Instead of using this `Dispatcher` as described in +<https://slide-rs.github.io/specs/03_dispatcher.html>, you do this in your +`quicksilver::lifecycle::State::update()` + +``` +struct OurGameState { + specs_world: specs::World, +} + +impl State for OurGameState { + fn new() -> Result<World> { + let specs_world = make_specs_world_and_register_components(); // Implemented elsewhere… + + Ok( + OurGameState { + specs_world, + } + ) + } + + fn update(&mut self, window: &mut Window) -> Result<()> { + let system_foo = SystemFoo; + let system_bar = SystemBar; + + system_foo.run_now(&selfworld.res); + system_bar.run_now(&world.res); + + world.maintain(); + + Ok(()) + } + + [imagine the rest of the quicksilver::lifecycle::State methods implemented here…] +} +``` + +But in order to sequentialize how you deal with `specs`, you'd need to change one more thing: + +### Lay off `specs::LazyUpdater`. + +If you do anything with `specs::LazyUpdate`, you would have to convert it into +another form, interacting with your `Component` `Storage`s directly with +`WriteStorage` or whatever.