DEV Community

Cover image for Why I Had to Learn About State Machines to Build a Desktop Pet
Mika Flowers
Mika Flowers

Posted on

Why I Had to Learn About State Machines to Build a Desktop Pet

While building Mochi, I ran into a problem that a lot of us hit eventually: making something happen is easy. Controlling when it happens, how long it lasts, and what comes before and after is the hard part.

It usually starts innocently enough:

If an application opens, play this animation
If the mouse moves here, make this happen
Enter fullscreen mode Exit fullscreen mode

And that works... for a while. Then the software grows up a little, and the questions get harder:

  • What happens when a user clicks while an animation is already playing?
  • What if the application closes halfway through an animation?
  • What if the same event fires twenty times in a row?

The If-Statement Trap

The natural instinct is to just add more conditions:

if terminal_open
if terminal_open and not dragging
if terminal_open and not dragging and not sleeping
Enter fullscreen mode Exit fullscreen mode

This works for a little while too — until it doesn't. Eventually the logic becomes too tangled to reason about or maintain. At that point, you're not actually solving the complexity anymore.

You're just spreading it around.

As the app grows, even basic questions become surprisingly hard to answer:

"What is my program actually doing right now?"
"What is it allowed to do next?"
"Who gets control when two things happen at once?"

That's the point where I stopped writing more conditionals and started learning about states, transitions, and lifecycles.

So, What the Heck Is a State?

A state is simply a description of what something is doing, or what condition it's currently in.

Here's the small, explicit state machine I ended up using in Mochi:

state machine diagram for Mochi

At any given moment, Mochi is in exactly one of these states:

IDLE
WALKING
SLEEPING
DRAGGING
TYPING
WATCHING_VIDEO
Enter fullscreen mode Exit fullscreen mode

Instead of every part of the system independently deciding which animation should play, the program maintains a single piece of truth:

Mochi is currently DRAGGING

Every other part of the app makes decisions based on that one fact. And suddenly, a bunch of edge cases answer themselves:

  • If Mochi is already being dragged, should an idle animation interrupt it? Probably not.
  • If Mochi is sleeping, should a random walking timer fire? Probably not.
  • If Mochi is typing and I pick him up, should dragging override typing? Probably yes.

Once you start asking questions like these, you're no longer thinking about individual animations in isolation.

You're thinking about behavior over time — and that shift is what a state machine actually buys you.

Top comments (0)