DEV Community

Trent Best
Trent Best

Posted on

Stop Getting Blocked: How a Simple Design Pattern Unlocks Your Project's Complex Logic

Have you ever started a project—a simple game, a complex UI, or any interactive system—only to feel completely overwhelmed by the chaos of your main logic loop? You add an if statement for one behavior, and it breaks another. You try to fix it, and it breaks three more. Sound familiar?

You're not alone. This is the moment when many new developers get blocked.

But what if I told you there's a simple, powerful structure you can design before you even write the code? This design acts as a scaffold, letting you build complex, reliable behavior piece by piece.

That structure is called the Finite State Machine (FSM), and we're going to break down a demo to show you how it works and how it can unblock your next project.


The Power of a Structured Design: FSMs

In its simplest form, a Finite State Machine is a way to model anything that behaves differently based on its current status. Every piece of logic is isolated into a State, and you define strict Transitions (rules) for moving between them.

This learned structure is the key to escaping the "spaghetti code" trap:

  1. Define Intent: Draw a diagram of what you want to happen.
  2. Implement Isolation: Write the code for each State and Transition in isolation.
  3. Know It Works: Since the FSM framework manages the flow, you know the overall logic will function as designed—you just have to fill in the behavior for each small piece.

Let's see this in action using the Quick Brown Fox demo.


Case Study: The Quick Brown Fox Demo

Our simulation is based on the classic phrase, "The quick brown fox jumps over the lazy sleeping dog". We have two agents, and we use FSMs to define their entire behavioral logic.

1. The Simulation Setup (SimpleDemoContext.cs)

This is the central application, which manages the world and the agents.

  • The Fox starts at Position 0.
  • The Dog starts at Position 3.
  • The goal is for the Fox to reach the WinPosition of 10.

Every frame, the simulation context performs three steps:

  1. Clear vision and collision data for all agents.
  2. Perform Vision and Collision checks between agents (our world rules).
  3. Calls FSM_API.Interaction.Update("Update") to tell every agent's FSM to run its logic for the current frame.

2. Modeling the Fox: The QuickBrownFoxFSM

The Fox's FSM is a perfect example of how a simple diagram can define complex behavior. The fox primarily Walks, Jumps over obstacles (the dog), or Flees if it collides.

Finite State Machine showing how the fox behaves:  Walking, jumping, fleeing, and Mangled (which is driven by the dog) with the transitions: ShouldJump, ShouldFlee, and ShouldLand

Here is a summary of the Fox's logic:

State Transition Condition Action (OnUpdate)
Walking ShouldJump: A visible agent is within 2 units. ShouldFlee: Collision with a dog. Increments position by 1 (Speed).
Jumping ShouldLand: Position is greater than or equal to JumpEnd (2 steps after jumping started). Increments position by 1.
Fleeing None (Terminal state). Increments position by 2 (Speed).
Mangled None (Terminal state). Outputs current status.

Notice how clean the logic is for a State like Walking:

private void OnUpdateWalking(IStateContext context)
{
    if (context is QuickBrownFox fox)
    {
        // Simple: Just move forward by its speed
        fox.Position += fox.Speed; 
        Console.WriteLine($"{fox.Name} is walking:  {fox.Position}");
    }
}
Enter fullscreen mode Exit fullscreen mode

Its complexity comes from the Transitions—the rules that change the state. The Fox will only switch from Walking to Jumping if the condition in ShouldJump is met:

private bool ShouldJump(IStateContext context)
{
    if (context is QuickBrownFox fox)
    {
        // Transition rule: Look at all visible agents (provided by SimpleDemoContext)
        foreach (var visible in fox.VisibleAgents)
        {
            var distance = visible.Position - fox.Position;
            if(distance <= 2) // If the visible agent is too close (within 2 units)
            {
                return true;
            }
        }
    }
    return false;
}
Enter fullscreen mode Exit fullscreen mode

The Fox isn't doing collision logic; the main simulation is. The Fox is only checking its readily available VisibleAgents list, keeping its own code extremely focused!

3. Interacting Agents: The LazyDogFSM

The Dog's behavior is even simpler. It starts Sleeping until an external force (a collision) wakes it up.

Finite State Machine for the Dog showing it's states: Sleeping, Awake, Chasing, Mangling and it's Transitions:  IsAwake, ShouldChase, and IsMangling

  • Sleeping to Awake: The transition condition IsAwake returns true if a collision has occurred.
  • Awake to Chasing: The dog sees the fox (ShouldChase is true) and begins to chase at speed 3.
  • Chasing to Mangling: Collision with the Fox occurs again (IsMangling is true).

The true power is seen in the Mangling state, which demonstrates Inter-FSM Communication:

private void OnEnterMangling(IStateContext context)
{
    if (context is LazySleepingDog dog)
    {
        Console.WriteLine($"{dog.Name} has started Mangling the fox!");
        // The dog reaches into the Fox's FSM and forces a state change!
        dog.CollidedAgents.FirstOrDefault()?.State.TransitionTo("Mangled");
    }
}
Enter fullscreen mode Exit fullscreen mode

The Dog doesn't need to know how the Fox gets mangled, only that it can force the Fox's FSM to the terminal Mangled state. This isolation keeps the Dog's code simple, too.


Your Takeaway: Design Before You Code

This simple example proves the structure works:

  • No monolithic if/else block is needed in one huge update function.
  • Design First: You can draft the FSM diagram first and use it as a blueprint for development.
  • Focus: You only need to think about what happens in that specific state and what rules trigger a specific transition.

This approach is your new scaffolding tool. It lets you design robust, complex applications without getting blocked by logic that breaks down the line. You know what needs to be implemented because you've already defined it on your diagram!

Get the FSM_API

You can access and support the FSM_API at the following links:

GitHub Repository: https://github.com/trentbest/fsm_api

NuGet Package: https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API/

💖 Support Us: https://www.paypal.com/paypalme/TheSingularityWorkshop

The Singularity Workshop

The singularity Workshop - a vortex of energy forming an eye with an internal computer background with circuitry

Top comments (0)