feat(bgm): add surface mounting and setup surfaces
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
# bgm-tabletop
|
||||
|
||||
a r3f based interactive component library to work with [bgm](./bgm-format.md) board games. will be used somewhere in the `web` app's bgm inspector routes.
|
||||
|
||||
## 1. stack
|
||||
|
||||
`react` - react, react router, tailwindv4
|
||||
`r3f` - r3f, drei, postprocessing
|
||||
`zustand` - for state management
|
||||
|
||||
## 2. states
|
||||
|
||||
source-of-truth game state:
|
||||
|
||||
```ts
|
||||
{
|
||||
surfaces: Record<string, boolean>, // enabled per surface id
|
||||
paths: Record<string, string[]>, // path -> part list
|
||||
}
|
||||
```
|
||||
|
||||
**assumption:** each piece on the board has a unique id, even tokens of the same type. so each entry in a path's list is a unique piece id, and a piece id never appears twice in the same path. 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 }` 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.
|
||||
|
||||
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.
|
||||
|
||||
## 3. components
|
||||
|
||||
- `SetupLoader` side effect only component that seeds the game state with setup (enabled surfaces + part placement).
|
||||
- `WorldSurfaceView` mounts a surface to world space.
|
||||
- `HudSurfaceView` mounts a surface to hud space.
|
||||
- `PartPlacement` a stable per-part component that positions a part on a surface location. uses the stacking hook (below) to apply the route's stacking strategy.
|
||||
- `PartView` used in `PartPlacement`, creates a mesh from part definition. a standalone component library, so it reuses geometry/shape code from `@tts/mesh` rather than the web app's viewers.
|
||||
|
||||
## 4. stacking
|
||||
|
||||
the format's stacking strategy (curve / limit / align / steps, see `bgm-format.md` §4) is implemented as a hook, e.g. `useStacking(route.stacking, index, stackSize)`, returning the offset/rotation to apply to a piece. `PartPlacement` consumes it.
|
||||
|
||||
## 5. usage
|
||||
|
||||
- we will inspect individual parts with `PartView` in the web app's part inspection route.
|
||||
- as a library, the public surface is the components above: mount a surface with `WorldSurfaceView`/`HudSurfaceView`, seed state with `SetupLoader`, and let `PartPlacement`/`PartView` render the pieces. the web app is one consumer; the library should not assume the web app's routes or store.
|
||||
- a surface is mounted only when enabled; a disabled surface is not rendered.
|
||||
Reference in New Issue
Block a user