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