116 lines
3.8 KiB
TypeScript
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 }
|
|
}
|