From 016b8e082fcf6da662b57718aa8d7cea9c44ee2d Mon Sep 17 00:00:00 2001
From: Dennis Postma <dennis@directonline.io>
Date: Sun, 21 Jul 2024 23:29:47 +0200
Subject: [PATCH] Fixed controls issues

---
 src/components/sprites/Character.vue  | 24 ++++-----
 src/components/utilities/Controls.vue | 74 +++++++++++++++++++--------
 src/stores/zoneEditor.ts              |  8 +--
 3 files changed, 69 insertions(+), 37 deletions(-)

diff --git a/src/components/sprites/Character.vue b/src/components/sprites/Character.vue
index 9f50363..6754e7b 100644
--- a/src/components/sprites/Character.vue
+++ b/src/components/sprites/Character.vue
@@ -1,7 +1,7 @@
 <template>
   <Container>
-    <Rectangle :x="tileToWorldX(layer, props.character?.position_x, props.character?.position_y)" :y="tileToWorldY(layer, props.character?.position_x, props.character?.position_y)" :origin-x="0.5" :origin-y="10.5" :fillColor="0xffffff" :width="74" :height="8">
-      <Rectangle :x="tileToWorldX(layer, props.character?.position_x, props.character?.position_y)" :y="tileToWorldY(layer, props.character?.position_x, props.character?.position_y)" :origin-x="0.5" :origin-y="20.5" :fillColor="0x09ad19" :width="70" :height="4" />
+    <Rectangle :x="tileToWorldX(layer, props.character?.position_x, props.character?.position_y)" :y="tileToWorldY(layer, props.character?.position_x, props.character?.position_y)" :origin-x="0.5" :origin-y="16" :fillColor="0xffffff" :width="74" :height="8">
+      <Rectangle :x="tileToWorldX(layer, props.character?.position_x, props.character?.position_y)" :y="tileToWorldY(layer, props.character?.position_x, props.character?.position_y)" :origin-x="0.5" :origin-y="31.5" :fillColor="0x09ad19" :width="70" :height="4" />
     </Rectangle>
     <Text
       @create="createText"
@@ -9,20 +9,20 @@
       :x="tileToWorldX(layer, props.character?.position_x, props.character?.position_y)"
       :y="tileToWorldY(layer, props.character?.position_x, props.character?.position_y)"
       :origin-x="0.5"
-      :origin-y="4.5"
+      :origin-y="7.5"
       :style="{
         fontFamily: 'Helvetica, Arial',
         color: '#FFF',
         fontSize: '14px'
       }"
     />
-    <Sprite ref="sprite" :x="tileToWorldX(layer, props.character?.position_x, props.character?.position_y)" :y="tileToWorldY(layer, props.character?.position_x, props.character?.position_y)" play="walk" />
+    <Sprite ref="sprite" :x="tileToWorldX(layer, props.character?.position_x, props.character?.position_y)" :y="tileToWorldY(layer, props.character?.position_x, props.character?.position_y)" :origin-y="1" play="walk" />
   </Container>
 </template>
 
 <script lang="ts" setup>
 import { Container, Rectangle, Sprite, Text, useScene } from 'phavuer'
-import { onBeforeMount, onMounted, ref } from 'vue'
+import { onBeforeMount, onBeforeUnmount, onMounted, ref } from 'vue'
 import { useGameStore } from '@/stores/game'
 import { type Character as CharacterT } from '@/types'
 import { getTile, tileToWorldX, tileToWorldXY, tileToWorldY } from '@/services/zone'
