Open Source Projects

Game of Life with Uint8Array & Canvas

Imagine gliders zipping forever across your screen, no lag, no bloat—just pure JS magic. This fresh Game of Life build shows why typed arrays beat the usual hacks for real-time sims.

Animated Gosper Glider Gun firing gliders on a toroidal Canvas grid

Key Takeaways

  • Uint8Arrays deliver GC-free perf and easy snapshots for smooth browser sims.
  • Toroidal wrapping + RAF timing make small grids feel infinite and tab-proof.
  • Vanilla JS blueprint inspires efficient web automata without deps or builds.

Your next hobby project just got faster. Devs tweaking cellular automata in the browser—think procedural worlds or AI viz—now have a blueprint that sidesteps garbage collection hell and keeps frames smooth at 60 steps a second.

And it’s not hype. This vanilla JS implementation of Conway’s Game of Life, packing Uint8Arrays for the grid and Canvas for pixels, hits live demos where the Gosper Glider Gun spits gliders endlessly. Real people? Students nailing JS perf basics. Indie game hackers prototyping without WebGL overhead. Even data viz folks simulating markets or epidemics without a framework crutch.

Look, everyone’s coded Life once. But this one’s surgical: toroidal edges so nothing vanishes, preset patterns to skip tedium, counters for generations and live cells. Click a preset—bam, chaos unfolds.

Why Uint8Arrays Crush Nested Arrays for Grids

Three solid options float around: nested arrays (easy but memory hogs), flat Uint8Array (goldilocks), or bit-packed Uint32s (fastest, ugliest math). Author picks flat Uint8—GC-friendly with one allocation, cache-hot rows, snapshot via next.set(current) in a blink.

An 80x50 grid? 4KB versus 500 bytes bit-packed. Trade readability for that on huge boards only. Here’s the creator’s rationale, straight up:

Typed arrays give you: GC-friendly memory: one allocation instead of h+1 arrays of references. Fast snapshotting: next.set(current) copies an entire grid in one call. Cache locality: rows sit contiguous in memory, which matters for the nested neighbor loop.

Smart. No one’s rewriting neighbor loops for marginal gains when education’s the game.

But—sharp take—bit-packing’s siren song ignores JS engines’ maturing SIMD. In 2024, with WebAssembly knocking, vanilla Uint8 future-proofs better. It’ll pair smoothly if you bolt on WASM compute later.

Does Toroidal Wrapping Fix Life’s Biggest Flaw?

Finite grids kill gliders dead. Torus? They loop forever, small boards feel infinite. The index function’s a gem:

export function index(grid, x, y) {
  const w = grid.width
  const h = grid.height
  // Toroidal wrap. Double-modulo to handle negatives correctly.
  const xx = ((x % w) + w) % w
  const yy = ((y % h) + h) % h
  return yy * w + xx
}

That ((x % w) + w) % w? JS % keeps signs—-1 % 80 is -1. Boom, fixed. Gliders re-enter like clockwork.

For real-world? Simulating toroidal economies or ecosystems—no edge artifacts screwing stats. Data-driven win.

Rules? Three lines, simultaneous via fresh array:

if (alive && (n === 2 || n === 3)) next[i] = 1 else if (!alive && n === 3) next[i] = 1

No in-place bugs poisoning counts. History? Stack ‘em for undo. Elegant.

Is the Gosper Glider Gun Still Mind-Blowing?

  1. Bill Gosper cracks: finite pattern with unbounded growth? $50 bounty claimed. Period-30 cycle, 36 cells, gliders every tick—forever.

Stored as coord lists—sparse perfection. Stamp ‘em anywhere. Beats dense grids for wide patterns.

Eight presets ship: Glider, Blinker, up to Gun. No hand-placing drudgery. Controls? Play/pause/step/reset/clear, 1-60 steps/sec, counters ticking.

Zero deps. No build. Lives at https://sen.ltd/portfolio/game-of-life/ —forkable on GitHub.

Here’s my bold call, absent from the post: This sparks a mini-revival in browser automata. With Canvas2DContext maturing, expect JS Life variants powering NFT art generators or real-time ML model viz. Not WASM, not Three.js—vanilla wins for teaching.

Ditch setInterval—requestAnimationFrame Rules

setInterval(step, 1000/N)? Tabs backgrounded, throttled to hell. RAF + timestamps? Bulletproof:

if (now - lastStepAt >= stepMs) {
  grid = step(grid)
  render()
  lastStepAt = now
}

Polls smartly. Speed 60? Per-frame bliss. Speed 1? Steady drip.

Market angle: Browser sims balloon—physics toys, fractals, now primed for ad-free web apps. This code’s your perf baseline.

Critique time. Patterns list is flat—JSON coords bloat on dense ones like Pulsar. But hey, Gosper’s the star; sparse shines.

Rendering? Canvas ctx.putImageData on Uint8ClampedArray view—blazing, sub-16ms loops easy.

Deeper: Why revisit Life now? JS perf leaped—V8 crushes loops. Typed arrays, once niche, standard for games. Echoes Gosper’s era: simple rules, emergent wonder. Prediction? This GitHub repo hits 1k stars, inspires WebGPU ports.


🧬 Related Insights

Frequently Asked Questions

What is Conway’s Game of Life? Cellular automaton: grid cells live/die by neighbor counts. Birth at 3, survival at 2-3. Emergent patterns from simplicity.

How to code Game of Life in JavaScript? Uint8Array grid, Canvas render, RAF loop. Toroidal index, double-buffer steps. Presets via coord stamps.

What’s a Gosper Glider Gun? 1970 pattern: spits gliders periodically, proving unbounded growth. 36 cells, spans wide—eternal chaos machine.

James Kowalski
Written by

Investigative tech reporter focused on AI ethics, regulation, and societal impact.

Frequently asked questions

What is Conway's Game of Life?
Cellular automaton: grid cells live/die by neighbor counts. Birth at 3, survival at 2-3. Emergent patterns from simplicity.
How to code Game of Life in JavaScript?
Uint8Array grid, Canvas render, RAF loop. Toroidal index, double-buffer steps. Presets via coord stamps.
What's a Gosper Glider Gun?
1970 pattern: spits gliders periodically, proving unbounded growth. 36 cells, spans wide—eternal chaos machine.

Worth sharing?

Get the best Open Source stories of the week in your inbox — no noise, no spam.

Originally reported by Dev.to

Stay in the loop

The week's most important stories from Open Source Beat, delivered once a week.