mediocrity.media

Ten Thousand Ways to Move a Bee Wrong

@mdcrty/bees started as an Easter egg and turned into a lesson about systems.

published 7 min read

The first bees appeared on OnliHoney, and they were never meant to be a feature. They were a reward for staying still.

The rule was simple: sit on a page long enough without scrolling or clicking, and bees would start to arrive. Not all at once - one or two at first, then clusters, ramping up the longer nothing disturbed them. They'd look for pollen, explore the comb, leave footprints behind them. Touch the screen and they'd scatter. Wait again and they'd come back.

That behaviour isn't invented. It's the single most accurate thing in the package, and it came from keeping bees rather than from writing code. Bees away from the hive are wary. Move near them and they leave. Stay still - genuinely still, longer than feels natural - and they carry on with what they were doing as though you'd stopped existing. Every colony I've worked has taught me the same lesson: the reward for being boring is that you get to watch.

So the whole thing hangs off idleDelaySec and a cluster ramp. Nothing happens until you've earned it.

Why bees, specifically

Because I keep them, but that's not the whole reason.

A hive is the most legible complex system I've ever had physical access to. Tens of thousands of near-identical creatures, genetically almost indistinguishable, running different jobs, none of them holding a plan. What emerges looks coordinated and isn't. It's simple rules, applied at volume, producing something that appears to be thinking.

That's also a description of how you build game AI, which is the other thing going on here. Somewhere behind this package is a hive management game I haven't built yet. Bees was the first time I stopped approaching a browser as a document and started approaching it as a world with things living in it.

It could have been starlings, or fireflies, or a school of fish - the fascination is the same, and a murmuration is arguably a better demo. But I know bees. I know what they do when it rains, how they move across comb, what a hive sounds like when something's wrong. Building the thing you've actually looked at is a real advantage, and it's not one you can research your way into.

Circles and lines

There isn't a single image file in this package.

Every bee is drawn from mathematical primitives on canvas: circles for the head and the eyes, circles for the abdomen segments, lines for the legs, geometry for the wings. No sprites, no rendered assets, nothing traced from a photograph. When a bee's abdomen flexes, that's the segment circles shifting relative to each other in code, not a frame of animation swapping out.

I want to be clear that this wasn't a purity exercise. It's that the moment you use a sprite, movement becomes a matter of picking frames, and I wanted movement to be a matter of solving it. If the legs are lines and the body is circles, then a bee walking convincingly means the maths of a bee walking is correct - there's nowhere to hide behind good artwork.

Ten thousand ways to move a bee wrong

Drawing a bee is easy. Making something read as a bee is the entire project.

Once I started watching hives properly I was floored by how much motion is going on at any moment. Nothing is still. Wings vibrate even at rest. Bodies shift constantly. Antennae move independently of everything else. Legs adjust in small corrections that have nothing to do with going anywhere. A bee standing perfectly still on comb is doing about six things.

Reproducing even a fraction of that meant six legs that keep pace with the body, wings that beat at a rate that reads as blur rather than flapping, and an abdomen that feels attached to the thorax rather than dragged behind it. And here's the thing every game developer learns eventually: the space of wrong is enormous and the space of right is tiny. Legs slightly too fast reads as a spider. Slightly too slow and it's a wind-up toy. Wings at the wrong frequency and you've got a housefly. The abdomen lagging by a few milliseconds too many turns the whole thing into a rag doll.

You don't reason your way to the right values. You get close, look at it, feel that it's wrong, adjust, and repeat until something clicks - and "clicks" is not a measurable quantity. That was the hardest lesson in the package, and it's the one that transferred most directly to thinking like a game developer rather than a web developer.

Some of it I gave up on. The antennae don't move - they're static, dropped for performance and for the complexity they'd have added, and at the size a bee renders on screen almost nobody will ever notice. I notice. It's on the list, along with most of the things that are on the list for exactly the same reason.

Collision, by comparison, was fine. Collision is just maths.

The invisible honeycomb

The feature I put the most effort into is the one almost nobody consciously sees.

Behind the bees there's a procedural honeycomb. It doesn't appear all at once and it isn't a grid - it grows outward from a single central seed, cell by cell, fading in as it goes. Each cell varies in size and in the shape of its edges, because real comb is built by thousands of bees working independently and it shows. A perfect tessellation reads as wallpaper. A slightly irregular one reads as something that was made.

The cells also have types, and the types have gravity. Honey cells pull workers toward them. Pollen cells are where the footprints come from. The bees aren't wandering randomly across a decorative background - they're responding to a structure with rules, and the structure is doing most of the work of making their movement look purposeful.

It's genuinely difficult to appreciate from the outside. It looks like a faint hexagonal pattern. It is a weighted procedural growth system with an attractor model sitting on top of it. Touch the screen and you might seed a new one.

What I haven't cracked

Plenty.

The honest limit is the third dimension. Bees in a real hive are not distributed across a plane - they're stacked, layered, walking over one another constantly. A frame of brood comb is closer to a sea of bees than a surface with bees on it. Getting that right means solving vertical position, apparent size, occlusion, and the question of when one bee is on another rather than beside it. I haven't solved it. I'm not certain the approach I've taken can be extended to solve it.

There's also a ceiling I hit that has nothing to do with elegance: browser memory. Every bee carries state - position, target, gait phase, wing phase, what it's currently interested in - and the honeycomb underneath carries its own. Push beeDensityRatio and the whole thing degrades. Some of that is optimisable and some of it is just what it costs to simulate individuals rather than fake a crowd. A real hive has fifty thousand bees in it. I am not going to get to fifty thousand bees.

The current version is an approximation and I'd rather say so than pretend otherwise.

Off my own site

The reason this became a package is deeply unglamorous. I wanted the bees on OnliHoney and I wanted to write about them here, which meant two copies of an increasingly complicated codebase and a change to one always needing to be carried to the other by hand. I consume npm packages constantly. How hard could publishing one be?

Not hard, as it happens, but the first one teaches you all the parts nobody writes down. Bees and Digital Rain became the first two packages under @mdcrty, and everything since has been easier for it.

The parts of that work I'd never have anticipated were the boring ones. The canvas spans the full document, which means it has to negotiate with scrollbars, sub-pixel rounding and the specific way different browsers compute viewport width. There is a deliberate one-pixel width adjustment in there purely to stop Chrome on Windows producing a horizontal scrollbar. It is the least interesting line of code in the project and it took a disproportionate amount of my life.

A promise

Looking back, I thought I was learning animation. I was actually learning systems - how simple rules applied to many small actors produce behaviour that looks intelligent from the outside. That's the thing that keeps pulling me back, and it's why starlings and schools of fish sit on the same list.

The movement isn't right yet. The hive isn't complete. The bees are stuck in two dimensions and there aren't enough of them.

But one day Bees will be a game. That's a promise I've made to myself, and writing it down in public is the cheapest way I know of making it harder to quietly drop.

Maybe you'll play it.

See it in action

The wall I'm at

Layered agents on a 2D canvas. Bees crawling over one another with believable apparent depth, no depth buffer, and a sort order that doesn't collapse the moment two of them occupy the same space.

If you've solved that - in a game, a simulation, a visualisation, anywhere - I want to know how. It's the difference between what this is now and what it needs to become, and I don't currently have a route to it.

Side projects have taught me more about engineering than any course or certification I've taken.