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