Skip to content

Commit 33e3dd0

Browse files
committed
CG-0MM40Y9K00GRIDAF: Add Splendor layout regression test and fix overlap
Add browser-based layout regression test for SplendorScene that verifies upper band sections (nobles, market, supply) don't overlap, player/AI section boxes don't overlap action buttons or instruction text, and action buttons don't overlap instruction text. Fix overlapping layout by decoupling section box height from ACTION_Y: - Introduce LOWER_BOX_H=156 constant for fixed section box height - Move ACTION_Y from 618 to 626 (5px clearance below section boxes) - Move INSTRUCTION_Y from 664 to 660 - Add getSectionBoxRects() and getLayoutConstants() test accessors The test was verified to fail before the fix (section box bottom 606 overlapped action button top 597 by 9px) and pass after.
1 parent a7d75e3 commit 33e3dd0

2 files changed

Lines changed: 454 additions & 4 deletions

File tree

example-games/splendor/scenes/SplendorScene.ts

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ const SECTION_BOX_PAD = 8; // padding around content
141141

142142
// ── Lower-band layout ──────────────────────────────────────
143143
const LOWER_TOP = 452; // top of lower band (slightly higher for more room)
144+
const LOWER_BOX_H = 156; // fixed height for player/AI section boxes
144145

145146
// Player area — left half of lower band
146147
const PLAYER_AREA_X = 20;
@@ -154,8 +155,10 @@ const AI_AREA_Y = LOWER_TOP;
154155
const DIVIDER_X = 640;
155156

156157
// Action buttons and instructions — centred at bottom
157-
const ACTION_Y = 618; // action buttons Y
158-
const INSTRUCTION_Y = 664; // instruction text Y (centred horizontally)
158+
// ACTION_Y must ensure button top (ACTION_Y - 21) is below section box bottom
159+
// Section box bottom = (LOWER_TOP - SECTION_BOX_PAD) + LOWER_BOX_H = 600
160+
const ACTION_Y = 626; // action buttons Y (top edge at 605, below box bottom 600)
161+
const INSTRUCTION_Y = 660; // instruction text Y (centred horizontally)
159162

160163
// ── Audio asset keys ────────────────────────────────────────
161164

@@ -453,14 +456,14 @@ export class SplendorScene extends Phaser.Scene {
453456
const playerBoxX = PLAYER_AREA_X - p;
454457
const playerBoxY = LOWER_TOP - p;
455458
const playerBoxW = DIVIDER_X - PLAYER_AREA_X;
456-
const playerBoxH = ACTION_Y - LOWER_TOP - 4;
459+
const playerBoxH = LOWER_BOX_H;
457460
this.drawSectionBox(playerBoxX, playerBoxY, playerBoxW, playerBoxH);
458461

459462
// AI area box
460463
const aiBoxX = DIVIDER_X + p;
461464
const aiBoxY = LOWER_TOP - p;
462465
const aiBoxW = AI_AREA_X - DIVIDER_X + p;
463-
const aiBoxH = ACTION_Y - LOWER_TOP - 4;
466+
const aiBoxH = LOWER_BOX_H;
464467
this.drawSectionBox(aiBoxX, aiBoxY, aiBoxW, aiBoxH);
465468
}
466469

@@ -1807,6 +1810,74 @@ export class SplendorScene extends Phaser.Scene {
18071810
});
18081811
}
18091812

1813+
// ── Test accessors ──────────────────────────────────────
1814+
1815+
/**
1816+
* Returns the computed section box rectangles for layout testing.
1817+
* Each rectangle is { x, y, w, h } representing the top-left origin box.
1818+
*/
1819+
getSectionBoxRects(): {
1820+
nobles: { x: number; y: number; w: number; h: number };
1821+
market: { x: number; y: number; w: number; h: number };
1822+
supply: { x: number; y: number; w: number; h: number };
1823+
player: { x: number; y: number; w: number; h: number };
1824+
ai: { x: number; y: number; w: number; h: number };
1825+
} {
1826+
const p = SECTION_BOX_PAD;
1827+
const lastCardRight = MARKET_X + 4 * (MARKET_CARD_W + MARKET_CARD_GAP) - MARKET_CARD_GAP;
1828+
return {
1829+
nobles: {
1830+
x: NOBLE_X - p,
1831+
y: MARKET_Y - p - 16,
1832+
w: NOBLE_W + p * 2,
1833+
h: MARKET_TOTAL_H + p * 2 + 16,
1834+
},
1835+
market: {
1836+
x: DECK_X - 90 - p,
1837+
y: MARKET_Y - p - 16,
1838+
w: lastCardRight - (DECK_X - 90 - p) + p,
1839+
h: MARKET_TOTAL_H + p * 2 + 16,
1840+
},
1841+
supply: {
1842+
x: SUPPLY_X - SUPPLY_TOKEN_R - 70 - p,
1843+
y: SUPPLY_Y - SUPPLY_TOKEN_R - p - 16,
1844+
w: SUPPLY_TOKEN_R + 70 + SUPPLY_TOKEN_R + p * 2,
1845+
h: SUPPLY_TOTAL_H + SUPPLY_TOKEN_R * 2 + p * 2 + 16,
1846+
},
1847+
player: {
1848+
x: PLAYER_AREA_X - p,
1849+
y: LOWER_TOP - p,
1850+
w: DIVIDER_X - PLAYER_AREA_X,
1851+
h: LOWER_BOX_H,
1852+
},
1853+
ai: {
1854+
x: DIVIDER_X + p,
1855+
y: LOWER_TOP - p,
1856+
w: AI_AREA_X - DIVIDER_X + p,
1857+
h: LOWER_BOX_H,
1858+
},
1859+
};
1860+
}
1861+
1862+
/**
1863+
* Returns the layout constants relevant for action/instruction positioning.
1864+
*/
1865+
getLayoutConstants(): {
1866+
actionY: number;
1867+
instructionY: number;
1868+
gameW: number;
1869+
gameH: number;
1870+
actionButtonH: number;
1871+
} {
1872+
return {
1873+
actionY: ACTION_Y,
1874+
instructionY: INSTRUCTION_Y,
1875+
gameW: GAME_W,
1876+
gameH: GAME_H,
1877+
actionButtonH: 42,
1878+
};
1879+
}
1880+
18101881
// ── Lifecycle cleanup ───────────────────────────────────
18111882

18121883
shutdown(): void {

0 commit comments

Comments
 (0)