class Pathfinding { constructor(scene) { this.scene = scene; // Offsets for 4 directions (Isometric grid) this.dirs = [ { x: 0, y: -1 }, // Up { x: 0, y: 1 }, // Down { x: -1, y: 0 }, // Left { x: 1, y: 0 } // Right ]; } findPath(startX, startY, endX, endY, limit = 50) { // Simple A* implementation const startNode = { x: startX, y: startY, g: 0, h: 0, f: 0, parent: null }; const openList = [startNode]; const closedSet = new Set(); let count = 0; while (openList.length > 0 && count < limit) { count++; // Sort by F cost (can be optimized with PriorityQueue) openList.sort((a, b) => a.f - b.f); const currentNode = openList.shift(); // Reached destination? (or close enough) if (currentNode.x === endX && currentNode.y === endY) { return this.reconstructPath(currentNode); } const key = `${currentNode.x},${currentNode.y}`; closedSet.add(key); // Explore neighbors for (const dir of this.dirs) { const neighborX = currentNode.x + dir.x; const neighborY = currentNode.y + dir.y; if (closedSet.has(`${neighborX},${neighborY}`)) continue; // Check collision if (!this.isValidMove(neighborX, neighborY)) continue; const gScore = currentNode.g + 1; const hScore = Math.abs(neighborX - endX) + Math.abs(neighborY - endY); const fScore = gScore + hScore; // Check if already in openList with lower G const existing = openList.find(n => n.x === neighborX && n.y === neighborY); if (existing) { if (gScore < existing.g) { existing.g = gScore; existing.f = fScore; existing.parent = currentNode; } } else { openList.push({ x: neighborX, y: neighborY, g: gScore, h: hScore, f: fScore, parent: currentNode }); } } } // Limit reached or no path - return simplified direction if possible return null; } reconstructPath(node) { const path = []; let curr = node; while (curr.parent) { path.unshift({ x: curr.x, y: curr.y }); curr = curr.parent; } return path; } isValidMove(x, y) { const terrain = this.scene.terrainSystem; if (!terrain) return true; // Bounds if (x < 0 || y < 0 || x >= terrain.width || y >= terrain.height) return false; // Tile Type const tile = terrain.tiles[y][x]; if (tile.type.name === 'water') return false; // Decorations collision const key = `${x},${y}`; if (terrain.decorationsMap.has(key)) { const decor = terrain.decorationsMap.get(key); const solidTypes = ['tree', 'stone', 'bush', 'wall', 'ruin', 'fence', 'house', 'gravestone']; if (solidTypes.includes(decor.type)) return false; } return true; } }