Phase 0: Project setup for agent-driven development
- 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>
This commit is contained in:
65
.cursor/rules/ecs-patterns.mdc
Normal file
65
.cursor/rules/ecs-patterns.mdc
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
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)
|
||||
Reference in New Issue
Block a user