- Phaser 3 + bitECS 0.4 + TypeScript + Vite stack - BootScene with title screen - 6 cursor rules (project context, agent workflow, ECS, chemistry, Phaser, data) - Vitest configured with happy-dom - GDD, engine analysis, implementation plan, progress tracking Co-authored-by: Cursor <cursoragent@cursor.com>
66 lines
1.9 KiB
Plaintext
66 lines
1.9 KiB
Plaintext
---
|
|
description: bitECS 0.4 component and system conventions
|
|
globs: src/ecs/**/*.ts
|
|
alwaysApply: false
|
|
---
|
|
|
|
# ECS Patterns (bitECS 0.4)
|
|
|
|
## Components — Plain Objects with Arrays
|
|
```typescript
|
|
// ✅ GOOD: plain object with number arrays
|
|
export const Position = { x: [] as number[], y: [] as number[] };
|
|
export const Health = { current: [] as number[], max: [] as number[] };
|
|
|
|
// ❌ BAD: old API (defineComponent, Types) — removed in 0.4
|
|
```
|
|
|
|
## Entity Lifecycle
|
|
```typescript
|
|
import { createWorld, addEntity, addComponent, removeEntity } from 'bitecs';
|
|
|
|
const world = createWorld();
|
|
const eid = addEntity(world);
|
|
addComponent(world, eid, Position);
|
|
Position.x[eid] = 100;
|
|
Position.y[eid] = 200;
|
|
```
|
|
|
|
## Queries — Direct Function Calls
|
|
```typescript
|
|
import { query, Not } from 'bitecs';
|
|
|
|
// ✅ 0.4 API: query(world, components)
|
|
const entities = query(world, [Position, Velocity]);
|
|
for (const eid of entities) {
|
|
Position.x[eid] += Velocity.x[eid] * delta;
|
|
}
|
|
|
|
// Operators: Not, And, Or, Any, None
|
|
const stationary = query(world, [Position, Not(Velocity)]);
|
|
```
|
|
|
|
## Observers (replace enterQuery/exitQuery)
|
|
```typescript
|
|
import { observe, onAdd, onRemove } from 'bitecs';
|
|
|
|
observe(world, onAdd(Position), (eid) => { /* entity gained Position */ });
|
|
observe(world, onRemove(Position), (eid) => { /* entity lost Position */ });
|
|
```
|
|
|
|
## Systems — Pure Functions
|
|
```typescript
|
|
export const movementSystem = (world: World, delta: number) => {
|
|
for (const eid of query(world, [Position, Velocity])) {
|
|
Position.x[eid] += Velocity.x[eid] * delta;
|
|
Position.y[eid] += Velocity.y[eid] * delta;
|
|
}
|
|
};
|
|
```
|
|
|
|
## Rules
|
|
- Components = plain objects with `[] as number[]` fields
|
|
- Never store strings in components — use numeric IDs, look up in registry
|
|
- Systems must not create Phaser objects — only the sync bridge does that
|
|
- Parameter order: `addComponent(world, eid, component)` (world first, then eid)
|