diff --git a/apps/client/src/scenes/game/GameView.tsx b/apps/client/src/scenes/game/GameView.tsx
index f31fea2..b2c3891 100644
--- a/apps/client/src/scenes/game/GameView.tsx
+++ b/apps/client/src/scenes/game/GameView.tsx
@@ -3,7 +3,7 @@
* ゲーム画面の描画専用コンポーネント
* タイマー表示,PixiJSの描画領域,入力UIの配置のみを担当する
*/
-import { JoystickInputLayer } from "./input/joystick/JoystickInputLayer";
+import { JoystickInputPresenter } from "./input/joystick/JoystickInputPresenter";
/** 表示と入力に必要なプロパティ */
type Props = {
@@ -51,7 +51,7 @@
{/* UI 配置領域 */}
-
+
);
diff --git a/apps/client/src/scenes/game/input/joystick/JoystickController.ts b/apps/client/src/scenes/game/input/joystick/JoystickController.ts
new file mode 100644
index 0000000..db5935e
--- /dev/null
+++ b/apps/client/src/scenes/game/input/joystick/JoystickController.ts
@@ -0,0 +1,70 @@
+/**
+ * JoystickController
+ * 入力イベントとジョイスティック計算結果の仲介を担うコントローラー
+ * useJoystick の出力を受けて onInput 通知と終了時リセット通知を統一する
+ */
+import { useCallback } from 'react';
+import type React from 'react';
+import type { NormalizedInput, Point } from './common';
+import { useJoystick } from './useJoystick';
+
+/** コントローラーに渡す入力設定 */
+type Props = {
+ onInput: (moveX: number, moveY: number) => void;
+ maxDist?: number;
+};
+
+/** コントローラーが返す描画状態と入力ハンドラ */
+type UseJoystickControllerReturn = {
+ isMoving: boolean;
+ center: Point;
+ knobOffset: Point;
+ radius: number;
+ handleStart: (e: React.TouchEvent | React.MouseEvent) => void;
+ handleMove: (e: React.TouchEvent | React.MouseEvent) => void;
+ handleEnd: () => void;
+};
+
+/** 入力イベントと通知処理を仲介するフック型コントローラー */
+export const useJoystickController = ({ onInput, maxDist }: Props): UseJoystickControllerReturn => {
+ const {
+ isMoving,
+ center,
+ knobOffset,
+ radius,
+ handleStart,
+ handleMove: baseHandleMove,
+ handleEnd: baseHandleEnd,
+ } = useJoystick({ maxDist });
+
+ const emitInput = useCallback(
+ (normalized: NormalizedInput) => {
+ onInput(normalized.x, normalized.y);
+ },
+ [onInput]
+ );
+
+ const handleMove = useCallback(
+ (e: React.TouchEvent | React.MouseEvent) => {
+ const normalized = baseHandleMove(e);
+ if (!normalized) return;
+ emitInput(normalized);
+ },
+ [baseHandleMove, emitInput]
+ );
+
+ const handleEnd = useCallback(() => {
+ baseHandleEnd();
+ emitInput({ x: 0, y: 0 });
+ }, [baseHandleEnd, emitInput]);
+
+ return {
+ isMoving,
+ center,
+ knobOffset,
+ radius,
+ handleStart,
+ handleMove,
+ handleEnd,
+ };
+};
diff --git a/apps/client/src/scenes/game/input/joystick/JoystickCoordinator.tsx b/apps/client/src/scenes/game/input/joystick/JoystickCoordinator.tsx
deleted file mode 100644
index da830ac..0000000
--- a/apps/client/src/scenes/game/input/joystick/JoystickCoordinator.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * JoystickCoordinator
- * JoystickInputLayer からの入力を受け取り,処理と描画をまとめて仲介する
- * 入力処理は useJoystick に委譲し,描画は JoystickView に委譲する
- */
-import { useCallback } from "react";
-import type React from "react";
-import { JoystickView } from "./JoystickView";
-import type { NormalizedInput } from "./common";
-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: baseHandleMove,
- handleEnd: baseHandleEnd,
- } = useJoystick({ maxDist });
-
- const emitInput = useCallback(
- (normalized: NormalizedInput) => {
- onInput(normalized.x, normalized.y);
- },
- [onInput]
- );
-
- const handleMove = useCallback(
- (e: React.TouchEvent | React.MouseEvent) => {
- const normalized = baseHandleMove(e);
- if (!normalized) return;
- emitInput(normalized);
- },
- [baseHandleMove, emitInput]
- );
-
- const handleEnd = useCallback(() => {
- baseHandleEnd();
- emitInput({ x: 0, y: 0 });
- }, [baseHandleEnd, emitInput]);
-
- 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
deleted file mode 100644
index b634672..0000000
--- a/apps/client/src/scenes/game/input/joystick/JoystickInputLayer.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * JoystickInputLayer
- * 画面上のジョイスティック入力レイヤーの入口
- * 入力イベントの受け口として JoystickCoordinator に処理を委譲する
- */
-import { JoystickCoordinator } from "./JoystickCoordinator";
-
-/** 入力半径の既定値を外部から参照できるように再公開 */
-export { MAX_DIST } from "./common";
-
-/** 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/JoystickInputPresenter.tsx b/apps/client/src/scenes/game/input/joystick/JoystickInputPresenter.tsx
new file mode 100644
index 0000000..9276e4e
--- /dev/null
+++ b/apps/client/src/scenes/game/input/joystick/JoystickInputPresenter.tsx
@@ -0,0 +1,47 @@
+/**
+ * JoystickInputPresenter
+ * ジョイスティック入力の受け取りと表示状態の橋渡しを担うプレゼンター
+ * 入力イベントをコントローラーへ委譲し,描画用状態をViewへ渡す
+ */
+import { useJoystickController } from "./JoystickController";
+import { JoystickView } from "./JoystickView";
+
+/** 入力半径の既定値を外部から参照できるように再公開 */
+export { MAX_DIST } from "./common";
+
+/** JoystickInputPresenter の入力コールバック */
+type Props = {
+ onInput: (moveX: number, moveY: number) => void;
+ maxDist?: number;
+};
+
+/** 入力と表示状態の橋渡しを行う */
+export const JoystickInputPresenter = ({ onInput, maxDist }: Props) => {
+ const { isMoving, center, knobOffset, radius, handleStart, handleMove, handleEnd } =
+ useJoystickController({ onInput, maxDist });
+
+ return (
+
+ {/* 入力イベントをコントローラーへ渡し,描画用状態をViewへ渡す */}
+
+
+ );
+};
diff --git a/apps/client/src/scenes/game/input/joystick/common/index.ts b/apps/client/src/scenes/game/input/joystick/common/index.ts
index 2c0838b..d291850 100644
--- a/apps/client/src/scenes/game/input/joystick/common/index.ts
+++ b/apps/client/src/scenes/game/input/joystick/common/index.ts
@@ -1,3 +1,8 @@
+/**
+ * index
+ * ジョイスティック入力の共通型と共通定数の再公開を担う
+ * 呼び出し側のimport先を共通化する
+ */
/** 共有型を再公開する */
export type { NormalizedInput, Point } from './joystick.types';