fix(移动系统): 修正近战攻击距离和友军间距逻辑
- 将 `minSpacingX` 拆分为 `meleeAttackRange` 和 `allySpacingX`,明确区分攻击范围和友军间距 - 在 `moveEntity` 方法中添加 `stopAtX` 参数,确保英雄在攻击范围内停止移动 - 新增 `clampXByAllies` 方法,防止友军单位在移动时相互重叠 - 更新 `hasAnyActorTooClose` 方法使用新的 `allySpacingX` 常量
This commit is contained in:
@@ -37,7 +37,8 @@ interface MoveFacConfig {
|
||||
|
||||
@ecs.register('MoveSystem')
|
||||
export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||
private readonly minSpacingX = 50;
|
||||
private readonly meleeAttackRange = 52;
|
||||
private readonly allySpacingX = 40;
|
||||
private readonly minSpacingY = 30;
|
||||
private readonly renderSortInterval = 0.05;
|
||||
private renderSortElapsed = 0;
|
||||
@@ -124,7 +125,7 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
const currentX = view.node.position.x;
|
||||
const enemyX = enemy.node.position.x;
|
||||
const dist = Math.abs(currentX - enemyX);
|
||||
const maxRange = this.minSpacingX;
|
||||
const maxRange = this.meleeAttackRange;
|
||||
|
||||
move.direction = enemyX > currentX ? 1 : -1;
|
||||
|
||||
@@ -133,7 +134,8 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
model.is_atking = true;
|
||||
} else {
|
||||
const speed = model.speed / 3;
|
||||
this.moveEntity(view, move.direction, speed);
|
||||
const stopAtX = enemyX - move.direction * maxRange;
|
||||
this.moveEntity(view, move.direction, speed, stopAtX);
|
||||
model.is_atking = true;
|
||||
}
|
||||
}
|
||||
@@ -233,7 +235,7 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
return 0;
|
||||
}
|
||||
|
||||
private moveEntity(view: HeroViewComp, direction: number, speed: number) {
|
||||
private moveEntity(view: HeroViewComp, direction: number, speed: number, stopAtX?: number) {
|
||||
const model = view.ent.get(HeroAttrsComp);
|
||||
const move = view.ent.get(MoveComp);
|
||||
if (!model || !move) return;
|
||||
@@ -252,10 +254,42 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
return;
|
||||
}
|
||||
newX = Math.max(moveMinX, Math.min(moveMaxX, newX));
|
||||
if (stopAtX !== undefined) {
|
||||
newX = direction > 0 ? Math.min(newX, stopAtX) : Math.max(newX, stopAtX);
|
||||
}
|
||||
newX = this.clampXByAllies(view.ent, model.fac, move.baseY, currentX, newX, direction);
|
||||
if (Math.abs(newX - currentX) < 0.01) {
|
||||
view.status_change("idle");
|
||||
return;
|
||||
}
|
||||
view.node.setPosition(newX, move.baseY, 0);
|
||||
view.status_change("move");
|
||||
}
|
||||
|
||||
private clampXByAllies(self: ecs.Entity, fac: number, baseY: number, currentX: number, proposedX: number, direction: number): number {
|
||||
let nearestAheadX = Infinity;
|
||||
let nearestBehindX = -Infinity;
|
||||
ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp, MoveComp)).forEach(e => {
|
||||
if (e === self) return;
|
||||
const attrs = e.get(HeroAttrsComp);
|
||||
const view = e.get(HeroViewComp);
|
||||
if (!attrs || !view?.node || attrs.is_dead) return;
|
||||
if (attrs.fac !== fac) return;
|
||||
if (Math.abs(view.node.position.y - baseY) >= this.minSpacingY) return;
|
||||
const x = view.node.position.x;
|
||||
if (x > currentX && x < nearestAheadX) nearestAheadX = x;
|
||||
if (x < currentX && x > nearestBehindX) nearestBehindX = x;
|
||||
});
|
||||
|
||||
if (direction > 0 && nearestAheadX !== Infinity) {
|
||||
return Math.min(proposedX, nearestAheadX - this.allySpacingX);
|
||||
}
|
||||
if (direction < 0 && nearestBehindX !== -Infinity) {
|
||||
return Math.max(proposedX, nearestBehindX + this.allySpacingX);
|
||||
}
|
||||
return proposedX;
|
||||
}
|
||||
|
||||
private hasAnyActorTooClose(self: ecs.Entity, x: number, y: number): boolean {
|
||||
const myAttrs = self.get(HeroAttrsComp);
|
||||
if (!myAttrs) return false;
|
||||
@@ -266,7 +300,7 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
if (attrs.fac !== myAttrs.fac) return false;
|
||||
const view = e.get(HeroViewComp);
|
||||
if (!view || !view.node) return false;
|
||||
return Math.abs(view.node.position.x - x) < this.minSpacingX
|
||||
return Math.abs(view.node.position.x - x) < this.allySpacingX
|
||||
&& Math.abs(view.node.position.y - y) < this.minSpacingY;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user