import { useEffect, useRef, useState } from 'react' import { useDebugStore } from '../store/debug' interface JoystickState { origin: { x: number; y: number } | null current: { x: number; y: number } | null } const MAX_RADIUS = 40 export function TouchControls() { const controllerMode = useDebugStore((s) => s.controllerMode) const [joystick, setJoystick] = useState({ origin: null, current: null }) const touchIdRef = useRef(null) useEffect(() => { const onStart = (e: TouchEvent) => { for (const touch of Array.from(e.changedTouches)) { if (touch.clientX < window.innerWidth / 2 && touchIdRef.current === null) { touchIdRef.current = touch.identifier setJoystick({ origin: { x: touch.clientX, y: touch.clientY }, current: { x: touch.clientX, y: touch.clientY }, }) } } } const onMove = (e: TouchEvent) => { for (const touch of Array.from(e.changedTouches)) { if (touch.identifier === touchIdRef.current) { setJoystick((prev) => prev.origin ? { ...prev, current: { x: touch.clientX, y: touch.clientY } } : prev, ) } } } const onEnd = (e: TouchEvent) => { for (const touch of Array.from(e.changedTouches)) { if (touch.identifier === touchIdRef.current) { touchIdRef.current = null setJoystick({ origin: null, current: null }) } } } window.addEventListener('touchstart', onStart, { passive: true }) window.addEventListener('touchmove', onMove, { passive: true }) window.addEventListener('touchend', onEnd, { passive: true }) return () => { window.removeEventListener('touchstart', onStart) window.removeEventListener('touchmove', onMove) window.removeEventListener('touchend', onEnd) } }, [controllerMode]) if (!joystick.origin) return null const dx = Math.max(-MAX_RADIUS, Math.min(MAX_RADIUS, (joystick.current?.x ?? joystick.origin.x) - joystick.origin.x)) const dy = Math.max(-MAX_RADIUS, Math.min(MAX_RADIUS, (joystick.current?.y ?? joystick.origin.y) - joystick.origin.y)) return (
{/* Joystick base */}
{/* Joystick dot */}
) }