diff --git a/apps/client/src/scenes/game/GameView.tsx b/apps/client/src/scenes/game/GameView.tsx
index a1c5732..7aa33b6 100644
--- a/apps/client/src/scenes/game/GameView.tsx
+++ b/apps/client/src/scenes/game/GameView.tsx
@@ -3,7 +3,7 @@
* ゲーム画面の描画専用コンポーネント
* タイマー表示,PixiJSの描画領域,入力UIの配置のみを担当する
*/
-import { Joystick } from "./input/joystick/Joystick";
+import { JoystickInputLayer } from "./input/joystick/JoystickInputLayer";
/** 表示と入力に必要なプロパティ */
type Props = {
@@ -51,7 +51,7 @@
{/* UI 配置領域 */}
-
+
);
diff --git a/apps/client/src/scenes/game/input/joystick/Joystick.tsx b/apps/client/src/scenes/game/input/joystick/Joystick.tsx
deleted file mode 100644
index 691c5cc..0000000
--- a/apps/client/src/scenes/game/input/joystick/Joystick.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * Joystick
- * 画面上のジョイスティックUIの入口
- * ポインターイベントを受け取り,useJoystick に処理を委譲し,描画は JoystickView に渡す
- */
-import { JoystickView } from "./JoystickView";
-import { MAX_DIST, useJoystick } from "./useJoystick";
-
-/** 入力半径の既定値を外部から参照できるように再公開 */
-export { MAX_DIST } from "./useJoystick";
-
-/** Joystick コンポーネントの入力コールバック */
-type Props = {
- onInput: (moveX: number, moveY: number) => void;
-};
-
-/** ポインター入力と描画を結びつけるジョイスティックUI */
-export const Joystick = ({ onInput }: Props) => {
- const { isMoving, center, knobOffset, radius, handleStart, handleMove, handleEnd } =
- useJoystick({ onInput });
-
- return (
-
- {/* 見た目のみの描画(入力は扱わない) */}
-
-
- );
-};
\ No newline at end of file
diff --git a/apps/client/src/scenes/game/input/joystick/JoystickCoordinator.tsx b/apps/client/src/scenes/game/input/joystick/JoystickCoordinator.tsx
new file mode 100644
index 0000000..bf5f96f
--- /dev/null
+++ b/apps/client/src/scenes/game/input/joystick/JoystickCoordinator.tsx
@@ -0,0 +1,35 @@
+/**
+ * JoystickCoordinator
+ * JoystickInputLayer からの入力を受け取り,処理と描画をまとめて仲介する
+ * 入力処理は useJoystick に委譲し,描画は JoystickView に委譲する
+ */
+import type React from "react";
+import { JoystickView } from "./JoystickView";
+import { useJoystick } from "./useJoystick";
+
+/** JoystickCoordinator が提供する描画用データと入力ハンドラ */
+type RenderProps = {
+ view: React.ReactNode;
+ handleStart: (e: React.TouchEvent | React.MouseEvent) => void;
+ handleMove: (e: React.TouchEvent | React.MouseEvent) => void;
+ handleEnd: () => void;
+};
+
+/** 表示に必要な座標と状態 */
+type Props = {
+ onInput: (moveX: number, moveY: number) => void;
+ maxDist?: number;
+ children: (props: RenderProps) => React.ReactNode;
+};
+
+/** 受け取った入力から描画用の状態を生成し,描画を仲介する */
+export const JoystickCoordinator = ({ onInput, maxDist, children }: Props) => {
+ const { isMoving, center, knobOffset, radius, handleStart, handleMove, handleEnd } =
+ useJoystick({ onInput, maxDist });
+
+ const view = (
+
+ );
+
+ return <>{children({ view, handleStart, handleMove, handleEnd })}>;
+};
diff --git a/apps/client/src/scenes/game/input/joystick/JoystickInputLayer.tsx b/apps/client/src/scenes/game/input/joystick/JoystickInputLayer.tsx
new file mode 100644
index 0000000..37bce33
--- /dev/null
+++ b/apps/client/src/scenes/game/input/joystick/JoystickInputLayer.tsx
@@ -0,0 +1,47 @@
+/**
+ * JoystickInputLayer
+ * 画面上のジョイスティック入力レイヤーの入口
+ * 入力イベントの受け口として JoystickCoordinator に処理を委譲する
+ */
+import { JoystickCoordinator } from "./JoystickCoordinator";
+
+/** 入力半径の既定値を外部から参照できるように再公開 */
+export { MAX_DIST } from "./joystick.constants";
+
+/** JoystickInputLayer の入力コールバック */
+type Props = {
+ onInput: (moveX: number, moveY: number) => void;
+ maxDist?: number;
+};
+
+/** 入力の入口として配線を行う */
+export const JoystickInputLayer = ({ onInput, maxDist }: Props) => {
+ return (
+
+ {({ view, handleStart, handleMove, handleEnd }) => (
+
+ {/* 入力イベントを仲介へ渡し,出力は別レイヤーで処理する */}
+ {view}
+
+ )}
+
+ );
+};
\ No newline at end of file
diff --git a/apps/client/src/scenes/game/input/joystick/JoystickView.tsx b/apps/client/src/scenes/game/input/joystick/JoystickView.tsx
index 5ef2feb..ef316d9 100644
--- a/apps/client/src/scenes/game/input/joystick/JoystickView.tsx
+++ b/apps/client/src/scenes/game/input/joystick/JoystickView.tsx
@@ -3,7 +3,7 @@
* ジョイスティックの見た目だけを描画するコンポーネント
* 入力処理は持たず,受け取った座標情報をもとにUIを描く
*/
-type Point = { x: number; y: number };
+import type { Point } from "./joystick.types";
/** 表示に必要な座標と状態 */
type Props = {
diff --git a/apps/client/src/scenes/game/input/joystick/joystick.constants.ts b/apps/client/src/scenes/game/input/joystick/joystick.constants.ts
new file mode 100644
index 0000000..88b2d7b
--- /dev/null
+++ b/apps/client/src/scenes/game/input/joystick/joystick.constants.ts
@@ -0,0 +1,8 @@
+/**
+ * joystick.constants
+ * ジョイスティック入力に関する定数をまとめる
+ * 共有する半径の既定値などを定義する
+ */
+
+/** UI側と共有する最大半径の既定値 */
+export const MAX_DIST = 60;
diff --git a/apps/client/src/scenes/game/input/joystick/joystick.types.ts b/apps/client/src/scenes/game/input/joystick/joystick.types.ts
new file mode 100644
index 0000000..9c7ce8d
--- /dev/null
+++ b/apps/client/src/scenes/game/input/joystick/joystick.types.ts
@@ -0,0 +1,8 @@
+/**
+ * joystick.types
+ * ジョイスティック入力で使う型をまとめる
+ * 座標や入力の共通表現を定義する
+ */
+
+/** 2D座標の簡易型 */
+export type Point = { x: number; y: number };
diff --git a/apps/client/src/scenes/game/input/joystick/useJoystick.ts b/apps/client/src/scenes/game/input/joystick/useJoystick.ts
index c8b0236..fe503e6 100644
--- a/apps/client/src/scenes/game/input/joystick/useJoystick.ts
+++ b/apps/client/src/scenes/game/input/joystick/useJoystick.ts
@@ -5,9 +5,8 @@
*/
import { useCallback, useState } from "react";
import type React from "react";
-
-/** UI側と共有する最大半径の既定値 */
-export const MAX_DIST = 60;
+import { MAX_DIST } from "./joystick.constants";
+import type { Point } from "./joystick.types";
/** フックに渡す入力コールバックと設定 */
type Props = {
@@ -15,9 +14,6 @@
maxDist?: number;
};
-/** 2D座標の簡易型 */
-type Point = { x: number; y: number };
-
/** フックが返すUI向けの状態とハンドラ */
type UseJoystickReturn = {
isMoving: boolean;