fast-astar 1.0.6 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Astar.js +1709 -0
- package/Grid.js +585 -0
- package/README.md +272 -36
- package/astar.wasm +0 -0
- package/index.js +282 -0
- package/package.json +23 -21
- package/wasm.d.ts +89 -0
- package/wasm.js +388 -0
- package/dist/Astar.js +0 -2
- package/dist/Grid.js +0 -2
- package/dist/index.js +0 -3
- package/test.js +0 -30
package/README.md
CHANGED
|
@@ -1,55 +1,291 @@
|
|
|
1
1
|
# fast-astar
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A high-performance A* pathfinding algorithm library with WebAssembly support. Small, fast, and memory-efficient.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🚀 **Multiple Implementations**: Ultra A*, Master A*, and WebAssembly A* with automatic selection
|
|
8
|
+
- ⚡ **High Performance**: Optimized for speed with WebAssembly support
|
|
9
|
+
- 💾 **Memory Efficient**: Sparse data structures for ultra-large maps (up to 100,000×100,000)
|
|
10
|
+
- 🎬 **Animation Support**: Full search process visualization with step-by-step callbacks
|
|
11
|
+
- 🌐 **Universal**: Works in Node.js, browsers, and Web Workers
|
|
12
|
+
- 📦 **Zero Dependencies**: Pure JavaScript/WebAssembly implementation
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
7
15
|
|
|
8
|
-
**Install:**
|
|
9
16
|
```bash
|
|
10
|
-
npm install fast-astar
|
|
17
|
+
npm install fast-astar
|
|
11
18
|
```
|
|
12
19
|
|
|
13
|
-
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### Basic Usage
|
|
23
|
+
|
|
14
24
|
```javascript
|
|
15
|
-
import {Grid,Astar} from
|
|
25
|
+
import { Grid, Astar } from 'fast-astar';
|
|
16
26
|
|
|
17
27
|
// Create a grid
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
// Add obstacles
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
const grid = new Grid({
|
|
29
|
+
col: 20, // width
|
|
30
|
+
row: 15, // height
|
|
31
|
+
render: function() {
|
|
32
|
+
// Optional: called when grid points change (for animation)
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Add obstacles
|
|
37
|
+
grid.setWalkAt(5, 5, false); // Set obstacle at (5, 5)
|
|
38
|
+
grid.setWalkAt(6, 5, false);
|
|
39
|
+
grid.setWalkAt(7, 5, false);
|
|
40
|
+
|
|
41
|
+
// Create A* instance
|
|
42
|
+
const astar = new Astar(grid);
|
|
43
|
+
|
|
44
|
+
// Find path
|
|
45
|
+
const path = await astar.search(
|
|
46
|
+
[0, 0], // start point [x, y]
|
|
47
|
+
[19, 14], // end point [x, y]
|
|
48
|
+
{
|
|
49
|
+
rightAngle: false, // Allow diagonal movement (default: false)
|
|
50
|
+
optimalResult: true // Ensure optimal path (default: true)
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
console.log(path); // [[0,0], [1,1], [2,2], ...]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Advanced Usage
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
import { Grid, Astar } from 'fast-astar';
|
|
61
|
+
|
|
62
|
+
// Create grid with memory-efficient mode for large maps
|
|
63
|
+
const grid = new Grid({
|
|
64
|
+
col: 10000,
|
|
65
|
+
row: 10000,
|
|
66
|
+
useMemoryEfficientMode: true // Enable for maps > 1000×1000
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Set obstacles in batch
|
|
70
|
+
const obstacles = [[5, 2], [5, 3], [5, 4], [10, 10]];
|
|
71
|
+
grid.setObstacles(obstacles);
|
|
72
|
+
|
|
73
|
+
// Create A* with specific algorithm preference
|
|
74
|
+
const astar = new Astar(grid, {
|
|
75
|
+
prefer: 'wasm', // 'ultra' | 'master' | 'wasm' | 'auto' (default)
|
|
76
|
+
strategy: 'auto' // 'auto' | 'performance' | 'memory' | 'compatibility'
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Search with options
|
|
80
|
+
const path = await astar.search(
|
|
81
|
+
[0, 0],
|
|
82
|
+
[9999, 9999],
|
|
83
|
+
{
|
|
84
|
+
rightAngle: false,
|
|
85
|
+
optimalResult: true
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
// Get current implementation info
|
|
90
|
+
const info = astar.getCurrentImplementation();
|
|
91
|
+
console.log(info.name); // e.g., "WebAssembly A*"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## API Reference
|
|
95
|
+
|
|
96
|
+
### Grid
|
|
97
|
+
|
|
98
|
+
#### Constructor
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
new Grid(options)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Options:**
|
|
105
|
+
- `col` (number): Grid width (columns)
|
|
106
|
+
- `row` (number): Grid height (rows)
|
|
107
|
+
- `render` (function, optional): Callback function triggered when grid points change
|
|
108
|
+
- `useMemoryEfficientMode` (boolean, optional): Enable memory-efficient mode for large maps (>1000×1000)
|
|
109
|
+
|
|
110
|
+
#### Methods
|
|
111
|
+
|
|
112
|
+
- `setWalkAt(x, y, walkable)`: Set whether a cell is walkable
|
|
113
|
+
- `isWalkableAt(x, y)`: Check if a cell is walkable
|
|
114
|
+
- `setObstacles(obstacles)`: Set multiple obstacles at once (array of [x, y] pairs)
|
|
115
|
+
- `clearObstacles()`: Remove all obstacles
|
|
116
|
+
- `get([x, y])`: Get node at position
|
|
117
|
+
- `set([x, y], key, value)`: Set node property (for animation)
|
|
118
|
+
|
|
119
|
+
### Astar
|
|
120
|
+
|
|
121
|
+
#### Constructor
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
new Astar(grid, options)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**Options:**
|
|
128
|
+
- `prefer` (string): Preferred algorithm - `'ultra'` | `'master'` | `'wasm'` | `'auto'` (default)
|
|
129
|
+
- `strategy` (string): Selection strategy - `'auto'` | `'performance'` | `'memory'` | `'compatibility'`
|
|
130
|
+
- `avoid` (string): Algorithm to avoid
|
|
131
|
+
- `debug` (boolean): Enable debug logging
|
|
132
|
+
|
|
133
|
+
#### Methods
|
|
134
|
+
|
|
135
|
+
- `search(start, end, options)`: Find path from start to end
|
|
136
|
+
- Returns: `Promise<Array<[x, y]> | null>`
|
|
137
|
+
- Options:
|
|
138
|
+
- `rightAngle` (boolean): Only allow 4-directional movement (default: false)
|
|
139
|
+
- `optimalResult` (boolean): Ensure optimal path (default: true)
|
|
140
|
+
- `getCurrentImplementation()`: Get current algorithm implementation info
|
|
141
|
+
- `getPerformanceStats()`: Get performance statistics
|
|
142
|
+
- `getMemoryUsage()`: Get memory usage information
|
|
143
|
+
|
|
144
|
+
## Algorithm Selection
|
|
145
|
+
|
|
146
|
+
The library automatically selects the optimal algorithm based on map size:
|
|
147
|
+
|
|
148
|
+
| Map Size | Algorithm | Performance |
|
|
149
|
+
|----------|-----------|-------------|
|
|
150
|
+
| ≤50×50 | Master A* | Best for small maps |
|
|
151
|
+
| 50×50 - 1000×1000 | WebAssembly A* | **17-25x faster** than JS |
|
|
152
|
+
| 1000×1000 - 10000×10000 | WebAssembly A* | **25x faster** than JS |
|
|
153
|
+
| ≥10000×10000 | WebAssembly A* (Sparse) | **18x faster** than JS |
|
|
154
|
+
|
|
155
|
+
### Manual Selection
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
// Force specific algorithm
|
|
159
|
+
const astar = new Astar(grid, { prefer: 'wasm' });
|
|
160
|
+
|
|
161
|
+
// Performance priority
|
|
162
|
+
const astar = new Astar(grid, { strategy: 'performance' });
|
|
163
|
+
|
|
164
|
+
// Memory priority
|
|
165
|
+
const astar = new Astar(grid, { strategy: 'memory' });
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Animation Support
|
|
169
|
+
|
|
170
|
+
For visualization, provide a `render` callback in the Grid constructor:
|
|
171
|
+
|
|
172
|
+
```javascript
|
|
173
|
+
const grid = new Grid({
|
|
174
|
+
col: 20,
|
|
175
|
+
row: 15,
|
|
176
|
+
render: function() {
|
|
177
|
+
// This is called during pathfinding
|
|
178
|
+
// Use grid.set([x, y], 'type', 'open'|'close'|'highlight'|'update')
|
|
179
|
+
// to track the search process
|
|
180
|
+
}
|
|
29
181
|
});
|
|
30
182
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
183
|
+
const astar = new Astar(grid);
|
|
184
|
+
const path = await astar.search([0, 0], [19, 14]);
|
|
185
|
+
|
|
186
|
+
// During search, the render callback will be triggered with:
|
|
187
|
+
// - 'open': Node added to open set
|
|
188
|
+
// - 'close': Node added to closed set
|
|
189
|
+
// - 'highlight': Current node being examined
|
|
190
|
+
// - 'update': Node cost updated
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Performance
|
|
194
|
+
|
|
195
|
+
Benchmark results (average of 3 runs):
|
|
196
|
+
|
|
197
|
+
| Map Size | WebAssembly A* | Ultra A* | Master A* |
|
|
198
|
+
|----------|----------------|----------|-----------|
|
|
199
|
+
| 100×100 | **0.12ms** | 1.9ms | 0.58ms |
|
|
200
|
+
| 500×500 | **2.3ms** | 37.9ms | 17.7ms |
|
|
201
|
+
| 1000×1000 | **9.6ms** | 167.7ms | 53.1ms |
|
|
202
|
+
| 5000×5000 | **1.0ms** | 25.7ms | 11.5ms |
|
|
203
|
+
| 10000×10000 | **2.3ms** | 58.6ms | 26.3ms |
|
|
204
|
+
| 50000×50000 | **20.6ms** | 369.4ms | - |
|
|
205
|
+
| 100000×100000 | **46.9ms** | 836.0ms | - |
|
|
206
|
+
|
|
207
|
+
## Memory Optimization
|
|
208
|
+
|
|
209
|
+
For large maps (>1000×1000), enable memory-efficient mode:
|
|
210
|
+
|
|
211
|
+
```javascript
|
|
212
|
+
const grid = new Grid({
|
|
213
|
+
col: 10000,
|
|
214
|
+
row: 10000,
|
|
215
|
+
useMemoryEfficientMode: true // Uses bitmap compression
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// Memory usage comparison:
|
|
219
|
+
// - Standard mode: ~1.4GB for 10000×10000
|
|
220
|
+
// - Memory-efficient mode: ~12MB for 10000×10000
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
For ultra-large maps (>10 billion nodes), WebAssembly automatically uses sparse HashMap implementation:
|
|
41
224
|
|
|
42
|
-
|
|
225
|
+
```javascript
|
|
226
|
+
// 100000×100000 map automatically uses sparse implementation
|
|
227
|
+
const grid = new Grid({ col: 100000, row: 100000 });
|
|
228
|
+
const astar = new Astar(grid, { prefer: 'wasm' });
|
|
229
|
+
// Automatically uses WebAssembly A* (Sparse) - only stores visited nodes
|
|
43
230
|
```
|
|
44
231
|
|
|
232
|
+
## Building from Source
|
|
233
|
+
|
|
234
|
+
### Prerequisites
|
|
235
|
+
|
|
236
|
+
- Rust (for WebAssembly compilation)
|
|
237
|
+
- wasm-pack
|
|
238
|
+
- Node.js 16+
|
|
239
|
+
|
|
240
|
+
### Build Commands
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
# Development build (faster compilation, includes debug info)
|
|
244
|
+
npm run build:dev
|
|
245
|
+
|
|
246
|
+
# Release build (optimized, smaller size)
|
|
247
|
+
npm run build:rel
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Testing
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
# Run performance tests
|
|
254
|
+
npm test
|
|
255
|
+
|
|
256
|
+
# Full test suite (requires more memory)
|
|
257
|
+
npm run test:full
|
|
258
|
+
|
|
259
|
+
# WebAssembly-specific tests
|
|
260
|
+
npm run test:wasm
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Browser Support
|
|
264
|
+
|
|
265
|
+
- Chrome/Edge: ✅ Full support
|
|
266
|
+
- Firefox: ✅ Full support
|
|
267
|
+
- Safari: ✅ Full support (iOS 11.3+)
|
|
268
|
+
- Node.js: ✅ Full support (v16+)
|
|
269
|
+
|
|
270
|
+
## License
|
|
271
|
+
|
|
272
|
+
MIT
|
|
273
|
+
|
|
274
|
+
## Related
|
|
275
|
+
|
|
276
|
+
- [A* Search Algorithm (Wikipedia)](https://en.wikipedia.org/wiki/A*_search_algorithm)
|
|
277
|
+
- [A* Pathfinding for Beginners](https://www.gamedev.net/articles/programming/artificial-intelligence/a-pathfinding-for-beginners-r2003/)
|
|
45
278
|
|
|
46
|
-
|
|
47
|
-
- [https://sbfkcel.github.io/fast-astar](https://sbfkcel.github.io/fast-astar)
|
|
279
|
+
## Contributing
|
|
48
280
|
|
|
49
|
-
|
|
50
|
-
- [wiki](http://wikipedia.moesalih.com/A*_search_algorithm)
|
|
51
|
-
- [achieve](https://www.gamedev.net/articles/programming/artificial-intelligence/a-pathfinding-for-beginners-r2003/)
|
|
281
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
52
282
|
|
|
283
|
+
## Changelog
|
|
53
284
|
|
|
54
|
-
|
|
55
|
-
|
|
285
|
+
### v0.1.0
|
|
286
|
+
- Initial release with WebAssembly support
|
|
287
|
+
- Multiple algorithm implementations (Ultra, Master, WASM)
|
|
288
|
+
- Automatic algorithm selection
|
|
289
|
+
- Memory-efficient mode for large maps
|
|
290
|
+
- Sparse implementation for ultra-large maps (100K×100K+)
|
|
291
|
+
- Animation support with step-by-step callbacks
|
package/astar.wasm
ADDED
|
Binary file
|
package/index.js
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
// 🚀 A* 算法最终整合版本 - 智能自适应入口
|
|
2
|
+
// 自动选择最优算法实现,支持所有环境
|
|
3
|
+
|
|
4
|
+
import Grid from './Grid.js';
|
|
5
|
+
import Astar from './Astar.js';
|
|
6
|
+
import { isNode, isBrowser, getEnvironmentInfo, checkCompatibility, getPerformanceNow } from './utils.js';
|
|
7
|
+
|
|
8
|
+
// 便捷创建函数
|
|
9
|
+
function createAstar(gridOptions = {}, astarOptions = {}) {
|
|
10
|
+
const grid = new Grid(gridOptions);
|
|
11
|
+
return new Astar(grid, astarOptions);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// 快速路径查找
|
|
15
|
+
function quickPath(gridSize, obstacles = [], start = [0, 0], end = null) {
|
|
16
|
+
// 输入验证
|
|
17
|
+
if (typeof gridSize !== 'number' && !Array.isArray(gridSize)) {
|
|
18
|
+
throw new Error('gridSize 必须是数字或数组 [width, height]');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (gridSize <= 0 || (Array.isArray(gridSize) && (gridSize[0] <= 0 || gridSize[1] <= 0))) {
|
|
22
|
+
throw new Error('网格大小必须大于0');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!Array.isArray(start) || start.length < 2) {
|
|
26
|
+
throw new Error('起点必须是包含至少2个元素的数组 [x, y]');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const size = Array.isArray(gridSize) ? gridSize : [gridSize, gridSize];
|
|
30
|
+
const grid = new Grid({ col: size[0], row: size[1] });
|
|
31
|
+
|
|
32
|
+
// 设置障碍物
|
|
33
|
+
if (obstacles.length > 0) {
|
|
34
|
+
if (!Array.isArray(obstacles)) {
|
|
35
|
+
throw new Error('障碍物必须是数组');
|
|
36
|
+
}
|
|
37
|
+
grid.setObstacles(obstacles);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 默认终点为右下角
|
|
41
|
+
const endPoint = end || [size[0] - 1, size[1] - 1];
|
|
42
|
+
|
|
43
|
+
if (!Array.isArray(endPoint) || endPoint.length < 2) {
|
|
44
|
+
throw new Error('终点必须是包含至少2个元素的数组 [x, y]');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const astar = new Astar(grid);
|
|
48
|
+
return astar.search(start, endPoint);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 批量路径查找
|
|
52
|
+
async function findMultiplePaths(gridOptions, pathRequests) {
|
|
53
|
+
// 输入验证
|
|
54
|
+
if (!gridOptions || (typeof gridOptions !== 'object' && typeof gridOptions !== 'number')) {
|
|
55
|
+
throw new Error('gridOptions 必须是对象或数字');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (!Array.isArray(pathRequests)) {
|
|
59
|
+
throw new Error('pathRequests 必须是数组');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (pathRequests.length === 0) {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const grid = new Grid(gridOptions);
|
|
67
|
+
const astar = new Astar(grid);
|
|
68
|
+
|
|
69
|
+
const results = [];
|
|
70
|
+
for (const request of pathRequests) {
|
|
71
|
+
try {
|
|
72
|
+
// 验证请求格式
|
|
73
|
+
if (!request || !Array.isArray(request.start) || !Array.isArray(request.end)) {
|
|
74
|
+
throw new Error('每个请求必须包含 start 和 end 数组');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const path = await astar.search(request.start, request.end, request.options || {});
|
|
78
|
+
results.push({
|
|
79
|
+
success: true,
|
|
80
|
+
path,
|
|
81
|
+
request
|
|
82
|
+
});
|
|
83
|
+
} catch (error) {
|
|
84
|
+
results.push({
|
|
85
|
+
success: false,
|
|
86
|
+
error: error.message,
|
|
87
|
+
request
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return results;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// 性能基准测试
|
|
96
|
+
function benchmark(gridSize = 100, iterations = 100) {
|
|
97
|
+
// 输入验证
|
|
98
|
+
if (typeof gridSize !== 'number' || gridSize <= 0) {
|
|
99
|
+
throw new Error('gridSize 必须是大于0的数字');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (typeof iterations !== 'number' || iterations <= 0) {
|
|
103
|
+
throw new Error('iterations 必须是大于0的数字');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (iterations > 10000) {
|
|
107
|
+
console.warn('⚠️ 迭代次数过大,可能会影响性能');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const grid = new Grid({ col: gridSize, row: gridSize });
|
|
111
|
+
const astar = new Astar(grid);
|
|
112
|
+
|
|
113
|
+
// 预热
|
|
114
|
+
for (let i = 0; i < 10; i++) {
|
|
115
|
+
astar.search([0, 0], [gridSize - 1, gridSize - 1]);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// 测试
|
|
119
|
+
const startTime = getPerformanceNow();
|
|
120
|
+
|
|
121
|
+
for (let i = 0; i < iterations; i++) {
|
|
122
|
+
astar.search([0, 0], [gridSize - 1, gridSize - 1]);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const endTime = getPerformanceNow();
|
|
126
|
+
const totalTime = endTime - startTime;
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
totalTime,
|
|
130
|
+
avgTime: totalTime / iterations,
|
|
131
|
+
throughput: iterations / (totalTime / 1000),
|
|
132
|
+
gridSize,
|
|
133
|
+
iterations
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// 预设配置
|
|
138
|
+
const presets = {
|
|
139
|
+
// 游戏开发预设
|
|
140
|
+
game: {
|
|
141
|
+
strategy: 'performance',
|
|
142
|
+
appType: 'game',
|
|
143
|
+
performance: 'high',
|
|
144
|
+
memory: 'moderate',
|
|
145
|
+
prefer: 'wasm'
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
// Web应用预设
|
|
149
|
+
web: {
|
|
150
|
+
strategy: 'auto',
|
|
151
|
+
appType: 'web',
|
|
152
|
+
performance: 'medium',
|
|
153
|
+
memory: 'moderate'
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
// 移动应用预设
|
|
157
|
+
mobile: {
|
|
158
|
+
strategy: 'memory',
|
|
159
|
+
appType: 'mobile',
|
|
160
|
+
performance: 'medium',
|
|
161
|
+
memory: 'strict',
|
|
162
|
+
avoid: 'wasm'
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
// 服务端预设
|
|
166
|
+
server: {
|
|
167
|
+
strategy: 'performance',
|
|
168
|
+
appType: 'server',
|
|
169
|
+
performance: 'extreme',
|
|
170
|
+
memory: 'relaxed',
|
|
171
|
+
prefer: 'wasm'
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
// 嵌入式预设
|
|
175
|
+
embedded: {
|
|
176
|
+
strategy: 'memory',
|
|
177
|
+
appType: 'embedded',
|
|
178
|
+
performance: 'low',
|
|
179
|
+
memory: 'strict',
|
|
180
|
+
avoid: 'wasm'
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// 预设工厂函数
|
|
185
|
+
function createPresetAstar(grid, presetName, customOptions = {}) {
|
|
186
|
+
const preset = presets[presetName];
|
|
187
|
+
if (!preset) {
|
|
188
|
+
throw new Error(`未知预设: ${presetName}. 可用预设: ${Object.keys(presets).join(', ')}`);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return new Astar(grid, { ...preset, ...customOptions });
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// 智能创建函数 - 根据网格大小自动选择最佳配置
|
|
195
|
+
function createSmartAstar(gridOptions, customOptions = {}) {
|
|
196
|
+
const grid = new Grid(gridOptions);
|
|
197
|
+
const gridSize = grid.col * grid.row;
|
|
198
|
+
|
|
199
|
+
let autoOptions = {};
|
|
200
|
+
|
|
201
|
+
// 根据网格大小自动选择策略
|
|
202
|
+
if (gridSize > 250000) {
|
|
203
|
+
autoOptions = { strategy: 'performance', prefer: 'wasm' };
|
|
204
|
+
} else if (gridSize > 50000) {
|
|
205
|
+
autoOptions = { strategy: 'performance', prefer: 'master' };
|
|
206
|
+
} else if (gridSize > 10000) {
|
|
207
|
+
autoOptions = { strategy: 'auto' };
|
|
208
|
+
} else {
|
|
209
|
+
autoOptions = { strategy: 'compatibility' };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return new Astar(grid, { ...autoOptions, ...customOptions });
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// 主要导出API
|
|
216
|
+
const AstarLib = {
|
|
217
|
+
// 核心类
|
|
218
|
+
Grid: Grid,
|
|
219
|
+
Astar: Astar,
|
|
220
|
+
|
|
221
|
+
// 工厂函数
|
|
222
|
+
create: createAstar,
|
|
223
|
+
createAstar,
|
|
224
|
+
createSmartAstar,
|
|
225
|
+
createPresetAstar,
|
|
226
|
+
|
|
227
|
+
// 便捷函数
|
|
228
|
+
quickPath,
|
|
229
|
+
findMultiplePaths,
|
|
230
|
+
|
|
231
|
+
// 工具函数
|
|
232
|
+
benchmark,
|
|
233
|
+
getEnvironmentInfo,
|
|
234
|
+
checkCompatibility,
|
|
235
|
+
|
|
236
|
+
// 预设配置
|
|
237
|
+
presets,
|
|
238
|
+
|
|
239
|
+
// 快速创建函数
|
|
240
|
+
createGameAstar: (grid, options = {}) => createPresetAstar(grid, 'game', options),
|
|
241
|
+
createWebAstar: (grid, options = {}) => createPresetAstar(grid, 'web', options),
|
|
242
|
+
createMobileAstar: (grid, options = {}) => createPresetAstar(grid, 'mobile', options),
|
|
243
|
+
createServerAstar: (grid, options = {}) => createPresetAstar(grid, 'server', options),
|
|
244
|
+
createEmbeddedAstar: (grid, options = {}) => createPresetAstar(grid, 'embedded', options),
|
|
245
|
+
|
|
246
|
+
// 版本信息
|
|
247
|
+
version: '2.0.0',
|
|
248
|
+
name: 'Smart A* Algorithm Library',
|
|
249
|
+
|
|
250
|
+
// 环境标识
|
|
251
|
+
isNode,
|
|
252
|
+
isBrowser
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
// 自动兼容性检查
|
|
256
|
+
const compatibility = checkCompatibility();
|
|
257
|
+
if (!compatibility.compatible) {
|
|
258
|
+
console.error('❌ 兼容性检查失败:', compatibility.issues);
|
|
259
|
+
|
|
260
|
+
// 在浏览器环境中,如果只是缺少一些API,不要抛出错误
|
|
261
|
+
if (isBrowser && compatibility.issues.length > 0) {
|
|
262
|
+
console.warn('⚠️ 浏览器环境兼容性问题,但将继续运行:', compatibility.issues);
|
|
263
|
+
} else {
|
|
264
|
+
throw new Error('环境不兼容: ' + compatibility.issues.join(', '));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (compatibility.warnings.length > 0 && typeof console !== 'undefined') {
|
|
269
|
+
console.warn('⚠️ 兼容性警告:', compatibility.warnings);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// 初始化日志
|
|
273
|
+
if (typeof console !== 'undefined' && console.log) {
|
|
274
|
+
console.log('🚀 Smart A* Algorithm Library v2.0.0 已加载');
|
|
275
|
+
console.log('📱 环境:', compatibility.environment.platform);
|
|
276
|
+
console.log('💾 内存:', compatibility.environment.memory);
|
|
277
|
+
console.log('🖥️ CPU核心:', compatibility.environment.cores);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// ES Module 导出
|
|
281
|
+
export default AstarLib;
|
|
282
|
+
export { Grid, Astar, createAstar, createSmartAstar, quickPath, benchmark, presets };
|
package/package.json
CHANGED
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fast-astar",
|
|
3
|
-
"
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "2.0.0",
|
|
4
5
|
"description": "fast-astar is an implementation of a* algorithm using javascript. Small and fast.",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
|
|
6
|
+
"files": [
|
|
7
|
+
"astar.wasm",
|
|
8
|
+
"wasm.js",
|
|
9
|
+
"wasm.d.ts",
|
|
10
|
+
"index.js",
|
|
11
|
+
"Grid.js",
|
|
12
|
+
"Astar.js"
|
|
13
|
+
],
|
|
14
|
+
"main": "index.js",
|
|
15
|
+
"types": "wasm.d.ts",
|
|
16
|
+
"sideEffects": [
|
|
17
|
+
"./snippets/*"
|
|
18
|
+
],
|
|
9
19
|
"repository": {
|
|
10
20
|
"type": "git",
|
|
11
21
|
"url": "git+https://github.com/sbfkcel/fast-astar.git"
|
|
12
22
|
},
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
],
|
|
22
|
-
"author": "sbfkcel@163.com",
|
|
23
|
-
"license": "MIT",
|
|
24
|
-
"bugs": {
|
|
25
|
-
"url": "https://github.com/sbfkcel/fast-astar/issues"
|
|
26
|
-
},
|
|
27
|
-
"homepage": "https://github.com/sbfkcel/fast-astar#readme"
|
|
28
|
-
}
|
|
23
|
+
"scripts": {
|
|
24
|
+
"test": "node tests/test.js",
|
|
25
|
+
"test:full": "node --max-old-space-size=8192 tests/test.js",
|
|
26
|
+
"test:wasm": "node tests/test_wasm.js",
|
|
27
|
+
"build:dev": "./scripts/build-dev.sh",
|
|
28
|
+
"build:rel": "./scripts/build-rel.sh"
|
|
29
|
+
}
|
|
30
|
+
}
|