feat(player): add mobile directional pad controls

This commit is contained in:
2026-09-10 21:23:38 +03:00
parent 5a806fb5b8
commit 8214e7f7ed
10 changed files with 405 additions and 47 deletions
+254 -7
View File
@@ -1561,7 +1561,7 @@ controlled measurement criteria:
## Milestone 017 — Avatar-centered drag steering and latency remediation
**Status:** `IN_PROGRESS`
**Status:** `COMPLETE`
### Objective
@@ -1678,12 +1678,6 @@ map moves below it; displacement controls speed; approximately 100 ms is ideal,
2,097,152 application bytes. `/home/sasa/.platformio/penv/bin/pio run -e
esp32-c6-devkitm-1 --target buildfs` passed and reported a fixed LittleFS
image of 2,031,616 of 2,031,616 bytes.
- `docs/M017_LATENCY_REPORT.md` records the M016 baseline, the browser backlog
remediation, the required isolated-LAN deployment setup, and the controlled
before-and-after retest procedure. The physical mobile usability observation,
isolated-network 200-sample runs, and maximum-session diagnostics are still
required for acceptance criteria 6, 7, 9, and 10. Milestone 017 remains
`IN_PROGRESS`; Milestone 018 has not been started.
- On 2026-09-09, an edge-projection correction translated the received maze so
the authoritative `self` cell remains below the centered avatar. Drag
displacement now starts at pointer-down, preventing a touch near the
@@ -1693,3 +1687,256 @@ map moves below it; displacement controls speed; approximately 100 ms is ideal,
25,346 of 1,572,864 allowed compressed bytes). Firmware and filesystem
rebuilds passed with 58,868 of 327,680 RAM bytes, 1,027,966 of 2,097,152
application bytes, and a 2,031,616-byte LittleFS image.
## Milestone 018 — Mobile directional controls and viewport refinement
**Status:** `IN_PROGRESS`
### Objective
Add a familiar, always-visible four-direction control cluster to the mobile
player view and refine the compact layout so a player can move without covering
the centered avatar or the most useful part of the maze with their finger.
### Scope
- Before implementation, reconcile `MVP.md`, `ARCHITECTURE.md`, and
`docs/UI_STYLE.md` with the project owner's decision to show directional
buttons during normal phone play. This explicitly supersedes the current
phone-specific rule that hides the directional-button cluster.
- Present four separate up, down, left, and right buttons as a conventional
cross-shaped directional pad in the lower-right control zone. Keep the
center of the cross inactive so diagonal input cannot be implied.
- Give every direction a large, distinct touch target, Russian accessible
label, and visible normal, pressed, disabled, and pending states. Prevent
browser scrolling, text selection, double-tap zoom, and stuck input during
normal button use.
- Send exactly one of the four existing orthogonal movement intentions from
each button interaction. Reuse the bounded latest-intent flow and server
cooldown; the browser must not predict movement or create a second movement
authority path.
- Retain avatar drag, directional swipe, and keyboard movement as optional
equivalent inputs. Directional buttons become the obvious default touch
control without removing the alternatives completed in earlier milestones.
- Rebalance the compact player HUD, maze viewport, key-drop action, secondary
controls, and transient notices so the map remains dominant and the player,
nearby maze cells, and important feedback remain visible while a thumb rests
on the directional pad.
- Keep the directional pad and key-drop action in separate lower-screen zones,
respect display safe areas and handed reach, and avoid overlap between
movement, drop-key, mute, reduced-motion, onboarding, or connection controls.
- Eliminate page-level scrolling and accidental overflow in supported portrait
and landscape player layouts, including the live approximately `412 x 915`
phone viewport as well as the canonical `412 x 916` validation viewport.
- Preserve Russian player-facing copy, observer read-only behavior,
hidden-state protection, local assets, reduced-motion behavior, and the
existing firmware and LittleFS budgets.
### Deliverables
- Updated mobile-control and responsive-layout contracts in `MVP.md`,
`ARCHITECTURE.md`, and `docs/UI_STYLE.md`.
- Responsive four-button directional pad integrated with the existing bounded
movement-intent path.
- Refined compact HUD, maze, key-drop, utility-control, and notice layout for
portrait and landscape mobile play.
- Russian accessible names and complete visual interaction states for all four
direction buttons.
- Deterministic browser tests and representative mobile-browser visual and
touch verification evidence.
### Acceptance criteria
1. At `412 x 915` and `412 x 916` CSS pixels in portrait orientation, all four
directional buttons, the key-drop action, essential player status, and the
maze are visible without page-level horizontal or vertical scrolling.
2. The directional buttons form an immediately recognizable cross with a
non-interactive center. Each visible button has a touch target of at least
`48 x 48` CSS pixels, remains inside the display safe area, and does not
overlap another control at any supported viewport.
3. A thumb operating any directional button does not cover the centered player
avatar. The current cell and enough adjacent maze context to understand the
next orthogonal move remain visible during button use.
4. Pressing or holding up, down, left, or right produces only the matching
existing cardinal movement intention through the bounded latest-intent
flow. Release, cancellation, pause, disconnect, blur, hidden-document
events, and lost pointer capture stop or clear button-generated intent.
5. Button input obeys the authoritative movement cooldown, never predicts a
successful move, and remains behaviorally equivalent to avatar drag, swipe,
and keyboard input for accepted and rejected movement.
6. Normal, pressed, disabled, and pending states are visually distinct without
relying on color alone. The buttons expose the Russian accessible labels
`Двигаться вверх`, `Двигаться вниз`, `Двигаться влево`, and
`Двигаться вправо`.
7. Button use does not cause page scrolling, text selection, double-tap zoom,
a context menu, diagonal commands, duplicate command streams, or movement
that continues after release.
8. The refined HUD and overlays keep the map as the dominant screen region;
key-drop, mute, reduced-motion, onboarding, connection state, errors, and
transient notices remain reachable and do not obscure one another in
portrait or landscape orientation.
9. Browser tests cover all four directions, tap and hold behavior, pointer and
touch cancellation, reset paths, cooldown and latest-intent bounds,
coexistence with drag/swipe/keyboard input, accessibility labels, safe-area
layout, control overlap, and zero page overflow at supported viewports.
10. All host tests pass, compressed web assets remain within the 1.5 MiB budget
and LittleFS partition, firmware remains within the factory partition, and
no player projection or observer-authority contract changes.
11. The project owner confirms on a representative mobile browser that the
four buttons are comfortable and familiar, the central play area stays
readable while moving, every essential control fits on screen, and normal
play no longer requires dragging the avatar, or explicitly approves a
documented evidence deviation.
### Evidence
Implementation and automated validation are in progress. The following
planning-time observation motivates the milestone:
- On 2026-09-10, the project owner reported that dragging the centered player
is unfamiliar and uncomfortable because the finger hides useful maze space,
and requested visible up, down, left, and right buttons plus a better-fitting
mobile layout. Read-only inspection of the live player page at approximately
`412 x 915` CSS pixels found a `96 x 96` centered avatar drag target, four
directional buttons present but hidden, and a document height of 923 CSS
pixels, slightly exceeding the 915 CSS-pixel viewport. Implementation and
completion verification are deferred until Milestone 017 is `COMPLETE`.
- On 2026-09-10, `MVP.md`, `ARCHITECTURE.md`, and `docs/UI_STYLE.md` were
reconciled to make the four-button lower-right directional pad the primary
phone control while preserving avatar drag, swipe, and keyboard alternatives.
The inactive centre prevents diagonal input. Each button is 62 by 62 CSS
pixels on compact phones (and at least 52 by 52 CSS pixels in compact
landscape), has Russian accessible text, and uses pointer capture plus a
170 ms bounded hold repeat through the existing latest-intent flow. The
compact application viewport is explicitly clipped to `100dvh` to prevent
page scrolling; the lower-left key action, lower-right pad, top-right utility
controls, and raised notices occupy separate zones.
- On 2026-09-10, `node --test test/web/test_player_app.js` passed all 20
browser tests. `bash scripts/run_host_tests.sh` passed all host tests and
deterministic web-asset verification
(`ecf9429fd873e27df67774616ec68684df19d88cce6913d53b0764b53e8e95cd`,
25,939 of 1,572,864 allowed compressed bytes). `/home/sasa/.platformio/penv/bin/pio
run -e esp32-c6-devkitm-1` passed with 58,868 of 327,680 RAM bytes and
1,027,966 of 2,097,152 application bytes. The matching `--target buildfs`
command passed and produced the fixed 2,031,616-byte LittleFS image.
- A representative physical mobile-browser touch/layout confirmation remains
required for acceptance criterion 11. Milestone 018 remains `IN_PROGRESS`;
Milestone 019 has not been started.
## Milestone 019 — Reference-derived SVG icon system
**Status:** `NOT_STARTED`
### Objective
Replace the current player and gameplay pictograms with a coherent local SVG
set derived from the project owner's supplied visual reference, and establish
yellow and blue as the two unmistakable player identities across players,
matching keys, and matching exits.
### Scope
- Before changing application markup, styling, or rendering, manually recreate
the supplied raster-reference silhouettes as clean, editable SVG artwork.
Do not embed, trace at runtime, or ship the raster reference itself.
- Create SVG symbols for the six supplied concepts: running player, key,
closed arched exit, vision crystal, opened arched exit with outward arrow,
and blocked-movement spikes.
- Treat the reference as visual direction rather than a source of product
requirements. Map its artwork only to existing maze32 gameplay states; the
spikes communicate a rejected move or wall collision and must not introduce
a trap, damage, or any other new mechanic.
- Review and approve the standalone SVG set before using it to replace icons in
the browser application. Keep source paths understandable, view boxes
consistent, silhouettes legible at gameplay sizes, and all colors controlled
through project-owned CSS or explicit documented SVG tokens.
- Reconcile `MVP.md`, `ARCHITECTURE.md`, `docs/UI_STYLE.md`, and supporting UI
documentation before implementation. Replace the current blue/pink identity
contract with Player 1 yellow and Player 2 blue across every player, key,
exit, status, map, onboarding, result, and observer presentation.
- Give each player's matching key and exit the same yellow or blue ownership
identity as its owner. Preserve different silhouettes and state treatments
for players, keys, closed exits, and opened exits so meaning never depends on
color alone.
- Replace the applicable current pictograms in the player HUD, maze, key-drop
control, onboarding, transient feedback, results, and observer view with the
approved SVG symbols. Retain or restyle icons not represented by the supplied
sample only as needed to keep the complete icon family visually coherent.
- Preserve Russian accessible labels, icon-first comprehension, reduced-motion
behavior, server authority, hidden-state rules, offline operation, and the
existing compressed-asset and Flash budgets.
- Verify that yellow remains distinguishable from warning states and blue from
pause states by pairing semantic colors with shape, outline, animation, or
labels, as appropriate.
### Deliverables
- A project-owned, editable SVG source set for the player, key, closed exit,
vision crystal, opened exit, and blocked-movement symbols.
- A documented mapping from each reference-derived SVG symbol and yellow/blue
variant to existing maze32 entities and UI states.
- Updated color and icon contracts in `MVP.md`, `ARCHITECTURE.md`,
`docs/UI_STYLE.md`, and affected supporting UI documentation.
- Replacement icons in player, observer, onboarding, HUD, feedback, and result
presentations without embedded raster images or external dependencies.
- Deterministic SVG validation, browser tests, asset-budget checks, and
representative mobile and desktop visual-verification evidence.
### Acceptance criteria
1. Before application icon replacement begins, the six reference-derived SVG
sources exist as editable vector paths, pass XML validation, have consistent
documented view boxes, contain no embedded raster data, and are approved by
the project owner against the supplied visual reference.
2. The running figure, key, closed arched exit, faceted vision crystal, opened
arched exit with outward arrow, and spikes remain recognizable at every
rendered application size without relying on accompanying text.
3. Player 1 is yellow and Player 2 is blue in every player and observer view.
Each player's key and exit carry the matching ownership color consistently,
including ground, inventory, closed, opened, onboarding, and result states.
4. Player, key, closed exit, and opened exit remain distinguishable by both
silhouette and state treatment in monochrome inspection; color is never the
only way to identify object type, ownership, or exit state.
5. The spikes appear only as blocked-movement or wall-collision feedback. No
trap object, damage rule, hidden-state field, protocol message, or server
state is added.
6. Yellow player identity cannot be confused with warnings, and blue player
identity cannot be confused with pause state: each conflicting semantic role
has an additional icon, outline, pattern, motion, or Russian label.
7. All applicable current player, key, exit, vision-artifact, and
blocked-movement pictograms are replaced across the maze, HUD, key-drop
action, onboarding, transient feedback, results, and observer presentation;
no obsolete duplicate icon remains visible in a reachable state.
8. SVG symbols render without clipping, distortion, unexpected inherited
color, or loss of contrast at the canonical `412 x 916` player viewport,
compact landscape, representative tablet and desktop player viewports, and
observer viewports of `1024 x 768` or larger.
9. Player-facing accessible labels remain in Russian, the icon-first onboarding
remains understandable, reduced motion preserves all state information, and
the application loads every icon locally without an internet dependency.
10. Automated checks validate SVG structure, required symbol identifiers,
yellow/blue ownership mapping, all closed/open and carried/ground variants,
absence of embedded raster content, blocked-feedback semantics, and the
removal of obsolete reachable icons.
11. All host and browser tests pass, the compressed web payload remains within
the 1.5 MiB budget and LittleFS partition, and firmware remains within the
factory partition without changing authoritative game or projection data.
12. The project owner confirms on representative mobile and desktop browsers
that the new icons match the supplied examples closely enough, yellow and
blue ownership is immediately understandable, keys and doors are assigned
to the correct player, and every icon is clear at normal gameplay size, or
explicitly approves a documented evidence deviation.
### Evidence
Completion evidence is not yet available because SVG authoring and application
replacement have not started. The following planning-time observation motivates
the milestone but does not satisfy its acceptance criteria:
- On 2026-09-10, the project owner supplied a raster visual reference containing
a yellow running figure, yellow key, red closed arched door, cyan faceted
crystal, green opened arched door with an outward arrow, and red spikes. The
owner requested that local SVG artwork be created from these examples before
icon replacement, and selected yellow and blue as the two player colors.
Implementation and completion verification are deferred until Milestone 018
is `COMPLETE`.