docs: add free interaction design to bgm specs
Add the command/dialog split to the state-model and interactions docs, declare role dialog and zone facing in the format spec, and let setups declare which dialogs power open interactions.
This commit is contained in:
@@ -180,6 +180,7 @@ by their `role=` (or, for real files, their filename) for either
|
||||
- `part`
|
||||
- `surface`
|
||||
- `setup`
|
||||
- `dialog`
|
||||
|
||||
a valid object can either be the root or in the list of the yaml block.
|
||||
|
||||
@@ -236,6 +237,10 @@ placed on the board via `setup`, and visualized by routes.
|
||||
- `size` — `size`. The token is scaled to fit in the box. The x/y aspect
|
||||
ratio is kept, but not z (thickness).
|
||||
- `fillet` — number in mm. Used to fillet the shape. Defaults to `0`.
|
||||
- `facing` — the **physical affordance**: the facings the piece supports.
|
||||
A card supports `[face, back, standing]`; a tile supports `[face, back]`.
|
||||
Declares what's *possible*, not what's legal on a given zone (see `surface`
|
||||
`layout`). Defaults to `[face]`.
|
||||
|
||||
#### example
|
||||
|
||||
@@ -366,6 +371,49 @@ initialization.
|
||||
A part's `facing` is seeded into the game state and can change at runtime; it
|
||||
only affects orientation, never the part's texture.
|
||||
|
||||
A setup also declares the **interaction affordances** — which dialogs are the
|
||||
tool for which open interactions on which paths:
|
||||
|
||||
```yaml
|
||||
interactions:
|
||||
- dialog: insert
|
||||
on: [draw, grid] # insertion uses the `insert` dialog on these paths
|
||||
- dialog: shuffle # open the shuffle dialog on any deck
|
||||
```
|
||||
|
||||
`interactions` is a list of declarations: each names a `dialog` (a `role:
|
||||
dialog` definition, see below) and the paths it applies to (`on`, matching by
|
||||
path or by stack). It declares the *interaction surface*, not the legality of
|
||||
the resulting command — rule scripts (later) gate legality. A dialog can be
|
||||
opened by a player gesture or pushed by a rule script; only the trigger differs.
|
||||
|
||||
### dialog
|
||||
|
||||
A `dialog` is declarative content shown in the layer-3 shell. Opening and
|
||||
closing it never issues a command or mutates state; it is pure UI. Its **action
|
||||
buttons** issue commands — the bridge between the dialog and the rule seam.
|
||||
|
||||
```yaml
|
||||
role: dialog
|
||||
type: prompt
|
||||
id: discard
|
||||
title: Choose a card to discard
|
||||
body: |
|
||||
Select a card from your hand.
|
||||
actions:
|
||||
- label: Confirm
|
||||
command: { move: { part: "#chosen", to: /discard } }
|
||||
widget: stack # a stack-of-parts content type
|
||||
```
|
||||
|
||||
A dialog's content is a **title**, **body**, **action buttons**, and an optional
|
||||
`widget`. Supported content types include a **stack of parts** — an ordered,
|
||||
scrolled view of a path's stack with an insertion cursor — which is what powers
|
||||
insertion and shuffling dialogs against the state store.
|
||||
|
||||
`dialog` is a same-shaped definition as the others: `type`/`id` identify it
|
||||
(`type#id` unique in the package), and it collides-checks like `part`/`setup`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Concepts
|
||||
@@ -384,6 +432,11 @@ A surface is enabled or disabled; a disabled surface is not rendered. Setup
|
||||
seeds the enabled set (see §3), and it changes at runtime as the game
|
||||
progresses (e.g. enabling the main board after an expansion-chooser scene).
|
||||
|
||||
Dialogs are **not** part of the state store. The dialog stack is UI state
|
||||
hosted by the shell; opening/closing a dialog never mutates the store. A dialog's
|
||||
action buttons issue commands (see `role: dialog` §3), which is the one-way
|
||||
bridge onto the state.
|
||||
|
||||
### Routing
|
||||
|
||||
A route is a **visualization route**: it maps a part to a location on a
|
||||
@@ -399,6 +452,15 @@ A route is an express-style URL path with named params, plus the `x`, `y`, and
|
||||
`rotation` of its anchor. Routes are defined in a **list**, not a map, so the
|
||||
same route path may appear more than once:
|
||||
|
||||
A route may also declare a zone `facing` — the **legal facing** on that zone.
|
||||
This constrains what the placed parts may be, independent of each part's
|
||||
physical affordance (see `part` `facing`). A state is legal only when the part's
|
||||
facing is in both the part's affordance *and* the zone's legal set. When omitted,
|
||||
the zone is unrestricted beyond the part's affordance. An MTG discard pile
|
||||
requires `[face]`; a play area allows `[face, tap]`; a facedown deck requires
|
||||
`[back]`. The same card is face-up in the discard but tapped in play — the
|
||||
piece's affordance is unchanged, only the zone's rule differs.
|
||||
|
||||
```yaml
|
||||
layout:
|
||||
- route: /dock/:seat
|
||||
|
||||
Reference in New Issue
Block a user