Quick Start • Features • Documentation • Examples • Philosophy • Roadmap
|
|
Entities = IDs • Components = Data • Systems = Logic
Built on proven ECS patterns for maximum performance and maintainability. Learn more →
bun add @danjdewhurst/ecs-tsRequirements: Bun 1.2+
import { World, BaseSystem, type Component } from "@danjdewhurst/ecs-ts";
// 1. Define components (pure data)
interface Position extends Component {
readonly type: "position";
x: number;
y: number;
}
// 2. Create systems (game logic)
class MovementSystem extends BaseSystem {
readonly name = "MovementSystem";
readonly priority = 1;
update(world: World, deltaTime: number): void {
const entities = this.queryEntities(world, "position", "velocity");
for (const entityId of entities) {
const pos = world.getComponent<Position>(entityId, "position");
const vel = world.getComponent<Velocity>(entityId, "velocity");
if (pos && vel) {
pos.x += vel.dx * deltaTime;
pos.y += vel.dy * deltaTime;
}
}
}
}
// 3. Create world and run
const world = new World();
world.addSystem(new MovementSystem());
const entity = world.createEntity();
world.addComponent(entity, { type: "position", x: 0, y: 0 });
world.addComponent(entity, { type: "velocity", dx: 10, dy: 5 });
world.update(1 / 60); // Update at 60 FPS| Concept | Description | Example |
|---|---|---|
| World | Container for all ECS data | const world = new World() |
| Entity | Unique ID representing a game object | world.createEntity() |
| Component | Pure data attached to entities | { type: 'health', hp: 100 } |
| System | Logic that processes entities | class MovementSystem extends BaseSystem |
| Query | Find entities by components | world.query('position', 'velocity') |
📡 Event System - Decoupled communication
// Subscribe to events
world.subscribeToEvent("player-death", (event) => {
console.log(`Player ${event.data.playerId} died`);
});
// Emit events
world.emitEvent({
type: "player-death",
timestamp: Date.now(),
data: { playerId: entity },
});🔗 System Dependencies - Automatic execution ordering
class PhysicsSystem extends BaseSystem {
readonly name = "PhysicsSystem";
readonly priority = 1;
// No dependencies - runs first
}
class CollisionSystem extends BaseSystem {
readonly name = "CollisionSystem";
readonly priority = 10; // Higher priority, but runs AFTER physics
readonly dependencies = ["PhysicsSystem"]; // Explicit dependency
}
class DamageSystem extends BaseSystem {
readonly name = "DamageSystem";
readonly priority = 1;
readonly dependencies = ["CollisionSystem"]; // Runs after collision
}
// Systems execute in dependency order: Physics → Collision → Damage
// Regardless of add order or priority
// Validate dependencies before adding
const validation = world.validateSystemDependencies([
new PhysicsSystem(),
new CollisionSystem(),
]);
// Get execution order
const order = world.getSystemExecutionOrder();
// [PhysicsSystem, CollisionSystem, DamageSystem]
// View dependency graph
const graph = world.getSystemDependencyGraph();Benefits:
- ✅ Prevents logic errors from incorrect system ordering
- ✅ Self-documenting system relationships
- ✅ Detects circular dependencies with helpful errors
- ✅ Foundation for future parallel execution
🌐 Multiplayer - WebSocket server built-in
import { GameServer } from "@danjdewhurst/ecs-ts/websocket";
const server = new GameServer(world, {
port: 3000,
maxClients: 100,
});
await server.start();🔌 Plugin System - Extend with custom functionality
class MyPlugin implements Plugin {
readonly name = "MyPlugin";
readonly version = "1.0.0";
async initialize(world: World): Promise<void> {
// Setup systems, components, etc.
}
}
const pluginManager = new PluginManager();
await pluginManager.loadPlugin(new MyPlugin());
await pluginManager.initializeAll(world);🛠️ CLI Scaffolding - Interactive code generation
# Launch interactive scaffolding wizard
bun run scaffold
# OR use direct commands with aliases
bun run scaffold component # Generate component (alias: c, comp)
bun run scaffold system # Generate system (alias: s, sys)
bun run scaffold example # Generate example (alias: e, ex)
bun run scaffold game # Generate game template (alias: g)
bun run scaffold plugin # Generate plugin (alias: p, plug)
bun run scaffold --help # Show all commands and options
# Automatically creates tests and updates index files
# Follows ECS patterns and project conventionsGenerate:
- Components with custom properties and factory functions
- Systems with dependencies and component queries
- Examples demonstrating specific functionality
- Game templates with complete setups
- Plugins following plugin architecture
⚡ Performance Tools - Optimization utilities
// Object pooling
const bulletPool = new ObjectPool(
() => ({ x: 0, y: 0, active: false }),
(bullet) => {
bullet.active = false;
}
);
// Dirty tracking for selective updates
world.dirtyTracker.markDirty(entityId, "position");# Clone and run examples
git clone https://github.com/danjdewhurst/ecs-ts.git
cd ecs-ts && bun install
bun examples/basic-example.ts # Core ECS
bun examples/system-dependencies-example.ts # System dependencies
bun examples/event-system-example.ts # Events
bun examples/websocket-example.ts # Multiplayer
bun examples/plugin-system-example.ts # Plugins
bun examples/performance-optimization.ts # Optimization# Install dependencies
bun install
# Development commands
bun test # Run tests (100% coverage)
bun run typecheck # Type checking
bun run check # Lint & format
bun run build # Build for production
bun run scaffold # Interactive code scaffolding
# Commit with conventional commits
bun run commit # Interactive commit helper- ✅ 24 test suites with comprehensive coverage
- ✅ Core ECS, Events, WebSocket, Plugins, Performance
- ✅ Unit and integration tests
- ✅ 100% critical path coverage
| Operation | Complexity | Notes |
|---|---|---|
| Entity Creation | O(1) | ID recycling |
| Component Add/Remove | O(1) | Hash map |
| Single Query | O(1) | Archetype lookup |
| Multi Query | O(k) | k = matching entities |
| System Update | O(n) | n = active entities |
Contributions welcome! Please follow conventional commits and ensure all tests pass.
See CONTRIBUTING.md for details.
MIT © 2025 danjdewhurst
GitHub • npm • Issues • Philosophy • Roadmap