An implementation of the Doom Fire in Rust exported via FFI, with three apps (Web, iOS, Android) that use it. I actually did this project for a Rust LATAM talk.
This project is not intended to be the best way to create a Rust library that can compile to Android
, iOS
and WebAssembly
.
It was created with the idea to share something that is not a hello world example of FFI that compiles to more than one platform.
It also contains a lot of the knowledge that me and Philipe Paixão (aka @piiih) acquired on building a project at Pagar.me (@pagarme) that uses the same technology and ideas, that unfortunally because of regulamentation issues, needs to be closed source.
doom-fire-interop
│
└───src
│ └─── all Rust code implementing the Doom Fire algorithm
│
└───DoomFireAndroid
│ └─── android app that consumes Rust library via FFI
│
└───DoomFireIOS
│ └─── ios app that consumes Rust library via FFI
│
└───DoomFireWeb
└─── web app that consumes Rust library via WebAssembly
The idea is that the Rust library has a PixelBoard
struct that contains a Vec
of bytes (u8
).
Each of those values represents the intensity of the fire for each of the pixels on the screen. Following this color pallette:
Then for each iteration of an infinity loop, an algorithm traverses all pixels and calculates their fire intensity based of: the pixel below, a "wind", and a random number.
The code below is the implementation needed to actually run the Rust code (actually WebAssembly that was compiled from Rust) on JavaScript and render it on screen.
import * as doom from 'doom'
function start() {
const pixelBoard = doom.create_board(60, 40)
doom.create_fire_source(pixelBoard) // sets the first line of pixels to 36
setInterval(() => doom.calculate_fire_propagation(pixelBoard, renderFire), 50)
}
function renderFire(pixelsArray) {
// pixelsArray = [35, 36, 22, 26, ...]
// ... do rendering on screen
}
start()
There is a whole book about tricks that the Developers of the Doom
game engine did, and there is an article, by the same author, just about the menu's fire:
http://fabiensanglard.net/doom_fire_psx/
Also, @filipedeschamps did a whole video about this, trying to simplify the algorithm:
https://www.youtube.com/watch?v=HCjDjsHPOco
The video is in portuguese, but it has subtitles 🙂
He also has a repository containing a LOT of implementations of this algorithm. Some of them actually made this project possible.
https://github.com/filipedeschamps/doom-fire-algorithm
Well, it isn't actually that simple, I recommend on reading this article by Mozilla that explains how it works to compile a Rust library and use it on an Android app: https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-21-rust-on-android.html.
Same as Android, it requires a lot of configuration, here is a tutorial by Mozilla: https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-06-rust-on-ios.html.
This one is actually simpler 😁
- Install these tools: https://rustwasm.github.io/book/game-of-life/setup.html;
- Clone this project;
- Change directory to its folder (aka
cd doom-fire-interop
); - Run
wasm-pack build
; - Change to the new
pkg
folder created bywasm-pack
(cd pkg
); - Run
npm link
; - Change to the
DoomFireWeb
folder (cd ../DoomFireWeb
); - Run
npm install
; - Run
npm link doom
; - Run
npm start
;
Then you should be able to see this at this URL: http://localhost:8080
:
Marcela Ziliotto for lending her 2011's Macbook so that I could create the iOS app. 💻 🍎
Philipe Paixão for working with me on the Pagar.me project that lead to all the knowledge I know about WebAssembly and FFI. 👨💻 👨💻
Deivis Windgert, Rodrigo Melo, Mateus Moog, Leonam Pereira, Allan Jorge and Pagar.me for letting me practice my Rust LATAM presentation to them and giving me feedback. 💬
Kassiano, Murilo da Paixão and Filipe Deschamps for putting your implementation open source so that I could actually know how to render pixels on screen. 🌐 🎮
More people contributed to this, like my family and girlfriend, and other people at Pagar.me. Thank you all!! ❤️