Making a small game in-browser with WebAssembly

Valeriy Kuzmin, Moonfare,

Berlin, 2021

The plan

  1. What is WebAssembly and emscripten
  2. How do you connect emscripten modules
  3. How do you create Box2D objects (coding)
  4. How do you add drawing via paper.js (coding)
  5. How to manage memory when you work with unmanaged languages in WASM
  6. How to add game logic (homework coding)

WTF is WASM?

WebAssembly is...

  • W3C developed platform specification
  • A virtual machine that works alongside JS
  • Text and binary format of the artifacts produced
  • Compilation target for С/С++/Rust/Kotlin/C#/etc

WebAssembly is...

  • Loads faster (than JS)
  • Is parsed faster (that JS)
  • Works waaay faster (than JS)

it's some binary blob with logic that...

Purpose - cpu- or memory-bound tasks

Low-level pdf work

Image processing

Cryptography *

Video processing

Data (de)serialization (xml, json)

GameDev

Launching other languages VMs

Browser in browser

Math, combinatorics

Server-side DBs in browser

Working with archives

Machine Learning

Applications - lately

Crypto mining and processing

Getting rid of native bridge / compilation in node.js

Isomorphic code (Blazor)

AssemblyScript

WASI

How do I get that magic binary?

C-like

wasm

JS

LLVM

emscripten

llvm8

Some kind of binary

Some useful code

Ready to use

emscripten

Rust: wasm-bindgen + wasm-pack

C++ embind

What is emscripten?

  • С/С++ to asm.js/wasm compiler
  • JS wrapper for resulting wasm files
  • Optimization and minififcaiton of the binary

Task 1

let's connect emscripten module

task1

Task 2.1

create Box2D objects

Cell width = wallSize = 1 meter

Left offset (in cells) - j

Top offset (in cells) - i

j = 2

i = 1

Target coords (2.5, 1.5)

task2.1

Task 2.2

create Box2D objects

new Box2D.b2Vec2(x : number, y : number);

bodyDef.set_position(pos : b2Vec2)

new Box2D.b2PolygonShape();

shape.SetAsBox(
    halfWidth : number, 
    halfHeight : number
);

bodyDef.set_type(type: Box2D.b2_dynamicBody);

body.CreateFixture(
    shape : b2Shape, 
    density : number
);

anyEMCObj.__destroy__();

body

fixture

fixture

fixture

task2.2

Task 3.1

draw paper.js sprites

yOffset=16

xOffset=0

80px

64px

dX

=

24

dY = 16

task3.1

Task 3.2

draw paper.js sprites

const path = new Paper.Shape.Rectangle({
            position: position,
            size: new Paper.Size(xSize, xSize),
            strokeColor: 'red',
        });
        

new Paper.Group([path, raster]);

group.scale(scaleTo);
group.clipped = true;

task3.2

Memory management in JS + WASM

JS: garbage collected

WASM: all manual

(talking about heap management)

Memory in JS

GC roots

business

logic

Memory in JS

GC roots

business

logic

delete

Memory in WASM

b2Vec2

b2Body

X

Y

...

...

...

ptr

JS-wrapper

это уже от emscripten

Память в WASM

b2Body

...

...

...

ptr

JS-wrapper

Module._free (ptr)

obj.__destroy__()

or

(emscripten)

(Box2D.wasm)

Memory: simple rules

  • Clean local variables immediately
  • First clean WASM, then JS wrapper
  • Long-living objects - only 1 owner
  • Limit the auto-growth

Task 4

implementing game logic

  1. In the boulder/tryBreak add creation of a few Rock objects
  2. In player/tryShoot create some Pickaxe objects

task4.2

task4.1

final

That's all!

Questions?

wasm-at-moonfare

By Valeriy Kuzmin

wasm-at-moonfare

  • 212