forked from noxious/client
119 lines
4.3 KiB
Vue
119 lines
4.3 KiB
Vue
<template>
|
|
<TilemapLayerC :tilemap="zoneTilemap" :tileset="exampleTilesArray as any" :layerIndex="0" :cull-padding-x="10" :cull-padding-y="10" />
|
|
<Controls :layer="tiles" />
|
|
|
|
<Container :depth="2">
|
|
<template v-for="item in sortedItems" :key="item.id">
|
|
<Image
|
|
v-if="item.type === 'object'"
|
|
:x="tileToWorldX(zoneTilemap as any, item.position_x, item.position_y)"
|
|
:y="tileToWorldY(zoneTilemap as any, item.position_x, item.position_y)"
|
|
:texture="item.object.id"
|
|
:originY="Number(item.object.origin_x)"
|
|
:originX="Number(item.object.origin_y)"
|
|
:depth="item.depth"
|
|
/>
|
|
<Character v-else :layer="zoneTilemap as any" :character="item" :depth="item.depth" />
|
|
</template>
|
|
</Container>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import config from '@/config'
|
|
import { Container, Image, TilemapLayer as TilemapLayerC, useScene } from 'phavuer'
|
|
import { onBeforeMount, onBeforeUnmount, ref, toRaw, computed } from 'vue'
|
|
import Controls from '@/components/utilities/Controls.vue'
|
|
import { useGameStore } from '@/stores/game'
|
|
import { useAssetStore } from '@/stores/assets'
|
|
import type { Zone, ZoneObject, ExtendedCharacter } from '@/types'
|
|
import TilemapLayer = Phaser.Tilemaps.TilemapLayer
|
|
import { useZoneStore } from '@/stores/zone'
|
|
import Character from '@/components/sprites/Character.vue'
|
|
import { createZoneData, createTilesetImages, initializeZoneTiles, updateZoneTiles, calculateDepth, sortByDepth, tileToWorldX, tileToWorldY } from '@/services/zone'
|
|
|
|
const scene = useScene()
|
|
const gameStore = useGameStore()
|
|
const assetStore = useAssetStore()
|
|
const zoneStore = useZoneStore()
|
|
|
|
const zoneData = createZoneData(gameStore.character?.zone?.width ?? 10, gameStore.character?.zone?.height ?? 10, config.tile_size.x, config.tile_size.y)
|
|
|
|
const zoneTilemap = new Phaser.Tilemaps.Tilemap(scene, zoneData)
|
|
const tilesetImages = createTilesetImages(zoneTilemap, toRaw(assetStore.assets), config.tile_size)
|
|
|
|
const tiles = zoneTilemap.createBlankLayer('tiles', tilesetImages, 0, config.tile_size.y) as TilemapLayer
|
|
const exampleTilesArray = initializeZoneTiles(zoneTilemap, tiles, gameStore.character?.zone?.width ?? 10, gameStore.character?.zone?.height ?? 10)
|
|
|
|
const zoneObjects = ref<ZoneObject[]>([])
|
|
|
|
// Computed property that combines and sorts both objects and characters
|
|
const sortedItems = computed(() => {
|
|
const objects = zoneObjects.value.map((obj) => ({
|
|
...obj,
|
|
type: 'object' as const,
|
|
depth: calculateDepth(obj.position_x, obj.position_y, zoneTilemap.width)
|
|
}))
|
|
|
|
const characters = zoneStore.characters.map((char) => ({
|
|
...char,
|
|
type: 'character' as const,
|
|
depth: calculateDepth(char.position_x, char.position_y, zoneTilemap.width)
|
|
}))
|
|
|
|
return sortByDepth([...objects, ...characters], zoneTilemap.width)
|
|
})
|
|
|
|
// Event listeners
|
|
gameStore.connection?.on('zone:character:join', (data: ExtendedCharacter) => {
|
|
zoneStore.addCharacter(data)
|
|
})
|
|
|
|
gameStore.connection?.on('zone:character:leave', (character_id: number) => {
|
|
zoneStore.removeCharacter(character_id)
|
|
})
|
|
|
|
gameStore.connection?.on('character:moved', (data: ExtendedCharacter) => {
|
|
zoneStore.updateCharacter(data)
|
|
})
|
|
|
|
onBeforeMount(() => {
|
|
if (gameStore.character?.zone) {
|
|
updateZoneTiles(zoneTilemap, tiles, gameStore.character.zone)
|
|
}
|
|
|
|
zoneObjects.value = gameStore.character?.zone?.zoneObjects ?? []
|
|
|
|
type TResponse = {
|
|
zone: Zone
|
|
characters: ExtendedCharacter[]
|
|
}
|
|
|
|
gameStore.connection?.emit('character:zone:request', { zoneId: gameStore.character?.zoneId }, (response: TResponse) => {
|
|
zoneStore.setZone(response.zone)
|
|
const uniqueCharacters = [...new Set(response.characters)]
|
|
zoneStore.setCharacters(uniqueCharacters)
|
|
updateZoneTiles(zoneTilemap, tiles, response.zone)
|
|
zoneObjects.value = response.zone.zoneObjects
|
|
})
|
|
})
|
|
|
|
onBeforeUnmount(() => {
|
|
zoneObjects.value = []
|
|
tiles.destroy()
|
|
zoneTilemap.removeAllLayers()
|
|
zoneTilemap.destroy()
|
|
zoneStore.reset()
|
|
|
|
gameStore.connection?.emit('character:zone:leave')
|
|
gameStore.connection?.off('character:zone:load')
|
|
gameStore.connection?.off('zone:character:join')
|
|
gameStore.connection?.off('user:disconnect')
|
|
gameStore.connection?.off('character:moved')
|
|
})
|
|
|
|
// center camera
|
|
const centerY = (zoneTilemap.height * zoneTilemap.tileHeight) / 2
|
|
const centerX = (zoneTilemap.width * zoneTilemap.tileWidth) / 2
|
|
scene.cameras.main.centerOn(centerX, centerY)
|
|
</script>
|