From 15dc331a4325edca8d648fb08973e5eeb71263fe Mon Sep 17 00:00:00 2001 From: Dennis Postma Date: Sun, 16 Feb 2025 17:14:24 +0100 Subject: [PATCH] Improved movement logic --- .../controls/useGameControlsComposable.ts | 123 ++++++++++++------ src/services/mapService.ts | 4 +- 2 files changed, 83 insertions(+), 44 deletions(-) diff --git a/src/composables/controls/useGameControlsComposable.ts b/src/composables/controls/useGameControlsComposable.ts index ced972b..8f9f6d1 100644 --- a/src/composables/controls/useGameControlsComposable.ts +++ b/src/composables/controls/useGameControlsComposable.ts @@ -7,7 +7,76 @@ 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 + + gameStore.connection?.emit(SocketEvent.MAP_CHARACTER_MOVE, { + positionX: x, + positionY: y + }) + + 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) } @@ -23,32 +92,21 @@ export function useGameControlsComposable(scene: Phaser.Scene, layer: Phaser.Til const pointerTile = getTile(layer, pointer.worldX, pointer.worldY) if (!pointerTile) return - gameStore.connection?.emit(SocketEvent.MAP_CHARACTER_MOVE, { - positionX: pointerTile.x, - positionY: pointerTile.y - }) + emitMovement(pointerTile.x, pointerTile.y) } - const pressedKeys = new Set() - let moveInterval: number | null = null - + // Keyboard Handlers function handleKeyDown(event: KeyboardEvent) { if (!gameStore.character) return - if (['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(event.key)) { - // Prevent key repeat events + if (ARROW_KEYS.includes(event.key as (typeof ARROW_KEYS)[number])) { if (event.repeat) return pressedKeys.add(event.key) - - // Start movement loop if not already running - if (!moveInterval) { - moveInterval = window.setInterval(moveCharacter, 50) - moveCharacter() // Move immediately on first press - } + updateCurrentPosition() + startMovementLoop() } - // Attack on CTRL if (event.key === 'Control') { gameStore.connection?.emit(SocketEvent.MAP_CHARACTER_ATTACK) } @@ -57,36 +115,14 @@ export function useGameControlsComposable(scene: Phaser.Scene, layer: Phaser.Til 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 - let newX = positionX - let newY = positionY - - // Calculate new position based on pressed keys - if (pressedKeys.has('ArrowLeft')) newX-- - if (pressedKeys.has('ArrowRight')) newX++ - if (pressedKeys.has('ArrowUp')) newY-- - if (pressedKeys.has('ArrowDown')) newY++ - - // Only emit if position changed - if (newX !== positionX || newY !== positionY) { - gameStore.connection?.emit(SocketEvent.MAP_CHARACTER_MOVE, { - positionX: newX, - positionY: newY - }) + 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) @@ -96,6 +132,9 @@ export function useGameControlsComposable(scene: Phaser.Scene, layer: Phaser.Til } 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) diff --git a/src/services/mapService.ts b/src/services/mapService.ts index 2c46726..ccafbb2 100644 --- a/src/services/mapService.ts +++ b/src/services/mapService.ts @@ -62,8 +62,8 @@ export function createTileArray(width: number, height: number, tile: string = 'b return Array.from({ length: height }, () => Array.from({ length: width }, () => tile)) } -export const calculateIsometricDepth = (positionX: number, positionY: number, pivotPoints: { x: number; y: number; }[] = []) => { - return Math.max(positionX + positionY); +export const calculateIsometricDepth = (positionX: number, positionY: number, pivotPoints: { x: number; y: number }[] = []) => { + return Math.max(positionX + positionY) } async function loadTileTextures(tiles: TileT[], scene: Phaser.Scene) {