diff --git a/docs/equipment-icon-accessory-pass.md b/docs/equipment-icon-accessory-pass.md new file mode 100644 index 0000000..3b3c15d --- /dev/null +++ b/docs/equipment-icon-accessory-pass.md @@ -0,0 +1,34 @@ +# Accessory Equipment Icon Pass + +Generated after the accessory icon rework in `src/game/scenes/BootScene.ts`. + +## Scope + +- `peach-charm` +- `war-manual` +- `mountain-guide-scroll` +- `bravery-token` +- `grain-pouch` +- `yellow-scarf-charm` +- `wind-quiver` + +## Before and After + +| item id | previous helper | current helper | previous primitives | current primitives | audit concerns | +| --- | --- | --- | ---: | ---: | --- | +| `bravery-token` | `drawTokenIcon` | `drawBraveryTokenIcon` | 4 | 19 | none | +| `mountain-guide-scroll` | `drawMapScrollIcon` | `drawMountainGuideScrollIcon` | 13 | 23 | none | +| `peach-charm` | `drawCharmIcon` | `drawPeachCharmIcon` | 4 | 22 | none | +| `war-manual` | `drawBookIcon` | `drawWarManualIcon` | 7 | 20 | none | +| `wind-quiver` | `drawQuiverIcon` | `drawWindQuiverIcon` | 8 | 24 | none | +| `grain-pouch` | `drawPouchIcon` | `drawGrainPouchIcon` | 7 | 22 | none | +| `yellow-scarf-charm` | `drawCharmIcon` | `drawYellowScarfCharmIcon` | 4 | 25 | none | + +## Browser QA + +![Sortie prep accessory icon QA](./equipment-icon-accessory-sortie-prep.png) + +- URL checked: `http://127.0.0.1:4200/heros_web/?debug&debugSortiePrep&renderer=canvas` +- Result: sortie prep opened on a desktop 1280x720 canvas and rendered the generated accessory textures in roster, slot, and detail surfaces. +- Browser console warnings/errors: none observed. +- Follow-up target from the updated audit: remaining low-detail equipment icons. diff --git a/docs/equipment-icon-accessory-sortie-prep.png b/docs/equipment-icon-accessory-sortie-prep.png new file mode 100644 index 0000000..e1bec97 Binary files /dev/null and b/docs/equipment-icon-accessory-sortie-prep.png differ diff --git a/docs/equipment-icon-quality-audit.md b/docs/equipment-icon-quality-audit.md index 4519ba8..718c7fc 100644 --- a/docs/equipment-icon-quality-audit.md +++ b/docs/equipment-icon-quality-audit.md @@ -28,22 +28,24 @@ Generated by `scripts/audit-equipment-icon-quality.mjs`. - The previous shared spear/polearm silhouettes now use item-specific helper shapes with enough primitive detail for 20px and 30px equipment UI reads. - armor silhouettes: `oath-robe`, `reinforced-lamellar`, `cloth-armor`, `lamellar-armor`, `rebel-vest` - The previous shared armor and robe silhouettes now use item-specific helper shapes with stronger outer contours and material cues. +- accessory charms and tokens: `bravery-token`, `mountain-guide-scroll`, `peach-charm`, `war-manual`, `wind-quiver`, `grain-pouch`, `yellow-scarf-charm` + - Accessory icons now use distinct badge, scroll, charm, pouch, manual, and quiver silhouettes at small camp UI sizes. ## Next Improvement Target -- Target: accessory charms and tokens -- Item ids: `bravery-token`, `mountain-guide-scroll`, `peach-charm`, `war-manual`, `wind-quiver`, `grain-pouch`, `yellow-scarf-charm` -- Reason: Accessories are the smallest UI read and several use compact badge-like shapes. +- Target: remaining low-detail equipment icons +- Item ids: `leader-axe`, `training-sword`, `yellow-turban-saber` +- Reason: All named batches are complete; remaining work should be selected from the low-detail inventory rows. ## Highest-Risk Shared Silhouette Groups | score | signature | slots | ranks | items | | ---: | --- | --- | --- | --- | -| 8 | `drawCharmIcon` | accessory | common, treasure | `peach-charm`, `yellow-scarf-charm` | | 6 | `drawAxeIcon` | weapon | common | `leader-axe` | | 6 | `drawSaberIcon` | weapon | common | `yellow-turban-saber` | | 6 | `drawSwordIcon` | weapon | common | `training-sword` | | 5 | `drawFanIcon` | weapon | treasure | `white-feather-fan` | +| 5 | `drawGreenDragonGlaiveIcon` | weapon | treasure | `green-dragon-glaive` | ## Full Item Inventory @@ -65,18 +67,18 @@ Generated by `scripts/audit-equipment-icon-quality.mjs`. | `cloth-armor` | armor | common | `drawClothArmorIcon` | 1 | 24 | 6 | none | | `lamellar-armor` | armor | common | `drawLamellarArmorIcon` | 1 | 23 | 4 | none | | `rebel-vest` | armor | common | `drawRebelVestIcon` | 1 | 24 | 7 | none | -| `bravery-token` | accessory | treasure | `drawTokenIcon` | 1 | 4 | 2 | low primitive detail | -| `mountain-guide-scroll` | accessory | treasure | `drawMapScrollIcon` | 1 | 13 | 5 | low primitive detail | -| `peach-charm` | accessory | treasure | `drawCharmIcon` | 1 | 4 | 2 | shared helper silhouette
low primitive detail | -| `war-manual` | accessory | treasure | `drawBookIcon` | 1 | 7 | 3 | low primitive detail | -| `wind-quiver` | accessory | treasure | `drawQuiverIcon` | 1 | 8 | 2 | low primitive detail | -| `grain-pouch` | accessory | common | `drawPouchIcon` | 1 | 7 | 2 | low primitive detail | -| `yellow-scarf-charm` | accessory | common | `drawCharmIcon` | 1 | 4 | 2 | shared helper silhouette
low primitive detail | +| `bravery-token` | accessory | treasure | `drawBraveryTokenIcon` | 1 | 19 | 5 | none | +| `mountain-guide-scroll` | accessory | treasure | `drawMountainGuideScrollIcon` | 1 | 23 | 7 | none | +| `peach-charm` | accessory | treasure | `drawPeachCharmIcon` | 1 | 22 | 5 | none | +| `war-manual` | accessory | treasure | `drawWarManualIcon` | 1 | 20 | 7 | none | +| `wind-quiver` | accessory | treasure | `drawWindQuiverIcon` | 1 | 24 | 6 | none | +| `grain-pouch` | accessory | common | `drawGrainPouchIcon` | 1 | 22 | 5 | none | +| `yellow-scarf-charm` | accessory | common | `drawYellowScarfCharmIcon` | 1 | 25 | 5 | none | ## Recommended Next Batch Definition -- Scope: improve accessory charms and tokens while keeping `item-${itemId}` texture keys stable. -- Item ids: `bravery-token`, `mountain-guide-scroll`, `peach-charm`, `war-manual`, `wind-quiver`, `grain-pouch`, `yellow-scarf-charm` -- Success criteria: Each accessory should keep a compact footprint while gaining a distinct readable prop shape at 20px and 30px. +- Scope: improve remaining low-detail equipment icons while keeping `item-${itemId}` texture keys stable. +- Item ids: `leader-axe`, `training-sword`, `yellow-turban-saber` +- Success criteria: Clear remaining low-detail concerns without changing stable texture keys. - Keep the existing 64px texture size unless a UI-wide equipment icon pass is planned. - Add before/after contact sheets and verify the sortie equipment list and equipment swap panel in a desktop browser. diff --git a/src/game/scenes/BootScene.ts b/src/game/scenes/BootScene.ts index 6998156..00c6a0c 100644 --- a/src/game/scenes/BootScene.ts +++ b/src/game/scenes/BootScene.ts @@ -51,13 +51,13 @@ export class BootScene extends Phaser.Scene { this.createItemIcon('item-reinforced-lamellar', (graphics) => this.drawReinforcedLamellarIcon(graphics)); this.createItemIcon('item-rebel-vest', (graphics) => this.drawRebelVestIcon(graphics)); - this.createItemIcon('item-peach-charm', (graphics) => this.drawCharmIcon(graphics, 0xf0a6a4, 0xd8b15f)); - this.createItemIcon('item-war-manual', (graphics) => this.drawBookIcon(graphics, 0x5b78a0, 0xe8dfca)); - this.createItemIcon('item-mountain-guide-scroll', (graphics) => this.drawMapScrollIcon(graphics, 0xcfae72, 0x5f8f65)); - this.createItemIcon('item-bravery-token', (graphics) => this.drawTokenIcon(graphics, 0xd8b15f, 0x9b4c3a)); - this.createItemIcon('item-grain-pouch', (graphics) => this.drawPouchIcon(graphics, 0xa7794a, 0xe8dfca)); - this.createItemIcon('item-yellow-scarf-charm', (graphics) => this.drawCharmIcon(graphics, 0xd8b15f, 0x8b6f2a)); - this.createItemIcon('item-wind-quiver', (graphics) => this.drawQuiverIcon(graphics, 0x8bb3c7, 0xe8dfca)); + this.createItemIcon('item-peach-charm', (graphics) => this.drawPeachCharmIcon(graphics)); + this.createItemIcon('item-war-manual', (graphics) => this.drawWarManualIcon(graphics)); + this.createItemIcon('item-mountain-guide-scroll', (graphics) => this.drawMountainGuideScrollIcon(graphics)); + this.createItemIcon('item-bravery-token', (graphics) => this.drawBraveryTokenIcon(graphics)); + this.createItemIcon('item-grain-pouch', (graphics) => this.drawGrainPouchIcon(graphics)); + this.createItemIcon('item-yellow-scarf-charm', (graphics) => this.drawYellowScarfCharmIcon(graphics)); + this.createItemIcon('item-wind-quiver', (graphics) => this.drawWindQuiverIcon(graphics)); } private createItemIcon(key: string, draw: (graphics: Phaser.GameObjects.Graphics) => void) { @@ -480,76 +480,213 @@ export class BootScene extends Phaser.Scene { graphics.fillCircle(18, 17, 1); } - private drawCharmIcon(graphics: Phaser.GameObjects.Graphics, baseColor: number, accentColor: number) { - graphics.fillStyle(baseColor, 1); - graphics.fillRoundedRect(8, 7, 12, 16, 2); - graphics.lineStyle(2, accentColor, 1); - graphics.strokeRoundedRect(8, 7, 12, 16, 2); - graphics.fillStyle(accentColor, 1); - graphics.fillCircle(14, 15, 3); - } - - private drawBookIcon(graphics: Phaser.GameObjects.Graphics, baseColor: number, pageColor: number) { - graphics.fillStyle(baseColor, 1); - graphics.fillRect(6, 6, 16, 18); - graphics.fillStyle(pageColor, 1); - graphics.fillRect(9, 8, 10, 14); - graphics.lineStyle(1, 0x101820, 0.65); + private drawPeachCharmIcon(graphics: Phaser.GameObjects.Graphics) { + graphics.lineStyle(2, 0xd8b15f, 1); graphics.beginPath(); - graphics.moveTo(14, 8); - graphics.lineTo(14, 22); + graphics.moveTo(14, 4); + graphics.lineTo(14, 8); + graphics.moveTo(10, 7); + graphics.lineTo(18, 7); graphics.strokePath(); - } - - private drawMapScrollIcon(graphics: Phaser.GameObjects.Graphics, paperColor: number, routeColor: number) { - graphics.fillStyle(0x8d5a3a, 1); - graphics.fillRoundedRect(5, 5, 5, 18, 2); - graphics.fillRoundedRect(18, 5, 5, 18, 2); - graphics.fillStyle(paperColor, 1); - graphics.fillRoundedRect(8, 6, 12, 16, 2); - graphics.lineStyle(1, 0x4e3522, 0.7); - graphics.strokeRoundedRect(8, 6, 12, 16, 2); - graphics.lineStyle(2, routeColor, 1); + graphics.fillStyle(0x5f8f65, 1); + graphics.fillEllipse(18, 7, 7, 4); + graphics.fillStyle(0xf0a6a4, 1); + graphics.fillEllipse(11, 15, 9, 13); + graphics.fillEllipse(17, 15, 9, 13); + graphics.fillTriangle(8, 16, 20, 16, 14, 24); + graphics.fillStyle(0xf7c7bd, 0.8); + graphics.fillEllipse(11, 13, 4, 7); + graphics.fillEllipse(17, 13, 4, 7); + graphics.lineStyle(1, 0x9b4c3a, 0.85); graphics.beginPath(); - graphics.moveTo(10, 18); - graphics.lineTo(13, 14); - graphics.lineTo(15, 16); - graphics.lineTo(18, 10); + graphics.moveTo(14, 10); + graphics.lineTo(14, 23); + graphics.moveTo(9, 17); + graphics.lineTo(19, 17); graphics.strokePath(); graphics.fillStyle(0xd8b15f, 1); - graphics.fillCircle(18, 10, 2); + graphics.fillCircle(14, 8, 2); + graphics.fillCircle(14, 19, 1); } - private drawTokenIcon(graphics: Phaser.GameObjects.Graphics, baseColor: number, accentColor: number) { - graphics.fillStyle(baseColor, 1); - graphics.fillCircle(14, 14, 9); - graphics.lineStyle(2, accentColor, 0.9); - graphics.strokeCircle(14, 14, 7); - graphics.fillStyle(accentColor, 1); - graphics.fillTriangle(14, 8, 18, 18, 10, 18); + private drawWarManualIcon(graphics: Phaser.GameObjects.Graphics) { + graphics.fillStyle(0x253d5a, 1); + graphics.fillRoundedRect(6, 5, 17, 20, 2); + graphics.fillStyle(0x5b78a0, 1); + graphics.fillRoundedRect(8, 6, 13, 18, 1); + graphics.fillStyle(0xe8dfca, 1); + graphics.fillRect(11, 8, 8, 14); + graphics.fillStyle(0xd8b15f, 1); + graphics.fillRect(8, 6, 3, 18); + graphics.fillRect(10, 5, 11, 2); + graphics.fillStyle(0x9b4c3a, 1); + graphics.fillTriangle(17, 8, 20, 8, 18, 13); + graphics.lineStyle(1, 0x101820, 0.8); + graphics.strokeRoundedRect(7, 6, 15, 18, 2); + graphics.beginPath(); + graphics.moveTo(14, 9); + graphics.lineTo(14, 22); + graphics.moveTo(12, 11); + graphics.lineTo(18, 11); + graphics.moveTo(12, 15); + graphics.lineTo(18, 15); + graphics.moveTo(12, 19); + graphics.lineTo(17, 19); + graphics.strokePath(); + graphics.fillStyle(0xf2e3bf, 1); + graphics.fillCircle(9, 10, 1); + graphics.fillCircle(9, 20, 1); } - private drawPouchIcon(graphics: Phaser.GameObjects.Graphics, baseColor: number, accentColor: number) { - graphics.fillStyle(baseColor, 1); - graphics.fillRoundedRect(7, 10, 14, 13, 4); + private drawMountainGuideScrollIcon(graphics: Phaser.GameObjects.Graphics) { + graphics.fillStyle(0x8d5a3a, 1); + graphics.fillRoundedRect(4, 5, 5, 18, 2); + graphics.fillRoundedRect(19, 5, 5, 18, 2); + graphics.fillStyle(0xcfae72, 1); + graphics.fillRoundedRect(7, 6, 14, 16, 2); + graphics.fillStyle(0xe8dfca, 0.82); + graphics.fillRect(10, 7, 8, 14); + graphics.fillStyle(0x6f7f5a, 1); + graphics.fillTriangle(9, 19, 13, 13, 16, 19); + graphics.fillTriangle(13, 20, 18, 11, 21, 20); + graphics.lineStyle(1, 0x4e3522, 0.8); + graphics.strokeRoundedRect(7, 6, 14, 16, 2); + graphics.beginPath(); + graphics.moveTo(11, 7); + graphics.lineTo(11, 22); + graphics.moveTo(17, 7); + graphics.lineTo(17, 22); + graphics.strokePath(); + graphics.lineStyle(2, 0x5f8f65, 1); + graphics.beginPath(); + graphics.moveTo(9, 17); + graphics.lineTo(12, 14); + graphics.lineTo(15, 16); + graphics.lineTo(19, 9); + graphics.strokePath(); + graphics.fillStyle(0xd8b15f, 1); + graphics.fillCircle(19, 9, 2); + graphics.fillCircle(9, 17, 1); + } + + private drawBraveryTokenIcon(graphics: Phaser.GameObjects.Graphics) { + graphics.fillStyle(0x9b4c3a, 1); + graphics.fillTriangle(10, 18, 7, 25, 13, 21); + graphics.fillTriangle(18, 18, 21, 25, 15, 21); + graphics.fillStyle(0xd8b15f, 1); + graphics.fillCircle(14, 13, 9); + graphics.fillStyle(0xf2d68b, 1); + graphics.fillCircle(14, 13, 6); + graphics.lineStyle(2, 0x9b4c3a, 0.95); + graphics.strokeCircle(14, 13, 8); + graphics.strokeCircle(14, 13, 4); + graphics.fillStyle(0x9b4c3a, 1); + graphics.fillTriangle(14, 7, 16, 12, 12, 12); + graphics.fillTriangle(14, 19, 16, 14, 12, 14); + graphics.fillTriangle(8, 13, 13, 11, 13, 15); + graphics.fillTriangle(20, 13, 15, 11, 15, 15); + graphics.lineStyle(1, 0x5d2d25, 0.9); + graphics.beginPath(); + graphics.moveTo(11, 4); + graphics.lineTo(17, 4); + graphics.moveTo(10, 22); + graphics.lineTo(18, 22); + graphics.strokePath(); + graphics.fillStyle(0x101820, 0.45); + graphics.fillCircle(14, 13, 1); + } + + private drawGrainPouchIcon(graphics: Phaser.GameObjects.Graphics) { + graphics.fillStyle(0x7a5535, 1); graphics.fillTriangle(10, 11, 18, 11, 14, 5); - graphics.lineStyle(2, accentColor, 1); + graphics.fillRoundedRect(6, 10, 16, 14, 5); + graphics.fillStyle(0xa7794a, 1); + graphics.fillRoundedRect(8, 11, 12, 12, 4); + graphics.fillStyle(0xe8dfca, 1); + graphics.fillEllipse(11, 17, 2, 4); + graphics.fillEllipse(14, 18, 2, 4); + graphics.fillEllipse(17, 16, 2, 4); + graphics.lineStyle(2, 0xe8dfca, 0.95); graphics.beginPath(); graphics.moveTo(8, 13); graphics.lineTo(20, 13); + graphics.moveTo(10, 10); + graphics.lineTo(18, 10); graphics.strokePath(); + graphics.lineStyle(1, 0x4e3522, 0.85); + graphics.strokeRoundedRect(7, 10, 14, 14, 4); + graphics.beginPath(); + graphics.moveTo(9, 15); + graphics.lineTo(8, 21); + graphics.moveTo(19, 15); + graphics.lineTo(20, 21); + graphics.strokePath(); + graphics.fillStyle(0xd8b15f, 1); + graphics.fillCircle(14, 12, 1); } - private drawQuiverIcon(graphics: Phaser.GameObjects.Graphics, baseColor: number, arrowColor: number) { - graphics.fillStyle(baseColor, 1); - graphics.fillRoundedRect(10, 8, 9, 16, 2); - graphics.lineStyle(2, arrowColor, 1); + private drawYellowScarfCharmIcon(graphics: Phaser.GameObjects.Graphics) { + graphics.fillStyle(0xd8b15f, 1); + graphics.fillRoundedRect(9, 5, 10, 10, 2); + graphics.fillTriangle(9, 12, 5, 24, 12, 19); + graphics.fillTriangle(19, 12, 23, 24, 16, 19); + graphics.fillStyle(0xf2d68b, 1); + graphics.fillRoundedRect(11, 7, 6, 6, 1); + graphics.fillStyle(0x8b6f2a, 1); + graphics.fillCircle(14, 12, 3); + graphics.fillTriangle(14, 6, 16, 12, 12, 12); + graphics.lineStyle(2, 0x8b6f2a, 0.95); graphics.beginPath(); - graphics.moveTo(7, 6); - graphics.lineTo(18, 20); - graphics.moveTo(13, 5); - graphics.lineTo(20, 19); + graphics.moveTo(10, 6); + graphics.lineTo(18, 14); + graphics.moveTo(18, 6); + graphics.lineTo(10, 14); + graphics.moveTo(8, 18); + graphics.lineTo(12, 16); + graphics.moveTo(20, 18); + graphics.lineTo(16, 16); graphics.strokePath(); + graphics.lineStyle(1, 0xe8dfca, 0.75); + graphics.beginPath(); + graphics.moveTo(8, 21); + graphics.lineTo(11, 19); + graphics.moveTo(20, 21); + graphics.lineTo(17, 19); + graphics.strokePath(); + graphics.fillStyle(0x9b4c3a, 1); + graphics.fillCircle(14, 12, 1); + } + + private drawWindQuiverIcon(graphics: Phaser.GameObjects.Graphics) { + graphics.fillStyle(0x4f7d92, 1); + graphics.fillRoundedRect(9, 8, 10, 17, 2); + graphics.fillStyle(0x8bb3c7, 1); + graphics.fillRoundedRect(11, 10, 7, 13, 2); + graphics.fillStyle(0x2f5f8f, 1); + graphics.fillTriangle(9, 9, 20, 8, 16, 13); + graphics.fillStyle(0xe8dfca, 1); + graphics.fillTriangle(6, 4, 10, 6, 8, 9); + graphics.fillTriangle(12, 3, 16, 5, 14, 8); + graphics.fillTriangle(18, 4, 22, 6, 20, 9); + graphics.lineStyle(2, 0xe8dfca, 1); + graphics.beginPath(); + graphics.moveTo(8, 6); + graphics.lineTo(15, 19); + graphics.moveTo(14, 5); + graphics.lineTo(18, 18); + graphics.moveTo(20, 6); + graphics.lineTo(17, 20); + graphics.strokePath(); + graphics.lineStyle(1, 0x101820, 0.75); + graphics.strokeRoundedRect(10, 9, 9, 15, 2); + graphics.beginPath(); + graphics.moveTo(12, 15); + graphics.lineTo(18, 13); + graphics.moveTo(12, 19); + graphics.lineTo(18, 17); + graphics.strokePath(); + graphics.fillStyle(0xd8b15f, 1); + graphics.fillCircle(14, 22, 1); } }