client/src/composables/controls/useGameControlsComposable.ts
2025-02-10 15:30:08 +01:00

116 lines
3.8 KiB
TypeScript

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)
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
gameStore.connection?.emit('map:character:move', {
positionX: pointerTile.x,
positionY: pointerTile.y
})
}
const pressedKeys = new Set<string>()
let moveInterval: number | null = null
function handleKeyDown(event: KeyboardEvent) {
if (!gameStore.character) return
if (['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(event.key)) {
// Prevent key repeat events
if (event.repeat) return
pressedKeys.add(event.key)
// Start movement loop if not already running
if (!moveInterval) {
moveInterval = window.setInterval(moveCharacter, 75) // Increased interval to match server throttle `MOVEMENT_THROTTLE`
moveCharacter() // Move immediately on first press
}
}
// Attack on CTRL
if (event.key === 'Control') {
gameStore.connection?.emit('map:character:attack')
}
}
function handleKeyUp(event: KeyboardEvent) {
pressedKeys.delete(event.key)
// If no movement keys are pressed, clear the interval
if (pressedKeys.size === 0 && moveInterval) {
clearInterval(moveInterval)
moveInterval = null
}
}
function moveCharacter() {
if (!gameStore.character) return
const { positionX, positionY } = gameStore.character
if (pressedKeys.has('ArrowLeft')) {
gameStore.connection?.emit('map:character:move', {
positionX: positionX - 1,
positionY: positionY
})
}
if (pressedKeys.has('ArrowRight')) {
gameStore.connection?.emit('map:character:move', {
positionX: positionX + 1,
positionY: positionY
})
}
if (pressedKeys.has('ArrowUp')) {
gameStore.connection?.emit('map:character:move', {
positionX: positionX,
positionY: positionY - 1
})
}
if (pressedKeys.has('ArrowDown')) {
gameStore.connection?.emit('map:character:move', {
positionX: positionX,
positionY: positionY + 1
})
}
}
const setupControls = () => {
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 = () => {
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 }
}