104 lines
3.3 KiB
Vue

<template>
<Container ref="characterContainer" :x="currentPositionX" :y="currentPositionY" :depth="isometricDepth">
<ChatBubble :mapCharacter="props.mapCharacter" />
<HealthBar :mapCharacter="props.mapCharacter" />
<CharacterHair :mapCharacter="props.mapCharacter" />
<Sprite ref="characterSprite" :origin-y="1" :flipX="isFlippedX" />
</Container>
</template>
<script lang="ts" setup>
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 { useCharacterSpriteComposable } from '@/composables/useCharacterSpriteComposable'
import { useSoundComposable } from '@/composables/useSoundComposable'
import { useGameStore } from '@/stores/gameStore'
import { useMapStore } from '@/stores/mapStore'
import { Container, Sprite, useScene } from 'phavuer'
import { onMounted, onUnmounted, watch } from 'vue'
const props = defineProps<{
tileMap: Phaser.Tilemaps.Tilemap
mapCharacter: MapCharacter
}>()
const gameStore = useGameStore()
const mapStore = useMapStore()
const scene = useScene()
const { characterContainer, characterSprite, currentPositionX, currentPositionY, isometricDepth, isFlippedX, updatePosition, playAnimation, calcDirection, updateSprite, initializeSprite, cleanup } = useCharacterSpriteComposable(scene, props.tileMap, props.mapCharacter)
const { playSound, stopSound } = useSoundComposable()
const handlePositionUpdate = (newValues: any, oldValues: any) => {
if (!newValues) return
if (!oldValues || newValues.positionX !== oldValues.positionX || newValues.positionY !== oldValues.positionY) {
updatePosition(newValues.positionX, newValues.positionY)
}
if (newValues.isMoving !== oldValues?.isMoving || newValues.rotation !== oldValues?.rotation) {
updateSprite()
}
}
/**
* Plays walk sound when character is moving
*/
watch(
() => props.mapCharacter.isMoving,
(newValue) => {
if (newValue) {
playSound('/assets/sounds/walk.wav', false, true)
} else {
stopSound('/assets/sounds/walk.wav')
}
}
)
/**
* Plays attack animation and sound when character is attacking
*/
watch(
() => props.mapCharacter.isAttacking,
(newValue) => {
if (newValue) {
playAnimation('attack')
playSound('/assets/sounds/attack.wav', false, true)
} else {
stopSound('/assets/sounds/attack.wav')
}
mapStore.updateCharacterProperty(props.mapCharacter.character.id, 'isAttacking', false)
}
)
/**
* Handles position updates and movement delay
*/
watch(
() => ({
positionX: props.mapCharacter.character.positionX,
positionY: props.mapCharacter.character.positionY,
isMoving: props.mapCharacter.isMoving,
rotation: props.mapCharacter.character.rotation,
isAttacking: props.mapCharacter.isAttacking
}),
(oldValues, newValues) => {
handlePositionUpdate(oldValues, newValues)
}
)
onMounted(async () => {
await initializeSprite()
if (props.mapCharacter.character.id === gameStore.character!.id) {
mapStore.setCharacterLoaded(true)
scene.cameras.main.startFollow(characterContainer.value as Phaser.GameObjects.Container)
}
})
onUnmounted(() => {
cleanup()
})
</script>