Renamed hair > characterHair, split character logic (chat bubble, healthbar etc) into separate components for better DX

This commit is contained in:
2024-11-24 15:13:11 +01:00
parent 89d83efca4
commit f7b8c235d8
10 changed files with 153 additions and 75 deletions

View File

@ -1,19 +1,8 @@
<template>
<!-- Chat bubble -->
<Container ref="charChatContainer" :depth="999" :x="currentX" :y="currentY">
<RoundRectangle @create="createChatBubble" :origin-x="0.5" :origin-y="7.5" :fillColor="0xffffff" :width="194" :height="21" :radius="20" />
<Text @create="createChatText" :style="{ fontSize: 13, fontFamily: 'Arial', color: '#000' }" />
</Container>
<!-- Character name and health -->
<Container :depth="999" :x="currentX" :y="currentY">
<Text @create="createNicknameText" :text="props.zoneCharacter.character.name" />
<RoundRectangle :origin-x="0.5" :origin-y="18.5" :fillColor="0xffffff" :width="74" :height="6" :radius="5" />
<RoundRectangle :origin-x="0.5" :origin-y="36.4" :fillColor="0x00b3b3" :width="70" :height="3" :radius="5" />
</Container>
<!-- Character sprite -->
<ChatBubble :zoneCharacter="props.zoneCharacter" :currentX="currentX" :currentY="currentY" />
<Healthbar :zoneCharacter="props.zoneCharacter" :currentX="currentX" :currentY="currentY" />
<Container ref="charContainer" :depth="isometricDepth" :x="currentX" :y="currentY">
<!-- HAIR-->
<Image :origin-y="4.2" :depth="1" :texture="props.zoneCharacter.character.hair?.spriteId + '-front'" />
<CharacterHair :zoneCharacter="props.zoneCharacter" :currentX="currentX" :currentY="currentY" />
<Sprite ref="charSprite" :origin-y="1" :flipX="isFlippedX" :flipY="false" />
</Container>
</template>
@ -27,22 +16,24 @@ import { watch, computed, ref, onMounted, onUnmounted } from 'vue'
import { Container, Image, refObj, RoundRectangle, Sprite, Text, useGame, useScene } from 'phavuer'
import { calculateIsometricDepth, tileToWorldX, tileToWorldY } from '@/composables/zoneComposable'
import { loadSpriteTextures } from '@/composables/gameComposable'
import ChatBubble from '@/components/game/character/partials/ChatBubble.vue'
import Healthbar from '@/components/game/character/partials/Healthbar.vue'
import CharacterHair from '@/components/game/character/partials/CharacterHair.vue'
enum Direction {
POSITIVE,
NEGATIVE,
UNCHANGED
}
const props = defineProps<{
layer: Phaser.Tilemaps.TilemapLayer
zoneCharacter: ZoneCharacter
}>()
const charChatContainer = refObj<Phaser.GameObjects.Container>()
const charContainer = refObj<Phaser.GameObjects.Container>()
const charSprite = refObj<Phaser.GameObjects.Sprite>()
const game = useGame()
const gameStore = useGameStore()
const zoneStore = useZoneStore()
const scene = useScene()
@ -133,41 +124,6 @@ const updateSprite = () => {
charSprite.value!.setTexture(charTexture.value)
}
const createChatBubble = (container: Phaser.GameObjects.Container) => {
container.setName(`${props.zoneCharacter.character.name}_chatBubble`)
}
const createChatText = (text: Phaser.GameObjects.Text) => {
text.setName(`${props.zoneCharacter.character.name}_chatText`)
text.setFontSize(13)
text.setFontFamily('Arial')
text.setOrigin(0.5, 10.9)
// Fix text alignment on Windows and Android
if (game.device.os.windows || game.device.os.android) {
text.setOrigin(0.5, 9.75)
if (game.device.browser.firefox) {
text.setOrigin(0.5, 10.9)
}
}
}
const createNicknameText = (text: Phaser.GameObjects.Text) => {
text.setFontSize(13)
text.setFontFamily('Arial')
text.setOrigin(0.5, 9)
// Fix text alignment on Windows and Android
if (game.device.os.windows || game.device.os.android) {
text.setOrigin(0.5, 8)
if (game.device.browser.firefox) {
text.setOrigin(0.5, 9)
}
}
}
watch(
() => props.zoneCharacter.character,
(newChar, oldChar) => {
@ -182,14 +138,6 @@ watch(
watch(() => props.zoneCharacter, updateSprite)
// Hair demo
loadSpriteTextures(scene, props.zoneCharacter.character.hair?.sprite as SpriteT)
.then(() => {})
.catch((error) => {
console.error('Error loading texture:', error)
})
loadSpriteTextures(scene, props.zoneCharacter.character.characterType?.sprite as SpriteT)
.then(() => {
charSprite.value!.setTexture(charTexture.value)
@ -200,8 +148,6 @@ loadSpriteTextures(scene, props.zoneCharacter.character.characterType?.sprite as
})
onMounted(() => {
charChatContainer.value!.setName(`${props.zoneCharacter.character!.name}_chatContainer`)
charChatContainer.value!.setVisible(false)
charContainer.value!.setName(props.zoneCharacter.character!.name)
if (props.zoneCharacter.character.id === gameStore.character!.id) {

View File

@ -0,0 +1,50 @@
<template>
<Image v-bind="imageProps" v-if="gameStore.getLoadedAsset(props.zoneCharacter.character.characterHair?.spriteId)" ref="image" />
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { Image, refObj, useScene } from 'phavuer'
import type { Sprite as SpriteT, ZoneCharacter } from '@/types'
import { loadSpriteTextures } from '@/composables/gameComposable'
import { useGameStore } from '@/stores/gameStore'
const props = defineProps<{
zoneCharacter: ZoneCharacter
currentX: number
currentY: number
}>()
const gameStore = useGameStore()
const scene = useScene()
const image = refObj<Phaser.GameObjects.Image>()
const isFlippedX = computed(() => [6, 4].includes(props.zoneCharacter.character.rotation ?? 0))
const texture = computed(() => {
const { rotation, characterHair } = props.zoneCharacter.character
const spriteId = characterHair?.sprite?.id
const direction = [0, 6].includes(rotation) ? 'back' : 'front'
return `${spriteId}-${direction}`
})
const imageProps = computed(() => ({
depth: 1,
x: props.currentX,
y: props.currentY,
flipX: false,
texture: texture.value,
}))
loadSpriteTextures(scene, props.zoneCharacter.character.characterHair?.sprite as SpriteT)
.then(() => {
console.log(texture.value)
image.value!.setTexture(texture.value!)
image.value!.setFlipX(isFlippedX.value)
})
.catch((error) => {
console.error('Error loading texture:', error)
})
</script>

View File

@ -0,0 +1,46 @@
<template>
<Container ref="charChatContainer" :depth="999" :x="currentX" :y="currentY">
<RoundRectangle @create="createChatBubble" :origin-x="0.5" :origin-y="7.5" :fillColor="0xffffff" :width="194" :height="21" :radius="20" />
<Text @create="createChatText" :style="{ fontSize: 13, fontFamily: 'Arial', color: '#000' }" />
</Container>
</template>
<script setup lang="ts">
import { Container, refObj, RoundRectangle, Text, useGame } from 'phavuer'
import type { ZoneCharacter } from '@/types'
import { onMounted } from 'vue'
const props = defineProps<{
zoneCharacter: ZoneCharacter
currentX: number
currentY: number
}>()
const game = useGame()
const charChatContainer = refObj<Phaser.GameObjects.Container>()
const createChatBubble = (container: Phaser.GameObjects.Container) => {
container.setName(`${props.zoneCharacter.character.name}_chatBubble`)
}
const createChatText = (text: Phaser.GameObjects.Text) => {
text.setName(`${props.zoneCharacter.character.name}_chatText`)
text.setFontSize(13)
text.setFontFamily('Arial')
text.setOrigin(0.5, 10.9)
// Fix text alignment on Windows and Android
if (game.device.os.windows || game.device.os.android) {
text.setOrigin(0.5, 9.75)
if (game.device.browser.firefox) {
text.setOrigin(0.5, 10.9)
}
}
}
onMounted(() => {
charChatContainer.value!.setName(`${props.zoneCharacter.character!.name}_chatContainer`)
charChatContainer.value!.setVisible(false)
})
</script>

View File

@ -0,0 +1,35 @@
<template>
<Container :depth="999" :x="currentX" :y="currentY">
<Text @create="createNicknameText" :text="props.zoneCharacter.character.name" />
<RoundRectangle :origin-x="0.5" :origin-y="18.5" :fillColor="0xffffff" :width="74" :height="6" :radius="5" />
<RoundRectangle :origin-x="0.5" :origin-y="36.4" :fillColor="0x00b3b3" :width="70" :height="3" :radius="5" />
</Container>
</template>
<script setup lang="ts">
import { Container, RoundRectangle, Text, useGame } from 'phavuer'
import type { ZoneCharacter } from '@/types'
const props = defineProps<{
zoneCharacter: ZoneCharacter
currentX: number
currentY: number
}>()
const game = useGame()
const createNicknameText = (text: Phaser.GameObjects.Text) => {
text.setFontSize(13)
text.setFontFamily('Arial')
text.setOrigin(0.5, 9)
// Fix text alignment on Windows and Android
if (game.device.os.windows || game.device.os.android) {
text.setOrigin(0.5, 8)
if (game.device.browser.firefox) {
text.setOrigin(0.5, 9)
}
}
}
</script>

View File

@ -3,7 +3,7 @@
</template>
<script setup lang="ts">
import { computed, onMounted } from 'vue'
import { computed } from 'vue'
import { Image, useScene } from 'phavuer'
import { calculateIsometricDepth, tileToWorldX, tileToWorldY } from '@/composables/zoneComposable'
import { loadTexture } from '@/composables/gameComposable'