feat: add facing orientation to parts

Replace the face/back boolean with a three-state facing (face, back,
standing) seeded from setup placements. Parts now orient about the
anchor at the resting face/edge, so back-down parts sit on the table
instead of below it and standing parts rest on their bottom edge.
This commit is contained in:
2026-08-10 11:47:58 +08:00
parent aa23e93b3f
commit d663f4afea
13 changed files with 126 additions and 36 deletions
+3 -3
View File
@@ -21,19 +21,19 @@ source-of-truth game state:
interface PartState {
path: string, // the path key this part is on
index: number, // the part's position in its path's stack
face: boolean, // whether the part's face is up
facing: 'face' | 'back' | 'standing', // how the part is oriented on the board
}
```
**assumption:** each piece on the board has a unique id, even tokens of the same type. so a part id appears at most once, and a path's ordered children (for stacking) are derived from the map by sorting on `index`. this makes the render list keyed by piece id stable and unambiguous.
derived surface render state: game state + surface routes => map of piece id to `{ surface, route, candidate, index, stackSize, face }` for rendering on a surface. keys of this map makes a stable render list.
derived surface render state: game state + surface routes => map of piece id to `{ surface, route, candidate, index, stackSize, facing }` for rendering on a surface. keys of this map makes a stable render list.
- `route` - the matched route.
- `candidate` - the matched candidate for a `:param` route, carrying its anchor `x`/`y`/`rotation`. absent for routes without candidates.
- `index` - the piece's position in its path's stack.
- `stackSize` - the number of pieces on the path.
- `face` - whether the piece's face is up.
- `facing` - how the piece is oriented on the board (`face` / `back` / `standing`).
the render map is per enabled surface: a piece may appear on more than one enabled surface (e.g. an expansion path and the main board), and each is rendered independently.