From d6aa03ab8de531f75c777b78040cd8f4420ff081 Mon Sep 17 00:00:00 2001 From: Haritabh Gupta <20576107+haritabh17@users.noreply.github.com> Date: Sun, 5 Jul 2026 18:55:35 +0100 Subject: [PATCH] fix(court): show near-side mascot backs and mirror racket hand by facing --- components/BadmintonCourt.tsx | 1 + components/PlayerMarker.tsx | 11 +- components/mascots.tsx | 218 ++++++++++++++++++++-------------- 3 files changed, 141 insertions(+), 89 deletions(-) diff --git a/components/BadmintonCourt.tsx b/components/BadmintonCourt.tsx index ced03f6..5763227 100644 --- a/components/BadmintonCourt.tsx +++ b/components/BadmintonCourt.tsx @@ -664,6 +664,7 @@ export default function BadmintonCourt() { color={customizations[id].color} size={customizations[id].size} isLeftHanded={customizations[id].isLeftHanded} + facingAway icon={customizations[id].icon} iconType={customizations[id].iconType} look={effectiveLooks[id]} diff --git a/components/PlayerMarker.tsx b/components/PlayerMarker.tsx index 3927866..26d83be 100644 --- a/components/PlayerMarker.tsx +++ b/components/PlayerMarker.tsx @@ -13,8 +13,10 @@ interface PlayerMarkerProps { position: { x: number; y: number }; color: string; size?: number; - /** Full-body mascot looks mirror for left-handed players. */ + /** Mascot looks mirror so the racket sits on the handedness' screen side. */ isLeftHanded?: boolean; + /** Near-court players (team 2) face away from the viewer; mascots show their back. */ + facingAway?: boolean; icon?: string; iconType?: 'icon' | 'text' | 'photo'; /** Selected look; mascot looks render the full-body figure. */ @@ -41,6 +43,7 @@ export function PlayerMarker({ color, size, isLeftHanded = false, + facingAway = false, icon = 'account', iconType = 'icon', look = 'classic', @@ -186,7 +189,11 @@ export function PlayerMarker({ band={color} label={label} width={markerSize} - flipped={isLeftHanded} + // Raw art holds the racket on the screen's right. Facing the viewer, + // a right hand reads on the screen's left, so front views mirror for + // right-handers; back views mirror for left-handers. + flipped={facingAway ? isLeftHanded : !isLeftHanded} + facingAway={facingAway} /> )} diff --git a/components/mascots.tsx b/components/mascots.tsx index 6e68d81..64411e2 100644 --- a/components/mascots.tsx +++ b/components/mascots.tsx @@ -22,6 +22,8 @@ import { sora } from '../constants/theme'; interface ArtProps { band: string; + /** Back view (near-court players): same figure minus face/front-only details. */ + back?: boolean; } interface MascotArt { @@ -52,17 +54,21 @@ const Racket = ({ transform = 'rotate(18 46 22)' }: { transform?: string }) => ( // ─── Panda ─────────────────────────────────────────────────────────────── -const pandaHead = ({ band }: ArtProps) => ( +const pandaHead = ({ band, back }: ArtProps) => ( <> - - - - - + {!back && ( + <> + + + + + + + )} ); @@ -82,7 +88,7 @@ const panda: MascotArt = { ), head: pandaHead, - body: ({ band }) => ( + body: ({ band, back }) => ( <> @@ -93,26 +99,30 @@ const panda: MascotArt = { - {pandaHead({ band })} + {pandaHead({ band, back })} ), }; // ─── Fox ───────────────────────────────────────────────────────────────── -const foxHead = ({ band }: ArtProps) => ( +const foxHead = ({ band, back }: ArtProps) => ( <> - - - - - - + {!back && ( + <> + + + + + + + + )} ); @@ -126,7 +136,7 @@ const fox: MascotArt = { ), head: foxHead, - body: ({ band }) => ( + body: ({ band, back }) => ( <> - + {!back && } - {foxHead({ band })} + {foxHead({ band, back })} ), }; // ─── Bear · jump smash ─────────────────────────────────────────────────── -const bearHead = ({ band }: ArtProps) => ( +const bearHead = ({ band, back }: ArtProps) => ( <> @@ -163,12 +173,16 @@ const bearHead = ({ band }: ArtProps) => ( - - - - - - + {!back && ( + <> + + + + + + + + )} ); @@ -184,7 +198,7 @@ const bear: MascotArt = { ), head: bearHead, - body: ({ band }) => ( + body: ({ band, back }) => ( <> @@ -201,8 +215,8 @@ const bear: MascotArt = { - - {bearHead({ band })} + {!back && } + {bearHead({ band, back })} @@ -212,7 +226,7 @@ const bear: MascotArt = { // ─── Tiger · sprint ────────────────────────────────────────────────────── -const tigerHead = ({ band }: ArtProps) => ( +const tigerHead = ({ band, back }: ArtProps) => ( <> @@ -220,13 +234,17 @@ const tigerHead = ({ band }: ArtProps) => ( - - - - - - - + {!back && ( + <> + + + + + + + + + )} ); @@ -241,7 +259,7 @@ const tiger: MascotArt = { ), head: tigerHead, - body: ({ band }) => ( + body: ({ band, back }) => ( <> @@ -257,9 +275,9 @@ const tiger: MascotArt = { - + {!back && } - {tigerHead({ band })} + {tigerHead({ band, back })} @@ -269,22 +287,30 @@ const tiger: MascotArt = { // ─── Frog · flying leap ────────────────────────────────────────────────── -const frogHead = ({ band }: ArtProps) => ( +const frogHead = ({ band, back }: ArtProps) => ( <> - - - - - - + {!back && ( + <> + + + + + + + + )} - - - + {!back && ( + <> + + + + + )} ); @@ -299,7 +325,7 @@ const frog: MascotArt = { ), head: frogHead, - body: ({ band }) => ( + body: ({ band, back }) => ( <> @@ -310,8 +336,8 @@ const frog: MascotArt = { - - {frogHead({ band })} + {!back && } + {frogHead({ band, back })} @@ -322,17 +348,21 @@ const frog: MascotArt = { // ─── Penguin · slide save ──────────────────────────────────────────────── -const penguinHead = ({ band }: ArtProps) => ( +const penguinHead = ({ band, back }: ArtProps) => ( <> - + {!back && } - - - - - + {!back && ( + <> + + + + + + + )} ); @@ -346,7 +376,7 @@ const penguin: MascotArt = { ), head: penguinHead, - body: ({ band }) => ( + body: ({ band, back }) => ( <> @@ -355,20 +385,20 @@ const penguin: MascotArt = { - + {!back && } - {penguinHead({ band })} + {penguinHead({ band, back })} ), }; // ─── Koala · gold cape ─────────────────────────────────────────────────── -const koalaHead = ({ band }: ArtProps) => ( +const koalaHead = ({ band, back }: ArtProps) => ( <> @@ -377,12 +407,16 @@ const koalaHead = ({ band }: ArtProps) => ( - - - - - - + {!back && ( + <> + + + + + + + + )} ); @@ -396,7 +430,7 @@ const koala: MascotArt = { ), head: koalaHead, - body: ({ band }) => ( + body: ({ band, back }) => ( <> - + {!back && } - {koalaHead({ band })} + {koalaHead({ band, back })} ), }; // ─── Owl · night cape ──────────────────────────────────────────────────── -const owlHead = ({ band }: ArtProps) => ( +const owlHead = ({ band, back }: ArtProps) => ( <> - - - - - - - + {!back && ( + <> + + + + + + + + + )} ); @@ -449,7 +487,7 @@ const owl: MascotArt = { ), head: owlHead, - body: ({ band }) => ( + body: ({ band, back }) => ( <> - - + {!back && ( + <> + + + + )} - {owlHead({ band })} + {owlHead({ band, back })} ), }; @@ -503,11 +545,13 @@ interface MascotViewProps { /** Number shown on the chip; omit to hide the chip (tiles show it though). */ label?: string; width: number; - /** Mirror for left-handed players; the number chip stays upright. */ + /** Mirror so the racket lands on the correct screen side; the chip stays upright. */ flipped?: boolean; + /** Near-court players show their back; the chip reads as the jersey-back number. */ + facingAway?: boolean; } -export function MascotView({ mascot, band, label, width, flipped = false }: MascotViewProps) { +export function MascotView({ mascot, band, label, width, flipped = false, facingAway = false }: MascotViewProps) { const art = MASCOT_ART[mascot]; const height = width * MASCOT_ASPECT; const s = width / 56; @@ -522,7 +566,7 @@ export function MascotView({ mascot, band, label, width, flipped = false }: Masc - + {label != null && (