import config from '@/application/config' import type { MapObject, Map as MapT, TextureData, Tile as TileT, UUID } from '@/application/types' import { unduplicateArray } from '@/application/utilities' import { loadTexture } from '@/services/textureService' import { MapStorage, TileStorage } from '@/storage/storages' import Tilemap = Phaser.Tilemaps.Tilemap import TilemapLayer = Phaser.Tilemaps.TilemapLayer import Tileset = Phaser.Tilemaps.Tileset import Tile = Phaser.Tilemaps.Tile export function getTile(layer: TilemapLayer | Tilemap, positionX: number, positionY: number): Tile | null { return layer.getTileAtWorldXY(positionX, positionY) } export function tileToWorldXY(layer: TilemapLayer | Tilemap, positionX: number, positionY: number) { const worldPoint = layer.tileToWorldXY(positionX, positionY) if (!worldPoint) return { worldPositionX: 0, worldPositionY: 0 } const worldPositionX = worldPoint.x + config.tile_size.height const worldPositionY = worldPoint.y return { worldPositionX, worldPositionY } } export function tileToWorldX(layer: TilemapLayer | Tilemap, positionX: number, positionY: number): number { const worldPoint = layer.tileToWorldXY(positionX, positionY) if (!worldPoint) return 0 return worldPoint.x + config.tile_size.width / 2 } export function tileToWorldY(layer: TilemapLayer | Tilemap, positionX: number, positionY: number): number { const worldPoint = layer.tileToWorldXY(positionX, positionY) if (!worldPoint) return 0 return worldPoint.y + config.tile_size.height * 1.5 } /** * Can also be used to replace tiles */ export function placeTile(map: Tilemap, layer: TilemapLayer, positionX: number, positionY: number, tileName: string) { let tileImg = map.getTileset(tileName) as Tileset if (!tileImg) { tileImg = map.getTileset('blank_tile') as Tileset } layer.putTileAt(tileImg.firstgid, positionX, positionY) } export function placeTiles(map: Tilemap, layer: TilemapLayer, tiles: string[][]) { if (!map || !layer || !tiles) return tiles.forEach((row: string[], y: number) => { row.forEach((tile: string, x: number) => { placeTile(map, layer, x, y, tile) }) }) } export function createTileArray(width: number, height: number, tile: string = 'blank_tile') { return Array.from({ length: height }, () => Array.from({ length: width }, () => tile)) } export const calculateIsometricDepth = ( positionX: number, positionY: number, objectWidth: number = 0, objectHeight: number = 0 ): number => { const tileWidth = config.tile_size.width; const tileHeight = config.tile_size.height; const tileSize = Math.max(tileWidth, tileHeight); const objectSize = Math.max(objectWidth, objectHeight); return Math.floor(positionY * tileSize + positionX * objectSize); }; async function loadTileTextures(tiles: TileT[], scene: Phaser.Scene) { // Load each tile into the scene for (let tile of tiles) { if (!tile?.id || !tile?.updatedAt) continue const textureData = { key: tile.id, data: '/textures/tiles/' + tile.id + '.png', group: 'tiles', updatedAt: tile.updatedAt } as TextureData await loadTexture(scene, textureData) } } export async function loadTileTexturesFromMapTileArray(map_id: string, scene: Phaser.Scene) { const mapStorage = new MapStorage() const tileStorage = new TileStorage() const map = await mapStorage.getById(map_id) if (!map) return const tileArray = unduplicateArray(map.tiles) const tiles = await tileStorage.getByIds(tileArray) if (!tiles) return await loadTileTextures(tiles, scene) } export async function loadAllTileTextures(scene: Phaser.Scene) { const tileStorage = new TileStorage() const tiles = await tileStorage.getAll() if (!tiles) return await loadTileTextures(tiles, scene) } export async function loadMapObjectTextures(mapObjects: MapObject[], scene: Phaser.Scene) { for (const mapObject of mapObjects) { const textureData = { key: mapObject.id, data: '/textures/map_objects/' + mapObject.id + '.png', group: 'map_objects', updatedAt: mapObject.updatedAt, frameWidth: mapObject.frameWidth, frameHeight: mapObject.frameHeight } as TextureData await loadTexture(scene, textureData) } } export function createTileMap(scene: Phaser.Scene, map: MapT) { const mapConfig = new Phaser.Tilemaps.MapData({ width: map.width, height: map.height, tileWidth: config.tile_size.width, tileHeight: config.tile_size.height, orientation: Phaser.Tilemaps.Orientation.ISOMETRIC, format: Phaser.Tilemaps.Formats.ARRAY_2D }) return new Phaser.Tilemaps.Tilemap(scene, mapConfig) } export function createTileLayer(tileMap: Phaser.Tilemaps.Tilemap, tilesArray: string[]) { // Load tiles into tileset const tilesetImages = tilesArray.map((tile: string, index: number) => { return tileMap.addTilesetImage(tile, tile, config.tile_size.width, config.tile_size.height, 1, 2, index + 1, { x: 0, y: -config.tile_size.height }) }) // Add blank tile tilesetImages.push(tileMap.addTilesetImage('blank_tile', 'blank_tile', config.tile_size.width, config.tile_size.height, 1, 2, 0, { x: 0, y: -config.tile_size.height })) // Create layer const layer = tileMap.createBlankLayer('tiles', tilesetImages as Tileset[], 0, config.tile_size.height) as Phaser.Tilemaps.TilemapLayer layer.setDepth(0) layer.setCullPadding(2, 2) return layer } //Recursive Array Clone export function cloneArray(arr: any[]): any[] { return arr.map((item) => (item instanceof Array ? cloneArray(item) : item)) }