diff --git a/src/components/game/character/Character.vue b/src/components/game/character/Character.vue index a1ecb00..88646c9 100644 --- a/src/components/game/character/Character.vue +++ b/src/components/game/character/Character.vue @@ -175,7 +175,7 @@ onMounted(async () => { mapStore.setCharacterLoaded(true) // #146 : Set camera position to character, need to be improved still - scene.cameras.main.startFollow(charSprite.value as Phaser.GameObjects.Sprite) + // scene.cameras.main.startFollow(charSprite.value as Phaser.GameObjects.Sprite) } updatePosition(character.positionX, character.positionY, character.rotation) diff --git a/src/components/gameMaster/mapEditor/Map.vue b/src/components/gameMaster/mapEditor/Map.vue index ff0eadb..8956569 100644 --- a/src/components/gameMaster/mapEditor/Map.vue +++ b/src/components/gameMaster/mapEditor/Map.vue @@ -27,28 +27,20 @@ function handlePointer(pointer: Phaser.Input.Pointer) { // Check if left mouse button is pressed if (!pointer.isDown) return - // Check if shift is not pressed, this means we are moving the camera - if (pointer.event.shiftKey) return + // Check if shift is pressed or if we're in move mode, this means we are moving the camera + if (pointer.event.shiftKey || mapEditor.tool.value === 'move') return // Check if draw mode is tile switch (mapEditor.drawMode.value) { case 'tile': mapTiles.value.handlePointer(pointer) + break case 'object': mapObjects.value.handlePointer(pointer) - case 'teleport': + break + case 'event': eventTiles.value.handlePointer(pointer) + break } } - -onMounted(() => { - scene.input.on(Phaser.Input.Events.POINTER_MOVE, handlePointer) - scene.input.on(Phaser.Input.Events.POINTER_DOWN, handlePointer) -}) - -onUnmounted(() => { - scene.input.off(Phaser.Input.Events.POINTER_MOVE, handlePointer) - scene.input.off(Phaser.Input.Events.POINTER_DOWN, handlePointer) - mapEditor.reset() -}) diff --git a/src/components/utilities/Controls.vue b/src/components/utilities/Controls.vue index c39b97d..ab97c55 100644 --- a/src/components/utilities/Controls.vue +++ b/src/components/utilities/Controls.vue @@ -3,8 +3,7 @@ diff --git a/src/composables/controls/useBaseControlsComposable.ts b/src/composables/controls/useBaseControlsComposable.ts new file mode 100644 index 0000000..5651152 --- /dev/null +++ b/src/composables/controls/useBaseControlsComposable.ts @@ -0,0 +1,69 @@ +import config from '@/application/config' +import { getTile, tileToWorldXY } from '@/composables/mapComposable' +import { useGameStore } from '@/stores/gameStore' +import { ref, type Ref } from 'vue' + +export function useBaseControlsComposable(scene: Phaser.Scene, layer: Phaser.Tilemaps.TilemapLayer, waypoint: Ref<{ visible: boolean; x: number; y: number }>, camera: Phaser.Cameras.Scene2D.Camera) { + const gameStore = useGameStore() + const pointerStartPosition = ref({ x: 0, y: 0 }) + const dragThreshold = 5 // pixels + + function updateWaypoint(worldX: number, worldY: number) { + const pointerTile = getTile(layer, worldX, worldY) + if (!pointerTile) { + waypoint.value.visible = false + return + } + const worldPoint = tileToWorldXY(layer, pointerTile.x, pointerTile.y) + if (!worldPoint.worldPositionX || !worldPoint.worldPositionX) return + + waypoint.value = { + visible: true, + x: worldPoint.worldPositionX, + y: worldPoint.worldPositionY + config.tile_size.height + 15 + } + } + + function handleDragMap(pointer: Phaser.Input.Pointer) { + if (!gameStore.game.isPlayerDraggingCamera) return + + const deltaX = pointer.x - pointerStartPosition.value.x + const deltaY = pointer.y - pointerStartPosition.value.y + + if (Math.abs(deltaX) <= dragThreshold && Math.abs(deltaY) <= dragThreshold) return + + const scrollX = camera.scrollX - (deltaX / camera.zoom) + const scrollY = camera.scrollY - (deltaY / camera.zoom) + + camera.setScroll(scrollX, scrollY) + pointerStartPosition.value = { x: pointer.x, y: pointer.y } + } + + function startDragging(pointer: Phaser.Input.Pointer) { + pointerStartPosition.value = { x: pointer.x, y: pointer.y } + gameStore.setPlayerDraggingCamera(true) + } + + function stopDragging() { + gameStore.setPlayerDraggingCamera(false) + } + + function handleZoom(pointer: Phaser.Input.Pointer) { + if (pointer.event instanceof WheelEvent && pointer.event.shiftKey) { + const deltaY = pointer.event.deltaY + const zoomLevel = camera.zoom - deltaY * 0.005 + if (zoomLevel > 0 && zoomLevel < 3) { + camera.setZoom(zoomLevel) + } + } + } + + return { + updateWaypoint, + handleDragMap, + startDragging, + stopDragging, + handleZoom, + pointerStartPosition + } +} \ No newline at end of file diff --git a/src/composables/controls/useGameControlsComposable.ts b/src/composables/controls/useGameControlsComposable.ts new file mode 100644 index 0000000..79e26d3 --- /dev/null +++ b/src/composables/controls/useGameControlsComposable.ts @@ -0,0 +1,46 @@ +import { getTile } from '@/composables/mapComposable' +import { useGameStore } from '@/stores/gameStore' +import { useBaseControlsComposable } from './useBaseControlsComposable' +import type { Ref } from 'vue' + +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 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) + } + + 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) + } + + return { setupControls, cleanupControls } +} diff --git a/src/composables/controls/useMapEditorControlsComposable.ts b/src/composables/controls/useMapEditorControlsComposable.ts new file mode 100644 index 0000000..8c3afa4 --- /dev/null +++ b/src/composables/controls/useMapEditorControlsComposable.ts @@ -0,0 +1,42 @@ +import { useMapEditorComposable } from '@/composables/useMapEditorComposable' +import { useBaseControlsComposable } from './useBaseControlsComposable' +import { computed, type Ref } from 'vue' + +export function useMapEditorControlsComposable(scene: Phaser.Scene, layer: Phaser.Tilemaps.TilemapLayer, waypoint: Ref<{ visible: boolean; x: number; y: number }>, camera: Phaser.Cameras.Scene2D.Camera) { + const mapEditor = useMapEditorComposable() + const baseHandlers = useBaseControlsComposable(scene, layer, waypoint, camera) + const isMoveTool = computed(() => mapEditor.tool.value === 'move') + + function handlePointerDown(pointer: Phaser.Input.Pointer) { + if (isMoveTool.value || pointer.event.shiftKey) { + baseHandlers.startDragging(pointer) + } + } + + function handlePointerMove(pointer: Phaser.Input.Pointer) { + if (isMoveTool.value || pointer.event.shiftKey) { + baseHandlers.handleDragMap(pointer) + } + baseHandlers.updateWaypoint(pointer.worldX, pointer.worldY) + } + + function handlePointerUp(pointer: Phaser.Input.Pointer) { + baseHandlers.stopDragging() + } + + 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) + } + + 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) + } + + return { setupControls, cleanupControls } +} diff --git a/src/composables/pointerHandlers/useGamePointerHandlers.ts b/src/composables/pointerHandlers/useGamePointerHandlers.ts deleted file mode 100644 index 117e4d6..0000000 --- a/src/composables/pointerHandlers/useGamePointerHandlers.ts +++ /dev/null @@ -1,70 +0,0 @@ -import config from '@/application/config' -import { getTile, tileToWorldXY } from '@/composables/mapComposable' -import { useGameStore } from '@/stores/gameStore' -import { ref, type Ref } from 'vue' - -export function useGamePointerHandlers(scene: Phaser.Scene, layer: Phaser.Tilemaps.TilemapLayer, waypoint: Ref<{ visible: boolean; x: number; y: number }>, camera: Phaser.Cameras.Scene2D.Camera) { - const gameStore = useGameStore() - const pointerStartPosition = ref({ x: 0, y: 0 }) - const dragThreshold = 5 // pixels - - function updateWaypoint(worldX: number, worldY: number) { - const pointerTile = getTile(layer, worldX, worldY) - if (!pointerTile) { - waypoint.value.visible = false - return - } - const worldPoint = tileToWorldXY(layer, pointerTile.x, pointerTile.y) - if (!worldPoint.worldPositionX || !worldPoint.worldPositionX) return - - waypoint.value = { - visible: true, - x: worldPoint.worldPositionX, - y: worldPoint.worldPositionY + config.tile_size.height + 15 - } - } - - function handlePointerDown(pointer: Phaser.Input.Pointer) { - pointerStartPosition.value = pointer.position - gameStore.setPlayerDraggingCamera(true) - } - - function handlePointerMove(pointer: Phaser.Input.Pointer) { - updateWaypoint(pointer.worldX, pointer.worldY) - - if (!gameStore.game.isPlayerDraggingCamera) return - - // If the distance is less than the drag threshold, return - // We do this to prevent the camera from scrolling too quickly - const distance = Phaser.Math.Distance.Between(pointerStartPosition.value.x, pointerStartPosition.value.y, pointer.x, pointer.y) - if (distance <= dragThreshold) return - - camera.setScroll(camera.scrollX - (pointer.x - pointer.prevPosition.x) / camera.zoom, camera.scrollY - (pointer.y - pointer.prevPosition.y) / camera.zoom) - } - - function handlePointerUp(pointer: Phaser.Input.Pointer) { - gameStore.setPlayerDraggingCamera(false) - - const pointerTile = getTile(layer, pointer.worldX, pointer.worldY) - if (!pointerTile) return - - gameStore.connection?.emit('map:character:move', { - positionX: pointerTile.x, - positionY: pointerTile.y - }) - } - - const setupPointerHandlers = () => { - 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) - } - - const cleanupPointerHandlers = () => { - 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) - } - - return { setupPointerHandlers, cleanupPointerHandlers } -} diff --git a/src/composables/pointerHandlers/useMapEditorPointerHandlers.ts b/src/composables/pointerHandlers/useMapEditorPointerHandlers.ts deleted file mode 100644 index e2f3a02..0000000 --- a/src/composables/pointerHandlers/useMapEditorPointerHandlers.ts +++ /dev/null @@ -1,86 +0,0 @@ -import config from '@/application/config' -import { getTile, tileToWorldXY } from '@/composables/mapComposable' -import { useMapEditorComposable } from '@/composables/useMapEditorComposable' -import { useGameStore } from '@/stores/gameStore' -import { computed, ref, type Ref } from 'vue' - -export function useMapEditorPointerHandlers(scene: Phaser.Scene, layer: Phaser.Tilemaps.TilemapLayer, waypoint: Ref<{ visible: boolean; x: number; y: number }>, camera: Phaser.Cameras.Scene2D.Camera) { - const gameStore = useGameStore() - const mapEditor = useMapEditorComposable() - const isMoveTool = computed(() => mapEditor.tool.value === 'move') - const pointerStartPosition = ref({ x: 0, y: 0 }) - const dragThreshold = 5 // pixels - - function updateWaypoint(worldX: number, worldY: number) { - const pointerTile = getTile(layer, worldX, worldY) - if (!pointerTile) { - waypoint.value.visible = false - return - } - const worldPoint = tileToWorldXY(layer, pointerTile.x, pointerTile.y) - if (!worldPoint.worldPositionX || !worldPoint.worldPositionX) return - - waypoint.value = { - visible: true, - x: worldPoint.worldPositionX, - y: worldPoint.worldPositionY + config.tile_size.height + 15 - } - } - - function handlePointerDown(pointer: Phaser.Input.Pointer) { - pointerStartPosition.value = { x: pointer.x, y: pointer.y } - if (isMoveTool.value || pointer.event.shiftKey) { - gameStore.setPlayerDraggingCamera(true) - } - } - - function dragMap(pointer: Phaser.Input.Pointer) { - if (!gameStore.game.isPlayerDraggingCamera) return - - const distance = Phaser.Math.Distance.Between(pointerStartPosition.value.x, pointerStartPosition.value.y, pointer.x, pointer.y) - - // If the distance is less than the drag threshold, return - // We do this to prevent the camera from scrolling too quickly - - if (distance <= dragThreshold) return - - camera.setScroll(camera.scrollX - (pointer.x - pointer.prevPosition.x) / camera.zoom, camera.scrollY - (pointer.y - pointer.prevPosition.y) / camera.zoom) - } - - function handlePointerMove(pointer: Phaser.Input.Pointer) { - if (isMoveTool.value || pointer.event.shiftKey) { - dragMap(pointer) - } - updateWaypoint(pointer.worldX, pointer.worldY) - } - - function handlePointerUp(pointer: Phaser.Input.Pointer) { - gameStore.setPlayerDraggingCamera(false) - } - - function handleZoom(pointer: Phaser.Input.Pointer) { - if (pointer.event instanceof WheelEvent && pointer.event.shiftKey) { - const deltaY = pointer.event.deltaY - const zoomLevel = camera.zoom - deltaY * 0.005 - if (zoomLevel > 0 && zoomLevel < 3) { - camera.setZoom(zoomLevel) - } - } - } - - const setupPointerHandlers = () => { - 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, handleZoom) - } - - const cleanupPointerHandlers = () => { - 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, handleZoom) - } - - return { setupPointerHandlers, cleanupPointerHandlers } -} diff --git a/src/composables/useCameraControls.ts b/src/composables/useCameraControls.ts deleted file mode 100644 index a85bd78..0000000 --- a/src/composables/useCameraControls.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { useGameStore } from '@/stores/gameStore' -import { useMapStore } from '@/stores/mapStore' - -export function useCameraControls(scene: Phaser.Scene) { - const gameStore = useGameStore() - const camera = scene.cameras.main - - const onPointerDown = () => gameStore.setPlayerDraggingCamera(true) - const onPointerUp = () => gameStore.setPlayerDraggingCamera(false) - - scene.input.on(Phaser.Input.Events.POINTER_DOWN, onPointerDown) - scene.input.on(Phaser.Input.Events.POINTER_UP, onPointerUp) - - return { camera } -} diff --git a/src/composables/useControlsComposable.ts b/src/composables/useControlsComposable.ts new file mode 100644 index 0000000..92cab72 --- /dev/null +++ b/src/composables/useControlsComposable.ts @@ -0,0 +1,19 @@ +import { useMapEditorComposable } from '@/composables/useMapEditorComposable' +import { computed, watch, type Ref } from 'vue' +import { useGameControlsComposable } from '@/composables/controls/useGameControlsComposable' +import { useMapEditorControlsComposable } from '@/composables/controls/useMapEditorControlsComposable' +import { useGameStore } from '@/stores/gameStore' + +export function useControlsComposable(scene: Phaser.Scene, layer: Phaser.Tilemaps.TilemapLayer, waypoint: Ref<{ visible: boolean; x: number; y: number }>) { + const camera = scene.cameras.main + const mapEditor = useMapEditorComposable() + const gameHandlers = useGameControlsComposable(scene, layer, waypoint, camera) + const mapEditorHandlers = useMapEditorControlsComposable(scene, layer, waypoint, camera) + + const currentHandlers = computed(() => (mapEditor.active.value ? mapEditorHandlers : gameHandlers)) + + const setupControls = () => currentHandlers.value.setupControls() + const cleanupControls = () => currentHandlers.value.cleanupControls() + + return { setupControls, cleanupControls, camera } +} diff --git a/src/composables/usePointerHandlers.ts b/src/composables/usePointerHandlers.ts deleted file mode 100644 index 09ce8c1..0000000 --- a/src/composables/usePointerHandlers.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { useMapEditorComposable } from '@/composables/useMapEditorComposable' -import { computed, watch, type Ref } from 'vue' -import { useGamePointerHandlers } from './pointerHandlers/useGamePointerHandlers' -import { useMapEditorPointerHandlers } from './pointerHandlers/useMapEditorPointerHandlers' - -export function usePointerHandlers(scene: Phaser.Scene, layer: Phaser.Tilemaps.TilemapLayer, waypoint: Ref<{ visible: boolean; x: number; y: number }>, camera: Phaser.Cameras.Scene2D.Camera) { - const mapEditor = useMapEditorComposable() - const gameHandlers = useGamePointerHandlers(scene, layer, waypoint, camera) - const mapEditorHandlers = useMapEditorPointerHandlers(scene, layer, waypoint, camera) - - const currentHandlers = computed(() => (mapEditor.active.value ? mapEditorHandlers : gameHandlers)) - - const setupPointerHandlers = () => currentHandlers.value.setupPointerHandlers() - const cleanupPointerHandlers = () => currentHandlers.value.cleanupPointerHandlers() - - watch( - () => mapEditor.active.value, - () => { - cleanupPointerHandlers() - setupPointerHandlers() - } - ) - - return { setupPointerHandlers, cleanupPointerHandlers } -}