@esengine/pathfinding 13.3.0 → 13.3.2
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/dist/{FlowController-Dc3nuLq5.d.ts → FlowController-BztOzQsW.d.ts} +36 -6
- package/dist/{chunk-NIKT3PQC.js → chunk-ZYGBA7VK.js} +29 -9
- package/dist/{chunk-NIKT3PQC.js.map → chunk-ZYGBA7VK.js.map} +1 -1
- package/dist/ecs.d.ts +27 -2
- package/dist/ecs.js +153 -2
- package/dist/ecs.js.map +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/ecs.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Component, EntitySystem, Entity } from '@esengine/ecs-framework';
|
|
2
|
-
import { S as IVector2, V as IPathPlanner, a7 as IFlowController, a0 as ILocalAvoidance, a2 as ICollisionResolver, _ as IObstacleData } from './FlowController-
|
|
3
|
-
export { ap as CollisionResolverAdapter, ab as DEFAULT_FLOW_CONTROLLER_CONFIG, ao as DEFAULT_ORCA_PARAMS, ar as FlowController, ag as GridPathfinderAdapter, a3 as ICongestionZone, a4 as IFlowAgentData, a5 as IFlowControlResult, a6 as IFlowControllerConfig, au as IGridPathfinderAdapterConfig, av as IIncrementalGridPathPlannerConfig, at as IORCAParams, ak as IncrementalGridPathPlannerAdapter, ae as NavMeshPathPlannerAdapter, am as ORCALocalAvoidanceAdapter, aa as PassPermission, ah as createAStarPlanner, aq as createDefaultCollisionResolver, as as createFlowController, aj as createHPAPlanner, al as createIncrementalAStarPlanner, ai as createJPSPlanner, af as createNavMeshPathPlanner, an as createORCAAvoidance } from './FlowController-
|
|
2
|
+
import { S as IVector2, V as IPathPlanner, a7 as IFlowController, a0 as ILocalAvoidance, a2 as ICollisionResolver, _ as IObstacleData } from './FlowController-BztOzQsW.js';
|
|
3
|
+
export { ap as CollisionResolverAdapter, ab as DEFAULT_FLOW_CONTROLLER_CONFIG, ao as DEFAULT_ORCA_PARAMS, ar as FlowController, ag as GridPathfinderAdapter, a3 as ICongestionZone, a4 as IFlowAgentData, a5 as IFlowControlResult, a6 as IFlowControllerConfig, au as IGridPathfinderAdapterConfig, av as IIncrementalGridPathPlannerConfig, at as IORCAParams, ak as IncrementalGridPathPlannerAdapter, ae as NavMeshPathPlannerAdapter, am as ORCALocalAvoidanceAdapter, aa as PassPermission, ah as createAStarPlanner, aq as createDefaultCollisionResolver, as as createFlowController, aj as createHPAPlanner, al as createIncrementalAStarPlanner, ai as createJPSPlanner, af as createNavMeshPathPlanner, an as createORCAAvoidance } from './FlowController-BztOzQsW.js';
|
|
4
4
|
import './CollisionResolver-CSgWsegP.js';
|
|
5
5
|
import '@esengine/ecs-framework-math';
|
|
6
6
|
|
|
@@ -609,6 +609,31 @@ declare class NavigationSystem extends EntitySystem {
|
|
|
609
609
|
* @en Resolve agent-agent collisions
|
|
610
610
|
*/
|
|
611
611
|
private resolveAgentCollisions;
|
|
612
|
+
/**
|
|
613
|
+
* @zh 查找有效的修正向量(不会进入障碍物)
|
|
614
|
+
* @en Find valid correction vector (won't enter obstacles)
|
|
615
|
+
*/
|
|
616
|
+
private findValidCorrection;
|
|
617
|
+
/**
|
|
618
|
+
* @zh 查找滑动位置(当目标位置不可行走时)
|
|
619
|
+
* @en Find slide position (when target position is not walkable)
|
|
620
|
+
*
|
|
621
|
+
* @zh 尝试只沿 X 轴或 Y 轴移动,实现沿墙滑动效果
|
|
622
|
+
* @en Try moving only along X or Y axis, achieving wall sliding effect
|
|
623
|
+
*/
|
|
624
|
+
private findSlidePosition;
|
|
625
|
+
/**
|
|
626
|
+
* @zh 检查位置是否可行走(考虑代理半径)
|
|
627
|
+
* @en Check if position is walkable (considering agent radius)
|
|
628
|
+
*
|
|
629
|
+
* @zh 检查代理边界框的4个角点和中心点,确保整个代理都在可行走区域
|
|
630
|
+
* @en Check 4 corners and center of agent bounding box, ensure entire agent is in walkable area
|
|
631
|
+
*
|
|
632
|
+
* @param position - @zh 位置 @en Position
|
|
633
|
+
* @param radius - @zh 代理半径 @en Agent radius
|
|
634
|
+
* @param tolerance - @zh 容差比例 (0-1),用于允许轻微重叠 @en Tolerance ratio (0-1), allows slight overlap
|
|
635
|
+
*/
|
|
636
|
+
private isPositionWalkable;
|
|
612
637
|
}
|
|
613
638
|
|
|
614
639
|
/**
|
package/dist/ecs.js
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
createNavMeshPathPlanner,
|
|
19
19
|
createORCAAvoidance,
|
|
20
20
|
isIncrementalPlanner
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-ZYGBA7VK.js";
|
|
22
22
|
import "./chunk-YKA3PWU3.js";
|
|
23
23
|
import "./chunk-3VEX32JO.js";
|
|
24
24
|
import {
|
|
@@ -1020,6 +1020,18 @@ var _NavigationSystem = class _NavigationSystem extends EntitySystem {
|
|
|
1020
1020
|
y: 0
|
|
1021
1021
|
};
|
|
1022
1022
|
}
|
|
1023
|
+
if (agent.state === NavigationState.Unreachable || agent.state === NavigationState.Arrived) {
|
|
1024
|
+
return {
|
|
1025
|
+
x: 0,
|
|
1026
|
+
y: 0
|
|
1027
|
+
};
|
|
1028
|
+
}
|
|
1029
|
+
if (agent.path.length === 0 && !agent.isComputingPath) {
|
|
1030
|
+
return {
|
|
1031
|
+
x: 0,
|
|
1032
|
+
y: 0
|
|
1033
|
+
};
|
|
1034
|
+
}
|
|
1023
1035
|
let targetX, targetY;
|
|
1024
1036
|
let isLastWaypoint = false;
|
|
1025
1037
|
if (agent.currentWaypointIndex < agent.path.length) {
|
|
@@ -1027,10 +1039,15 @@ var _NavigationSystem = class _NavigationSystem extends EntitySystem {
|
|
|
1027
1039
|
targetX = waypoint.x;
|
|
1028
1040
|
targetY = waypoint.y;
|
|
1029
1041
|
isLastWaypoint = agent.currentWaypointIndex === agent.path.length - 1;
|
|
1030
|
-
} else {
|
|
1042
|
+
} else if (agent.path.length > 0) {
|
|
1031
1043
|
targetX = agent.destination.x;
|
|
1032
1044
|
targetY = agent.destination.y;
|
|
1033
1045
|
isLastWaypoint = true;
|
|
1046
|
+
} else {
|
|
1047
|
+
return {
|
|
1048
|
+
x: 0,
|
|
1049
|
+
y: 0
|
|
1050
|
+
};
|
|
1034
1051
|
}
|
|
1035
1052
|
const dx = targetX - agent.position.x;
|
|
1036
1053
|
const dy = targetY - agent.position.y;
|
|
@@ -1090,6 +1107,22 @@ var _NavigationSystem = class _NavigationSystem extends EntitySystem {
|
|
|
1090
1107
|
if (this.config.enableCollisionResolution && this.collisionResolver && allObstacles.length > 0) {
|
|
1091
1108
|
newPosition = this.collisionResolver.resolveCollision(newPosition, agent.radius, allObstacles);
|
|
1092
1109
|
}
|
|
1110
|
+
if (!this.isPositionWalkable(newPosition, agent.radius)) {
|
|
1111
|
+
const slidPosition = this.findSlidePosition(agent.position, newPosition, agent.radius);
|
|
1112
|
+
if (slidPosition) {
|
|
1113
|
+
newPosition = slidPosition;
|
|
1114
|
+
agent.velocity = {
|
|
1115
|
+
x: (newPosition.x - agent.position.x) / deltaTime,
|
|
1116
|
+
y: (newPosition.y - agent.position.y) / deltaTime
|
|
1117
|
+
};
|
|
1118
|
+
} else {
|
|
1119
|
+
agent.velocity = {
|
|
1120
|
+
x: 0,
|
|
1121
|
+
y: 0
|
|
1122
|
+
};
|
|
1123
|
+
return;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1093
1126
|
agent.position = newPosition;
|
|
1094
1127
|
this.checkArrival(agent);
|
|
1095
1128
|
}
|
|
@@ -1182,12 +1215,130 @@ var _NavigationSystem = class _NavigationSystem extends EntitySystem {
|
|
|
1182
1215
|
x: agent.position.x + correction.x,
|
|
1183
1216
|
y: agent.position.y + correction.y
|
|
1184
1217
|
};
|
|
1218
|
+
if (!this.isPositionWalkable(newPosition, agent.radius, 1)) {
|
|
1219
|
+
const partialCorrection = this.findValidCorrection(agent.position, correction, agent.radius);
|
|
1220
|
+
if (partialCorrection) {
|
|
1221
|
+
newPosition = {
|
|
1222
|
+
x: agent.position.x + partialCorrection.x,
|
|
1223
|
+
y: agent.position.y + partialCorrection.y
|
|
1224
|
+
};
|
|
1225
|
+
} else {
|
|
1226
|
+
continue;
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1185
1229
|
if (allObstacles.length > 0) {
|
|
1186
1230
|
newPosition = this.collisionResolver.resolveCollision(newPosition, agent.radius, allObstacles);
|
|
1187
1231
|
}
|
|
1232
|
+
if (!this.isPositionWalkable(newPosition, agent.radius, 1)) {
|
|
1233
|
+
continue;
|
|
1234
|
+
}
|
|
1188
1235
|
agent.position = newPosition;
|
|
1189
1236
|
}
|
|
1190
1237
|
}
|
|
1238
|
+
/**
|
|
1239
|
+
* @zh 查找有效的修正向量(不会进入障碍物)
|
|
1240
|
+
* @en Find valid correction vector (won't enter obstacles)
|
|
1241
|
+
*/
|
|
1242
|
+
findValidCorrection(currentPos, correction, radius = 0) {
|
|
1243
|
+
if (!this.pathPlanner) return correction;
|
|
1244
|
+
const steps = [
|
|
1245
|
+
0.75,
|
|
1246
|
+
0.5,
|
|
1247
|
+
0.25,
|
|
1248
|
+
0.1
|
|
1249
|
+
];
|
|
1250
|
+
for (const scale of steps) {
|
|
1251
|
+
const testPos = {
|
|
1252
|
+
x: currentPos.x + correction.x * scale,
|
|
1253
|
+
y: currentPos.y + correction.y * scale
|
|
1254
|
+
};
|
|
1255
|
+
if (this.isPositionWalkable(testPos, radius, 1)) {
|
|
1256
|
+
return {
|
|
1257
|
+
x: correction.x * scale,
|
|
1258
|
+
y: correction.y * scale
|
|
1259
|
+
};
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
return null;
|
|
1263
|
+
}
|
|
1264
|
+
/**
|
|
1265
|
+
* @zh 查找滑动位置(当目标位置不可行走时)
|
|
1266
|
+
* @en Find slide position (when target position is not walkable)
|
|
1267
|
+
*
|
|
1268
|
+
* @zh 尝试只沿 X 轴或 Y 轴移动,实现沿墙滑动效果
|
|
1269
|
+
* @en Try moving only along X or Y axis, achieving wall sliding effect
|
|
1270
|
+
*/
|
|
1271
|
+
findSlidePosition(currentPos, targetPos, radius) {
|
|
1272
|
+
const dx = targetPos.x - currentPos.x;
|
|
1273
|
+
const dy = targetPos.y - currentPos.y;
|
|
1274
|
+
const xOnlyPos = {
|
|
1275
|
+
x: targetPos.x,
|
|
1276
|
+
y: currentPos.y
|
|
1277
|
+
};
|
|
1278
|
+
if (Math.abs(dx) > 1e-3 && this.isPositionWalkable(xOnlyPos, radius)) {
|
|
1279
|
+
return xOnlyPos;
|
|
1280
|
+
}
|
|
1281
|
+
const yOnlyPos = {
|
|
1282
|
+
x: currentPos.x,
|
|
1283
|
+
y: targetPos.y
|
|
1284
|
+
};
|
|
1285
|
+
if (Math.abs(dy) > 1e-3 && this.isPositionWalkable(yOnlyPos, radius)) {
|
|
1286
|
+
return yOnlyPos;
|
|
1287
|
+
}
|
|
1288
|
+
const halfPos = {
|
|
1289
|
+
x: currentPos.x + dx * 0.5,
|
|
1290
|
+
y: currentPos.y + dy * 0.5
|
|
1291
|
+
};
|
|
1292
|
+
if (this.isPositionWalkable(halfPos, radius)) {
|
|
1293
|
+
return halfPos;
|
|
1294
|
+
}
|
|
1295
|
+
return null;
|
|
1296
|
+
}
|
|
1297
|
+
/**
|
|
1298
|
+
* @zh 检查位置是否可行走(考虑代理半径)
|
|
1299
|
+
* @en Check if position is walkable (considering agent radius)
|
|
1300
|
+
*
|
|
1301
|
+
* @zh 检查代理边界框的4个角点和中心点,确保整个代理都在可行走区域
|
|
1302
|
+
* @en Check 4 corners and center of agent bounding box, ensure entire agent is in walkable area
|
|
1303
|
+
*
|
|
1304
|
+
* @param position - @zh 位置 @en Position
|
|
1305
|
+
* @param radius - @zh 代理半径 @en Agent radius
|
|
1306
|
+
* @param tolerance - @zh 容差比例 (0-1),用于允许轻微重叠 @en Tolerance ratio (0-1), allows slight overlap
|
|
1307
|
+
*/
|
|
1308
|
+
isPositionWalkable(position, radius = 0, tolerance = 0.8) {
|
|
1309
|
+
if (!this.pathPlanner) return true;
|
|
1310
|
+
if (!this.pathPlanner.isWalkable(position)) {
|
|
1311
|
+
return false;
|
|
1312
|
+
}
|
|
1313
|
+
if (radius <= 0) {
|
|
1314
|
+
return true;
|
|
1315
|
+
}
|
|
1316
|
+
const checkRadius = radius * tolerance;
|
|
1317
|
+
const corners = [
|
|
1318
|
+
{
|
|
1319
|
+
x: position.x - checkRadius,
|
|
1320
|
+
y: position.y - checkRadius
|
|
1321
|
+
},
|
|
1322
|
+
{
|
|
1323
|
+
x: position.x + checkRadius,
|
|
1324
|
+
y: position.y - checkRadius
|
|
1325
|
+
},
|
|
1326
|
+
{
|
|
1327
|
+
x: position.x - checkRadius,
|
|
1328
|
+
y: position.y + checkRadius
|
|
1329
|
+
},
|
|
1330
|
+
{
|
|
1331
|
+
x: position.x + checkRadius,
|
|
1332
|
+
y: position.y + checkRadius
|
|
1333
|
+
}
|
|
1334
|
+
];
|
|
1335
|
+
for (const corner of corners) {
|
|
1336
|
+
if (!this.pathPlanner.isWalkable(corner)) {
|
|
1337
|
+
return false;
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
return true;
|
|
1341
|
+
}
|
|
1191
1342
|
};
|
|
1192
1343
|
__name(_NavigationSystem, "NavigationSystem");
|
|
1193
1344
|
var NavigationSystem = _NavigationSystem;
|