diff --git a/assets/images/ta/arm-structures.png b/assets/images/ta/arm-structures.png index 301b0c8..afcdbcd 100644 Binary files a/assets/images/ta/arm-structures.png and b/assets/images/ta/arm-structures.png differ diff --git a/assets/images/ta/arm-structures.psd b/assets/images/ta/arm-structures.psd index 0666ad1..a5fea03 100644 Binary files a/assets/images/ta/arm-structures.psd and b/assets/images/ta/arm-structures.psd differ diff --git a/assets/images/ta/arm-units.png b/assets/images/ta/arm-units.png index 53b058d..d6a5284 100644 Binary files a/assets/images/ta/arm-units.png and b/assets/images/ta/arm-units.png differ diff --git a/assets/images/ta/arm-units.psd b/assets/images/ta/arm-units.psd index 2b9bcdc..da32a48 100644 Binary files a/assets/images/ta/arm-units.psd and b/assets/images/ta/arm-units.psd differ diff --git a/assets/images/ta/core-structures.png b/assets/images/ta/core-structures.png index bf4a8da..df45457 100644 Binary files a/assets/images/ta/core-structures.png and b/assets/images/ta/core-structures.png differ diff --git a/assets/images/ta/core-structures.psd b/assets/images/ta/core-structures.psd index f1dd286..d732599 100644 Binary files a/assets/images/ta/core-structures.psd and b/assets/images/ta/core-structures.psd differ diff --git a/assets/images/ta/core-units.png b/assets/images/ta/core-units.png index 4b421d1..354d903 100644 Binary files a/assets/images/ta/core-units.png and b/assets/images/ta/core-units.png differ diff --git a/assets/images/ta/core-units.psd b/assets/images/ta/core-units.psd index ac42c2e..c06f4d5 100644 Binary files a/assets/images/ta/core-units.psd and b/assets/images/ta/core-units.psd differ diff --git a/data/totalannihilation-artwork.json b/data/totalannihilation-artwork.json index 4e674ea..cb1f800 100644 --- a/data/totalannihilation-artwork.json +++ b/data/totalannihilation-artwork.json @@ -67,7 +67,7 @@ }, "icons": { "key": "ta-icons", "path": null, "kind": "icon", - "frameWidth": 44, "frameHeight": 44, "cols": 10, + "frameWidth": 64, "frameHeight": 64, "cols": 10, "rows": 4 } }, diff --git a/src/games/totalannihilation/TAHud.js b/src/games/totalannihilation/TAHud.js index 648914e..0e410da 100644 --- a/src/games/totalannihilation/TAHud.js +++ b/src/games/totalannihilation/TAHud.js @@ -273,6 +273,9 @@ export default class TAHud { this._clearGrid(); const s = this.scene; const army = this.state.armies[this.playerArmy]; + // Real art or the procedural fallback (TAArt.js always supplies one or the other), so this + // is only null for a def that predates the `icon` field — see the fallback layout below. + const iconKey = this.view.sheetKeys?.icons; options.forEach((def, i) => { const col = i % GRID_COLS, row = Math.floor(i / GRID_COLS); // The container is placed at the button's CENTRE, not its top-left — see below. @@ -286,13 +289,23 @@ export default class TAHud { // child here is centred on (0,0) so the visual and the hit area coincide. const box = s.add.rectangle(0, 0, BTN_W, BTN_H, affordable ? 0x22304a : 0x1a2130, 1) .setStrokeStyle(2, affordable ? EDGE : 0x2a3244); - const label = s.add.text(0, -BTN_H / 2 + 12, shortName(def.name), { - fontFamily: FONT, fontSize: '20px', color: affordable ? TEXT : '#5d6b80', + const children = [box]; + const hasIcon = iconKey != null && def.icon != null; + // The icon carries the button's identity at a glance once one exists; name and cost drop + // underneath it rather than owning the whole button the way they did before icons. + if (hasIcon) { + const icon = s.add.image(0, -18, iconKey, def.icon).setDisplaySize(36, 36); + if (!affordable) icon.setAlpha(0.5); + children.push(icon); + } + const label = s.add.text(0, hasIcon ? 2 : -BTN_H / 2 + 12, shortName(def.name), { + fontFamily: FONT, fontSize: hasIcon ? '14px' : '20px', color: affordable ? TEXT : '#5d6b80', }).setOrigin(0.5, 0); - const cost = s.add.text(0, -BTN_H / 2 + 44, `${def.cost.mass}m ${def.cost.energy}e`, { - fontFamily: FONT, fontSize: '15px', color: affordable ? DIM : '#4e5a6d', + const cost = s.add.text(0, hasIcon ? 18 : -BTN_H / 2 + 44, `${def.cost.mass}m ${def.cost.energy}e`, { + fontFamily: FONT, fontSize: hasIcon ? '12px' : '15px', color: affordable ? DIM : '#4e5a6d', }).setOrigin(0.5, 0); - c.add([box, label, cost]); + children.push(label, cost); + c.add(children); c.setSize(BTN_W, BTN_H); c.setInteractive({ useHandCursor: true }); c.on('pointerover', () => box.setFillStyle(affordable ? 0x2e3f5f : 0x1a2130, 1)); diff --git a/src/games/totalannihilation/sprites.md b/src/games/totalannihilation/sprites.md index 7e09352..addd49e 100644 --- a/src/games/totalannihilation/sprites.md +++ b/src/games/totalannihilation/sprites.md @@ -30,14 +30,14 @@ capacity the verify script holds every `frame` index to, and it is measured off | Sheet name (JSON key) | Texture key | Cell | Cols | Contents | |---|---|---|---|---| -| `arm-units` | `ta-arm-units` | 64×64 | 8 | ARM mobile units | -| `core-units` | `ta-core-units` | 64×64 | 8 | CORE mobile units | +| `arm-units` | `ta-arm-units` | 128×128 | 8 | ARM mobile units | +| `core-units` | `ta-core-units` | 128×128 | 8 | CORE mobile units | | `arm-structures` | `ta-arm-structures` | 192×192 | 6×4 | ARM buildings | | `core-structures` | `ta-core-structures` | 192×192 | 6×4 | CORE buildings | | `terrain-grasslands` | `ta-terrain-grasslands` | 64×64 | 9 | Grassland tiles | | `terrain-snowfields` | `ta-terrain-snowfields` | 64×64 | 9 | Snow tiles | | `terrain-tropics` | `ta-terrain-tropics` | 64×64 | 9 | Jungle tiles | -| `icons` | `ta-icons` | 44×44 | 10 | Command/build glyphs | +| `icons` | `ta-icons` | 64×64 | 10 | Command/build glyphs — shared, NOT per-army | Frames are numbered **left to right, then top to bottom**, starting at 0. @@ -228,24 +228,69 @@ The theme then appears in the skirmish setup screen automatically. --- -## Icons (44×44 cells, 10 per row) +## Icons (64×64 cells, 10 per row) Build-menu and command glyphs. Frame numbers come from each def's `icon` in the rules JSON and from `commandIcons`, so this table is a reflection of that file, not a second source of -truth. Purely decorative today — the build menu labels itself from unit names — so this sheet -is the lowest priority of the eight. +truth. + +**Shared across both armies — this is the one sheet that does NOT get the "paint every army's +sheet in its own finished colours" treatment** from the top of this doc. There's a single +`icons` entry in the artwork JSON, not an `arm-icons`/`core-icons` pair, and the same frame +renders in either player's build menu. Paint it in a neutral palette (dark plate + light +linework is what the procedural fallback already does) rather than ARM blue or CORE red/orange. + +**Wired into the build menu** (`TAHud._drawGrid`, since 2026-08-16): every button in the +build/production grid — buildings AND units — now draws this sheet's `def.icon` frame above the +shortened name and cost, at a **36×36 display size**. The command bar (Move/Attack/Patrol/…) +still renders text-only for now; its glyphs (frames 20–29) only exist for the procedural +fallback painter today. + +**The 64×64 source is intentionally bigger than that 36×36 display size.** Painting at exactly +the display size (the old 44×44 spec was already close to that trap) means every icon gets +upscaled a little and softens; painting bigger and letting Phaser scale down is what keeps it +crisp. Draw at the full 64×64 canvas — don't pre-shrink your art to "look right" at a smaller +preview size. | Frames | Contents | |---|---| | 0–9 | Units: commander, infantry, sniper, jeep, tank, rocket tank, rocket trooper, construction vehicle, fighter, bomber | | 10–16 | Buildings: energy gen, mass gen, barracks, vehicle plant, laser tower, missile launcher, advanced vehicle plant | | 17–19 | Overflow: hover constructor (unit), airfield, radar tower | -| 30–31 | Advanced radar, radar jammer | | 20–29 | Commands: move, attack, attack-move, stop, hold, patrol, guard, assist, repair, rally | +| 30–31 | Advanced radar, radar jammer | +| 32 | Megatank (unit) | Row 0 filled up before the Airfield units were added, which is why the hover constructor sits next to the buildings at 17 rather than with the other units. Nothing reads a row as a -category — only the `icon` numbers matter. +category — only the `icon` numbers matter. Frames 33–39 are free. + +### Painting priority: buildings the Commander and Construction Vehicle put up + +This is the set that actually appears in the build-menu grid during a normal game — the union +of everything `commander`, `constructor` and `hoverconstructor` can build — in a sensible +painting order (the 8 the Commander itself can queue from turn one, then the 3 that need a +Construction Vehicle or Hover Constructor first): + +| Frame | Building | Also needs a Constructor? | Footprint | +|---|---|---|---| +| 10 | Energy Generator | no — Commander builds it too | 2×2 | +| 11 | Mass Generator | no | 2×2 | +| 12 | Barracks | no | 3×3 | +| 13 | Vehicle Plant | no | 3×3 | +| 14 | Laser Tower | no | 1×1 | +| 15 | Missile Launcher | no | 2×2 | +| 18 | Airfield | no | 3×3 | +| 19 | Radar Tower | no | 2×2 | +| 16 | Advanced Vehicle Plant | **yes** | 4×4 | +| 30 | Advanced Radar | **yes** | 2×2 | +| 31 | Radar Jammer | **yes** | 2×2 | + +Draw each as a simplified, high-contrast read of its full structure-sheet art (see Structure +sheets below), not a literal crop of it — a 128–192px building shrunk straight down to 64px +loses its silhouette to surface detail. Keep the same silhouette and colour language (Laser +Tower's plinth-and-emitter, the Radar family's dish/mast/broken-rings distinction, etc.) so an +icon and its full-size building are still recognisably the same thing at a glance. ---