From 8484aab2a77dd6898f6299f11722385db3871694 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B8rn=20Birch=20Moltu?= Date: Tue, 1 Aug 2023 23:55:02 +0200 Subject: [PATCH 1/3] Make it compile for wasm --- .gitignore | 5 ++++- Makefile | 18 ++++++++++++++++ engine/src/speedy2d.rs | 48 ++++++++++++++++++++++++++++++------------ wasm/index.html | 26 +++++++++++++++++++++++ 4 files changed, 82 insertions(+), 15 deletions(-) create mode 100644 Makefile create mode 100644 wasm/index.html diff --git a/.gitignore b/.gitignore index 570bfc0..c5bebac 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ -target +/target/ +/wasm/*.wasm +/wasm/*.ts +/wasm/*.js [Tt]humbs.db .DS_Store diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f4de4a7 --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +.PHONY: check run dev clippy wasm + +check: + cargo check + cargo check --features dyn + +run: + cargo run + +dev: + cargo run --features dyn + +clippy: + cargo clippy --features dyn + +wasm: + cargo build --target wasm32-unknown-unknown + wasm-bindgen target/wasm32-unknown-unknown/debug/space_tennis.wasm --out-dir wasm --target web diff --git a/engine/src/speedy2d.rs b/engine/src/speedy2d.rs index fe0bdc7..bc15e0f 100644 --- a/engine/src/speedy2d.rs +++ b/engine/src/speedy2d.rs @@ -1,12 +1,13 @@ use interface::game::*; use std::collections::HashMap; +#[cfg(not(target_arch = "wasm32"))] use std::thread; use std::rc::Rc; use std::time::{Duration, Instant}; extern crate speedy2d; -use speedy2d::{Graphics2D, Window}; +use speedy2d::Graphics2D; use speedy2d::color::Color as spColor; use speedy2d::dimen::Vector2; use speedy2d::font::{Font, TextLayout, TextOptions, FormattedTextBlock}; @@ -14,15 +15,20 @@ use speedy2d::shape::Rectangle; use speedy2d::window::{ MouseButton as spMouseButton, VirtualKeyCode, - WindowCreationOptions, WindowHandler, WindowHelper, - WindowSize, }; +#[cfg(target_arch="wasm32")] +use speedy2d::WebCanvas; +#[cfg(not(target_arch = "wasm32"))] +use speedy2d::Window; +#[cfg(not(target_arch="wasm32"))] +use speedy2d::window::{WindowCreationOptions, WindowSize}; extern crate fxhash; use fxhash::FxBuildHasher; +#[cfg(not(target_arch="wasm32"))] const UPDATE_RATE: u32 = 125; // the standard USB polling rate. fn map_key(key: VirtualKeyCode) -> Option { @@ -93,6 +99,7 @@ struct GameWrapper { } impl WindowHandler for GameWrapper { + #[cfg(not(target_arch="wasm32"))] fn on_start(&mut self, h: &mut WindowHelper<()>, _: speedy2d::window::WindowStartupInfo @@ -116,6 +123,9 @@ impl WindowHandler for GameWrapper { } fn on_draw(&mut self, h: &mut WindowHelper<()>, g: &mut Graphics2D) { + #[cfg(target_arch="wasm32")] + self.on_user_event(h, ()); + g.clear_screen(spColor::BLACK); self.game.render(&mut self.shapes); @@ -226,16 +236,6 @@ impl WindowHandler for GameWrapper { #[inline(never)] pub fn start(game: G, name: &'static str, initial_size: [f32; 2]) { - let window_size = Vector2 { x: initial_size[0], y: initial_size[1] }; - let window_size = WindowSize::ScaledPixels(window_size); - let options = WindowCreationOptions::new_windowed(window_size, None) - .with_always_on_top(false) - .with_decorations(true) - .with_resizable(true) - .with_transparent(false) - .with_vsync(true); - let window = Window::new_with_options(name, options).unwrap(); - let wrapper = GameWrapper { game, window_size: initial_size, @@ -243,5 +243,25 @@ pub fn start(game: G, name: &'static str, initial_size: [f32; shapes: Graphics::default(), text: TextCache::new(), }; - window.run_loop(wrapper); + + #[cfg(target_arch="wasm32")] + { + let _ = name; + WebCanvas::new_for_id("space_tennis_game", wrapper) + .expect("bind to canvas"); + // .unregister_when_dropped() would make the game end immediately. + } + #[cfg(not(target_arch="wasm32"))] + { + let window_size = Vector2 { x: initial_size[0], y: initial_size[1] }; + let window_size = WindowSize::ScaledPixels(window_size); + let options = WindowCreationOptions::new_windowed(window_size, None) + .with_always_on_top(false) + .with_decorations(true) + .with_resizable(true) + .with_transparent(false) + .with_vsync(true); + let window = Window::new_with_options(name, options).unwrap(); + window.run_loop(wrapper); + } } diff --git a/wasm/index.html b/wasm/index.html new file mode 100644 index 0000000..b6af07c --- /dev/null +++ b/wasm/index.html @@ -0,0 +1,26 @@ + + + + + + + + + + + + From 9204c9cc84377df898f1ccded9ebaa5b79101cad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B8rn=20Birch=20Moltu?= Date: Tue, 1 Aug 2023 23:58:09 +0200 Subject: [PATCH 2/3] Fix crashing early due to std::time not being supported --- Cargo.lock | 24 ++++++++++++++++++++++++ Cargo.toml | 5 +++++ engine/src/speedy2d.rs | 18 +++++++++++------- interface/src/lib.rs | 11 +++++++++++ 4 files changed, 51 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9654723..8562cd5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -160,6 +160,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen", +] + [[package]] name = "core-foundation" version = "0.7.0" @@ -1299,9 +1309,12 @@ dependencies = [ name = "space_tennis" version = "1.2.0" dependencies = [ + "console_error_panic_hook", "engine", "game", "interface", + "log", + "wasm-logger", ] [[package]] @@ -1524,6 +1537,17 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +[[package]] +name = "wasm-logger" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "074649a66bb306c8f2068c9016395fa65d8e08d2affcbf95acf3c24c3ab19718" +dependencies = [ + "log", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wayland-client" version = "0.29.5" diff --git a/Cargo.toml b/Cargo.toml index 6450e5f..567f864 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,11 @@ interface = {path="interface"} engine = {path="engine"} game = {path="game/", optional=true} +[target.'cfg(target_arch="wasm32")'.dependencies] +log = "0.4" +wasm-logger = "0.2" +console_error_panic_hook = "0.1.6" + [features] dyn = ["engine/dyn", "interface/dyn", "game"] piston = ["engine/piston"] diff --git a/engine/src/speedy2d.rs b/engine/src/speedy2d.rs index bc15e0f..a3eae44 100644 --- a/engine/src/speedy2d.rs +++ b/engine/src/speedy2d.rs @@ -1,10 +1,11 @@ use interface::game::*; use std::collections::HashMap; +use std::rc::Rc; #[cfg(not(target_arch = "wasm32"))] use std::thread; -use std::rc::Rc; -use std::time::{Duration, Instant}; +#[cfg(not(target_arch = "wasm32"))] +use std::time::Duration; extern crate speedy2d; use speedy2d::Graphics2D; @@ -12,6 +13,7 @@ use speedy2d::color::Color as spColor; use speedy2d::dimen::Vector2; use speedy2d::font::{Font, TextLayout, TextOptions, FormattedTextBlock}; use speedy2d::shape::Rectangle; +use speedy2d::time::Stopwatch; use speedy2d::window::{ MouseButton as spMouseButton, VirtualKeyCode, @@ -93,7 +95,8 @@ impl TextCache { struct GameWrapper { game: G, window_size: [f32; 2], // changes if window is resized - last_physics: Instant, + stopwatch: Stopwatch, + last_physics: f64, shapes: Graphics, text: TextCache, } @@ -117,9 +120,9 @@ impl WindowHandler for GameWrapper { fn on_user_event(&mut self, _: &mut WindowHelper<()>, _: ()) { let prev = self.last_physics; - self.last_physics = Instant::now(); - let elapsed = self.last_physics.saturating_duration_since(prev); - self.game.update(elapsed.as_secs_f32()); + self.last_physics = self.stopwatch.secs_elapsed(); + let elapsed = self.last_physics - prev; + self.game.update(elapsed as f32); } fn on_draw(&mut self, h: &mut WindowHelper<()>, g: &mut Graphics2D) { @@ -239,7 +242,8 @@ pub fn start(game: G, name: &'static str, initial_size: [f32; let wrapper = GameWrapper { game, window_size: initial_size, - last_physics: Instant::now(), + stopwatch: Stopwatch::new().expect("create stopwatch"), + last_physics: 0.0, shapes: Graphics::default(), text: TextCache::new(), }; diff --git a/interface/src/lib.rs b/interface/src/lib.rs index 2e545a5..dbb4108 100644 --- a/interface/src/lib.rs +++ b/interface/src/lib.rs @@ -17,6 +17,10 @@ macro_rules! expose_game{($mod:tt::$game:tt) => { #[macro_export] macro_rules! impl_main {($dir:tt) => { extern crate engine; + #[cfg(target_arch="wasm32")] + extern crate wasm_logger; + #[cfg(target_arch="wasm32")] + extern crate log; #[cfg(feature="dyn")] extern crate $dir; @@ -24,6 +28,13 @@ macro_rules! impl_main {($dir:tt) => { mod $dir; fn main() { + #[cfg(target_arch="wasm32")] + { + wasm_logger::init(wasm_logger::Config::default()); + std::panic::set_hook(Box::new(console_error_panic_hook::hook)); + log::info!("{} WebGL", game::NAME); + } + let game = game::create_game(); #[cfg(feature="dyn")] engine::reload::start_reloading(&game); From f999b9dec26fb61a441830380c5cb3feeea6ee7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B8rn=20Birch=20Moltu?= Date: Wed, 2 Aug 2023 00:10:34 +0200 Subject: [PATCH 3/3] Fix wrong size until browser window is resized --- engine/src/speedy2d.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/engine/src/speedy2d.rs b/engine/src/speedy2d.rs index a3eae44..7c59800 100644 --- a/engine/src/speedy2d.rs +++ b/engine/src/speedy2d.rs @@ -102,14 +102,17 @@ struct GameWrapper { } impl WindowHandler for GameWrapper { - #[cfg(not(target_arch="wasm32"))] fn on_start(&mut self, h: &mut WindowHelper<()>, - _: speedy2d::window::WindowStartupInfo + info: speedy2d::window::WindowStartupInfo ) { + let size = info.viewport_size_pixels().into_f32(); + self.window_size = [size.x, size.y]; h.set_cursor_visible(true); h.set_cursor_grab(false).unwrap(); + #[cfg(not(target_arch="wasm32"))] let sender = h.create_user_event_sender(); + #[cfg(not(target_arch="wasm32"))] thread::spawn(move || { loop { sender.send_event(()).unwrap();