You're reading the 2.x docs. quantum-forge 3.0 is out: this page in 3.x / migration guide

Skip to content

Engine ​

The Engine<TState> base class is the state coordinator at the heart of every game.

Usage ​

typescript
import { Engine } from "quantum-forge-engine/engine";

interface GameState {
  player: { x: number; y: number; health: number };
  enemies: Enemy[];
  score: number;
}

class MyEngine extends Engine<GameState> {
  constructor(logger?: any) {
    const initialState: GameState = {
      player: { x: 400, y: 300, health: 100 },
      enemies: [],
      score: 0,
    };
    super(initialState, { logger });
  }

  getHelpers() {
    return {
      movePlayer: (dx: number, dy: number) => {
        const state = this.getState();
        this.setState({
          ...state,
          player: { ...state.player, x: state.player.x + dx, y: state.player.y + dy },
        });
      },

      spawnEnemy: (x: number, y: number) => {
        const state = this.getState();
        this.setState({
          ...state,
          enemies: [...state.enemies, { x, y, health: 50 }],
        });
      },

      addScore: (points: number) => {
        const state = this.getState();
        this.setState({ ...state, score: state.score + points });
      },
    };
  }

  reset() {
    this.setState({
      player: { x: 400, y: 300, health: 100 },
      enemies: [],
      score: 0,
    });
  }
}

API ​

MethodDescription
getState()Returns Readonly<TState>. Spread it into a new object instead of mutating
getHelpers()Abstract. Implement it to return state-mutating functions
reset()Abstract. Implement it to reset to initial state

setState(newState) is protected. It is the helper's tool, not part of the public surface, so callers outside the subclass cannot reach it.

Config ​

typescript
interface EngineConfig {
  logger?: LoggerInterface;
  eventBus?: EventBus<any>;
}

With an eventBus, every setState() emits "state-changed" carrying { state }. That is the hook renderers and UI subscribe to instead of polling getState().

typescript
class MyEngine extends Engine<GameState> {
  constructor(config: EngineConfig = {}) {
    super(initialState, config);
  }
  // ...
}

const eventBus = new EventBus<MyGameEvents>();
const engine = new MyEngine({ logger, eventBus });

eventBus.on("state-changed", ({ state }) => hud.update(state));

See Events.

Quantum registry ​

Games pass a quantum registry to the engine and expose quantum operations through helpers:

typescript
class PongEngine extends Engine<PongState> {
  private registry: QuantumRegistry;

  constructor(logger?: any) {
    super(initialState, { logger });
    this.registry = new QuantumRegistry(logger);
  }

  getHelpers() {
    return {
      enterQuantumZone: (ballId: string) => {
        this.registry.entangleSplit(ballId, `${ballId}-ghost`);
        const state = this.getState();
        // Add ghost ball to state...
        this.setState({ ...state });
      },

      scoreBall: (ballId: string) => {
        const exists = this.registry.measureExistence(ballId);
        const state = this.getState();
        this.setState({ ...state, score: state.score + (exists === 1 ? 1 : 0) });
      },
    };
  }
}

Powered by Quantum Forge