diff --git a/apps/client/src/hooks/useSocketSubscriptions.ts b/apps/client/src/hooks/useSocketSubscriptions.ts index 8663c7b..ad75a40 100644 --- a/apps/client/src/hooks/useSocketSubscriptions.ts +++ b/apps/client/src/hooks/useSocketSubscriptions.ts @@ -16,6 +16,38 @@ setScenePhase: (phase: appTypes.ScenePhase) => void; }; +type AppSocketHandlers = { + handleConnect: (id: string) => void; + handleRoomUpdate: (updatedRoom: roomTypes.Room) => void; + handleGameStart: () => void; + handleGameResult: (payload: GameResultPayload) => void; +}; + +const registerConnectionSubscriptions = ({ handleConnect }: AppSocketHandlers): void => { + socketManager.common.onConnect(handleConnect); +}; + +const unregisterConnectionSubscriptions = ({ handleConnect }: AppSocketHandlers): void => { + socketManager.common.offConnect(handleConnect); +}; + +const registerRoomSubscriptions = ({ handleRoomUpdate }: AppSocketHandlers): void => { + socketManager.lobby.onRoomUpdate(handleRoomUpdate); +}; + +const unregisterRoomSubscriptions = ({ handleRoomUpdate }: AppSocketHandlers): void => { + socketManager.lobby.offRoomUpdate(handleRoomUpdate); +}; + +const registerGameSubscriptions = ({ handleGameStart, handleGameResult }: AppSocketHandlers): void => { + socketManager.game.onceGameStart(handleGameStart); + socketManager.game.onGameResult(handleGameResult); +}; + +const unregisterGameSubscriptions = ({ handleGameResult }: AppSocketHandlers): void => { + socketManager.game.offGameResult(handleGameResult); +}; + /** アプリ共通のソケット購読を登録しクリーンアップするフック */ export const useSocketSubscriptions = ({ completeJoinRequest, @@ -25,36 +57,37 @@ setScenePhase, }: UseSocketSubscriptionsParams): void => { useEffect(() => { - const handleConnect = (id: string) => { + const handlers: AppSocketHandlers = { + handleConnect: (id: string) => { setMyId(id); - }; + }, - const handleRoomUpdate = (updatedRoom: roomTypes.Room) => { + handleRoomUpdate: (updatedRoom: roomTypes.Room) => { completeJoinRequest(); setRoom(updatedRoom); setScenePhase(appConsts.ScenePhase.LOBBY); - }; + }, - const handleGameStart = () => { + handleGameStart: () => { setGameResult(null); setScenePhase(appConsts.ScenePhase.PLAYING); - }; + }, - const handleGameResult = (payload: GameResultPayload) => { + handleGameResult: (payload: GameResultPayload) => { setGameResult(payload); setScenePhase(appConsts.ScenePhase.RESULT); + }, }; - socketManager.common.onConnect(handleConnect); - socketManager.lobby.onRoomUpdate(handleRoomUpdate); - socketManager.game.onceGameStart(handleGameStart); - socketManager.game.onGameResult(handleGameResult); + registerConnectionSubscriptions(handlers); + registerRoomSubscriptions(handlers); + registerGameSubscriptions(handlers); return () => { completeJoinRequest(); - socketManager.common.offConnect(handleConnect); - socketManager.lobby.offRoomUpdate(handleRoomUpdate); - socketManager.game.offGameResult(handleGameResult); + unregisterConnectionSubscriptions(handlers); + unregisterRoomSubscriptions(handlers); + unregisterGameSubscriptions(handlers); }; }, [completeJoinRequest, setGameResult, setMyId, setRoom, setScenePhase]); }; diff --git a/apps/client/src/scenes/game/entities/player/PlayerView.ts b/apps/client/src/scenes/game/entities/player/PlayerView.ts index 9c55c23..0740720 100644 --- a/apps/client/src/scenes/game/entities/player/PlayerView.ts +++ b/apps/client/src/scenes/game/entities/player/PlayerView.ts @@ -6,6 +6,8 @@ import { Assets, Sprite, Texture } from "pixi.js"; import { config } from "@client/config"; +const ENABLE_DEBUG_LOG = import.meta.env.DEV; + export class PlayerView { public readonly displayObject: Sprite; @@ -54,7 +56,6 @@ } /** BASE_URL対応のURLで画像を読み込み、スプライトに反映する */ - /** BASE_URL対応のURLで画像を読み込み、スプライトに反映する */ private async applyTexture(imageFileName: string): Promise { try { const imageUrl = `${import.meta.env.BASE_URL}${imageFileName}`; @@ -69,10 +70,11 @@ this.displayObject.width = PLAYER_RADIUS_PX * 2 * scaleRate; this.displayObject.height = PLAYER_RADIUS_PX * 2 * scaleRate; - // 👇 ちゃんとこの処理が実行されているか、ブラウザのログに出す! - console.log( - `🎨 画像を ${scaleRate} 倍のサイズ(${this.displayObject.width})に拡大しました!`, - ); + if (ENABLE_DEBUG_LOG) { + console.log( + `[PlayerView] 画像を ${scaleRate} 倍のサイズ(${this.displayObject.width})に拡大`, + ); + } } catch (error) { console.error( `[PlayerView] 画像の読み込みに失敗: ${imageFileName}`, diff --git a/apps/client/src/scenes/result/ResultScene.tsx b/apps/client/src/scenes/result/ResultScene.tsx index d801ebd..e3225de 100644 --- a/apps/client/src/scenes/result/ResultScene.tsx +++ b/apps/client/src/scenes/result/ResultScene.tsx @@ -4,6 +4,7 @@ * 順位,チーム名,塗り率の3項目をテーブル形式で描画する */ import type { GameResultPayload } from "@repo/shared"; +import type { CSSProperties } from "react"; type Props = { result: GameResultPayload | null; @@ -11,6 +12,56 @@ const formatPaintRate = (value: number): string => `${value.toFixed(1)}%`; +const ROW_GRID_TEMPLATE = "120px 1fr 180px"; + +const ROOT_STYLE: CSSProperties = { + width: "100vw", + height: "100dvh", + background: "#111", + color: "white", + display: "flex", + flexDirection: "column", + alignItems: "center", + padding: "24px", + boxSizing: "border-box", +}; + +const TITLE_STYLE: CSSProperties = { + margin: "0 0 20px 0", + fontSize: "clamp(1.6rem, 4vw, 2.2rem)", +}; + +const TABLE_STYLE: CSSProperties = { + width: "100%", + maxWidth: "720px", + border: "1px solid #444", + borderRadius: "8px", + overflow: "hidden", +}; + +const HEADER_ROW_STYLE: CSSProperties = { + display: "grid", + gridTemplateColumns: ROW_GRID_TEMPLATE, + background: "#222", + padding: "12px 16px", + fontWeight: "bold", +}; + +const RIGHT_ALIGN_STYLE: CSSProperties = { textAlign: "right" }; + +const RATE_STYLE: CSSProperties = { + textAlign: "right", + fontVariantNumeric: "tabular-nums", +}; + +const getBodyRowStyle = (index: number): CSSProperties => ({ + display: "grid", + gridTemplateColumns: ROW_GRID_TEMPLATE, + padding: "12px 16px", + borderTop: "1px solid #333", + background: index % 2 === 0 ? "#171717" : "#1d1d1d", +}); + /** 最終結果データを受け取り,順位一覧を表示する */ export const ResultScene = ({ result }: Props) => { if (!result) { @@ -18,58 +69,21 @@ } return ( -
-

結果発表

+
+

結果発表

-
-
+
+
順位 チーム名 - 塗り率 + 塗り率
{result.rankings.map((row, index) => ( -
+
{row.rank}位 {row.teamName} - + {formatPaintRate(row.paintRate)}
diff --git a/apps/server/src/index.ts b/apps/server/src/index.ts index d737722..b3bc22b 100644 --- a/apps/server/src/index.ts +++ b/apps/server/src/index.ts @@ -4,7 +4,7 @@ */ import { createHttpServer } from "./network/bootstrap/createHttpServer"; import { boot } from "./network/bootstrap/boot"; -import { config } from "@server/config"; +import { config } from "./config"; // サーバー待受ポート const PORT = process.env.PORT || config.NETWORK_CONFIG.DEV_SERVER_PORT;