Game AI Basics

Finite State Machines (FSM)

20 min read Intermediate Interactive Demo

The Problem with "If/Else Spaghetti"

When creating a simple enemy, you might start with a bunch of boolean flags: isChasing, isAttacking, isPatrolling. Soon, your code looks like a nightmare of nested if statements.

The solution? Finite State Machines. An FSM ensures an enemy can only be in one state at a time, and clearly defines how to switch between them.

The State Pattern

Instead of one giant update function, we split behaviors into separate classes or objects. Each "State" handles its own update logic.

state-structure.js
const PatrolState = {
    enter: (enemy) => {
        enemy.color = 'green';
        enemy.findNextWaypoint();
    },
    update: (enemy) => {
        enemy.moveToWaypoint();
        
        // Transition Condition
        if (enemy.canSeePlayer()) {
            return 'CHASE'; // Switch state!
        }
    },
    exit: (enemy) => {
        console.log("Stopped patrolling");
    }
};

Interactive AI Demo

Move your mouse (the "Player") near the Bot. Observe how it switches behavior based on distance.

Enemy AI Simulation
Current State: PATROL Distance: 0px

The State Machine Manager

To glue it all together, we need a simple manager that handles the current state and switching.

state-machine.js
class StateMachine {
    constructor(initialState, owner) {
        this.currentState = initialState;
        this.owner = owner;
        this.currentState.enter(this.owner);
    }

    update() {
        // Run current state logic
        const nextStateName = this.currentState.update(this.owner);

        // Handle transition if a new state is returned
        if (nextStateName) {
            this.changeState(nextStateName);
        }
    }

    changeState(newStateName) {
        this.currentState.exit(this.owner);
        this.currentState = States[newStateName];
        this.currentState.enter(this.owner);
    }
}