import { SocketEvent } from '@/application/enums' import { socketManager } from '@/managers/SocketManager' import { getTile } from '@/services/mapService' import { useGameStore } from '@/stores/gameStore' import type { Ref } from 'vue' import { useBaseControlsComposable } from './useBaseControlsComposable' export function useGameControlsComposable(scene: Phaser.Scene, layer: Phaser.Tilemaps.TilemapLayer, waypoint: Ref<{ visible: boolean; x: number; y: number }>, camera: Phaser.Cameras.Scene2D.Camera) { const gameStore = useGameStore() const baseHandlers = useBaseControlsComposable(scene, layer, waypoint, camera) const pressedKeys = new Set() let moveTimeout: NodeJS.Timeout | null = null let currentPosition = { x: 0, y: 0 } // Movement constants const MOVEMENT_DELAY = 110 // Milliseconds between moves const ARROW_KEYS = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'] as const function updateCurrentPosition() { if (!gameStore.character) return currentPosition = { x: gameStore.character.positionX, y: gameStore.character.positionY } } function calculateNewPosition() { let newX = currentPosition.x let newY = currentPosition.y if (pressedKeys.has('ArrowLeft')) newX-- if (pressedKeys.has('ArrowRight')) newX++ if (pressedKeys.has('ArrowUp')) newY-- if (pressedKeys.has('ArrowDown')) newY++ return { newX, newY } } function emitMovement(x: number, y: number) { if (x === currentPosition.x && y === currentPosition.y) return socketManager.emit(SocketEvent.MAP_CHARACTER_MOVE, [x, y]) socketManager.on(SocketEvent.MAP_CHARACTER_MOVE, ([characterId, posX, posY, rot, isMoving]: [string, number, number, number, boolean]) => { if (characterId !== gameStore.character?.id) return currentPosition = { x: posX, y: posY } }) currentPosition = { x, y } } function startMovementLoop() { if (moveTimeout) return const move = () => { if (pressedKeys.size === 0) { stopMovementLoop() return } updateCurrentPosition() const { newX, newY } = calculateNewPosition() emitMovement(newX, newY) moveTimeout = setTimeout(move, MOVEMENT_DELAY) } move() } function stopMovementLoop() { if (moveTimeout) { clearTimeout(moveTimeout) moveTimeout = null } } // Pointer Handlers function handlePointerDown(pointer: Phaser.Input.Pointer) { baseHandlers.startDragging(pointer) } function handlePointerMove(pointer: Phaser.Input.Pointer) { baseHandlers.updateWaypoint(pointer.worldX, pointer.worldY) baseHandlers.handleDragMap(pointer) } function handlePointerUp(pointer: Phaser.Input.Pointer) { baseHandlers.stopDragging() const pointerTile = getTile(layer, pointer.worldX, pointer.worldY) if (!pointerTile) return emitMovement(pointerTile.x, pointerTile.y) } // Keyboard Handlers function handleKeyDown(event: KeyboardEvent) { if (!gameStore.character) return if (ARROW_KEYS.includes(event.key as (typeof ARROW_KEYS)[number])) { if (event.repeat) return pressedKeys.add(event.key) updateCurrentPosition() startMovementLoop() } if (event.key === 'Control') { socketManager.emit(SocketEvent.MAP_CHARACTER_ATTACK) } } function handleKeyUp(event: KeyboardEvent) { pressedKeys.delete(event.key) if (pressedKeys.size === 0) { stopMovementLoop() } } const setupControls = () => { updateCurrentPosition() // Initialize position scene.input.on(Phaser.Input.Events.POINTER_DOWN, handlePointerDown) scene.input.on(Phaser.Input.Events.POINTER_MOVE, handlePointerMove) scene.input.on(Phaser.Input.Events.POINTER_UP, handlePointerUp) scene.input.on(Phaser.Input.Events.POINTER_WHEEL, baseHandlers.handleZoom) scene.input.keyboard!.on('keydown', handleKeyDown) scene.input.keyboard!.on('keyup', handleKeyUp) } const cleanupControls = () => { stopMovementLoop() pressedKeys.clear() scene.input.off(Phaser.Input.Events.POINTER_DOWN, handlePointerDown) scene.input.off(Phaser.Input.Events.POINTER_MOVE, handlePointerMove) scene.input.off(Phaser.Input.Events.POINTER_UP, handlePointerUp) scene.input.off(Phaser.Input.Events.POINTER_WHEEL, baseHandlers.handleZoom) scene.input.keyboard!.off('keydown', handleKeyDown) scene.input.keyboard!.off('keyup', handleKeyUp) } return { setupControls, cleanupControls } }