React + Rust + Wasm: Game Engine
In this article, we will use Bevy game engine in our React application from our Rust WASM library to draw a 2D Image. We will build on the previous tutorial available here.
Add bevy to the dependencies
First of all, let’s add bevy
as a dependency:
# Cargo.toml
[package]
name = "rust-wasm-lib"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib"]
[dependencies]
js-sys = "0.3.60"
wasm-bindgen = "0.2.83"
photon-rs = "0.3.1"
bevy = "0.9.0"
[dependencies.web-sys]
version = "0.3.4"
features = [
'Document',
'Element',
'HtmlElement',
'Node',
'Window',
'CanvasRenderingContext2d',
'HtmlCanvasElement',
'WebGlBuffer',
'WebGlVertexArrayObject',
'WebGl2RenderingContext',
'WebGlProgram',
'WebGlShader'
]
Run a Bevy App using Rust
Last time, we exposed a function to alter an image using photon APIs. Now, let’s modify our lib.rs
to expose another function that will create a simple Bevy app.
Import Bevy
...
use bevy::prelude::*;
...
Create a Bevy App
#[wasm_bindgen]
pub fn run_bevy_app() {
App::new()
.add_plugins(DefaultPlugins)
.add_startup_system(setup) //Defined below
.run();
}
Setup commands for camera and 2D image
pub fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2dBundle::default());
commands.spawn(SpriteBundle {
texture: asset_server.load("branding/icon.png"),
..default()
});
}
Build the new wasm library
Let’s run wasm-pack again to build the updated library
wasm-pack build --target web
Setup the image path correctly
In the setup command, we passed a path to the image as branding/icon.png
. For bevy
to find this image, let's create a folder named assets
inside public
with the image stored under branding/icon.png
.
Call the new function from the demo app
Finally, let’s add a button to load the wasm and call run_bevy_app
function from our App.ts
file like so:
// App.ts
import init, { run_bevy_app } from "rust-wasm-lib";
import './App.css';
function App() {
const runBevyApp = async () => {
await init();
run_bevy_app();
};
return (
<div className="App">
<button onClick={runBevyApp}>Run Bevy App</button>
</div>
);
}
export default App;
Now, if you run the updated app and click on Run Bevy App
, you should see a canvas with the image in the centre. :)
If you liked this article, subscribe here to get the complete code and updates for the entire collection: