mapa
This commit is contained in:
99
src/utils/Pathfinding.js
Normal file
99
src/utils/Pathfinding.js
Normal file
@@ -0,0 +1,99 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user