This is Wireworld! Sorry, you don't know what a Wireworld is? How dare you not intimately know something I learned a few minutes ago!
A Wireworld is similar to the famous Game of Life. An infinite world of square cells, each in a distinct, finite state. But unlike boring life that has only two states: alive and dead; Wireworld has four! That's like... twice as good?
A Wireworld cell could either be: nothing, a conductor (wire), an electron tail, or an electron head. An electron head always becomes an electron tail which always becomes a wire, while a wire will stay a wire unless exactly one or two neighbors are an electron head, in which case it will follow suit (and nothing continues to be nothing).
You can see those rules in action in the animation above. You can also play with those rules over here: wireworld.klmntn.com (warning, it's only somewhat useable on mobile)
The Making Of
Every three months, Root sets aside three days (called "hack days") for all its engineers to work on something of their choice. This time around I wanted to have some fun and also learn a little about Svelte (Root mostly uses React & React Native). So I chose to make a browser-based Wireworld using Svelte!
kallmanation / wireworld
A Wireworld (duh)
Wireworld
A Wireworld is a cellular automaton (like Conway's Game of Life) with four states:
- null
- wire
- electron head
- electron tail
These four states transition by the following rules:
- null -> null
- tail -> wire
- head -> tail
- wire -> head (iff exactly 1 or 2 neighbors are an electron head)
- wire -> wire (otherwise)
Wireworlds are Turing-complete and are interesting in that they can so closely mirror digital transistor behavior with such simple rules.
This is an implementation of a Wireworld and can be found at wireworld.klmntn.com.
Decisions, Decisions, Decisions
Framework
How did I settle on Svelte? I'm already working in React and Vue and have worked a little with Ember long ago (I've even played with the now abandoned Cell.js). Angular seems to be a different flavor of the React/Vue/Ember gang. Svelte though looks to have some novel ideas that I wanted to expose myself to.
Graphics
There's really only three options for displaying anything on web:
- HTML + CSS
- SVG (+ light CSS)
- Canvas
The nature of a Wireworld's rendering requirements makes HTML + CSS a no-go. Canvas honestly might be the most appropriate as it can be optimized for high-frequency re-rendering. But future things I'd like to build would work well in SVG and I've already played with Canvas in the past, so I wanted to learn about graphics in SVG!
World Loop
At the base of the simulation, something will need to decide what the next state should be based on the current state. This could be done in a procedural way with a switch / ifs or functional way or object-oriented. I've written about the similarities and differences before. I chose an object-oriented approach where each cell will be an object that responds to nextState
; call nextState
on all the cells and the world's next state has been found.
What I Learned
SVG Just Works
And by this I mean two things. First, SVG does not present a lot to learn above and beyond HTML + CSS (compared to the whole drawing API of a Canvas). I just put SVG tags right into Svelte components and, bang, graphics.
Second, SVG solves some of my biggest pains of drawing on Canvas. On Canvas, everything needs to be constantly erased and redrawn and if I ever want to move my viewport I'll need to do all the math to scale and translate my graphics (or learn and use another library to do it for me). With SVG, one viewBox
attribute on the top <svg>
tag handles all the scaling and translations (written by people who know a lot more about graphics than I do and offloaded to the browser so no JS needs spend time on those calculations).
Unless you have a very high paced game or some 3D graphics to render, I would recommend going down the SVG road.
Svelte Stores are Great
I've always heard that Svelte is good because it compiles down to vanilla JavaScript not needing virtual DOM, making it faster. But the state management available with Svelte's stores is fantastic (suck it Redux). The derived stores open even more possibilities. But by far my favorite are the custom stores: I absolutely love the patterns that opens up.
The State of Capturing Input Sucks
I had no idea how bad listening for things like key presses and dragging events are today. Given how nice and fairly standard a lot of the APIs across browsers and platforms have become, I was shocked at how rough this space is. I think if I had to do this again, this will be one area where I defer to a library (like hammer.js).
Svelte Seems to be Lacking Tutorials
There's plenty of examples over on the REPL site. But those examples have next to no explanation on how they work; nearly every search I tried led me to one of those examples, so it was a bit of work piecing the things together, looking at docs, and doing experiments to get things working.
Wireworlds Like to Light On Fire
Very often a misplaced wire or extra spark will cause my whole creation to devolve into closely packed electrons shooting every which way. This happens shockingly easily and I think makes a wonderful allegory to why our real computers are so hard to make and keep working correctly.
Things To Make and Do in a Wireworld
If you just want to go play with it now: wireworld.klmntn.com. First, go check out the few examples already included. A main building block in Wireworlds is the "transistor":
Like a real P-type transistor; our Wireworld transistor allows the signal to pass when nothing is on the gate, but blocks the signal when the gate is "on" (it even looks like a transistor diagram).
The next piece used in most designs is a signal generator:
Any loop of any shape with an electron moving around it can continuously emit electrons at a regular interval.
And go have fun! Export your creations and comment below.
Top comments (0)