diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 2f56457..f06c20f 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -323,6 +323,12 @@ renders only server-provided visible state. The observer view supports fitting, panning, or zooming the complete `32 x 32` map without changing server authority. +The browser renders Player 1 as yellow and Player 2 as blue. The matching key +and exit use the owner's color as a secondary identity signal, while distinct +SVG silhouettes and open/closed treatments identify object type and state. This +presentation mapping is local only and does not alter authoritative game or +projection data. + `docs/UI_STYLE.md` is the canonical browser presentation contract. The player layout supports a minimum `412 x 916` CSS-pixel viewport. Observer mode requires at least `1024 x 768` CSS pixels and presents a large-screen requirement message diff --git a/MVP.md b/MVP.md index 487e515..40a0ccb 100644 --- a/MVP.md +++ b/MVP.md @@ -222,9 +222,11 @@ Browser controls must support: `docs/UI_STYLE.md`. - All player-facing UI copy, game messages, and browser errors are in Russian. - The UI uses a near-black background, purple panels, turquoise interactive - accents, blue for Player 1, pink for Player 2, and plant-like green maze - walls. Important state is distinguished by icons, labels, outlines, or - shapes in addition to color. + accents, yellow for Player 1, blue for Player 2, and plant-like green maze + walls. Each player's matching key and exit use the same ownership color. + Important state is distinguished by icons, labels, outlines, or shapes in + addition to color; amber warnings and blue pause states use distinct + treatments so they cannot be confused with player identity. - The player map consumes all space not required by fixed status and control panels. The player view supports a minimum `412 x 916` CSS-pixel viewport without page scrolling. diff --git a/PLANS.md b/PLANS.md index 132b474..52b3b7a 100644 --- a/PLANS.md +++ b/PLANS.md @@ -1690,7 +1690,7 @@ map moves below it; displacement controls speed; approximately 100 ms is ideal, ## Milestone 018 — Mobile directional controls and viewport refinement -**Status:** `IN_PROGRESS` +**Status:** `COMPLETE` ### Objective @@ -1819,13 +1819,10 @@ planning-time observation motivates the milestone: 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` +**Status:** `IN_PROGRESS` ### Objective @@ -1929,14 +1926,45 @@ matching keys, and matching exits. ### 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: +Implementation and automated verification are in progress. The following +evidence satisfies the source, integration, and automated acceptance criteria; +the project-owner visual confirmation remains outstanding: - 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`. +- On 2026-09-10, `web/icons.svg` was replaced with project-owned editable SVG + symbols `player`, `key`, `exit-closed`, `crystal`, `exit-open`, and `spikes`. + Each reference-derived symbol uses the documented `64 x 64` view box and + `currentColor`; the sprite contains no ``, `foreignObject`, or embedded + raster data. `xmllint --noout web/icons.svg` passed. +- The player, key, closed/opened exit, vision-artifact, blocked-movement, + onboarding, avatar, lobby, observer, and result renderers now use the new + SVG symbols where the supplied reference applies. Player 1 is yellow + (`#ffd33d`) and Player 2 is blue (`#41b6ff`); their keys and exits share the + matching ownership color, while dashed secondary treatments and distinct + silhouettes preserve non-color identification. Amber warnings and + periwinkle pause semantics remain distinct from player identities. Spikes + are used only in the client-side blocked-movement notice. +- `node --test test/web/test_player_app.js` passed all 21 tests, including the + new deterministic SVG-structure, ownership-color, local-asset, and + blocked-feedback checks. `bash scripts/run_host_tests.sh` passed all host + suites and deterministic asset verification + (`c7f3bd8217e51e81b46eaeaf2636f5cd1cf85a7d8e27b07cb5293ea97a1f3f41`, + 26,510 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 reported the fixed + 2,031,616-byte LittleFS image within its partition. +- On 2026-09-10, `pio run -e esp32-c6-devkitm-1 --target uploadfs + --upload-port /dev/ttyACM0` wrote and hash-verified the LittleFS image to the + confirmed ESP32-C6FH4. A read-only live-page check at `412 x 916` CSS pixels + confirmed a `412 x 916` document with no overflow and references to the + local `player` and `spikes` symbols. It did not create or alter a player + session, so full active-match visual confirmation remains for the project + owner. +- Milestone 019 remains `IN_PROGRESS` pending the project owner's + representative mobile and desktop confirmation that the new icon shapes, + yellow/blue ownership, keys, and exits are clear at normal gameplay size. diff --git a/data/index.html.gz b/data/index.html.gz index a984561..3e5d75f 100644 Binary files a/data/index.html.gz and b/data/index.html.gz differ diff --git a/docs/PLAYER_UI.md b/docs/PLAYER_UI.md index e560d67..b8de562 100644 --- a/docs/PLAYER_UI.md +++ b/docs/PLAYER_UI.md @@ -12,6 +12,20 @@ locally authored `icons.svg` sprite. The deterministic asset build compresses each file with gzip for LittleFS. There are no remote fonts, frameworks, analytics, icon services, or runtime network dependencies beyond the local ESP. +## Gameplay icon mapping + +`icons.svg` contains editable, local SVG symbols with a shared `64 x 64` view +box for the reference-derived gameplay set: `player`, `key`, `exit-closed`, +`crystal`, `exit-open`, and `spikes`. Player 1 is yellow and Player 2 is blue; +their matching keys and exits use the same owner color. The player, key, and +exit silhouettes remain distinct, and Player 2 uses a dashed secondary +treatment so ownership does not depend on color alone. + +The closed and opened arched exits show the existing locked and opened exit +states. The crystal represents the existing vision artifact. Spikes appear only +with local blocked-movement feedback and do not add a trap, damage, protocol, +or server-state feature. + ## Input contract Arrow keys and WASD map to `north`, `east`, `south`, and `west` move intentions. diff --git a/docs/UI_STYLE.md b/docs/UI_STYLE.md index 49bcfda..a6238c0 100644 --- a/docs/UI_STYLE.md +++ b/docs/UI_STYLE.md @@ -30,10 +30,11 @@ roles must remain stable: - black or near-black for the application and map background; - purple for panels and elevated surfaces; - turquoise for interactive accents; -- blue for Player 1 and pink for Player 2 across every screen, map object, and - message; -- green for success, yellow for warnings, red for errors, blue for pause, and - orange for disconnection; +- yellow for Player 1 and blue for Player 2 across every screen, map object, + and message; each player's matching key and exit use the same ownership + color; +- green for success, amber for warnings, red for errors, periwinkle for pause, + and orange for disconnection; - green vegetation, bushes, and plants for maze walls. When two semantic roles use related colors, icons, labels, outlines, or shapes @@ -41,6 +42,11 @@ must keep them unambiguous. Important player and object information must not be communicated by color alone. Key objects use an additional label, outline, or marker. +The gameplay icon family is locally authored SVG artwork derived from the +approved running-player, key, arched-exit, crystal, opened-exit, and spike +reference silhouettes. The spike icon communicates only blocked movement or a +wall collision; it never represents a trap or a new gameplay mechanic. + WCAG AA contrast certification and dedicated color-vision-deficiency palettes are not MVP requirements. diff --git a/test/web/test_player_app.js b/test/web/test_player_app.js index 0ba523f..ae82dbe 100644 --- a/test/web/test_player_app.js +++ b/test/web/test_player_app.js @@ -269,6 +269,31 @@ test("player assets are local, Russian, accessible, and responsive", () => { assert.match(icons, /id="maze"/); }); +test("reference-derived SVG gameplay symbols preserve local yellow and blue ownership", () => { + const icons = fs.readFileSync(path.join(project, "web/icons.svg"), "utf8"); + const script = fs.readFileSync(path.join(project, "web/player.js"), "utf8"); + const css = fs.readFileSync(path.join(project, "web/player.css"), "utf8"); + const html = fs.readFileSync(path.join(project, "web/index.html"), "utf8"); + const playerUi = fs.readFileSync(path.join(project, "docs/PLAYER_UI.md"), "utf8"); + for (const iconId of ["player", "key", "exit-closed", "crystal", "exit-open", "spikes"]) { + assert.match(icons, new RegExp(``)); + } + assert.doesNotMatch(icons, /<(?:image|foreignObject)\b/i); + assert.doesNotMatch(icons, /data:image\//i); + assert.match(script, /icon\(variant \? "exit-open" : "exit-closed", "object object-exit"\)/); + assert.match(script, /icon\("crystal", "object object-vision"\)/); + assert.match(script, /icon\("player", `pawn/); + assert.match(html, /\/icons\.svg#spikes/); + assert.match(css, /--p1: #ffd33d/); + assert.match(css, /--p2: #41b6ff/); + assert.match(css, /--warning: #ffad38/); + assert.match(css, /--pause: #9b8cff/); + assert.match(css, /\.pawn-owner-two \{ border-style: dashed; \}/); + assert.match(html, /Жёлтый/); + assert.match(html, /Синий/); + assert.match(playerUi, /`player`, `key`, `exit-closed`,\n`crystal`, `exit-open`, and `spikes`/); +}); + test("observer view fits large screens and bounds zoom", () => { assert.equal(player.observerFitScale(1024, 600, 32, 32), 2.25); assert.equal(player.clampObserverZoom(.01), .25); diff --git a/web/icons.svg b/web/icons.svg index 63be1aa..25d94b1 100644 --- a/web/icons.svg +++ b/web/icons.svg @@ -1,5 +1,11 @@ - + + + + + + + @@ -9,7 +15,6 @@ - diff --git a/web/index.html b/web/index.html index f49f2b3..a47ad64 100644 --- a/web/index.html +++ b/web/index.html @@ -34,8 +34,8 @@

Игроки

-
P1СвободноСлот грустит
-
P2СвободноСлот грустит
+
СвободноСлот грустит
+
СвободноСлот грустит

Зрительный зал

0 / 4 эксперта по чужим ошибкам.

Большая красная кнопка

Старт доступен Игроку 1, когда оба слота на месте.

@@ -44,7 +44,7 @@