From bdbda6456c421e6ff5e69fd7d49d41fbe42c2132 Mon Sep 17 00:00:00 2001
From: Dennis Postma <dennis@directonline.io>
Date: Tue, 28 Jan 2025 16:32:16 +0100
Subject: [PATCH] CharHair work

---
 src/components/game/character/Character.vue   | 61 +++++++++++--------
 .../game/character/partials/CharacterHair.vue | 33 ++++++----
 src/storage/storages.ts                       |  5 ++
 3 files changed, 61 insertions(+), 38 deletions(-)

diff --git a/src/components/game/character/Character.vue b/src/components/game/character/Character.vue
index 2c0807f..a1ecb00 100644
--- a/src/components/game/character/Character.vue
+++ b/src/components/game/character/Character.vue
@@ -1,12 +1,14 @@
 <template>
   <ChatBubble :mapCharacter="props.mapCharacter" :currentX="currentPositionX" :currentY="currentPositionY" />
   <Healthbar :mapCharacter="props.mapCharacter" :currentX="currentPositionX" :currentY="currentPositionY" />
+  <CharacterHair :mapCharacter="props.mapCharacter" :currentX="currentPositionX" :currentY="currentPositionY" />
   <Sprite ref="charSprite" :depth="isometricDepth" :x="currentPositionX" :y="currentPositionY" :origin-y="1" :flipX="isFlippedX" />
 </template>
 
 <script lang="ts" setup>
 import config from '@/application/config'
 import { type MapCharacter } from '@/application/types'
+import CharacterHair from '@/components/game/character/partials/CharacterHair.vue'
 import ChatBubble from '@/components/game/character/partials/ChatBubble.vue'
 import Healthbar from '@/components/game/character/partials/Healthbar.vue'
 import { loadSpriteTextures } from '@/composables/gameComposable'
@@ -103,21 +105,41 @@ const calcDirection = (oldPositionX: number, oldPositionY: number, newPositionX:
 
 const isFlippedX = computed(() => [6, 4].includes(props.mapCharacter.character.rotation ?? 0))
 
+const currentDirection = computed(() => {
+  return [0, 6].includes(props.mapCharacter.character.rotation ?? 0) ? 'left_up' : 'right_down'
+})
+
+const currentAction = computed(() => {
+  return props.mapCharacter.isMoving ? 'walk' : 'idle'
+})
+
 const charTexture = computed(() => {
   const spriteId = charSpriteId.value ?? 'idle_right_down'
-  const action = props.mapCharacter.isMoving ? 'walk' : 'idle'
-  const direction = [0, 6].includes(props.mapCharacter.character.rotation) ? 'left_up' : 'right_down'
-
-  return `${spriteId}-${action}_${direction}`
+  return `${spriteId}-${currentAction.value}_${currentDirection.value}`
 })
 
 const updateSprite = () => {
+  if (!charSprite.value) return
+
   if (props.mapCharacter.isMoving) {
-    charSprite.value!.anims.play(charTexture.value, true)
+    charSprite.value.anims.play(charTexture.value, true)
   } else {
-    charSprite.value!.anims.stop()
-    charSprite.value!.setFrame(0)
-    charSprite.value!.setTexture(charTexture.value)
+    charSprite.value.anims.stop()
+    charSprite.value.setFrame(0)
+    charSprite.value.setTexture(charTexture.value)
+  }
+}
+
+const handlePositionUpdate = (newValues: any, oldValues: any) => {
+  if (!newValues) return
+
+  if (!oldValues || newValues.positionX !== oldValues.positionX || newValues.positionY !== oldValues.positionY) {
+    const direction = !oldValues ? Direction.POSITIVE : calcDirection(oldValues.positionX, oldValues.positionY, newValues.positionX, newValues.positionY)
+    updatePosition(newValues.positionX, newValues.positionY, direction)
+  }
+
+  if (newValues.isMoving !== oldValues?.isMoving || newValues.rotation !== oldValues?.rotation) {
+    updateSprite()
   }
 }
 
@@ -128,19 +150,7 @@ watch(
     isMoving: props.mapCharacter.isMoving,
     rotation: props.mapCharacter.character.rotation
   }),
