This commit is contained in:
bridge
2025-11-20 23:55:22 +08:00
parent 0713881b71
commit 5a51b6638d
10 changed files with 560 additions and 34 deletions

View File

@@ -9,6 +9,10 @@ const props = defineProps<{
tileSize: number
}>()
const emit = defineEmits<{
(e: 'select', payload: { type: 'avatar'; id: string; name?: string }): void
}>()
const { textures } = useTextures()
const app = useApplication()
@@ -90,6 +94,14 @@ const nameStyle = {
alpha: 0.8
}
}
function handlePointerTap() {
emit('select', {
type: 'avatar',
id: props.avatar.id,
name: props.avatar.name
})
}
</script>
<template>
@@ -97,6 +109,9 @@ const nameStyle = {
:x="currentX"
:y="currentY"
:z-index="Math.floor(currentY)"
event-mode="static"
cursor="pointer"
@pointertap="handlePointerTap"
>
<sprite
v-if="getTexture()"

View File

@@ -4,6 +4,14 @@ import AnimatedAvatar from './AnimatedAvatar.vue'
const store = useGameStore()
const TILE_SIZE = 64
const emit = defineEmits<{
(e: 'avatarSelected', payload: { type: 'avatar'; id: string; name?: string }): void
}>()
function handleAvatarSelect(payload: { type: 'avatar'; id: string; name?: string }) {
emit('avatarSelected', payload)
}
</script>
<template>
@@ -13,6 +21,7 @@ const TILE_SIZE = 64
:key="avatar.id"
:avatar="avatar"
:tile-size="TILE_SIZE"
@select="handleAvatarSelect"
/>
</container>
</template>

View File

@@ -13,10 +13,23 @@ const { loadBaseTextures, isLoaded } = useTextures()
const mapSize = ref({ width: 2000, height: 2000 })
const emit = defineEmits<{
(e: 'avatarSelected', payload: { type: 'avatar'; id: string; name?: string }): void
(e: 'regionSelected', payload: { type: 'region'; id: string; name?: string }): void
}>()
function onMapLoaded(size: { width: number, height: number }) {
mapSize.value = size
}
function handleAvatarSelected(payload: { type: 'avatar'; id: string; name?: string }) {
emit('avatarSelected', payload)
}
function handleRegionSelected(payload: { type: 'region'; id: string; name?: string }) {
emit('regionSelected', payload)
}
const devicePixelRatio = window.devicePixelRatio || 1
onMounted(() => {
@@ -46,8 +59,8 @@ onMounted(() => {
:world-width="mapSize.width"
:world-height="mapSize.height"
>
<MapLayer @mapLoaded="onMapLoaded" />
<EntityLayer />
<MapLayer @mapLoaded="onMapLoaded" @regionSelected="handleRegionSelected" />
<EntityLayer @avatarSelected="handleAvatarSelected" />
</Viewport>
</Application>
</div>

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, onMounted, watch, inject } from 'vue'
import { ref, onMounted, watch } from 'vue'
import { Container, Sprite } from 'pixi.js'
import { useTextures } from './composables/useTextures'
@@ -8,7 +8,10 @@ const { textures, isLoaded, loadSectTexture } = useTextures()
const TILE_SIZE = 64
const regions = ref<any[]>([])
const emit = defineEmits(['mapLoaded'])
const emit = defineEmits<{
(e: 'mapLoaded', payload: { width: number, height: number }): void
(e: 'regionSelected', payload: { type: 'region'; id: string; name?: string }): void
}>()
async function initMap() {
if (!mapContainer.value || !isLoaded.value) return
@@ -113,8 +116,8 @@ function getRegionStyle(type: string) {
const base = {
fontFamily: '"Microsoft YaHei", sans-serif',
fontSize: type === 'sect' ? 48 : 64,
fill: type === 'sect' ? 0xffcc00 : (type === 'city' ? 0xccffcc : 0xffffff),
stroke: { color: 0x000000, width: 8, join: 'round' },
fill: type === 'sect' ? '#ffcc00' : (type === 'city' ? '#ccffcc' : '#ffffff'),
stroke: { color: '#000000', width: 8, join: 'round' },
align: 'center',
dropShadow: {
color: '#000000',
@@ -126,6 +129,14 @@ function getRegionStyle(type: string) {
}
return base
}
function handleRegionSelect(region: any) {
emit('regionSelected', {
type: 'region',
id: String(region.id),
name: region.name
})
}
</script>
<template>
@@ -135,6 +146,7 @@ function getRegionStyle(type: string) {
<!-- Region Labels Layer (Above tiles) -->
<container :z-index="200">
<!-- @vue-ignore -->
<text
v-for="r in regions"
:key="r.name"
@@ -143,6 +155,9 @@ function getRegionStyle(type: string) {
:y="r.y * TILE_SIZE + TILE_SIZE / 2"
:anchor="0.5"
:style="getRegionStyle(r.type)"
event-mode="static"
cursor="pointer"
@pointertap="handleRegionSelect(r)"
/>
</container>
</container>