From 08af676c84566a1934fd704c7fc6ba46da2aea2d Mon Sep 17 00:00:00 2001 From: panw Date: Wed, 18 Mar 2026 09:22:46 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E7=A7=BB=E5=8A=A8):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=9B=9F=E5=8F=8B=E9=97=B4=E8=B7=9D=E8=AE=A1=E7=AE=97=E4=BB=A5?= =?UTF-8?q?=E5=85=81=E8=AE=B8=E7=9B=AE=E6=A0=87=E9=87=8D=E5=8F=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 引入 allyOverlapSpacingX 和 displacementReleaseX 常量,在特定条件下允许盟友目标位置重叠。 当盟友已被显著位移且自身需要前进时,使用更小的间距,避免不必要的移动阻塞。 --- assets/script/game/hero/MoveComp.ts | 50 +++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/assets/script/game/hero/MoveComp.ts b/assets/script/game/hero/MoveComp.ts index 8ca2331b..3769dcff 100644 --- a/assets/script/game/hero/MoveComp.ts +++ b/assets/script/game/hero/MoveComp.ts @@ -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 {