Skip to content

Commit bcf0a36

Browse files
committed
Improve ux a bit
Signed-off-by: Seonghyeon Cho <seonghyeoncho96@gmail.com>
1 parent aa4e3f3 commit bcf0a36

3 files changed

Lines changed: 474 additions & 94 deletions

File tree

packages/client/src/scenes/GameScene.ts

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,22 @@ export class GameScene extends Container implements IScene {
155155
const screenWidth = this.app.screen.width;
156156
const screenHeight = this.app.screen.height;
157157

158-
const availableWidth = screenWidth - IMAGE_GAP - UI_PADDING * 2;
159-
const availableHeight = screenHeight - UI_PADDING * 2 - 80;
158+
// Vertical layout band. Above the images: padding + timer chip + gap +
159+
// floating StageTracker (header + pills + IMAGE_HUG_GAP=36). Below the
160+
// images: padding + floating Hint button + IMAGE_HUG_GAP=36. The
161+
// middle-row arrow buttons float at the canvas center and don't claim
162+
// layout space. Constants are kept conservative so the floating React
163+
// pieces never overlap the panels.
164+
const TOP_RESERVE = UI_PADDING + 36 + 16 + 108; // ≈180
165+
const BOTTOM_RESERVE = UI_PADDING + 76; // ≈96 (Hint reserve regardless of mode for stable image position)
166+
167+
// Horizontal layout band: subtract room for the floating prev/next
168+
// arrows that flank the image pair. ARROW_BUTTON (48) + ARROW_GAP (48)
169+
// each side, mirrored from src/ui/react/GameHud.tsx so the arrows
170+
// always fit even on narrow viewports.
171+
const ARROW_RESERVE = (48 + 48) * 2;
172+
const availableWidth = screenWidth - IMAGE_GAP - UI_PADDING * 2 - ARROW_RESERVE;
173+
const availableHeight = screenHeight - TOP_RESERVE - BOTTOM_RESERVE;
160174
const maxImageWidth = availableWidth / 2;
161175

162176
const scaleX = maxImageWidth / IMAGE_WIDTH;
@@ -168,9 +182,22 @@ export class GameScene extends Container implements IScene {
168182

169183
const totalWidth = scaledWidth * 2 + IMAGE_GAP;
170184
const startX = (screenWidth - totalWidth) / 2;
171-
const startY = (screenHeight - scaledHeight) / 2 + 20;
185+
// Center the image within the available band — NOT the whole viewport —
186+
// so the floating tracker / hint above and below stay clear.
187+
const startY = TOP_RESERVE + Math.max(0, (availableHeight - scaledHeight) / 2);
172188

173189
this.gameArea.position.set(startX, startY);
190+
191+
// Tell the React HUD where the rendered image pair lives so it can hug
192+
// the panels: the StageTracker sits just above `top`, the Hint sits just
193+
// below `bottom`, and the prev/next arrows in MiddleRow hug the left/right
194+
// edges based on `width`. Republished on every layout pass so resize
195+
// (and image-scale recalculation) keeps the HUD anchored.
196+
useUIStore.getState().setImagePairBounds({
197+
width: totalWidth,
198+
top: startY,
199+
bottom: startY + scaledHeight,
200+
});
174201
}
175202

176203
private createPlaceholders(): void {
@@ -201,16 +228,16 @@ export class GameScene extends Container implements IScene {
201228
this.uiLayer.addChild(this.menuIcon);
202229
}
203230

204-
this.navButtons.position.set(
205-
this.app.screen.width / 2 - 55,
206-
this.app.screen.height - UI_PADDING - 50,
207-
);
231+
// NavButtons used to live as a Pixi widget at the bottom-center; the
232+
// React StageTracker now owns prev/next + per-pair jumps and exposes the
233+
// 5-dots-per-pair structure that Pixi text couldn't communicate. Keep
234+
// the instance around so existing setForceDisabled hooks remain valid,
235+
// but never add it to the scene graph.
208236
this.navButtons.setCallbacks(
209237
() => gameState.prevImage(),
210238
() => gameState.nextImage(),
211239
);
212240
this.navButtons.updateState(0, IMAGES_PER_GAME);
213-
this.uiLayer.addChild(this.navButtons);
214241
// HUD state (foundCount, currentImageIndex, opponentFoundCount, gameType)
215242
// was hydrated from gameState by ui.mountHud() in init() and stays in
216243
// sync via the store<->gameState bridge. Nothing to wire here.
@@ -750,7 +777,6 @@ export class GameScene extends Container implements IScene {
750777
resize(width: number, height: number): void {
751778
this.setupLayout();
752779
this.menuIcon.position.set(width - UI_PADDING - 44, UI_PADDING);
753-
this.navButtons.position.set(width / 2 - 55, height - UI_PADDING - 50);
754780
this.countdownOverlay.resize(width, height);
755781

756782
if (this.placeholderContainer.children.length > 0) {

0 commit comments

Comments
 (0)