/* eslint-disable no-restricted-globals */ // Preprost A* Pathfinding v Web Workerju let grid = []; let width = 0; let height = 0; self.onmessage = function (e) { const { type, payload, id } = e.data; if (type === 'UPDATE_GRID') { grid = payload.grid; width = payload.width; height = payload.height; // console.log('đŸ•·ïž Worker: Grid updated', width, height); } else if (type === 'FIND_PATH') { if (!grid || grid.length === 0) { self.postMessage({ type: 'PATH_FOUND', id, path: [] }); return; } const { startX, startY, endX, endY } = payload; const path = findPath(startX, startY, endX, endY); self.postMessage({ type: 'PATH_FOUND', id, path }); } }; function findPath(startX, startY, endX, endY) { // Preverimo meje if (startX < 0 || startX >= width || startY < 0 || startY >= height) return []; if (endX < 0 || endX >= width || endY < 0 || endY >= height) return []; // Če cilj ni prehoden, vrni prazno (ali najdi najbliĆŸjo točko - za zdaj prazno) if (!isWalkable(endX, endY)) return []; const openSet = []; const closedSet = new Set(); const cameFrom = new Map(); const gScore = new Map(); const fScore = new Map(); const startKey = `${startX},${startY}`; const endKey = `${endX},${endY}`; openSet.push({ x: startX, y: startY, f: heuristic(startX, startY, endX, endY) }); gScore.set(startKey, 0); fScore.set(startKey, heuristic(startX, startY, endX, endY)); let iterations = 0; while (openSet.length > 0) { iterations++; if (iterations > 1000) return []; // Safety break // Najdi vozliơče z najniĆŸjim fScore openSet.sort((a, b) => a.f - b.f); const current = openSet.shift(); const currentKey = `${current.x},${current.y}`; if (current.x === endX && current.y === endY) { return reconstructPath(cameFrom, current); } closedSet.add(currentKey); const neighbors = getNeighbors(current.x, current.y); for (const neighbor of neighbors) { const neighborKey = `${neighbor.x},${neighbor.y}`; if (closedSet.has(neighborKey)) continue; const tentativeGScore = (gScore.get(currentKey) || 0) + 1; if (tentativeGScore < (gScore.get(neighborKey) || Infinity)) { cameFrom.set(neighborKey, current); gScore.set(neighborKey, tentativeGScore); const f = tentativeGScore + heuristic(neighbor.x, neighbor.y, endX, endY); fScore.set(neighborKey, f); if (!openSet.some(n => n.x === neighbor.x && n.y === neighbor.y)) { openSet.push({ x: neighbor.x, y: neighbor.y, f: f }); } } } } return []; // Pot ni najdena } function isWalkable(x, y) { if (x < 0 || x >= width || y < 0 || y >= height) return false; // Predpostavljamo 1D array: y * width + x. 0 = prehodno, 1 = ovira. return grid[y * width + x] === 0; } function getNeighbors(x, y) { const neighbors = []; const dirs = [[0, 1], [0, -1], [1, 0], [-1, 0]]; // Samo 4 smeri (Manhattan) for (const [dx, dy] of dirs) { const nx = x + dx; const ny = y + dy; if (isWalkable(nx, ny)) { neighbors.push({ x: nx, y: ny }); } } return neighbors; } function heuristic(x1, y1, x2, y2) { return Math.abs(x1 - x2) + Math.abs(y1 - y2); } function reconstructPath(cameFrom, current) { const totalPath = [current]; let currentKey = `${current.x},${current.y}`; while (cameFrom.has(currentKey)) { current = cameFrom.get(currentKey); currentKey = `${current.x},${current.y}`; totalPath.unshift(current); } return totalPath; }