-  (newValues, oldValues) => {
-    if (!newValues) return
-
-    if (!oldValues || newValues.positionX !== oldValues.positionX || newValues.positionY !== oldValues.positionY) {
-      const direction = !oldValues ? Direction.POSITIVE : calcDirection(oldValues.positionX, oldValues.positionY, newValues.positionX, newValues.positionY)
-      updatePosition(newValues.positionX, newValues.positionY, direction)
-    }
-
-    // Handle animation updates
-    if (newValues.isMoving !== oldValues?.isMoving || newValues.rotation !== oldValues?.rotation) {
-      updateSprite()
-    }
-  }
+  handlePositionUpdate
 )
 
 onMounted(async () => {
@@ -155,10 +165,11 @@ onMounted(async () => {
 
   await loadSpriteTextures(scene, spriteId)
 
-  charSprite.value!.setTexture(charTexture.value)
-  charSprite.value!.setFlipX(isFlippedX.value)
-
-  charSprite.value!.setName(props.mapCharacter.character!.name)
+  if (charSprite.value) {
+    charSprite.value.setTexture(charTexture.value)
+    charSprite.value.setFlipX(isFlippedX.value)
+    charSprite.value.setName(props.mapCharacter.character.name)
+  }
 
   if (character.id === gameStore.character!.id) {
     mapStore.setCharacterLoaded(true)
diff --git a/src/components/game/character/partials/CharacterHair.vue b/src/components/game/character/partials/CharacterHair.vue
index 23a651c..8e563fb 100644
--- a/src/components/game/character/partials/CharacterHair.vue
+++ b/src/components/game/character/partials/CharacterHair.vue
@@ -1,13 +1,14 @@
 <template>
-  <Image v-bind="imageProps" v-if="gameStore.getLoadedAsset(texture)" />
+  <Image v-bind="imageProps" v-if="gameStore.isTextureLoaded(texture)" />
 </template>
 
 <script lang="ts" setup>
 import type { MapCharacter, Sprite as SpriteT } from '@/application/types'
 import { loadSpriteTextures } from '@/composables/gameComposable'
+import { CharacterHairStorage, CharacterTypeStorage, SpriteStorage } from '@/storage/storages'
 import { useGameStore } from '@/stores/gameStore'
 import { Image, useScene } from 'phavuer'
-import { computed } from 'vue'
+import { computed, onMounted, ref } from 'vue'
 
 const props = defineProps<{
   mapCharacter: MapCharacter
@@ -17,21 +18,21 @@ const props = defineProps<{
 
 const gameStore = useGameStore()
 const scene = useScene()
+const hairSpriteId = ref('')
+const sprite = ref<SpriteT | null>(null)
 
 const texture = computed(() => {
-  const { rotation, characterHair } = props.mapCharacter.character
-  const spriteId = characterHair?.sprite?.id
+  const { rotation } = props.mapCharacter.character
   const direction = [0, 6].includes(rotation) ? 'back' : 'front'
 
-  return `${spriteId}-${direction}`
+  return `${hairSpriteId.value}-${direction}`
 })
 
 const isFlippedX = computed(() => [6, 4].includes(props.mapCharacter.character.rotation ?? 0))
 
 const imageProps = computed(() => {
-  // Get the current sprite action based on direction
   const direction = [0, 6].includes(props.mapCharacter.character.rotation ?? 0) ? 'back' : 'front'
-  const spriteAction = props.mapCharacter.character.characterHair?.sprite?.spriteActions?.find((spriteAction) => spriteAction.action === direction)
+  const spriteAction = sprite.value?.spriteActions?.find((spriteAction) => spriteAction.action === direction)
 
   return {
     depth: 1,
@@ -39,13 +40,19 @@ const imageProps = computed(() => {
     originY: Number(spriteAction?.originY) ?? 0,
     flipX: isFlippedX.value,
     texture: texture.value,
-    y: props.mapCharacter.isMoving ? Math.floor(Date.now() / 250) % 2 : 0
+    y: props.currentY,
+    x: props.currentX
   }
 })
 
-loadSpriteTextures(scene, props.mapCharacter.character.characterHair?.sprite as SpriteT)
-  .then(() => {})
-  .catch((error) => {
-    console.error('Error loading texture:', error)
-  })
+onMounted(async () => {
+  const characterHairStorage = new CharacterHairStorage()
+  const spriteId = await characterHairStorage.getSpriteId(props.mapCharacter.character.characterHair!)
+  if (!spriteId) return
+
+  hairSpriteId.value = spriteId
+  const spriteStorage = new SpriteStorage()
+  sprite.value = await spriteStorage.get(spriteId)
+  await loadSpriteTextures(scene, spriteId)
+})
 </script>
diff --git a/src/storage/storages.ts b/src/storage/storages.ts
index 96bf41b..396f6ac 100644
--- a/src/storage/storages.ts
+++ b/src/storage/storages.ts
@@ -40,4 +40,9 @@ export class CharacterHairStorage extends BaseStorage<any> {
   constructor() {
     super('characterHairs', 'id, name, createdAt, updatedAt')
   }
+
+  async getSpriteId(characterTypeId: string) {
+    const characterType = await this.get(characterTypeId)
+    return characterType?.sprite
+  }
 }