Project
+- 13
An arcade dodger built in 13 KB with WebGL2 SDF rendering and radiance cascades.
+- 13 is a JS13K 2024 arcade game about chasing or avoiding a moving 13, depending on the wave. The visuals are built entirely from signed distance fields, then lit using a multi-pass radiance-cascade renderer that runs in raw WebGL2.
Player feedback
"Very cool visual effect. I remember from last year, your games are very technical, which is interesting. Would like to have a look at the postmortem." -- Isaac Benitez
"This is my favorite 'need to take it apart and learn how it's done' game this year." -- Mark Vasilkov
"Impressive lighting effects! Gameplay is simple but funny. Having a music is cool too!" -- Jonathan Vallet
"The lighting was impressive." -- Jasper Renow-Clarke
Rendering pipeline (SDF + radiance cascades)
df.fragment.glslbuilds the whole scene with SDF primitives: capsules for the stick figure and custom digit glyphs for the 1-13 tiles.- Tile data is packed into a
mat4 u_boxes[13]uniform array (position, velocity, value, color, radiance) to keep WebGL uniforms compact. - The distance field is rendered into a float texture via an offscreen framebuffer.
rc.fragment.glslraymarches the distance field in multiple cascades, merging lower-resolution radiance probes into higher detail levels for soft global illumination.- Each cascade pass feeds the next via
u_lastTexture, mipmaps, and a ping-pong FBO setup.
Game simulation and collisions
The update loop runs at requestAnimationFrame cadence and handles:
- 13 roaming tiles that spawn off-screen, drift toward the center, and bounce off each other.
- A wave rule that alternates between "avoid 13" and "hunt 13".
- Player collision with SAT-style polygon checks (rotated stickman vs. axis-aligned boxes).
- A "super mode" shield that spends charge to let you collect any tile safely.
Input, UI, and scoring
- Keyboard input (WASD or arrows) drives inertial movement with capped acceleration and smoothing.
- The UI is HTML/CSS layered over the canvas for timer, score, lives, and shield charge.
- Local storage keeps a top-10 scoreboard, with scores normalized by screen resolution.
Audio synthesis
Two procedural systems handle audio:
sound.tsbuilds short SFX buffers from custom wave formulas and plays them on demand.music.tsschedules chords, melody, bass, and drums with increasing tempo every wave, using Web Audio oscillators, filters, and a convolution reverb.
Build and size constraints
The pipeline uses TypeScript + Webpack, GLSL minification, and JS13K-friendly compression:
webpack-glsl-minifyfor shader shrinking.- Roadroller and AdvZip in
build-finalto squeeze the final bundle into the 13 KB contest limit.