feat: add Ship-Class Silhouettes and Red Sunk Markers
This commit is contained in:
@@ -1123,3 +1123,216 @@ At completion, report:
|
||||
- Measurements: `make -C test/host run` passed all ten host suites; `node --test test/web/test_target_interaction.js` passed 4/4; `node --check data/app.js`, `git diff --check`, and `pio run -t buildfs` passed. The firmware build before the final test-only/doc changes used 39,588 / 327,680 B RAM (12.1%) and 1,019,170 / 2,097,152 B flash (48.6%). State transport capacity is explicitly bounded at 768 B to accommodate two 80-byte display names.
|
||||
- Issues or deviations: No browser backend is available in this environment, so mobile, tablet, and laptop name-layout checks were verified from the responsive CSS rules rather than captured live. No device upload was performed.
|
||||
- Next action: Milestone 019 is not started.
|
||||
|
||||
# Milestone 019 — Amendment: Distinct Ship-Class Silhouettes and Red Sunk Markers
|
||||
|
||||
**Status:** DONE
|
||||
**Depends on:** Milestone 018
|
||||
|
||||
Update the fleet-status milestone so that every ship class has its own independently designed SVG silhouette.
|
||||
|
||||
Do not create all ships by stretching or repeating one generic boat image.
|
||||
|
||||
## Distinct ship classes
|
||||
|
||||
Create four unique silhouettes:
|
||||
|
||||
1. One-cell ship — patrol boat or cutter.
|
||||
2. Two-cell ship — destroyer or torpedo boat.
|
||||
3. Three-cell ship — cruiser.
|
||||
4. Four-cell ship — battleship.
|
||||
|
||||
Each silhouette must visibly represent a different vessel class.
|
||||
|
||||
The differences should include:
|
||||
|
||||
- hull profile;
|
||||
- bow and stern shape;
|
||||
- relative height;
|
||||
- superstructure;
|
||||
- bridge position;
|
||||
- turret or equipment placement;
|
||||
- overall visual mass;
|
||||
- length-to-height proportion.
|
||||
|
||||
The one-cell ship should look like a small, light vessel. The four-cell ship should look substantially larger and heavier, not like an enlarged cutter.
|
||||
|
||||
## SVG structure
|
||||
|
||||
Store the four independently drawn silhouettes in one local SVG sprite:
|
||||
|
||||
- `ship-1-cutter`;
|
||||
- `ship-2-destroyer`;
|
||||
- `ship-3-cruiser`;
|
||||
- `ship-4-battleship`.
|
||||
|
||||
Each `<symbol>` must have its own path data and an appropriate `viewBox`.
|
||||
|
||||
Using one sprite file is an asset-delivery optimization only. It must not result in the same geometry being reused for every ship class.
|
||||
|
||||
Do not:
|
||||
|
||||
- stretch one silhouette to multiple lengths;
|
||||
- create a ship by repeating identical rectangular sections;
|
||||
- use emoji or Unicode ship characters;
|
||||
- use external images or icon libraries;
|
||||
- embed raster images inside the SVG;
|
||||
- add excessive decorative details that become unreadable at mobile sizes.
|
||||
|
||||
## Proportional sizing
|
||||
|
||||
Use a shared visual unit based on one board-cell width.
|
||||
|
||||
Approximate displayed widths:
|
||||
|
||||
- cutter: 1 unit;
|
||||
- destroyer: 2 units;
|
||||
- cruiser: 3 units;
|
||||
- battleship: 4 units.
|
||||
|
||||
Height does not need to be identical between classes. Larger classes may be slightly taller to communicate visual mass.
|
||||
|
||||
However:
|
||||
|
||||
- all fleet rows must remain aligned;
|
||||
- different intrinsic heights must not cause layout jumping;
|
||||
- every silhouette must remain recognizable on a mobile screen;
|
||||
- the four-cell battleship must fit within the available width;
|
||||
- SVGs must preserve their aspect ratios;
|
||||
- do not distort silhouettes with independent horizontal and vertical scaling.
|
||||
|
||||
Use a bounded fleet-display unit independent of the actual board-cell size when necessary. The status list must remain readable without forcing the game grid to shrink.
|
||||
|
||||
## Orientation
|
||||
|
||||
Fleet-status silhouettes should use one consistent orientation, preferably horizontal with the bow facing right.
|
||||
|
||||
The status list represents ship condition, not the hidden orientation of ships on the game board.
|
||||
|
||||
Never use the actual opponent ship orientation in this list, because doing so could expose hidden game information.
|
||||
|
||||
## Alive state
|
||||
|
||||
An alive ship should use the normal fleet color with strong contrast against the dark background.
|
||||
|
||||
Its silhouette should remain visually clean and readable at small sizes.
|
||||
|
||||
Do not use green as the only indication that a ship is alive.
|
||||
|
||||
## Sunk state
|
||||
|
||||
A sunk ship must have:
|
||||
|
||||
- a muted or desaturated silhouette;
|
||||
- reduced opacity;
|
||||
- a clearly visible red diagonal cross placed over the entire ship.
|
||||
|
||||
Draw the cross using two diagonal red strokes:
|
||||
|
||||
- top-left to bottom-right;
|
||||
- top-right to bottom-left.
|
||||
|
||||
The cross must:
|
||||
|
||||
- be bright enough to remain visible against both the ship and background;
|
||||
- use rounded stroke caps;
|
||||
- scale with the complete ship bounding box;
|
||||
- cover the silhouette without completely obscuring its class;
|
||||
- remain inside the fleet-item bounds;
|
||||
- use a consistent apparent stroke thickness across all four ship sizes.
|
||||
|
||||
Prefer rendering the red cross as a shared lightweight SVG or CSS overlay rather than duplicating it inside every ship symbol.
|
||||
|
||||
Suggested visual treatment:
|
||||
|
||||
- red color consistent with the application’s destructive-action palette;
|
||||
- approximately 80–100% cross opacity;
|
||||
- approximately 35–55% ship opacity when sunk;
|
||||
- optional subtle dark backing or outline when required for contrast.
|
||||
|
||||
The sunk state must not rely only on the red color. Include an accessible textual status and the muted silhouette treatment.
|
||||
|
||||
## Fleet rendering
|
||||
|
||||
Render the classic fleet using the appropriate unique symbol:
|
||||
|
||||
- 1 × battleship;
|
||||
- 2 × cruisers;
|
||||
- 3 × destroyers;
|
||||
- 4 × cutters.
|
||||
|
||||
Do not render only one icon per ship class with a numeric counter unless a compact fallback is required for an exceptionally narrow viewport.
|
||||
|
||||
The preferred presentation shows all ten ships, allowing the player to understand fleet losses at a glance.
|
||||
|
||||
## Responsive layout
|
||||
|
||||
### Mobile
|
||||
|
||||
- Arrange ships in compact class-based rows.
|
||||
- Recommended order: battleship, cruisers, destroyers, cutters.
|
||||
- Keep all members of a class together where practical.
|
||||
- Allow rows to wrap deliberately.
|
||||
- Ensure the battleship and its red cross fit without horizontal overflow.
|
||||
- Do not make the status section taller than the game board unless unavoidable.
|
||||
|
||||
### Tablet and laptop
|
||||
|
||||
- The fleet may appear below the corresponding board or in a narrow side panel.
|
||||
- Preserve proportional differences between all vessel classes.
|
||||
- Align equivalent fleet sections consistently when two boards are visible.
|
||||
|
||||
## Accessibility labels
|
||||
|
||||
Every rendered ship instance must have an accessible text equivalent, for example:
|
||||
|
||||
- “Катер — цел”;
|
||||
- “Эсминец — потоплен”;
|
||||
- “Крейсер — цел”;
|
||||
- “Линкор — потоплен”.
|
||||
|
||||
Decorative SVG geometry and the red cross should be hidden from assistive technology so the label is not announced twice.
|
||||
|
||||
## Information safety
|
||||
|
||||
The silhouettes describe only fleet composition and public sunk status.
|
||||
|
||||
Do not expose:
|
||||
|
||||
- opponent ship coordinates;
|
||||
- opponent ship orientation;
|
||||
- damaged but not yet sunk ship length, unless already public under the established game rules;
|
||||
- untouched opponent ship placement.
|
||||
|
||||
For the opponent fleet, change a silhouette to the sunk state only after the server authoritatively announces the ship’s destruction and its publicly known length.
|
||||
|
||||
## Asset-size expectations
|
||||
|
||||
Keep all four silhouettes and the shared cross overlay in one maintainable SVG sprite.
|
||||
|
||||
Target sizes:
|
||||
|
||||
- preferably below 15 KB uncompressed;
|
||||
- preferably below 5 KB after gzip.
|
||||
|
||||
These are optimization targets, not reasons to reuse incorrect geometry.
|
||||
|
||||
After implementation, report:
|
||||
|
||||
- the source and gzip size of the SVG sprite;
|
||||
- the size contribution of related CSS and JavaScript;
|
||||
- the new LittleFS image size;
|
||||
- screenshots or visual verification of all four ship classes;
|
||||
- alive and sunk examples at mobile and tablet sizes;
|
||||
- confirmation that the red cross remains readable on every silhouette.
|
||||
|
||||
### Execution record
|
||||
|
||||
- Date: 2026-08-30
|
||||
- Board model and revision: ESP32-C6FH4 QFN32, revision v0.2.
|
||||
- Toolchain and library versions: PlatformIO Core 6.1.19; `espressif32` 7.0.1; ESP-IDF 6.0.1; `esp_littlefs` 1.20.4.
|
||||
- Result: PASS.
|
||||
- Evidence: Added one local SVG sprite with independently drawn cutter, destroyer, cruiser, and battleship symbols. Each board now presents all ten standard fleet vessels in compact class rows. Ship state is derived only from public `4` (sunk) cells in that board's existing role-safe view; no unsunk opponent placement, orientation, or damaged-length data is rendered. Sunk vessels use a shared CSS red, rounded-cap diagonal cross and muted 48% silhouette, while every vessel has an accessible Russian status label.
|
||||
- Measurements: `test/web/test_ship_sprite.js` verifies all four distinct symbols, sprite raw size below 15 KiB, and shared cross styling; it and the existing interaction tests passed 6/6. `make -C test/host run`, `node --check data/app.js`, `git diff --check`, `pio run -e esp32-c6-devkitm-1 -t buildfs`, and `pio run -e esp32-c6-devkitm-1` passed. Sprite size is 1,032 B raw / 419 B gzip; related CSS is 11,721 B raw / 3,130 B gzip; JavaScript is 23,305 B raw / 6,299 B gzip; the generated LittleFS image is 2,031,616 B. Firmware uses 39,588 / 327,680 B RAM (12.1%) and 1,019,306 / 2,097,152 B flash (48.6%).
|
||||
- Issues or deviations: No browser backend is attached in this environment, so live mobile/tablet screenshots and visual cross-readability checks remain physical-browser verification steps. No firmware or filesystem upload was performed.
|
||||
- Next action: Milestone 020 is not started.
|
||||
|
||||
Reference in New Issue
Block a user