Making a small game in-browser with WebAssembly
Valeriy Kuzmin, Moonfare,
Berlin, 2021
The plan
- What is WebAssembly and emscripten
- How do you connect emscripten modules
- How do you create Box2D objects (coding)
- How do you add drawing via paper.js (coding)
- How to manage memory when you work with unmanaged languages in WASM
- 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
More stuff https://github.com/mbasso/awesome-wasm
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
- In the boulder/tryBreak add creation of a few Rock objects
- 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