refactor(hero): 统一英雄编队与出生点的位置配置

1. 将硬编码的英雄排位置常量迁移至FightSet枚举,实现单一数据源
2. 重构英雄编队逻辑,按职业优先级分为三排站位
3. 调整召唤队列,按职业优先级排序后串行登场
This commit is contained in:
pan
2026-08-20 11:11:44 +08:00
parent 8039b052d2
commit 1523aab402
3 changed files with 90 additions and 47 deletions

View File

@@ -14,7 +14,7 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ec
import { HeroViewComp } from "./HeroViewComp";
import { HeroAttrsComp } from "./HeroAttrsComp";
import { smc } from "../common/SingletonModuleComp";
import { BoxSet, FacSet } from "../common/config/GameSet";
import { BoxSet, FacSet, FightSet } from "../common/config/GameSet";
import { HRole } from "../common/config/heroSet";
import { Node } from "cc";
@@ -54,9 +54,16 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
// ======================== 英雄编队排队 ========================
/** 编队锚点:最右迎敌位(与 MissionHeroComp.HERO_ROW_FRONT 的 x 对齐,避免循环依赖在此独立定义) */
private static readonly QUEUE_ANCHOR_X = -200;
/** 编队槽位默认间隔(像素);人数超出边界宽度时自动压缩间距 */
/**
* 三排编队锚点 x单一数据源取自 FightSet与 MissionHeroComp 的 HERO_ROW_FRONT/MID/BACK 一致):
* 前排 / 中排 / 后排。准备阶段按"职业优先级名次"映射到三排(见 rebuildHeroQueueSlots
*/
private static readonly ROW_FRONT_X = FightSet.HERO_ROW_FRONT_X;
private static readonly ROW_MID_X = FightSet.HERO_ROW_MID_X;
private static readonly ROW_BACK_X = FightSet.HERO_ROW_BACK_X;
/** 编队排队允许向左扩展到的最小 x后排自锚点向左排开时的下限 */
private static readonly QUEUE_LEFT_LIMIT = FightSet.HERO_ROW_BACK_X - 120;
/** 编队槽位默认间隔(像素);后排人数过多时自动压缩间距 */
private static readonly QUEUE_SPACING = 30;
/** 编队槽位重算节流间隔(秒):召唤/死亡后最多延迟一次重算 */
private readonly queueRebuildInterval = 0.1;
@@ -155,8 +162,9 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
/**
* 英雄编队排队:
* 按 坦克→战士→刺客→射手→法师→辅助 的职业优先级(即 HRole 枚举值升序),
* 从最右迎敌位QUEUE_ANCHOR_X向左依次排开防止同类型英雄落点重叠
* 按 坦克→战士→刺客→射手→法师→辅助 的职业优先级(即 HRole 枚举值升序)做全局排序
* 再按名次映射三排锚点:第 1 名→前排、第 2 名→中排、第 3 名起→后排向左排开
* 槽位互不重叠,保证一个位置仅一个英雄。
*
* @param entity 当前英雄实体
* @param model 英雄属性(取 speed / role
@@ -181,8 +189,10 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
const dir = targetX > selfX ? 1 : -1;
move.direction = dir;
view.scale = dir;
/** 编队排队允许突破战斗左边界LETF_END=后排锚点),扩展至 QUEUE_LEFT_LIMIT */
const queueClamp = (x: number): number => Math.max(MoveSystem.QUEUE_LEFT_LIMIT, x);
const delta = (model.speed / 3) * this.dt * dir;
const newX = this.clampByFacBoundary(selfX + delta, model.fac);
const newX = queueClamp(selfX + delta);
if (Math.abs(newX - selfX) >= 0.01) {
view.node.setPosition(newX, view.node.position.y, 0);
view.status_change("move");
@@ -204,8 +214,14 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
/**
* 重算编队槽位:
* 收集全部存活英雄,按 职业优先级 → 出生序 → eid 稳定排序
* 从 QUEUE_ANCHOR_X 向左按间隔分配;人数过多时压缩间距,保证不越过 LETF_END。
* 收集全部存活英雄,按 职业优先级HRole 升序)→ 出生序 → eid 稳定排序得到全局名次 rank
* 再按名次映射三排锚点:
* - rank 0最优先→ 前排 ROW_FRONT_X
* - rank 1 → 中排 ROW_MID_X
* - rank ≥ 2 → 后排,自 ROW_BACK_X 起按 (rank-1) 个间隔向左依次排开
* 效果:高优先级职业永远占据更靠前的排;当更高优先级英雄插入时,低优先级英雄自动向后让位
* (如 近战+射手+近战 → 两近战分占前/中排,射手被挤到后排)。
* 后排人数过多时压缩间距,下限不越过 QUEUE_LEFT_LIMIT。
*/
private rebuildHeroQueueSlots(): void {
const heroes: { eid: number; role: number; spawnOrder: number }[] = [];
@@ -223,15 +239,25 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
(a.eid - b.eid)
);
const count = heroes.length;
const maxWidth = MoveSystem.QUEUE_ANCHOR_X - BoxSet.LETF_END;
const spacing = count > 1
? Math.min(MoveSystem.QUEUE_SPACING, maxWidth / (count - 1))
: 0;
/** 后排人数 = 总名次从 rank2 起的数量,用于预压缩间距 */
const backCount = Math.max(0, heroes.length - 2);
const backMaxWidth = MoveSystem.ROW_BACK_X - MoveSystem.QUEUE_LEFT_LIMIT;
const backSpacing = backCount > 1
? Math.min(MoveSystem.QUEUE_SPACING, backMaxWidth / (backCount - 1))
: MoveSystem.QUEUE_SPACING;
this.queueSlots.length = 0;
for (let i = 0; i < count; i++) {
this.queueSlots.push({ eid: heroes[i].eid, targetX: MoveSystem.QUEUE_ANCHOR_X - i * spacing });
for (let rank = 0; rank < heroes.length; rank++) {
let targetX: number;
if (rank === 0) {
targetX = MoveSystem.ROW_FRONT_X;
} else if (rank === 1) {
targetX = MoveSystem.ROW_MID_X;
} else {
/** 后排rank2 在锚点rank3 起向左排开 */
targetX = MoveSystem.ROW_BACK_X - (rank - 2) * backSpacing;
}
this.queueSlots.push({ eid: heroes[rank].eid, targetX });
}
}