Skip to content

About

AI-first, pure-data ECS 2D game engine — headless core + PixiJS rendering bridge

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Sub-Engine

The layer beneath the game.
AI-first, pure-data ECS 2D engine — headless core with an optional PixiJS bridge.

packages @sub-engine/core @sub-engine/pixi MIT TypeScript strict 201 tests zero dependencies by Type-3 Studio

Quick start · Why · Reference games · Identity


npx create-sub-engine my-game
cd my-game && npm install && npm run dev

Why

Most 2D engines make you choose between a simulation you can test and a game you can look at. Sub-Engine doesn't: the simulation is pure data and runs in Node, and PixiJS is a bridge you attach when you want pixels.

  • Entities are integers. There is no object graph to serialise, diff or inspect. An agent can read the entire world state as JSON and write it back.
  • The core has zero dependencies. @sub-engine/core has no dependencies field at all and will not touch window. Simulation logic runs in a test, a CI job or a game server.
  • Systems are pure functions. (registry, dt) => registry. No hidden state, no lifecycle, nothing to mock.
  • Every write is validated. Schemas are registered once; a typo in a component name throws at the call site instead of at 3am.
  • Typing is structural. Registry<M> is parameterised by your ComponentMap, so getEntitiesWith destructures to exactly the components the query asked for.

Packages

Package npm Description
@sub-engine/core npm Headless ECS (Registry, schemas, systems, utilities) — zero browser deps
@sub-engine/pixi npm PixiJS 8 rendering bridge (responsive, sprites, tilemaps, debug overlay)
create-sub-engine CLI Scaffold new game projects

Quick Start

npm install @sub-engine/pixi pixi.js
import { createRegistry, registerSchema } from '@sub-engine/core'
import { createResponsiveContainer, DebugOverlay } from '@sub-engine/pixi'
import { Application } from 'pixi.js'

registerSchema('Position', { x: { type: 'number', required: true }, y: { type: 'number', required: true } })

const app = new Application()
await app.init({ resizeTo: window })

const registry = createRegistry()
const player = registry.createEntity()
registry.addComponent(player, 'Position', { x: 0, y: 0 })

Features

  • Pure-data ECS — Entities are integers. Components are flat JSON. Systems are pure functions (registry, dt) => registry.
  • Headless-first — Run simulation in Node.js. No browser needed for game logic.
  • Fully typed — Generic Registry<M> parameterized by your ComponentMap interface.
  • Schema validation — Every write validates against registered schemas. Catches typos instantly.
  • Built-in systems — Movement, combat, camera (follow + clamp + zoom), AABB collision (groups/masks), pathfinding (A*), particles, audio, z-ordering, tile maps.
  • Utilities — Spatial hash grid, fixed-timestep game loop (GameLoop), entity factory, undo/redo, serialization, debug overlay (F12).
  • Tiled support — Load .tmj/.tsj maps. Spritesheet + collection-of-images tilesets. Procedural map generation.
  • Columnar storage — Optional createColumnarRegistry() for 11x faster bulk numeric operations.
  • AI-friendly — Clean JSON data, no classes, no hidden state.

Architecture

┌─────────────────────┐     ┌──────────────────────────┐
│  @sub-engine/core   │     │   @sub-engine/pixi       │
│                     │     │                          │
│  Registry           │     │  createResponsiveContainer│
│  Entity CRUD        │     │  createAnimManager       │
│  Schema validation  │     │  createTiledMapRenderer  │
│  Built-in schemas   │     │  DebugOverlay            │
│  Common systems     │     │  (depends on core)       │
│  Utilities          │     │                          │
└─────────────────────┘     └──────────────────────────┘
         ▲                            ▲
         │                            │
         └──────── game code ─────────┘
              (imports both)

Reference Games

The games/ directory contains 10 complete reference implementations. Run any with:

npm run dev:td        npm run dev:castle     npm run dev:movement
npm run dev:combat    npm run dev:map        npm run dev:input
npm run dev:serial    npm run dev:character  npm run dev:camera
npm run dev:tilemap

Read games/tower-defense/ first — it's the most complete reference.

Development

npm install           # Install workspace
npm run dev           # Root playground (arrow key movement demo)
npm run typecheck     # Full type check (0 errors)
npm test              # Run 201 engine tests
npm run build:pkgs    # Build both packages to dist/

Project Structure

├── packages/
│   ├── core/            # @sub-engine/core (headless ECS)
│   ├── pixi/            # @sub-engine/pixi (rendering bridge)
│   └── create-app/      # create-sub-engine CLI + template
├── games/               # 10 reference implementations
├── tests/               # 201 engine tests (vitest)
├── src/                 # Root dev playground
├── package.json         # Workspace root
└── tsconfig.json

Identity

The mark is a block in section — two seams the data rests on, one gate every system crosses, one entity in flight.

Sub-Engine brand system

Assets live in assets/ and the full system — exploration, construction, specification and the rules it ships under — is in brand/.

lockup assets/logo-lockup.svg
mark assets/logo-mark.svg — 32px and up
inverse assets/logo-mark-inverse.svg — dark surfaces
favicon assets/favicon.svg — the designed 16px cut

Solar orange #FF5A1F is inherited from Type-3 Studio; everything else is Sub-Engine's own.

License

MIT

About

AI-first, pure-data ECS 2D game engine — headless core + PixiJS rendering bridge

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages