React + Rust + Wasm: Game Engine

Nikhil Gupta
2 min readNov 14, 2022

--

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:

--

--

Responses (2)