diff --git a/src/components/game/map/partials/PlacedMapObject.vue b/src/components/game/map/partials/PlacedMapObject.vue index ee2d1bd..4c27a6a 100644 --- a/src/components/game/map/partials/PlacedMapObject.vue +++ b/src/components/game/map/partials/PlacedMapObject.vue @@ -5,15 +5,19 @@ <script setup lang="ts"> import type { PlacedMapObject, TextureData } from '@/application/types' import { loadTexture } from '@/composables/gameComposable' -import { calculateIsometricDepth } from '@/composables/mapComposable' +import { calculateIsometricDepth, tileToWorldXY } from '@/composables/mapComposable' import { useGameStore } from '@/stores/gameStore' import { Image, useScene } from 'phavuer' import { computed, onMounted } from 'vue' import config from '@/application/config' import { useMapEditorComposable } from '@/composables/useMapEditorComposable' +import Tilemap = Phaser.Tilemaps.Tilemap +import TilemapLayer = Phaser.Tilemaps.TilemapLayer const props = defineProps<{ - placedMapObject: PlacedMapObject + placedMapObject: PlacedMapObject, + tileMap: Tilemap + tileMapLayer: TilemapLayer }>() const gameStore = useGameStore() @@ -32,12 +36,11 @@ const imageProps = computed(() => ({ })) function calculateObjectPlacement(mapObj: PlacedMapObject) : {x: number; y: number} { - let position = { x: mapObj.positionX, y: mapObj.positionY } - let halfTileWidth = config.tile_size.width/2 - let halfTileHeight = config.tile_size.height/2 + let position = tileToWorldXY(props.tileMapLayer, mapObj.positionX, mapObj.positionY) + return { - x: position.x-mapObj.mapObject.frameWidth/2, - y: position.y-mapObj.mapObject.frameHeight/2-halfTileHeight + x: position.worldPositionX-mapObj.mapObject.frameWidth/2, + y: position.worldPositionY-mapObj.mapObject.frameHeight/2+config.tile_size.height } } diff --git a/src/components/gameMaster/mapEditor/Map.vue b/src/components/gameMaster/mapEditor/Map.vue index cf74943..321ebd7 100644 --- a/src/components/gameMaster/mapEditor/Map.vue +++ b/src/components/gameMaster/mapEditor/Map.vue @@ -1,7 +1,7 @@ <template> - <MapTiles ref="mapTiles" @tileMap:create="tileMap = $event" /> - <PlacedMapObjects ref="mapObjects" v-if="tileMap" :tileMap /> - <MapEventTiles ref="eventTiles" v-if="tileMap" :tileMap /> + <MapTiles ref="mapTiles" v-if="tileMap && tileMapLayer" :tileMapLayer :tileMap @tileMap:create="tileMap = $event" /> + <PlacedMapObjects ref="mapObjects" v-if="tileMap && tileMapLayer" :tileMapLayer :tileMap /> + <MapEventTiles ref="eventTiles" v-if="tileMap && tileMapLayer" :tileMapLayer :tileMap /> </template> <script setup lang="ts"> @@ -11,8 +11,11 @@ import PlacedMapObjects from '@/components/gameMaster/mapEditor/mapPartials/Plac import { useMapEditorComposable } from '@/composables/useMapEditorComposable' import { useScene } from 'phavuer' import { onBeforeUnmount, onMounted, onUnmounted, shallowRef, useTemplateRef } from 'vue' +import { createTileLayer, createTileMap } from '@/composables/mapComposable' const tileMap = shallowRef<Phaser.Tilemaps.Tilemap>() +const tileMapLayer = shallowRef<Phaser.Tilemaps.TilemapLayer>() + const mapEditor = useMapEditorComposable() const scene = useScene() @@ -72,6 +75,10 @@ function handlePointerUp(pointer: Phaser.Input.Pointer) { } onMounted(() => { + tileMap.value = createTileMap(scene, mapEditor.currentMap.value!) + mapTiles.value?.$emit('tileMap:create', tileMap.value) + tileMapLayer.value = createTileLayer(tileMap.value, mapEditor.currentMap.value) + addEventListener('keydown', handleKeyDown) scene.input.on(Phaser.Input.Events.POINTER_DOWN, handlePointerDown) scene.input.on(Phaser.Input.Events.POINTER_MOVE, handlePointerMove) @@ -79,6 +86,12 @@ onMounted(() => { }) onUnmounted(() => { + if (tileMap.value) { + tileMap.value.destroyLayer('tiles') + tileMap.value.removeAllLayers() + tileMap.value.destroy() + } + scene.input.off(Phaser.Input.Events.POINTER_DOWN, handlePointerDown) scene.input.off(Phaser.Input.Events.POINTER_MOVE, handlePointerMove) scene.input.off(Phaser.Input.Events.POINTER_UP, handlePointerUp) diff --git a/src/components/gameMaster/mapEditor/mapPartials/MapEventTiles.vue b/src/components/gameMaster/mapEditor/mapPartials/MapEventTiles.vue index 518bd5d..9c0f808 100644 --- a/src/components/gameMaster/mapEditor/mapPartials/MapEventTiles.vue +++ b/src/components/gameMaster/mapEditor/mapPartials/MapEventTiles.vue @@ -3,7 +3,7 @@ </template> <script setup lang="ts"> -import { MapEventTileType, type MapEventTile, type Map as MapT } from '@/application/types' +import { MapEventTileType, type MapEventTile, type Map as MapT, type UUID } from '@/application/types' import { uuidv4 } from '@/application/utilities' import { getTile, tileToWorldX, tileToWorldY } from '@/composables/mapComposable' import { useMapEditorComposable } from '@/composables/useMapEditorComposable' @@ -42,7 +42,7 @@ function pencil(pointer: Phaser.Input.Pointer, map: MapT) { if (mapEditor.drawMode.value === 'teleport' && !mapEditor.teleportSettings.value.toMapId) return const newEventTile = { - id: uuidv4(), + id: uuidv4() as UUID, mapId: map.id, map: map.id, type: mapEditor.drawMode.value === 'blocking tile' ? MapEventTileType.BLOCK : MapEventTileType.TELEPORT, @@ -56,7 +56,7 @@ function pencil(pointer: Phaser.Input.Pointer, map: MapT) { toPositionY: mapEditor.teleportSettings.value.toPositionY, toRotation: mapEditor.teleportSettings.value.toRotation } - : undefined + : {} } map.mapEventTiles.push(newEventTile) diff --git a/src/components/gameMaster/mapEditor/mapPartials/MapTiles.vue b/src/components/gameMaster/mapEditor/mapPartials/MapTiles.vue index 0d4deb4..3408bde 100644 --- a/src/components/gameMaster/mapEditor/mapPartials/MapTiles.vue +++ b/src/components/gameMaster/mapEditor/mapPartials/MapTiles.vue @@ -1,5 +1,5 @@ <template> - <Controls v-if="tileLayer" :layer="tileLayer" :depth="0" /> + <Controls v-if="props.tileMapLayer" :layer="props.tileMapLayer" :depth="0" /> </template> <script setup lang="ts"> @@ -16,11 +16,13 @@ const scene = useScene() const mapEditor = useMapEditorComposable() const tileStorage = new TileStorage() -const tileMap = shallowRef<Phaser.Tilemaps.Tilemap>() -const tileLayer = shallowRef<Phaser.Tilemaps.TilemapLayer>() - defineExpose({ handlePointer, finalizeCommand, undo, redo }) +const props = defineProps<{ + tileMap: Phaser.Tilemaps.Tilemap + tileMapLayer: Phaser.Tilemaps.TilemapLayer +}>() + class EditorCommand { public operation: 'draw' | 'erase' = 'draw' public tileName: string = "blank_tile" @@ -46,14 +48,12 @@ function pencil(pointer: Phaser.Input.Pointer) { // Check if there is a selected tile if (!mapEditor.selectedTile.value) return - if (!tileMap.value || !tileLayer.value) return - // Check if there is a tile - const tile = getTile(tileLayer.value, pointer.worldX, pointer.worldY) + const tile = getTile(props.tileMapLayer, pointer.worldX, pointer.worldY) if (!tile) return // Place tile - placeTile(tileMap.value, tileLayer.value, tile.x, tile.y, mapEditor.selectedTile.value) + placeTile(props.tileMap, props.tileMapLayer, tile.x, tile.y, mapEditor.selectedTile.value) createCommandUpdate(tile.x, tile.y, mapEditor.selectedTile.value, 'draw') @@ -65,14 +65,12 @@ function eraser(pointer: Phaser.Input.Pointer) { let map = mapEditor.currentMap.value if (!map) return - if (!tileMap.value || !tileLayer.value) return - // Check if there is a tile - const tile = getTile(tileLayer.value, pointer.worldX, pointer.worldY) + const tile = getTile(props.tileMapLayer, pointer.worldX, pointer.worldY) if (!tile) return // Place tile - placeTile(tileMap.value, tileLayer.value, tile.x, tile.y, 'blank_tile') + placeTile(props.tileMap, props.tileMapLayer, tile.x, tile.y, 'blank_tile') createCommandUpdate(tile.x, tile.y, 'blank_tile', 'erase') @@ -81,10 +79,9 @@ function eraser(pointer: Phaser.Input.Pointer) { } function paint(pointer: Phaser.Input.Pointer) { - if (!tileMap.value || !tileLayer.value) return // Set new tileArray with selected tile - const tileArray = createTileArray(tileMap.value.width, tileMap.value.height, mapEditor.selectedTile.value) - setLayerTiles(tileMap.value, tileLayer.value, tileArray) + const tileArray = createTileArray(props.tileMap.width, props.tileMap.height, mapEditor.selectedTile.value) + setLayerTiles(props.tileMap, props.tileMapLayer, tileArray) // Adjust mapEditorStore.map.tiles if (mapEditor.currentMap.value) { @@ -97,10 +94,8 @@ function tilePicker(pointer: Phaser.Input.Pointer) { let map = mapEditor.currentMap.value if (!map) return - if (!tileMap.value || !tileLayer.value) return - // Check if there is a tile - const tile = getTile(tileLayer.value, pointer.worldX, pointer.worldY) + const tile = getTile(props.tileMapLayer, pointer.worldX, pointer.worldY) if (!tile) return // Select the tile @@ -108,8 +103,6 @@ function tilePicker(pointer: Phaser.Input.Pointer) { } function handlePointer(pointer: Phaser.Input.Pointer) { - if (!tileMap.value || !tileLayer.value) return - // Check if left mouse button is pressed if (!pointer.isDown && pointer.button === 0) return @@ -187,13 +180,13 @@ function applyCommands(tiles: string[][], ...commands: EditorCommand[]): string[ } function updateMapTiles() { - if (!tileMap.value || !tileLayer.value || !mapEditor.currentMap.value) return + if (!mapEditor.currentMap.value) return let indexedCommands = commandStack.slice(0, commandIndex.value) let modifiedTiles = applyCommands(originTiles, ...indexedCommands) //replaceTiles(mapEditor.currentMap.value.tiles, layer, tileMap.value.width, tileMap.value.height) - setLayerTiles(tileMap.value, tileLayer.value, modifiedTiles) + setLayerTiles(props.tileMap, props.tileMapLayer, modifiedTiles) mapEditor.currentMap.value.tiles = modifiedTiles } @@ -205,10 +198,10 @@ function cloneArray(arr: any[]) : any[] { watch( () => mapEditor.shouldClearTiles, (shouldClear) => { - if (shouldClear && mapEditor.currentMap.value && tileMap.value && tileLayer.value) { - const blankTiles = createTileArray(tileLayer.value.width, tileLayer.value.height, 'blank_tile') - setLayerTiles(tileMap.value, tileLayer.value, blankTiles) - replaceTiles(mapEditor.currentMap.value.tiles, blankTiles, tileLayer.value.width, tileLayer.value.height) + if (shouldClear && mapEditor.currentMap.value) { + const blankTiles = createTileArray(props.tileMapLayer.width, props.tileMapLayer.height, 'blank_tile') + setLayerTiles(props.tileMap, props.tileMapLayer, blankTiles) + replaceTiles(mapEditor.currentMap.value.tiles, blankTiles, props.tileMapLayer.width, props.tileMapLayer.height) mapEditor.resetClearTilesFlag() } } @@ -230,20 +223,9 @@ onMounted(async () => { const mapState = mapEditor.currentMap.value //Clone - originTiles = cloneArray(mapEditor.currentMap.value.tiles) + originTiles = cloneArray(mapState.tiles) - tileMap.value = createTileMap(scene, mapEditor.currentMap.value) - emit('tileMap:create', tileMap.value) - tileLayer.value = createTileLayer(tileMap.value, mapEditor.currentMap.value) - - setLayerTiles(tileMap.value, tileLayer.value, mapState.tiles) + setLayerTiles(props.tileMap, props.tileMapLayer, mapState.tiles) }) -onUnmounted(() => { - if (tileMap.value) { - tileMap.value.destroyLayer('tiles') - tileMap.value.removeAllLayers() - tileMap.value.destroy() - } -}) </script> diff --git a/src/components/gameMaster/mapEditor/mapPartials/PlacedMapObjects.vue b/src/components/gameMaster/mapEditor/mapPartials/PlacedMapObjects.vue index f6c0c04..dd0e2e9 100644 --- a/src/components/gameMaster/mapEditor/mapPartials/PlacedMapObjects.vue +++ b/src/components/gameMaster/mapEditor/mapPartials/PlacedMapObjects.vue @@ -1,10 +1,10 @@ <template> <SelectedPlacedMapObjectComponent v-if="mapEditor.selectedPlacedObject.value" :placedMapObject="mapEditor.selectedPlacedObject.value" @move="moveMapObject" @rotate="rotatePlacedMapObject" @delete="deletePlacedMapObject" /> - <PlacedMapObject v-for="placedMapObject in mapEditor.currentMap.value?.placedMapObjects" :placedMapObject @pointerdown="clickPlacedMapObject(placedMapObject)" /> + <PlacedMapObject :tileMapLayer :tileMap v-for="placedMapObject in mapEditor.currentMap.value?.placedMapObjects" :placedMapObject @pointerdown="clickPlacedMapObject(placedMapObject)" /> </template> <script setup lang="ts"> -import type { Map as MapT, PlacedMapObject as PlacedMapObjectT } from '@/application/types' +import type { Map as MapT, PlacedMapObject as PlacedMapObjectT, UUID } from '@/application/types' import { uuidv4 } from '@/application/utilities' import PlacedMapObject from '@/components/game/map/partials/PlacedMapObject.vue' import SelectedPlacedMapObjectComponent from '@/components/gameMaster/mapEditor/partials/SelectedPlacedMapObject.vue' @@ -13,6 +13,7 @@ import { useScene } from 'phavuer' import { ref, watch } from 'vue' import { getTile, tileToWorldX, tileToWorldY } from '@/composables/mapComposable' import Tilemap = Phaser.Tilemaps.Tilemap +import TilemapLayer = Phaser.Tilemaps.TilemapLayer const scene = useScene() const mapEditor = useMapEditorComposable() @@ -20,7 +21,8 @@ const mapEditor = useMapEditorComposable() defineExpose({ handlePointer }) const props = defineProps<{ - tileMap: Tilemap + tileMap: Tilemap, + tileMapLayer: TilemapLayer }>() function pencil(pointer: Phaser.Input.Pointer, map: MapT) { @@ -33,13 +35,13 @@ function pencil(pointer: Phaser.Input.Pointer, map: MapT) { if (!mapEditor.selectedMapObject.value) return const newPlacedMapObject: PlacedMapObjectT = { - id: uuidv4(), + id: uuidv4() as UUID, depth: 0, map: map, mapObject: mapEditor.selectedMapObject.value, isRotated: false, - positionX: tileToWorldX(props.tileMap, tile.x, tile.y), - positionY: tileToWorldY(props.tileMap, tile.x, tile.y) + positionX: tile.x, + positionY: tile.y } // Add new object to mapObjects @@ -75,9 +77,11 @@ function moveMapObject(id: string, map: MapT) { function handlePointerMove(pointer: Phaser.Input.Pointer) { if (!mapEditor.movingPlacedObject.value) return + const tile = getTile(props.tileMap, pointer.worldX, pointer.worldY) + if (!tile) return - mapEditor.movingPlacedObject.value.positionX = pointer.worldX - mapEditor.movingPlacedObject.value.positionY = pointer.worldY + mapEditor.movingPlacedObject.value.positionX = tile.x + mapEditor.movingPlacedObject.value.positionY = tile.y } scene.input.on(Phaser.Input.Events.POINTER_MOVE, handlePointerMove) @@ -103,7 +107,7 @@ function rotatePlacedMapObject(id: string, map: MapT) { } function deletePlacedMapObject(id: string, map: MapT) { - let mapE = mapEditor.currentMap.value + let mapE = mapEditor.currentMap.value! mapE.placedMapObjects = map.placedMapObjects.filter((object) => object.id !== id) mapEditor.selectedPlacedObject.value = null } diff --git a/src/components/gameMaster/mapEditor/partials/Toolbar.vue b/src/components/gameMaster/mapEditor/partials/Toolbar.vue index 999a55a..ac9cd42 100644 --- a/src/components/gameMaster/mapEditor/partials/Toolbar.vue +++ b/src/components/gameMaster/mapEditor/partials/Toolbar.vue @@ -105,7 +105,7 @@ let selectEraserOpen = ref(false) let tileListShown = ref(false) let mapObjectListShown = ref(false) -let checkboxValue = ref(false) +let checkboxValue = ref<Boolean>(false) defineExpose({ tileListShown, mapObjectListShown }) diff --git a/src/components/screens/MapEditor.vue b/src/components/screens/MapEditor.vue index f161734..da220a7 100644 --- a/src/components/screens/MapEditor.vue +++ b/src/components/screens/MapEditor.vue @@ -4,7 +4,7 @@ <Scene name="main" @preload="preloadScene"> <div v-if="!isLoaded" class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-white text-3xl font-ui">Loading...</div> <div v-else> - <Map :key="mapEditor.currentMap.value?.id" /> + <Map v-if="mapEditor.currentMap.value" :key="mapEditor.currentMap.value?.id" /> <Toolbar ref="toolbar" @save="save"