fix(移动): 优化盟友间距计算以允许目标重叠
引入 allyOverlapSpacingX 和 displacementReleaseX 常量,在特定条件下允许盟友目标位置重叠。 当盟友已被显著位移且自身需要前进时,使用更小的间距,避免不必要的移动阻塞。
This commit is contained in:
@@ -38,6 +38,8 @@ interface MoveFacConfig {
|
||||
export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||
private readonly meleeAttackRange = 52;
|
||||
private readonly allySpacingX = 40;
|
||||
private readonly allyOverlapSpacingX = 8;
|
||||
private readonly displacementReleaseX = 24;
|
||||
private readonly minSpacingY = 30;
|
||||
private readonly renderSortInterval = 0.05;
|
||||
private renderSortElapsed = 0;
|
||||
@@ -170,14 +172,14 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
const maxRange = this.meleeAttackRange;
|
||||
|
||||
move.direction = enemyX > currentX ? 1 : -1;
|
||||
move.targetX = enemyX - move.direction * maxRange;
|
||||
|
||||
if (dist <= maxRange) {
|
||||
view.status_change("idle");
|
||||
model.is_atking = true;
|
||||
} else {
|
||||
const speed = model.speed / 3;
|
||||
const stopAtX = enemyX - move.direction * maxRange;
|
||||
this.moveEntity(view, move.direction, speed, stopAtX);
|
||||
this.moveEntity(view, move.direction, speed, move.targetX);
|
||||
model.is_atking = true;
|
||||
}
|
||||
}
|
||||
@@ -289,30 +291,52 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
|
||||
private clampXByAllies(self: ecs.Entity, fac: number, baseY: number, currentX: number, proposedX: number, direction: number): number {
|
||||
const selfAttrs = self.get(HeroAttrsComp);
|
||||
const selfMove = self.get(MoveComp);
|
||||
const selfPriority = selfAttrs ? this.getCombatPriority(selfAttrs) : 0;
|
||||
let nearestAheadX = Infinity;
|
||||
let nearestBehindX = -Infinity;
|
||||
let clampedX = proposedX;
|
||||
ecs.query(this.getHeroMoveMatcher()).forEach(e => {
|
||||
if (e === self) return;
|
||||
const attrs = e.get(HeroAttrsComp);
|
||||
const view = e.get(HeroViewComp);
|
||||
const allyMove = e.get(MoveComp);
|
||||
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 allyPriority = this.getCombatPriority(attrs);
|
||||
if (allyPriority < selfPriority) return;
|
||||
const x = view.node.position.x;
|
||||
if (x > currentX && x < nearestAheadX) nearestAheadX = x;
|
||||
if (x < currentX && x > nearestBehindX) nearestBehindX = x;
|
||||
const spacing = this.resolveAllySpacing(selfAttrs, selfMove, currentX, direction, allyMove, x, allyPriority, selfPriority);
|
||||
if (direction > 0 && x > currentX) {
|
||||
clampedX = Math.min(clampedX, x - spacing);
|
||||
}
|
||||
if (direction < 0 && x < currentX) {
|
||||
clampedX = Math.max(clampedX, x + spacing);
|
||||
}
|
||||
});
|
||||
return clampedX;
|
||||
}
|
||||
|
||||
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 resolveAllySpacing(
|
||||
selfAttrs: HeroAttrsComp | null,
|
||||
selfMove: MoveComp | null,
|
||||
currentX: number,
|
||||
direction: number,
|
||||
allyMove: MoveComp | null,
|
||||
allyX: number,
|
||||
allyPriority: number,
|
||||
selfPriority: number
|
||||
): number {
|
||||
if (!selfAttrs || !selfMove || !allyMove) return this.allySpacingX;
|
||||
if (allyPriority !== selfPriority) return this.allySpacingX;
|
||||
const selfTargetX = selfMove.targetX;
|
||||
const allyTargetX = allyMove.targetX;
|
||||
const selfHasTarget = Math.abs(selfTargetX) > 0.01;
|
||||
const allyHasTarget = Math.abs(allyTargetX) > 0.01;
|
||||
if (!selfHasTarget || !allyHasTarget) return this.allySpacingX;
|
||||
const allyDisplaced = Math.abs(allyX - allyTargetX) >= this.displacementReleaseX;
|
||||
const selfNeedAdvance = direction > 0 ? selfTargetX > currentX + 2 : selfTargetX < currentX - 2;
|
||||
if (allyDisplaced && selfNeedAdvance) return this.allyOverlapSpacingX;
|
||||
return this.allySpacingX;
|
||||
}
|
||||
|
||||
private getCombatPriority(model: HeroAttrsComp): number {
|
||||
|
||||
Reference in New Issue
Block a user