<template> <Controls v-if="tileLayer" :layer="tileLayer" :depth="0" /> </template> <script setup lang="ts"> import config from '@/application/config' import Controls from '@/components/utilities/Controls.vue' import { createTileArray, getTile, placeTile, setLayerTiles } from '@/composables/mapComposable' import { useMapEditorComposable } from '@/composables/useMapEditorComposable' import { TileStorage } from '@/storage/storages' import { useScene } from 'phavuer' import { onMounted, onUnmounted, shallowRef, watch } from 'vue' import Tileset = Phaser.Tilemaps.Tileset const emit = defineEmits(['tileMap:create']) const scene = useScene() const mapEditor = useMapEditorComposable() const tileStorage = new TileStorage() const tileMap = shallowRef<Phaser.Tilemaps.Tilemap>() const tileLayer = shallowRef<Phaser.Tilemaps.TilemapLayer>() function createTileMap() { const mapData = new Phaser.Tilemaps.MapData({ width: mapEditor.currentMap.value?.width, height: mapEditor.currentMap.value?.height, tileWidth: config.tile_size.width, tileHeight: config.tile_size.height, orientation: Phaser.Tilemaps.Orientation.ISOMETRIC, format: Phaser.Tilemaps.Formats.ARRAY_2D }) const newTileMap = new Phaser.Tilemaps.Tilemap(scene, mapData) emit('tileMap:create', newTileMap) return newTileMap } async function createTileLayer(currentTileMap: Phaser.Tilemaps.Tilemap) { const tiles = await tileStorage.getAll() const tilesetImages = [] for (const tile of tiles) { tilesetImages.push(currentTileMap.addTilesetImage(tile.id, tile.id, config.tile_size.width, config.tile_size.height, 1, 2, tilesetImages.length + 1, { x: 0, y: -config.tile_size.height })) } // Add blank tile tilesetImages.push(currentTileMap.addTilesetImage('blank_tile', 'blank_tile', config.tile_size.width, config.tile_size.height, 1, 2, 0, { x: 0, y: -config.tile_size.height })) const layer = currentTileMap.createBlankLayer('tiles', tilesetImages as Tileset[], 0, config.tile_size.height) as Phaser.Tilemaps.TilemapLayer layer.setDepth(0) layer.setCullPadding(2, 2) return layer } function pencil(pointer: Phaser.Input.Pointer) { if (!tileMap.value || !tileLayer.value) return // Check if map is set if (!mapEditor.currentMap.value) return console.log(mapEditor.tool.value) // Check if tool is pencil if (mapEditor.tool.value !== 'pencil') return // Check if draw mode is tile if (mapEditor.drawMode.value !== 'tile') return // Check if there is a selected tile if (!mapEditor.selectedTile.value) return // Changed this line to access .value // Check if left mouse button is pressed if (!pointer.isDown) return // Check if shift is not pressed, this means we are moving the camera if (pointer.event.shiftKey) return // Check if there is a tile const tile = getTile(tileLayer.value, pointer.worldX, pointer.worldY) if (!tile) return // Place tile placeTile(tileMap.value, tileLayer.value, tile.x, tile.y, mapEditor.selectedTile.value) // Adjust mapEditor tiles mapEditor.currentMap.value.tiles[tile.y][tile.x] = mapEditor.selectedTile.value } function eraser(pointer: Phaser.Input.Pointer) { if (!tileMap.value || !tileLayer.value) return // Check if map is set if (!mapEditor.currentMap.value) return // Check if tool is pencil if (mapEditor.tool.value !== 'eraser') return // Check if draw mode is tile if (mapEditor.eraserMode.value !== 'tile') return // Check if left mouse button is pressed if (!pointer.isDown) return // Check if shift is not pressed, this means we are moving the camera if (pointer.event.shiftKey) return // Check if alt is pressed if (pointer.event.altKey) return // Check if there is a tile const tile = getTile(tileLayer.value, pointer.worldX, pointer.worldY) if (!tile) return // Place tile placeTile(tileMap.value, tileLayer.value, tile.x, tile.y, 'blank_tile') // Adjust mapEditor.map.tiles mapEditor.currentMap.value.tiles[tile.y][tile.x] = 'blank_tile' } function paint(pointer: Phaser.Input.Pointer) { if (!tileMap.value || !tileLayer.value) return // Check if map is set if (!mapEditor.currentMap.value) return // Check if tool is pencil if (mapEditor.tool.value !== 'paint') return // Check if there is a selected tile if (!mapEditor.selectedTile.value) return // Check if left mouse button is pressed if (!pointer.isDown) return // Check if shift is not pressed, this means we are moving the camera if (pointer.event.shiftKey) return // Check if alt is pressed if (pointer.event.altKey) return // Set new tileArray with selected tile setLayerTiles(tileMap.value, tileLayer.value, createTileArray(tileMap.value.width, tileMap.value.height, mapEditor.selectedTile.value)) // Adjust mapEditor.map.tiles mapEditor.currentMap.value.tiles = createTileArray(tileMap.value.width, tileMap.value.height, mapEditor.selectedTile.value) } // When alt is pressed, and the pointer is down, select the tile that the pointer is over function tilePicker(pointer: Phaser.Input.Pointer) { if (!tileMap.value || !tileLayer.value) return // Check if map is set if (!mapEditor.currentMap.value) return // Check if tool is pencil if (mapEditor.tool.value !== 'pencil') return // Check if draw mode is tile if (mapEditor.drawMode.value !== 'tile') return // Check if left mouse button is pressed if (!pointer.isDown) return // Check if shift is not pressed, this means we are moving the camera if (pointer.event.shiftKey) return // Check if alt is pressed if (!pointer.event.altKey) return // Check if there is a tile const tile = getTile(tileLayer.value, pointer.worldX, pointer.worldY) if (!tile) return // Select the tile mapEditor.setSelectedTile(mapEditor.currentMap.value.tiles[tile.y][tile.x]) } watch( () => mapEditor.shouldClearTiles.value, (shouldClear) => { if (shouldClear && mapEditor.currentMap.value && tileMap.value && tileLayer.value) { const blankTiles = createTileArray(tileMap.value.width, tileMap.value.height, 'blank_tile') setLayerTiles(tileMap.value, tileLayer.value, blankTiles) mapEditor.currentMap.value.tiles = blankTiles mapEditor.resetClearTilesFlag() } } ) onMounted(async () => { if (!mapEditor.currentMap.value?.tiles) return console.log(mapEditor.currentMap.value) tileMap.value = createTileMap() tileLayer.value = await createTileLayer(tileMap.value) // First fill the entire map with blank tiles using current map dimensions const blankTiles = createTileArray(mapEditor.currentMap.value.width, mapEditor.currentMap.value.height, 'blank_tile') // Then overlay the map tiles, but only within the current map dimensions const mapTiles = mapEditor.currentMap.value.tiles for (let y = 0; y < mapEditor.currentMap.value.height; y++) { for (let x = 0; x < mapEditor.currentMap.value.width; x++) { if (mapTiles[y] && mapTiles[y][x] !== undefined) { blankTiles[y][x] = mapTiles[y][x] } } } setLayerTiles(tileMap.value, tileLayer.value, blankTiles) scene.input.on(Phaser.Input.Events.POINTER_MOVE, pencil) scene.input.on(Phaser.Input.Events.POINTER_MOVE, eraser) scene.input.on(Phaser.Input.Events.POINTER_DOWN, paint) scene.input.on(Phaser.Input.Events.POINTER_DOWN, tilePicker) }) 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) scene.input.off(Phaser.Input.Events.POINTER_DOWN, tilePicker) if (tileMap.value) { tileMap.value.destroyLayer('tiles') tileMap.value.removeAllLayers() tileMap.value.destroy() } }) </script>