diff --git a/src/components/gameMaster/zoneEditor/EventTiles.vue b/src/components/gameMaster/zoneEditor/EventTiles.vue index 76ecc63..00ffdb8 100644 --- a/src/components/gameMaster/zoneEditor/EventTiles.vue +++ b/src/components/gameMaster/zoneEditor/EventTiles.vue @@ -8,7 +8,7 @@ import { useZoneEditorStore } from '@/stores/zoneEditorStore' import { Image, useScene } from 'phavuer' import { getTile, tileToWorldX, tileToWorldY } from '@/composables/zoneComposable' import { uuidv4 } from '@/utilities' -import { onBeforeMount, onBeforeUnmount } from 'vue' +import { onMounted, onUnmounted } from 'vue' const scene = useScene() const zoneEditorStore = useZoneEditorStore() @@ -102,14 +102,14 @@ function eraser(pointer: Phaser.Input.Pointer) { zoneEditorStore.zone.zoneEventTiles = zoneEditorStore.zone.zoneEventTiles.filter((eventTile) => eventTile.id !== existingEventTile.id) } -onBeforeMount(() => { +onMounted(() => { scene.input.on(Phaser.Input.Events.POINTER_DOWN, pencil) scene.input.on(Phaser.Input.Events.POINTER_MOVE, pencil) scene.input.on(Phaser.Input.Events.POINTER_DOWN, eraser) scene.input.on(Phaser.Input.Events.POINTER_MOVE, eraser) }) -onBeforeUnmount(() => { +onUnmounted(() => { scene.input.off(Phaser.Input.Events.POINTER_DOWN, pencil) scene.input.off(Phaser.Input.Events.POINTER_MOVE, pencil) scene.input.off(Phaser.Input.Events.POINTER_DOWN, eraser) diff --git a/src/components/gameMaster/zoneEditor/Objects.vue b/src/components/gameMaster/zoneEditor/Objects.vue index 8eacc87..ce0d3aa 100644 --- a/src/components/gameMaster/zoneEditor/Objects.vue +++ b/src/components/gameMaster/zoneEditor/Objects.vue @@ -10,7 +10,7 @@ import { Image, useScene } from 'phavuer' import { useZoneEditorStore } from '@/stores/zoneEditorStore' import type { ZoneObject } from '@/types' import SelectedZoneObject from '@/components/gameMaster/zoneEditor/partials/SelectedZoneObject.vue' -import { onBeforeMount, onBeforeUnmount, ref, watch } from 'vue' +import { onMounted, onUnmounted, ref, watch } from 'vue' const scene = useScene() const zoneEditorStore = useZoneEditorStore() @@ -155,14 +155,14 @@ function deleteZoneObject(id: string) { selectedZoneObject.value = null } -onBeforeMount(() => { +onMounted(() => { scene.input.on(Phaser.Input.Events.POINTER_DOWN, pencil) scene.input.on(Phaser.Input.Events.POINTER_MOVE, pencil) scene.input.on(Phaser.Input.Events.POINTER_DOWN, eraser) scene.input.on(Phaser.Input.Events.POINTER_MOVE, eraser) }) -onBeforeUnmount(() => { +onUnmounted(() => { scene.input.off(Phaser.Input.Events.POINTER_DOWN, pencil) scene.input.off(Phaser.Input.Events.POINTER_MOVE, pencil) scene.input.off(Phaser.Input.Events.POINTER_DOWN, eraser) diff --git a/src/components/gameMaster/zoneEditor/Tiles.vue b/src/components/gameMaster/zoneEditor/Tiles.vue index cfd6c67..b4ad75a 100644 --- a/src/components/gameMaster/zoneEditor/Tiles.vue +++ b/src/components/gameMaster/zoneEditor/Tiles.vue @@ -7,7 +7,7 @@ import config from '@/config' import { useScene } from 'phavuer' import { useGameStore } from '@/stores/gameStore' import { useZoneEditorStore } from '@/stores/zoneEditorStore' -import { onBeforeMount, onBeforeUnmount } from 'vue' +import { onMounted, onUnmounted } from 'vue' import { createTileArray, getTile, placeTile, setLayerTiles } from '@/composables/zoneComposable' import Controls from '@/components/utilities/Controls.vue' @@ -123,7 +123,7 @@ function paint(pointer: Phaser.Input.Pointer) { zoneEditorStore.zone.tiles = createTileArray(zoneTilemap.width, zoneTilemap.height, zoneEditorStore.selectedTile.id) } -onBeforeMount(() => { +onMounted(() => { if (!zoneEditorStore.zone?.tiles) { return } @@ -134,7 +134,7 @@ onBeforeMount(() => { scene.input.on(Phaser.Input.Events.POINTER_DOWN, paint) }) -onBeforeUnmount(() => { +onUnmounted(() => { scene.input.off(Phaser.Input.Events.POINTER_MOVE, pencil) scene.input.off(Phaser.Input.Events.POINTER_MOVE, eraser) scene.input.off(Phaser.Input.Events.POINTER_DOWN, paint) diff --git a/src/components/utilities/Notifications.vue b/src/components/utilities/Notifications.vue index c964e11..f188299 100644 --- a/src/components/utilities/Notifications.vue +++ b/src/components/utilities/Notifications.vue @@ -12,7 +12,7 @@ <script setup lang="ts"> import { useGameStore } from '@/stores/gameStore' import Modal from '@/components/utilities/Modal.vue' -import { onBeforeMount, onBeforeUnmount, watch } from 'vue' +import { onBeforeMount, onBeforeUnmount, onMounted, onUnmounted, watch } from 'vue' const gameStore = useGameStore() @@ -34,7 +34,7 @@ function setupNotificationListener(connection: any) { }) } -onBeforeMount(() => { +onMounted(() => { const connection = gameStore.connection if (connection) { setupNotificationListener(connection) @@ -49,7 +49,7 @@ onBeforeMount(() => { } }) -onBeforeUnmount(() => { +onUnmounted(() => { const connection = gameStore.connection if (connection) { connection.off('notification') diff --git a/src/components/zone/Zone.vue b/src/components/zone/Zone.vue index 5cf3a46..093eab3 100644 --- a/src/components/zone/Zone.vue +++ b/src/components/zone/Zone.vue @@ -7,7 +7,7 @@ <script setup lang="ts"> import { useGameStore } from '@/stores/gameStore' import { useZoneStore } from '@/stores/zoneStore' -import { onBeforeUnmount, ref, onBeforeMount } from 'vue' +import { ref, onUnmounted, onMounted } from 'vue' import type { Character as CharacterT, Zone as ZoneT, ExtendedCharacter as ExtendedCharacterT } from '@/types' import ZoneTiles from '@/components/zone/ZoneTiles.vue' import ZoneObjects from '@/components/zone/ZoneObjects.vue' @@ -51,15 +51,15 @@ gameStore.connection!.on('character:move', (data: ExtendedCharacterT) => { zoneStore.updateCharacter(data) }) -onBeforeMount(async () => { +onMounted(async () => { + // Emit zone:character:join event to server and wait for response, then set zone and characters gameStore!.connection!.emit('zone:character:join', async (response: zoneLoadData) => { - // Set zone and characters zoneStore.setZone(response.zone) zoneStore.setCharacters(response.characters) }) }) -onBeforeUnmount(() => { +onUnmounted(() => { zoneStore.reset() gameStore.connection!.off('zone:character:teleport') gameStore.connection!.off('zone:character:join') diff --git a/src/components/zone/ZoneTiles.vue b/src/components/zone/ZoneTiles.vue index 116d105..008a64e 100644 --- a/src/components/zone/ZoneTiles.vue +++ b/src/components/zone/ZoneTiles.vue @@ -6,17 +6,34 @@ import config from '@/config' import { useScene } from 'phavuer' import { useZoneStore } from '@/stores/zoneStore' -import { onBeforeMount, onBeforeUnmount } from 'vue' -import { setLayerTiles } from '@/composables/zoneComposable' +import { onBeforeUnmount } from 'vue' +import { setLayerTiles, loadZoneTileTexture } from '@/composables/zoneComposable' import Controls from '@/components/utilities/Controls.vue' const emit = defineEmits(['tilemap:create']) const zoneStore = useZoneStore() const scene = useScene() + +const tilesFromZone = zoneStore.zone?.tiles +const uniqueTiles = new Set(tilesFromZone.flat().filter(Boolean)) + +/** + * @TODO fix this + */ +for (const tile of uniqueTiles) { + console.log(tile) + await loadZoneTileTexture(scene, tile, new Date()) +} + const zoneTilemap = createTilemap() const tiles = createTileLayer() +/** + * A Tilemap is a container for Tilemap data. + * This isn't a display object, rather, it holds data about the map and allows you to add tilesets and tilemap layers to it. + * A map can have one or more tilemap layers, which are the display objects that actually render the tiles. + */ function createTilemap() { const zoneData = new Phaser.Tilemaps.MapData({ width: zoneStore.zone?.width, @@ -31,6 +48,9 @@ function createTilemap() { return tilemap } +/** + * A Tileset is a combination of a single image containing the tiles and a container for data about each tile. + */ function createTileLayer() { const tilesFromZone = zoneStore.zone?.tiles || [] const uniqueTiles = new Set(tilesFromZone.flat().filter(Boolean)) @@ -49,12 +69,7 @@ function createTileLayer() { return layer } -onBeforeMount(() => { - if (!zoneStore.zone?.tiles) { - return - } - setLayerTiles(zoneTilemap, tiles, zoneStore.zone.tiles) -}) +setLayerTiles(zoneTilemap, tiles, zoneStore.zone?.tiles) onBeforeUnmount(() => { zoneTilemap.destroyLayer('tiles') diff --git a/src/components/zone/partials/ZoneObject.vue b/src/components/zone/partials/ZoneObject.vue index fbf9df0..dba2a80 100644 --- a/src/components/zone/partials/ZoneObject.vue +++ b/src/components/zone/partials/ZoneObject.vue @@ -3,14 +3,9 @@ </template> <script setup lang="ts"> -import { ref, onMounted, computed } from 'vue' +import { ref, computed } from 'vue' import { Image, useScene } from 'phavuer' -import { - calculateIsometricDepth, - loadZoneObjectTexture, - tileToWorldX, - tileToWorldY -} from '@/composables/zoneComposable' +import { calculateIsometricDepth, loadZoneObjectTexture, tileToWorldX, tileToWorldY } from '@/composables/zoneComposable' import type { ZoneObject } from '@/types' const props = defineProps<{ @@ -31,13 +26,11 @@ const imageProps = computed(() => ({ originX: Number(props.zoneObject.object.originY) })) -onMounted(() => { - loadZoneObjectTexture(scene, props.zoneObject.object.id, props.zoneObject.object.updatedAt) - .then((loaded) => { - isTextureLoaded.value = loaded - }) - .catch((error) => { - console.error('Error loading texture:', error) - }) -}) +loadZoneObjectTexture(scene, props.zoneObject.object.id, props.zoneObject.object.updatedAt) + .then((loaded) => { + isTextureLoaded.value = loaded + }) + .catch((error) => { + console.error('Error loading texture:', error) + }) </script> diff --git a/src/composables/zoneComposable.ts b/src/composables/zoneComposable.ts index 6204483..b8161a4 100644 --- a/src/composables/zoneComposable.ts +++ b/src/composables/zoneComposable.ts @@ -52,6 +52,8 @@ export function placeTile(zone: Tilemap, layer: TilemapLayer, x: number, y: numb } export function setLayerTiles(zone: Tilemap, layer: TilemapLayer, tiles: string[][]) { + if (!tiles) return + tiles.forEach((row: string[], y: number) => { row.forEach((tile: string, x: number) => { placeTile(zone, layer, x, y, tile) @@ -71,6 +73,33 @@ export const calculateIsometricDepth = (x: number, y: number, width: number = 0, return baseDepth + (width + height) / (2 * config.tile_size.x) } +export async function loadZoneTileTexture(scene: Phaser.Scene, textureId: string, updatedAt: Date): Promise<boolean> { + const assetManager = useAssetManager + + // Check if the texture is already loaded in Phaser + if (scene.textures.exists(textureId)) { + return true + } + + let assetData = await assetManager.getAsset(textureId) + + if (!assetData) { + await assetManager.downloadAsset(textureId, `/assets/tiles/${textureId}.png`, 'tiles', updatedAt) + assetData = await assetManager.getAsset(textureId) + } + + if (assetData) { + return new Promise<boolean>((resolve) => { + scene.textures.addBase64(textureId, assetData.data) + scene.textures.once(`addtexture-${textureId}`, () => { + resolve(true) + }) + }) + } + + return false +} + export async function loadZoneObjectTexture(scene: Phaser.Scene, textureId: string, updatedAt: Date): Promise<boolean> { const assetManager = useAssetManager diff --git a/src/screens/Game.vue b/src/screens/Game.vue index a77d9a2..c9cf98d 100644 --- a/src/screens/Game.vue +++ b/src/screens/Game.vue @@ -83,24 +83,24 @@ function preloadScene(scene: Phaser.Scene) { * We're using rex-await-loader to load assets asynchronously * Phaser does not support this out of the box, so we're using this plugin */ - scene.load.rexAwait(async function (successCallback) { - await assetManager.getAssetsByGroup('tiles').then((assets) => { - assets.forEach((asset) => { - if (scene.load.textureManager.exists(asset.key)) return - scene.textures.addBase64(asset.key, asset.data) - }) - }) - - // Load objects - await assetManager.getAssetsByGroup('objects').then((assets) => { - assets.forEach((asset) => { - if (scene.load.textureManager.exists(asset.key)) return - scene.textures.addBase64(asset.key, asset.data) - }) - }) - - successCallback() - }) + // scene.load.rexAwait(async function (successCallback) { + // await assetManager.getAssetsByGroup('tiles').then((assets) => { + // assets.forEach((asset) => { + // if (scene.load.textureManager.exists(asset.key)) return + // scene.textures.addBase64(asset.key, asset.data) + // }) + // }) + // + // // Load objects + // await assetManager.getAssetsByGroup('objects').then((assets) => { + // assets.forEach((asset) => { + // if (scene.load.textureManager.exists(asset.key)) return + // scene.textures.addBase64(asset.key, asset.data) + // }) + // }) + // + // successCallback() + // }) } function createScene(scene: Phaser.Scene) { @@ -108,15 +108,15 @@ function createScene(scene: Phaser.Scene) { * Create sprite animations * This is done here because phaser forces us to */ - assetManager.getAssetsByGroup('sprite_animations').then((assets) => { - assets.forEach((asset) => { - scene.anims.create({ - key: asset.key, - frameRate: 7, - frames: scene.anims.generateFrameNumbers(asset.key, { start: 0, end: asset.frameCount! - 1 }), - repeat: -1 - }) - }) - }) + // assetManager.getAssetsByGroup('sprite_animations').then((assets) => { + // assets.forEach((asset) => { + // scene.anims.create({ + // key: asset.key, + // frameRate: 7, + // frames: scene.anims.generateFrameNumbers(asset.key, { start: 0, end: asset.frameCount! - 1 }), + // repeat: -1 + // }) + // }) + // }) } </script>