This commit is contained in:
bridge
2025-11-24 23:02:57 +08:00
parent 36bac598d6
commit 9295d71a90
104 changed files with 109 additions and 18 deletions

View File

@@ -14,7 +14,7 @@ const emit = defineEmits<{
(e: 'select', payload: { type: 'avatar'; id: string; name?: string }): void
}>()
const { textures } = useTextures()
const { textures, availableAvatars } = useTextures()
// Target position (grid coordinates)
const targetX = ref(props.avatar.x)
@@ -50,7 +50,25 @@ useSharedTicker((delta) => {
})
function getTexture() {
const key = `${(props.avatar.gender || 'male').toLowerCase()}_${props.avatar.pic_id || 1}`
const gender = (props.avatar.gender || 'male').toLowerCase()
let pid = props.avatar.pic_id
// Fallback logic if pic_id is missing
if (!pid) {
const list = availableAvatars.value[gender === 'female' ? 'females' : 'males']
if (list && list.length > 0) {
let hash = 0
const str = props.avatar.id || props.avatar.name || 'default'
for (let i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash)
}
pid = list[Math.abs(hash) % list.length]
} else {
pid = 1
}
}
const key = `${gender}_${pid}`
return textures.value[key]
}

View File

@@ -1,5 +1,6 @@
import { ref } from 'vue'
import { Assets, Texture, TextureStyle } from 'pixi.js'
import { gameApi } from '@/api/game'
// 设置全局纹理缩放模式为 nearest (像素风)
TextureStyle.defaultOptions.scaleMode = 'nearest'
@@ -7,6 +8,7 @@ TextureStyle.defaultOptions.scaleMode = 'nearest'
// 全局纹理缓存,避免重复加载
const textures = ref<Record<string, Texture>>({})
const isLoaded = ref(false)
const availableAvatars = ref<{ males: number[], females: number[] }>({ males: [], females: [] })
export function useTextures() {
@@ -14,6 +16,19 @@ export function useTextures() {
const loadBaseTextures = async () => {
if (isLoaded.value) return
// Load Avatar Meta first
try {
const meta = await gameApi.fetchAvatarMeta()
if (meta.males) availableAvatars.value.males = meta.males
if (meta.females) availableAvatars.value.females = meta.females
console.log('Avatar meta loaded:', availableAvatars.value)
} catch (e) {
console.warn('Failed to load avatar meta, using default range', e)
// Fallback
availableAvatars.value.males = Array.from({length: 47}, (_, i) => i + 1)
availableAvatars.value.females = Array.from({length: 41}, (_, i) => i + 1)
}
const manifest: Record<string, string> = {
'PLAIN': '/assets/tiles/plain.png',
'WATER': '/assets/tiles/water.png',
@@ -41,19 +56,24 @@ export function useTextures() {
}
})
const avatarPromises = Array.from({ length: 16 }, (_, index) => index + 1).map(async (i) => {
const maleUrl = `/assets/males/${i}.png`
const femaleUrl = `/assets/females/${i}.png`
await Promise.allSettled([
Assets.load(maleUrl).then((tex) => {
textures.value[`male_${i}`] = tex
}),
Assets.load(femaleUrl).then((tex) => {
textures.value[`female_${i}`] = tex
})
])
})
// Load Avatars based on available IDs
const avatarPromises: Promise<void>[] = []
for (const id of availableAvatars.value.males) {
avatarPromises.push(
Assets.load(`/assets/males/${id}.png`)
.then(tex => { textures.value[`male_${id}`] = tex })
.catch(e => console.warn(`Failed male_${id}`, e))
)
}
for (const id of availableAvatars.value.females) {
avatarPromises.push(
Assets.load(`/assets/females/${id}.png`)
.then(tex => { textures.value[`female_${id}`] = tex })
.catch(e => console.warn(`Failed female_${id}`, e))
)
}
await Promise.all([...tilePromises, ...avatarPromises])
@@ -83,7 +103,8 @@ export function useTextures() {
textures,
isLoaded,
loadBaseTextures,
loadSectTexture
loadSectTexture,
availableAvatars
}
}