TwoRS
Easily render 2D graphics in a canvas using WASM - entirely powered by Rust!!! 🦀
🙋 Who is this project for?
This tiny renderer is for people who:
- Need an example on how setup WASM & interact with the canvas
- Play around with Rust the fun way - by making a small 2D game
😎 Why Rust/WASM?
WASM's use case is either the reuse of code written in another language or to offload heavy computations to the near-native execution speeds of WASM.
However this is not free - traversing the WASM boundary means going trough some glue code and copying data from JS to the WASM module memory and back. In the case of strings it's even more expensive - because JS strings are UTF-16 and Rust strings use UTF-8 any string passtrough needs to go trough a copy AND a re-encode.
twors doesn't have any complicated physics to offload to WASM at this point in time - neither
is it making use of some advanced pre-existing Rust library. So why Rust then?
⭐ Simply because Rust is the best!!! ⭐
⚡ Quick start
- To quickly play with
tworsyou can run theexamples/playgroundcrate in this repo- Move the player via the WASD keys (player can't exit the green area)
- Spawn items at the players' location via the left mouse button
- Drag spawned items via the right mouse button
# edit the source code in examples/playground and manually refresh http://localhost:8080
- To add
tworsto your own crate - check out the Installation and build guide
✨ Features
✅ TwoRS's goal is to be simple. It provides:
- ✅ A main loop with precalculated delta time
- ✅ Keyboard/mouse
- ✅ Basic component system (not ECS)
❌ TwoRS does not currently have (and aim) to provide:
- a physics engine
- an algorithm library (e.g. pathfinding)
- a sound library
- a UI library
🛠️ Installation and build
Compiling a WASM library is a bit more involved than simply executing cargo run, but
it's pretty straightforward if you know the steps.
We'll basically:
- set up our crate for WASM compilation
- add the bare minimum code to run the
tworsengine - add an
index.htmlwith some JavaScript (just enough to run our WASM library) - serve all of this goodness via an HTTP server
Once we do this all of the remaining code can be written entirely in Rust!
You are of course free to mix and match as you like.
Step 1 - Create a lib crate
In order to compile Rust into WASM via wasm-pack
(an amazing WASM compilation helper) it's necessary to have a lib crate first
Step 2 - Install twors, wasm_bindgen and console_log
- A browser-capable logging backend crate like
console_log is needed to enable
logging in the browser console
- You will also need a logging frontend crate like log to be able to print messages yourself.
- wasm_bindgen will generate the necessary JS/Rust
glue to enhance what can go trough the WASM/JS boundary.
- Without it our Rust code that's called from JS (and vice-versa) would be able to only take numbers as arguments and return numbers as a result. With this crate we enable a lot more types in our JS/WASM boundary API.
Step 3 - Create and run the twors engine.
- For now we won't add any components, so we'll see a blank canvas when we open our application in the browser.
use ;
use wasm_bindgen;
use HashMap;
use console_log;
// The "wasm_bindgen" attribute will generate glue both on the JS and on the WASM sides.
// Passing Rust types like `&str` from JS is thanks to the magic of `wasm_bindgen`.
Step 4 - Change the crate type to a dynamic library intended to be loaded from another language
Add a lib section to your Cargo.toml file (if you don't already have one) and set
the crate-type property to cdylib.
The wasm32-unknown-unknown compile target (what wasm-pack makes the Rust compiler use) will
detect this and produce a WASM library.
[lib]
crate-type = ["cdylib"]
Step 5 - Install wasm-pack and build your WASM library
The following wasm-pack --build command will produce a pkg folder in your crate's root -
this folder will contain the WASM library as well as the JS part of the glue code that's
needed for the WASM-JS communication.
Step 6 - Copy examples/assets/index.html to the pkg folder in your crate's root
We have compiled our WASM library - now we need to call it from JS. The example index.html
will:
- create a full screen canvas
- run our Rust
entrymethod (that we created earlier) by passing it the canvas ID.
# navigate to your crate root and execute the following
NOTE: If you don't have the
cpcommand (e.g. if you are using Windows CMD) you can always copy theindex.htmlmanually.
Step 7 - Serve the pkg directory at the crate root
You will need to serve the WASM library with the application/wasm MIME type or the browser
will refuse to run it. A great server that does this automatically is
miniserve
💻 Development
Experiments and manual testing during development can be done in the examples/playground crate.
# convenience scripts - see "Makefile.toml" for full list of commands
# run local pre-commit checks - will be run on "build" automatically
# other commands
Notes
- Make sure to use
wasm_assert!instead ofassert!in non-test code to see error messages in the browser console.