diff --git a/assets/script/game/hero/MoveComp.ts b/assets/script/game/hero/MoveComp.ts index aed73e01..271d95ed 100644 --- a/assets/script/game/hero/MoveComp.ts +++ b/assets/script/game/hero/MoveComp.ts @@ -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; }); }