-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmap.js
More file actions
99 lines (88 loc) · 4.59 KB
/
map.js
File metadata and controls
99 lines (88 loc) · 4.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
'use strict';
// ══════════════════════════════════════════════
// MAP
// ══════════════════════════════════════════════
const MW = 32, MH = 32;
const MAP = [
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,1,
1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,
1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,
1,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,
1,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,
1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,1,
1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,
1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,
1,0,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
];
const mapAt = (x, y) => {
const mx = x|0, my = y|0;
if (mx < 0 || mx >= MW || my < 0 || my >= MH) return 1;
return MAP[my * MW + mx];
};
// ── BFS pathfinder ──────────────────────────
// Returns direction vector {dx, dy} toward target, navigating around walls.
// Falls back to direct line if already in LOS or on same cell.
const _bfsDist = new Int16Array(MW * MH);
const _bfsQueue = new Int16Array(MW * MH * 2); // flat [x,y,x,y,...]
function pathDir(fromX, fromY, toX, toY) {
const fx = fromX | 0, fy = fromY | 0;
const tx = toX | 0, ty = toY | 0;
// Same cell — go direct
if (fx === tx && fy === ty) return { dx: toX - fromX, dy: toY - fromY };
// BFS from target to source (reverse BFS so we can read the direction at source)
_bfsDist.fill(-1);
let head = 0, tail = 0;
_bfsQueue[tail++] = tx; _bfsQueue[tail++] = ty;
_bfsDist[ty * MW + tx] = 0;
while (head < tail) {
const cx = _bfsQueue[head++], cy = _bfsQueue[head++];
const cd = _bfsDist[cy * MW + cx];
if (cx === fx && cy === fy) break;
for (let d = 0; d < 4; d++) {
const nx = cx + (d === 0 ? 1 : d === 1 ? -1 : 0);
const ny = cy + (d === 2 ? 1 : d === 3 ? -1 : 0);
if (nx < 0 || nx >= MW || ny < 0 || ny >= MH) continue;
if (MAP[ny * MW + nx]) continue;
if (_bfsDist[ny * MW + nx] >= 0) continue;
_bfsDist[ny * MW + nx] = cd + 1;
_bfsQueue[tail++] = nx; _bfsQueue[tail++] = ny;
}
}
// If no path found, go direct
if (_bfsDist[fy * MW + fx] < 0) return { dx: toX - fromX, dy: toY - fromY };
// Find neighbor of source with lowest distance to target
let bestD = _bfsDist[fy * MW + fx], bestX = fx, bestY = fy;
for (let d = 0; d < 4; d++) {
const nx = fx + (d === 0 ? 1 : d === 1 ? -1 : 0);
const ny = fy + (d === 2 ? 1 : d === 3 ? -1 : 0);
if (nx < 0 || nx >= MW || ny < 0 || ny >= MH) continue;
if (MAP[ny * MW + nx]) continue;
const nd = _bfsDist[ny * MW + nx];
if (nd >= 0 && nd < bestD) { bestD = nd; bestX = nx; bestY = ny; }
}
// Direction: aim at center of best neighbor cell
return { dx: (bestX + 0.5) - fromX, dy: (bestY + 0.5) - fromY };
}