2024-01-27

Project Raygine #18 - it's alive!

I've managed to build a web runtime that loads my project game data. This here is only a test project that I made to test the runtime:

Getting this running took probably 10h of my time. There were a lot of issues to resolve, so here's a write down on what I did:

Building raylib with emscripten

This was an easy step: Just follow the instruction and it'll work. I later deviated a little however: Per default, the raylib makefile's output library name and path is identical, regardless what your build target is. That makes it a little painful when building a project that has different platform targets. So I changed the makefile to output the emscripten library into a separate folder.

The respective change to the makefile can be found on my public raylib fork.

Lua

This was a bigger chunk. LuaJIT isn't compatible with emscripten according to my research, so I didn't even try. After some consideration, I decided to use Lua 5.1.5 as a compatible version. It's mostly compatible, but I still had to modify my Lua scripts since I had a few gotos in the scripts to emulate the "continue" keyword in loops.

I added a compatibility file to provide some functions that are missing in 5.1.5 - it's mostly related to adding libraries. I am really glad I didn't use FFI to create my bindings and chose the traditional C API instead. FFI is said to be more performant in general, but with doing web builds and not having an FFI implementation, I would have faced a lot more work to get it running.

One particular problem that cost me some time to figure out what's wrong is, that the emscripten build is using 32 bit ints. This caused trouble because I use hexadecimal numbers like 0xff0000ff for passing color values. I initially didn't see any of my render commands issued by my Lua code and it took me a while to figure out that the alpha values were negative and therefore 0. I fixed this in my color reading function to read the number as double and casting it to an unsigned integer.

File loading

The file loading worked pretty much out of the box and how I envisioned it: The file package is loaded via JavaScript and is then passed into the virtual filesystem of emscripten where I can access it via the regular C file API. From that moment on, the runtime looks like as if running on a desktop system.

Loader

The loader is the web runtime facing part and it's pretty slim. I could have done it just in C, but I started out testing if Lua and the raylib bindings work. Going from there, I added a Lua script that displays a loading bar using the raylib drawing functions. To load the package and displaying the progress bar, it injects some JavaScript code into the page that in return calls back into the Lua script to update the progress bar and kicking of the game start.

Game start

As mentioned above, the game start is kicked off by the loader. It causes the client to tear down the loading screen script and creeating a runtime object that is also used in the desktop runtime. From there on it's the same code path.

Summary

I expected this to take much longer. My ahead planning worked out well and I was also lucky with some decisions I made playing out nice. I am really happy that I got this working. It's a huge milestone for me. I am now able to run my editor projects in the browser, which means that future blog updates will like use this as a feature.

Next steps

As everything is thrown together on the go while trying to keep running forward, the entire project is quite messy still. There are a bunch of things that the web runtime could do better, but I will skip all that and instead will try to get to my next planned step: Making a small game using the editor and then pushing it on the web. There are still a huge number of things in the editor that makes working with it quite painful and I want to make those things smooth.

One of my medium time goals is, that I want to participate in a game jam with my editor and therefore, the editor must allow working fast and smoothly when creating content and scripts. One part is getting accustomed to the APIs I have created and making them more accessible. Another part is to make the editor UX better, like making adding entities and components and assets a smooth experience. This'll all take much time, but now I have another motivation on the horizon: Making a small game with it that can be actually published where people can play it. I am really looking forward to that.

🍪