Pixl - A Predictable Pal in a Pixelated Playground

Give me a clock, three counters, and a few coloured squares, and I will show you something that sleeps under the stars: Pixl.


A Keychain, a Clock, and a Dream

In the midst of the 2008 financial crysis, my pocket rattled with a plastic egg that beeped for food every two hours. It died often. It taught persistence, empathy, and the power of a single pixel turning from 😊 to 😢.

Pixl itself

Pixl is a love-letter to that era—an attempt to prove that, even in a world of trillion-parameter transformers, small deterministic systems still spark genuine delight. There is no server, no randomness, no hidden neural net. Only the browser’s Date object, three integers, and a handful of SVG sprites that look best on a pretend-CRT background.

Pixl snoozing under a summer moon

Go play with Pixl right now at pixl.humbertowoody.xyz — the code lives on
GitHub if you want to fork, tweak, or time-travel.


Three Numbers, Infinite Gestures

Stat Role Good direction
happiness emotional brightness higher
hunger distance from a full tummy lower
energy readiness to bounce on the screen higher

Every 30s the numbers drift: happinesst+30=happinesst    2hungert+30=hungert  +  3energyt+30=energyt    1\begin{aligned} \text{happiness}_{t+30} &= \text{happiness}_{t}\;-\;2 \\ \text{hunger}_{t+30} &= \text{hunger}_{t} \;+ \;3 \\ \text{energy}_{t+30} &= \text{energy}_{t} \;- \;1 \end{aligned}

Left alone for half an hour Pixl grows hungry, drowsy, and a little gloomy—entropy with boundaries.

Pixl stats


The Breath of the Machine

animation(h)  =  {sleeping  or  sleepy,22:00h<5:00awake  and others,5:00h<22:00\text{animation}(h) \;=\; \begin{cases} \texttt{sleeping} \;\text{or}\; \texttt{sleepy}, & 22:00 \le h < 5:00 \\ \texttt{awake} \;\text{and others}, & 5:00 \le h < 22:00 \end{cases}

A laptop in Tokyo and a phone in Tijuana will see the same snores at the same moment. Pixl exists as a single, shared creature drifting through each visitor’s local midnight.


Five Axioms of Pixl’s World

  1. Circadian
    Pixl dozes whenever the local clock reads between 10 PM and 5 AM. h[22,24)[0,5)    sleeping/sleepyh \in [22,24) \cup [0,5) \;\Longrightarrow\; \texttt{sleeping/sleepy}

  2. Dominant Need
    Physical necessities outrank mood: starving pixels grumble, exhausted ones sag. hunger>70    idle_hungryenergy<20    idle_tired\begin{aligned} \text{hunger} > 70 \;&\Longrightarrow\; \texttt{idle\_hungry}\\ \text{energy} < 20 \;&\Longrightarrow\; \texttt{idle\_tired} \end{aligned}

  3. Mood Gradient
    The emotional dial swings between 😊 , 😐 , and 😢 depending on morale. {happiness>70idle_happyhappiness<30idle_sadotherwiseidle_neutral\begin{cases} \text{happiness} > 70 &\Rightarrow \texttt{idle\_happy}\\[4pt] \text{happiness} < 30 &\Rightarrow \texttt{idle\_sad}\\[4pt] \text{otherwise} &\Rightarrow \texttt{idle\_neutral} \end{cases}

  4. Reinforcement
    Sustained affection lifts Pixl into brief, exuberant euphoria. (pet+play)24h>5    animation=idle_happy    idle_ecstatic(\text{pet}+\text{play})_{24h} > 5 \;\land\; \texttt{animation}=\texttt{idle\_happy} \;\Longrightarrow\; \texttt{idle\_ecstatic}

  5. Scarcity of Kindness
    Limiting each action to three times per day turns care into a ritual rather than a click-spree. a{feed, pet, play},  countday(a)3\forall\,a \in \{\text{feed, pet, play}\},\; \text{count}_{\text{day}}(a) \le 3

Pixl stats text summary

Maslow’s hierarchy distilled to five if statements—predictable yet expressive.

Skip one meal and you meet a grumbling blob; lavish attention and you earn that rare ecstatic bounce.


Portraits in Thirty-Two Squares

All art is plain SVG8×88\times8 or 32×3232\times32 grids rendered with the property shapeRendering="crispEdges". The result are simple, pixel-perfect images that evoke the retro charm of early computer graphics.

Pixl idle sleeping

A sleeping Pixl, eyes closed, dreaming of pixelated adventures.


A Walk Through the Source

Conceived as a single event-loop, Pixl’s logic is a few hundred lines of lightweight JavaScript. The core function, tick, runs every 30 seconds, updating the creature’s state and rendering the scene.

function tick(now):  
  stats ← loadStats()   # from localStorage  
  stats ← decay(stats)  # metabolic drift  
  scenery ← chooseScenery(now)  
  animation ← chooseAnimation(stats, now)  
  render(scenery, animation, stats)

A few key functions drive the experience:

The entire illusion stands on ≈200 lines of logic and the viewer’s willingness to anthropomorphise.


Implementation in Brief

Layer Choice & Rationale
Framework Next.js 14, App Router – static export, zero backend needed
State & I/O React hooks + localStorage
Art Pipeline In-code SVG sprites (shapeRendering="crispEdges")
Styling Tailwind; font VT323 for gentle CRT nostalgia
Hosting Static files on GitHub Pages

Want to expand the universe? Add a PR to the GitHub repo with some new clothing, behaviour, or scenery! Anything to keep Pixl’s world fresh and captivating.


Constraint as a Lens

The contemporary narrative says emergent behaviour requires a datacentre’s worth of silicon. Pixl demurs. Here, a single event-loop— armed only with a clock and three counters—displays recognisable moods, invites care, and even teaches patience through daily limits. The marvel is not that such simplicity suffices but that our minds long to complete the pattern.

Technology, at its most humane, is a conversation between what is specified and what is imagined. Pixl is my contribution to that conversation: a reminder that small, transparent mechanisms can still whisper stories.

As always, if you have any comments, want to chat, kill some time or cook some pancakes, you can always find me on Twitter: @humbertowoody.

Pixl itself

Go play with Pixl right now at pixl.humbertowoody.xyz — the code lives on
GitHub if you want to fork, tweak, or time-travel.