A cros-platform snake game written in the WebAssembly text format (WAT).
Play the web version here https://0scarb.github.io/wat-the-snake/.
Currently the native version of the application can only run on Linux and Windows with x86 CPUs (all PCs and most laptops, except those with ARM CPUs -- Chrome Books, suface Laptops, etc.).
You can download the native executables by clicking "download native executables" at the bottom right of the website https://0scarb.github.io/wat-the-snake/ and then clicking on the Linux or Windows options respectively. The linux version will be downloaded as a .tar archive which you can extract in your downloads folder.
Alternatively, you can also downloads the relevant source file --
snake-x86-64-linux
or
snake-x86-64-win.exe
-- directly from this
git repository.
You can download snake-web.html
and open it in
your browser as a static file. No internet connection required!
(The download links won't work because the link to seperate files.)
The software would not be possible without the awesome 3rd-party tools and assets that it depends on and uses:
-
WebAssembly for truely cross-platform code and the WebAssembly Binary Toolkit as tooling
-
GLFW for creating native PC / Laptop applications
Copyright (c) 2002-2006 Marcus Geelnard
Copyright (c) 2006-2019 Camilla LöwySee contributers here: https://github.com/glfw/glfw/blob/master/CONTRIBUTORS.md. It provides sensible, well-made window creation, input handling and wrapping of OpenGL for visuals!
-
Awesome Font Awesome icons to provide some visual finesse to the GitHub Pages website.
The following steps assume you're working in a linux terminal. Submit an issue if you want to hack on the project in a different developer environment.
Before getting started, your linux environment should have following external dependencies set up:
- The commands
cmake
,pkg-config
should be on your$PATH
- Fairly recent OpenGl headers should be discoverable by
pkg-config
-- if you don't know what this means, don't worry about it, it'll probably work out of the box. - You should install MinGW-w64 https://www.mingw-w64.org/ and its
x86_64-w64-mingw32-gcc
command should be on your$PATH
- Probably some other stuff that I'm forgetting
- Clone the repo
git clone [email protected]:0scarB/wat-the-snake.git
and cd to it. - Run the
./setup.sh
shell script. This will a) download and compile the WebAssembly Binary Toolkit and b) dowload and compile GLFW
After the setup you can run the build script ./build.sh
.
This will:
- Compile the WebAssembly text file
src/snake.wat
to the WebAssembly binarysnake.wasm
using thewat2wasm
from the WebAssembly Binary Toolkit. - (Re-)Generated
snake-web.html
fromsrc/web.html
, embedding thesnake.wasm
binary as a base64-encoded string in the HTML file. - Generate C code in
snake-c/
from thesnake.wasm
file and copysrc/native.c
tosnake-c/main.c
- Build the native Linux and Windows applications from the
C code in
snake-c/
, linking with GLFW and OpenGl. - Copy
snake-web.html
to (docs/index.html
)[./docs/index.html] and tar and copy the executables for download to thedocs/
directory. The contents of thedocs/
directory are served on the GitHub Pages website https://0scarb.github.io/wat-the-snake/.
I started this project because I wanted to learn a bit about WebAssembly and ended up also learning a bit about creating cross-platform applications, without the bloat and inefficiencies of stuff like Electron.
Working in the WebAssembly Binary Text Format (.wat) improved my intuition regarding manual memory management. Among other things it forced me to use a circular buffer to store the snake data. It turns out to be easier to implement and much more efficient than a linked listed -- contiguous in memory, better cache coherence. I'll be on the lookout for future use cases (you still need a linked listed when operating on data that is in the middle though)!
Working in .wat isn't very practial and is better suited as a compile target, once understood. Working in lower-level, simpler programming languages does highlight what you miss and is actually necessary in higher-level languages though.
Because I wanted to keep most of the logic in .wat file, the pixel data is stored in WebAssembly's linear memory, meaning that I had to custom-implement circle rendering, rasterization and even font rendering. This is of course much less efficient that utilizing hardware acceleration the GPU via OpenGL/WebGL. Looking at the results of profiling, the major bottle-neck is actually copying the pixel data into GPUs VRAM (you need to use OpenGL / WebGL to actually display the pixels) which is done every frame. This could be improved be keeping track of the bounding boxes of only the pixels that changed from one frame to the next, requiring only those regions to be copied, but I couldn't be bothered to implement it because the project already took longer to finish than I expected. To sum up, there's a lot of performance being left on the table and I wouldn't copy this approach for professional work. Despite that, I'm easily able to reach 60FPS and my laptop.
This project is licensed under the The Open Software License 3.0 license with the intention of allowing others redistribute this code, to modify derivate software and reuse sections of the code for other open source projects, under the conditions that the derivate source code stays open and that attribution is provided under the terms of the license.
All non-code, non-3rd-party assets and materials, that do not fall under the OSL-3.0, contained in the git repository, are licensed under the Creative Commons Attribution-ShareAlike 4.0 International license CC BY-SA 4.0 license.
I'm open to discussing sublicensing if the OSL-3.0 does not meet your needs. This is permissible as stated in paragraph 4 of the license, "Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License".