← all games
match-3-sol-medium — GAME.md
# Starbloom
## Player experience
Starbloom is a portrait match-3 game about restoring a magical grove. A move should feel tactile before it is committed and celebratory after it succeeds: the dragged charm follows the pointer, both charms visibly exchange places, matches pause for recognition, cleared charms burst into colored starlight, and that starlight flows into the score.
The game supports mouse, touch, and tap-two-neighbors input. A valid drag uses the dominant axis and previews only one adjacent cell. Releasing commits the swap. Invalid swaps visibly return to their original cells without spending a move.
## Scene graph and ownership
The shipped build currently uses one YAGE scene with explicit screen modes. The next structural pass will replace those modes with `LevelMapScene`, `LevelIntroScene`, `PlayScene`, and `ResultScene`; pause remains an overlay because it preserves the live board.
Within play:
- `GameController` owns turn sequencing, objectives, level results, and orchestration.
- `BoardModel` owns deterministic board rules and contains no presentation state.
- `BoardGesture` owns pointer capture and drag-preview calculations.
- `MatchEffects` owns transient particles, score glow, and special activation effects.
- The renderer reads board and effect state but does not mutate game rules.
- `GroveAudio` owns procedural sound playback.
- `Inventory` and `Abilities` remain YAGE addon components.
The source tree uses a layer-first organization because the project is small: `game/` for rules, `input/` for gestures, `presentation/` for visuals, `audio/` for sound, and `scenes/` for composition.
## Communication
- Stable, synchronous ownership uses direct references: the controller calls the board model, gesture state, effects renderer, audio service, and inventory.
- Cross-entity or cross-scene work should use typed events. Planned scene transitions are `level:selected`, `level:started`, `level:completed`, `level:failed`, and `navigation:map`.
- Visual effects receive immutable snapshots of removed pieces. They never inspect cells after the board has mutated.
## Turn sequence
1. Pointer movement previews a neighboring swap without changing the board. Both charms travel the same distance in opposite directions, and the dragged charm renders above the board.
2. Pointer release commits the model swap and continues both pieces from their preview positions into the cell centers.
3. A valid result enters a recognition beat while matched charms remain on the board.
4. Resolution mutates the board. Ghost charms bloom outward while colored motes hover.
5. Special activations add row beams, column beams, burst rings, or prism waves.
6. Gravity and refill animate every moved piece from its prior position with a soft landing.
7. Motes converge on the score panel and pulse it in the dominant match color.
8. Cascades repeat from the recognition beat. A dead board reshuffles by piece identity rather than popping instantly.
## Verification
- Drag slowly in all four directions and confirm the source charm follows the pointer while its neighbor yields.
- Pause during play and confirm each menu label is centered in its button and no gameplay label renders above the overlay.
- Release a valid and an invalid swap; both must animate, and only the valid move spends a move.
- Resolve horizontal, vertical, four-, five-, and T/L-shaped matches.
- Trigger row, column, burst, prism, and two-special combinations.
- Confirm match recognition occurs before removal, every removed colored charm emits score-bound motes, and the score panel glows on arrival.
- Confirm refill and reshuffle preserve piece identity during movement.
- Repeat with mouse and a mobile touch viewport, then run the production build and verification harness.