Skip to content

Game State Machine

Organise game flow with distinct states (title, playing, game over). Clean separation of game phases.

state-machinegame-looparchitecture

Overview

A state machine keeps your game organised by separating distinct phases — title screen, gameplay, pause, game over — into independent states. Each state handles its own input, updates, and rendering. Transitions between states are explicit and controlled.

This pattern works identically on any platform. The concept is the same whether you’re coding in 6502, Z80, or 68000.

Pseudocode

; Game states (constants)
STATE_TITLE     = 0
STATE_PLAYING   = 1
STATE_PAUSED    = 2
STATE_GAMEOVER  = 3

; Current state variable
game_state: byte = STATE_TITLE

; Main loop
game_loop:
    switch (game_state)
        case STATE_TITLE:
            call title_update
        case STATE_PLAYING:
            call playing_update
        case STATE_PAUSED:
            call paused_update
        case STATE_GAMEOVER:
            call gameover_update

    goto game_loop

; State handlers
title_update:
    draw title screen
    if fire pressed:
        game_state = STATE_PLAYING
        call init_game
    return

playing_update:
    read input
    update player
    update enemies
    check collisions
    draw game
    if player_dead:
        game_state = STATE_GAMEOVER
    if pause pressed:
        game_state = STATE_PAUSED
    return

paused_update:
    draw "PAUSED"
    if pause pressed:
        game_state = STATE_PLAYING
    return

gameover_update:
    draw "GAME OVER"
    draw final score
    if fire pressed:
        game_state = STATE_TITLE
    return

Implementation Notes

6502/Z80 (jump tables):

; Load state, multiply by 2, use as index into jump table
lda game_state
asl              ; * 2 for 16-bit addresses
tax
jmp (state_table,x)

state_table:
    .word title_update
    .word playing_update
    .word paused_update
    .word gameover_update

68000 (jump tables):

; States are word offsets
move.w  game_state,d0
add.w   d0,d0           ; * 2 for word table
lea     state_table,a0
move.w  (a0,d0.w),d0
jmp     (a0,d0.w)

Trade-offs

AspectCost
CPUMinimal — one table lookup per frame
Memory~20-50 bytes for jump table + state variable
ComplexityLow — very readable and maintainable

When to use: Any game with multiple screens or phases.

When to avoid: Extremely simple single-screen games where a state machine adds unnecessary complexity.

Benefits

  • Clean separation — each state is self-contained
  • Easy debugging — you always know which state you’re in
  • Simple transitions — just set the state variable
  • Extensible — adding new states is trivial