From 1754e0d408d4d198010018cc0cc79c51b9169959 Mon Sep 17 00:00:00 2001 From: panFD Date: Sun, 13 Sep 2026 11:50:05 +0800 Subject: [PATCH] =?UTF-8?q?fix(map,hero):=20=E5=AE=8C=E5=96=84=E6=80=AA?= =?UTF-8?q?=E7=89=A9=E5=85=A5=E5=9C=BA=E6=8E=92=E9=98=9F=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 给怪物刷出生成方法添加rank参数,用于计算出生位置 2. 新增怪物入场归位逻辑,替换原有的闲置状态处理 3. 更新注释描述,修正准备阶段怪物行为说明 --- assets/script/game/hero/MoveComp.ts | 40 ++++++++++++++++++++++-- assets/script/game/map/MissionMonComp.ts | 12 ++++--- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/assets/script/game/hero/MoveComp.ts b/assets/script/game/hero/MoveComp.ts index 757dad05..624e3c09 100644 --- a/assets/script/game/hero/MoveComp.ts +++ b/assets/script/game/hero/MoveComp.ts @@ -134,14 +134,14 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate } } - /** 准备阶段:不推进不索敌;英雄向编队槽位排队移动,怪物原地待命 */ + /** 准备阶段:不推进不索敌;英雄向编队槽位排队移动,怪物向出生目标位归位 */ if (!smc.mission.in_fight) { this.clearCombatTarget(model); model.is_atking = false; if (model.fac === FacSet.HERO) { this.processHeroQueue(e, model, move, view); } else { - view.status_change("idle"); + this.processMonQueue(move, view, model); } return; } @@ -220,6 +220,42 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate } } + // ======================== 怪物入场归位(准备阶段) ======================== + + /** + * 怪物入场归位:从屏幕右边缘向 move.targetX(目标排锚点)移动,到位后 idle。 + * 与英雄 processHeroQueue 对称,但怪物目标位在出生时由 MissionMonComp 一次性写入 targetX,无需动态重算槽位。 + * 到位容差 2px,与英雄一致。 + */ + private processMonQueue(move: MoveComp, view: HeroViewComp, model: HeroAttrsComp): void { + const targetX = move.targetX; + const selfX = view.node.position.x; + + if (Math.abs(targetX - selfX) <= 2) { + if (Math.abs(selfX - targetX) > 0.01) { + view.node.setPosition(targetX, view.node.position.y, 0); + } + view.scale = -1; + view.status_change("idle"); + return; + } + + const dir = targetX > selfX ? 1 : -1; + move.direction = dir; + view.scale = dir; + const dist = Math.abs(targetX - selfX); + const speed = Math.max(model.speed / 3, dist / MoveSystem.QUEUE_ARRIVE_TIME); + const delta = speed * this.dt * dir; + let newX = selfX + delta; + if ((dir > 0 && newX > targetX) || (dir < 0 && newX < targetX)) { + newX = targetX; + } + if (Math.abs(newX - selfX) >= 0.01) { + view.node.setPosition(newX, view.node.position.y, 0); + view.status_change("move"); + } + } + /** 查询当前英雄的编队槽位目标 X(无槽位返回 null) */ private resolveHeroQueueTargetX(entity: ecs.Entity): number | null { const now = Date.now() / 1000; diff --git a/assets/script/game/map/MissionMonComp.ts b/assets/script/game/map/MissionMonComp.ts index e0e5fdab..0ca4fd6f 100644 --- a/assets/script/game/map/MissionMonComp.ts +++ b/assets/script/game/map/MissionMonComp.ts @@ -172,14 +172,15 @@ export class MissionMonCompComp extends CCComp { }); // 立即刷出 batch=0 的怪物(处理 delay 字段) - for (const mon of immediate) { + for (let i = 0; i < immediate.length; i++) { + const mon = immediate[i]; if (mon.delay && mon.delay > 0) { // Boss 延迟刷出 this.scheduleOnce(() => { - this.spawnMonster(mon); + this.spawnMonster(mon, i); }, mon.delay); } else { - this.spawnMonster(mon); + this.spawnMonster(mon, i); } } @@ -202,14 +203,15 @@ export class MissionMonCompComp extends CCComp { /** * 刷出单个怪物(统一入口) * @param monData 怪物生成数据 + * @param rank 编队优先级排序后的名次(0=前排,1=中排,≥2=后排);缺省回退到 spawnIndex */ - private spawnMonster(monData: GeneratedMonster) { + private spawnMonster(monData: GeneratedMonster, rank?: number) { const posIndex = monData.spawnIndex; let mon = ecs.getEntity(Monster); let scale = -1; const basePos = MissionMonCompComp.MON_POSITIONS[posIndex % MissionMonCompComp.MON_POSITIONS.length]; - const landingX = this.resolveSpawnX(posIndex); + const landingX = this.resolveSpawnX(rank ?? posIndex); const landingY = basePos.y; // 出生点位于目标排右侧屏幕外(dropToY=landingY 无下落),落地即 moving=true 从右跑入 const spawnPos: Vec3 = v3(landingX + MissionMonCompComp.MON_SPAWN_OFFSET_X, landingY, 0);