@@ -50,7 +50,7 @@ function setupSelf() {
 }
 
 function onPointerClick(pointer: Phaser.Input.Pointer) {
-  if (!isSelf) return
+  if (!isSelf || gameStore.isMovingCamera) return
 
   const px = scene.cameras.main.worldView.x + pointer.x
   const py = scene.cameras.main.worldView.y + pointer.y
@@ -62,7 +62,7 @@ function onPointerClick(pointer: Phaser.Input.Pointer) {
 
   gameStore.connection?.emit('character:move', { position_x: pointer_tile.x, position_y: pointer_tile.y })
 
-  //Directions for player sprite + animations
+  // Directions for player sprite + animations
   if (px < 0 && py > 0) {
     console.log('down left')
   } else if (px < 0 && py < 0) {
@@ -74,10 +74,8 @@ function onPointerClick(pointer: Phaser.Input.Pointer) {
   }
 }
 
-/**
- * Resources:
- * https://www.youtube.com/watch?v=9sWrGohw9qo
- * https://jsfiddle.net/juwalbose/pu0gt7nc/
- *
- */
+onBeforeUnmount(() => {
+  if (!isSelf) return
+  scene.input.off(Phaser.Input.Events.POINTER_UP, onPointerClick)
+})
 </script>
diff --git a/src/components/utilities/Controls.vue b/src/components/utilities/Controls.vue
index fab14f7..b605c2e 100644
--- a/src/components/utilities/Controls.vue
+++ b/src/components/utilities/Controls.vue
@@ -11,9 +11,11 @@ import { getTile, tileToWorldXY } from '@/services/zone'
 import { useZoneEditorStore } from '@/stores/zoneEditor'
 import { useGameStore } from '@/stores/game'
 
-const props = defineProps<{
+interface Props {
   layer: Phaser.Tilemaps.TilemapLayer
-}>()
+}
+
+const props = defineProps<Props>()
 
 const scene = useScene()
 const zoneEditorStore = useZoneEditorStore()
@@ -27,10 +29,16 @@ const waypoint = ref({
 })
 
 const cam = ref(scene.cameras.main)
+const isDragging = ref(false)
+let pointerDownTimer: number | null = null
+let pointerUpTimer: number | null = null
+
+const DRAG_DELAY = 150
+const MOVE_RESET_DELAY = 100
 
 function updateWaypoint(pointer: Phaser.Input.Pointer) {
   const { x: px, y: py } = scene.cameras.main.getWorldPoint(pointer.x, pointer.y)
-  const pointerTile = getTile(px, py, props.layer) as Phaser.Tilemaps.Tile
+  const pointerTile = getTile(px, py, props.layer)
 
   if (!pointerTile) {
     waypoint.value.visible = false
@@ -46,42 +54,68 @@ function updateWaypoint(pointer: Phaser.Input.Pointer) {
 }
 
 function dragZone(pointer: Phaser.Input.Pointer) {
-  if (!pointer.isDown) return
+  if (!isDragging.value) return
   const { x, y, prevPosition } = pointer
   cam.value.scrollX -= (x - prevPosition.x) / cam.value.zoom
   cam.value.scrollY -= (y - prevPosition.y) / cam.value.zoom
 }
 
-function handleZoom(pointer: Phaser.Input.Pointer, _: any, __: any, deltaY: number) {
-  if (pointer.event.altKey) {
+function handleZoom(pointer: Phaser.Input.Pointer, _: unknown, __: unknown, deltaY: number) {
+  if (pointer.event instanceof WheelEvent && pointer.event.altKey) {
     scene.scale.setZoom(scene.scale.zoom - deltaY * 0.01)
     cam.value = scene.cameras.main
   }
 }
 
+function onPointerDown(pointer: Phaser.Input.Pointer) {
+  if (pointer.event instanceof MouseEvent && (pointer.event.altKey || tool.value === 'move')) {
+    pointerDownTimer = setTimeout(() => {
+      isDragging.value = true
+      gameStore.setMovingCamera(true)
+      scene.input.on(Phaser.Input.Events.POINTER_MOVE, dragZone)
+    }, DRAG_DELAY)
+  }
+}
+
+function onPointerUp() {
+  if (pointerDownTimer) {
+    clearTimeout(pointerDownTimer)
+    pointerDownTimer = null
+  }
+  isDragging.value = false
+  scene.input.off(Phaser.Input.Events.POINTER_MOVE, dragZone)
+
+  if (pointerUpTimer) {
+    clearTimeout(pointerUpTimer)
+  }
+
+  pointerUpTimer = setTimeout(() => {
+    gameStore.setMovingCamera(false)
+  }, MOVE_RESET_DELAY)
+}
+
 function setupEventListeners() {
   scene.input.on(Phaser.Input.Events.POINTER_MOVE, updateWaypoint)
   scene.input.on(Phaser.Input.Events.POINTER_WHEEL, handleZoom)
-
-  scene.input.on(Phaser.Input.Events.POINTER_DOWN, (pointer: Phaser.Input.Pointer) => {
-    if (pointer.event.altKey || tool.value === 'move') {
-      gameStore.setMovingCamera(true)
-      scene.input.on(Phaser.Input.Events.POINTER_MOVE, dragZone)
-    }
-  })
-
-  scene.input.on(Phaser.Input.Events.POINTER_UP, () => {
-    gameStore.setMovingCamera(false)
-    scene.input.off(Phaser.Input.Events.POINTER_MOVE, dragZone)
-  })
+  scene.input.on(Phaser.Input.Events.POINTER_DOWN, onPointerDown)
+  scene.input.on(Phaser.Input.Events.POINTER_UP, onPointerUp)
 }
 
 function cleanupEventListeners() {
   scene.input.off(Phaser.Input.Events.POINTER_MOVE, updateWaypoint)
   scene.input.off(Phaser.Input.Events.POINTER_MOVE, dragZone)
-  scene.input.off(Phaser.Input.Events.POINTER_DOWN)
-  scene.input.off(Phaser.Input.Events.POINTER_UP)
+  scene.input.off(Phaser.Input.Events.POINTER_DOWN, onPointerDown)
+  scene.input.off(Phaser.Input.Events.POINTER_UP, onPointerUp)
   scene.input.off(Phaser.Input.Events.POINTER_WHEEL, handleZoom)
+
+  if (pointerDownTimer) {
+    clearTimeout(pointerDownTimer)
+    pointerDownTimer = null
+  }
+  if (pointerUpTimer) {
+    clearTimeout(pointerUpTimer)
+    pointerUpTimer = null
+  }
 }
 
 setupEventListeners()
diff --git a/src/stores/zoneEditor.ts b/src/stores/zoneEditor.ts
index 113c860..1b800a6 100644
--- a/src/stores/zoneEditor.ts
+++ b/src/stores/zoneEditor.ts
@@ -1,5 +1,5 @@
 import { defineStore } from 'pinia'
-import { useGameStore } from '@/stores/game';
+import { useGameStore } from '@/stores/game'
 import type { Zone, Object, Tile, ZoneObject } from '@/types'
 
 export const useZoneEditorStore = defineStore('zoneEditor', {
@@ -63,9 +63,9 @@ export const useZoneEditorStore = defineStore('zoneEditor', {
       this.selectedObject = object
     },
     setSelectedZoneObject(zoneObject: ZoneObject) {
-      const gameStore = useGameStore(); // Access the gameStore
-      if (gameStore.isMovingCamera) return; // Step 2: Check isMovingCamera before proceeding
-      
+      const gameStore = useGameStore() // Access the gameStore
+      if (gameStore.isMovingCamera) return // Step 2: Check isMovingCamera before proceeding
+
       this.selectedZoneObject = zoneObject
     },
     setObjectDepth(depth: number) {