From 8d4ebcfdd8057e4f0ac78c9bac6afece6a0cb1a2 Mon Sep 17 00:00:00 2001 From: walkpan Date: Fri, 13 Mar 2026 16:04:53 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E7=A7=BB=E5=8A=A8=E7=B3=BB=E7=BB=9F):=20?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=A4=9A=E7=BA=BF=E7=AB=99=E4=BD=8D=E5=92=8C?= =?UTF-8?q?=E9=98=B2=E9=87=8D=E5=8F=A0=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将移动边界配置从 min/max 改为 front/back 以支持双向移动逻辑 - 增加四条站位线(LINE1~LINE4)实现纵向分层站位 - 添加防重叠检测,防止同阵营单位位置冲突 - 调整游戏地平线高度和地图元素位置以适配新站位系统 - 禁用地图中多余的游戏对象以优化性能 --- assets/resources/game/map/map_rpg.prefab | 12 +-- assets/script/game/common/config/GameSet.ts | 2 +- assets/script/game/hero/MoveComp.ts | 90 +++++++++++++++++---- 3 files changed, 80 insertions(+), 24 deletions(-) diff --git a/assets/resources/game/map/map_rpg.prefab b/assets/resources/game/map/map_rpg.prefab index 8c33aa6f..ef5641d3 100644 --- a/assets/resources/game/map/map_rpg.prefab +++ b/assets/resources/game/map/map_rpg.prefab @@ -584,7 +584,7 @@ "_lpos": { "__type__": "cc.Vec3", "x": 0, - "y": -295.746, + "y": -245.746, "z": 0 }, "_lrot": { @@ -856,7 +856,7 @@ "_lpos": { "__type__": "cc.Vec3", "x": 0, - "y": -278.047, + "y": -228.047, "z": 0 }, "_lrot": { @@ -992,7 +992,7 @@ "_lpos": { "__type__": "cc.Vec3", "x": 0, - "y": -282.963, + "y": -232.963, "z": 0 }, "_lrot": { @@ -1128,7 +1128,7 @@ "_lpos": { "__type__": "cc.Vec3", "x": 0, - "y": -580.208, + "y": -530.208, "z": 0 }, "_lrot": { @@ -1264,7 +1264,7 @@ "_lpos": { "__type__": "cc.Vec3", "x": 0, - "y": -320, + "y": -270, "z": 0 }, "_lrot": { @@ -1433,7 +1433,7 @@ "__id__": 62 } ], - "_active": true, + "_active": false, "_components": [ { "__id__": 70 diff --git a/assets/script/game/common/config/GameSet.ts b/assets/script/game/common/config/GameSet.ts index 6e076716..3d8b1784 100644 --- a/assets/script/game/common/config/GameSet.ts +++ b/assets/script/game/common/config/GameSet.ts @@ -18,7 +18,7 @@ export enum BoxSet { LETF_END = -420, RIGHT_END = 420, //游戏地平线 - GAME_LINE = -215, + GAME_LINE = -165 //攻击距离 } diff --git a/assets/script/game/hero/MoveComp.ts b/assets/script/game/hero/MoveComp.ts index 0ffacaf5..9b4812e7 100644 --- a/assets/script/game/hero/MoveComp.ts +++ b/assets/script/game/hero/MoveComp.ts @@ -28,26 +28,35 @@ export class MoveComp extends ecs.Comp { } interface MoveFacConfig { - moveMinX: number; - moveMaxX: number; - retreatMinX: number; - retreatMaxX: number; + moveFrontX: number; + moveBackX: number; + retreatFrontX: number; + retreatBackX: number; } @ecs.register('MoveSystem') export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate { + private readonly ySlots = [ + { offset: 0, lineName: "LINE2" }, + { offset: 5, lineName: "LINE1" }, + { offset: -5, lineName: "LINE3" }, + { offset: -10, lineName: "LINE4" }, + ]; + private readonly samePointXThreshold = 12; + private readonly samePointYThreshold = 3; + private readonly facConfigs: Record = { [FacSet.HERO]: { - moveMinX: -320, - moveMaxX: 320, - retreatMinX: -300, - retreatMaxX: 300, + moveFrontX: 320, + moveBackX: -320, + retreatFrontX: 300, + retreatBackX: -300, }, [FacSet.MON]: { - moveMinX: -320, - moveMaxX: 320, - retreatMinX: -300, - retreatMaxX: 300, + moveFrontX: -320, + moveBackX: 320, + retreatFrontX: -300, + retreatBackX: 300, } }; @@ -72,6 +81,7 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate return; } + this.applyLineAndY(e, view, move, view.node.position.x); this.updateRenderOrder(e); const nearestEnemy = this.findNearestEnemy(e); if (nearestEnemy) { @@ -177,8 +187,10 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate private performRetreat(view: HeroViewComp, move: MoveComp, model: HeroAttrsComp, currentX: number) { const cfg = this.facConfigs[model.fac] || this.facConfigs[FacSet.HERO]; + const retreatMinX = Math.min(cfg.retreatBackX, cfg.retreatFrontX); + const retreatMaxX = Math.max(cfg.retreatBackX, cfg.retreatFrontX); const safeRetreatX = currentX - move.direction * 50; - if (safeRetreatX >= cfg.retreatMinX && safeRetreatX <= cfg.retreatMaxX) { + if (safeRetreatX >= retreatMinX && safeRetreatX <= retreatMaxX) { const retreatSpeed = (model.speed / 3) * 0.8; this.moveEntity(view, -move.direction, retreatSpeed); model.is_atking = false; @@ -233,23 +245,67 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate const move = view.ent.get(MoveComp); if (!model || !move) return; const cfg = this.facConfigs[model.fac] || this.facConfigs[FacSet.HERO]; + const moveMinX = Math.min(cfg.moveBackX, cfg.moveFrontX); + const moveMaxX = Math.max(cfg.moveBackX, cfg.moveFrontX); const currentX = view.node.position.x; const delta = speed * this.dt * direction; let newX = view.node.position.x + delta; - if (currentX < cfg.moveMinX && direction < 0) { + if (currentX < moveMinX && direction < 0) { view.status_change("idle"); return; } - if (currentX > cfg.moveMaxX && direction > 0) { + if (currentX > moveMaxX && direction > 0) { view.status_change("idle"); return; } - newX = Math.max(cfg.moveMinX, Math.min(cfg.moveMaxX, newX)); - const newY = view.node.position.y; + newX = Math.max(moveMinX, Math.min(moveMaxX, newX)); + const newY = this.applyLineAndY(view.ent, view, move, newX); view.node.setPosition(newX, newY, 0); view.status_change("move"); } + private applyLineAndY(entity: ecs.Entity, view: HeroViewComp, move: MoveComp, x: number): number { + if (!view.node) return 0; + const baseY = move.baseY; + for (const slot of this.ySlots) { + const y = baseY + slot.offset; + if (!this.hasTeammateAtPoint(entity, x, y)) { + const lineNode = this.getLineNode(slot.lineName); + if (lineNode && view.node.parent !== lineNode) { + view.node.parent = lineNode; + } + return y; + } + } + const fallback = this.ySlots[0]; + const fallbackNode = this.getLineNode(fallback.lineName); + if (fallbackNode && view.node.parent !== fallbackNode) { + view.node.parent = fallbackNode; + } + return baseY + fallback.offset; + } + + private getLineNode(lineName: string) { + const scene = smc.map?.MapView?.scene; + const layerRoot = scene?.entityLayer?.node; + if (!layerRoot) return null; + return layerRoot.getChildByName(lineName); + } + + private hasTeammateAtPoint(self: ecs.Entity, x: number, y: number): boolean { + const myAttrs = self.get(HeroAttrsComp); + if (!myAttrs) return false; + return ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp)).some(e => { + if (e === self) return false; + const attrs = e.get(HeroAttrsComp); + if (!attrs || attrs.fac !== myAttrs.fac || attrs.is_dead) return false; + const view = e.get(HeroViewComp); + if (!view || !view.node) return false; + return Math.abs(view.node.position.x - x) <= this.samePointXThreshold + && Math.abs(view.node.position.y - y) <= this.samePointYThreshold; + }); + } + private resolveCombatRange(model: HeroAttrsComp, defaultMin: number, defaultMax: number): [number, number] { const minRange = model.getCachedMinSkillDistance(); const maxRange = model.getCachedMaxSkillDistance();