forked from noxious/client
82 lines
2.9 KiB
Vue
82 lines
2.9 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 { Direction } from '@/application/enums'
|
|
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 { useGameComposable } from '@/composables/useGameComposable'
|
|
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 } = useGameComposable()
|
|
|
|
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()
|
|
}
|
|
}
|
|
|
|
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)
|
|
|
|
if (props.mapCharacter.isAttacking) {
|
|
// Play attack animation
|
|
playAnimation('attack')
|
|
// Play hit sound
|
|
playSound('/assets/sounds/hit.wav')
|
|
// Disable attack immediately after playing the animation
|
|
mapStore.updateCharacterProperty(props.mapCharacter.character.id, 'isAttacking', false)
|
|
}
|
|
}
|
|
)
|
|
|
|
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>
|