docs: 为游戏地图模块添加详细的代码注释

为游戏地图模块的脚本文件添加全面的注释,说明每个组件的职责、关键设计、依赖关系和使用方式。注释覆盖了英雄信息面板、技能卡槽位管理器、排行榜弹窗、卡牌控制器、背景滚动组件等核心功能模块,提高了代码的可读性和维护性。

同时修复了英雄预制体的激活状态和技能效果预制体的尺寸参数。
This commit is contained in:
walkpan
2026-04-07 19:00:30 +08:00
parent 9a1d517aa9
commit e880613f8f
21 changed files with 1840 additions and 242 deletions

View File

@@ -1,3 +1,30 @@
/**
* @file MissionHeroComp.ts
* @description 英雄召唤与合成管理组件(逻辑层 + 视图层)
*
* 职责:
* 1. 处理 **英雄召唤**:接收 CallHero 事件 → 通过串行队列执行召唤。
* 2. 处理 **英雄合成**:检测同 UUID 同等级英雄是否达到合成条件 →
* 执行合成动画 → 销毁素材 → 生成高一级英雄。
* 3. 支持 **链式合成**:合成完成后自动检测更高等级是否也满足合成条件。
* 4. 管理英雄的出生点和掉落动画。
*
* 关键设计:
* - summon_queue + processSummonQueue() 确保召唤请求 **串行处理**
* 避免同帧并发导致合成判断错误。
* - handleSingleSummon() 在每次召唤后检测是否触发合成。
* - mergeGroupHeroes() 执行完整合成流程:
* 聚合属性 → 向出生点汇聚动画 → 爆点特效 → 生成高级英雄。
* - merge_need_count 控制合成所需数量2 合 1 或 3 合 1
* - merge_max_lv 控制合成上限等级。
*
* 依赖:
* - Herohero/Hero.ts—— 英雄 ECS 实体类
* - HeroAttrsComp —— 英雄属性组件
* - HeroInfo / HeroPos / HTypeheroSet—— 英雄静态配置
* - FightSet —— 战斗常量MERGE_NEED / MERGE_MAX
* - oneCom —— 一次性特效组件(控制爆点特效生命周期)
*/
import { _decorator, instantiate, Prefab, v3, Vec3 } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
@@ -12,16 +39,26 @@ import { FacSet, FightSet } from "../common/config/GameSet";
import { oneCom } from "../skill/oncend";
const { ccclass } = _decorator;
/** 视图层对象 */
/**
* MissionHeroCompComp —— 英雄召唤与合成管理器
*
* 管理英雄的召唤请求队列、出生动画和合成系统。
* 合成支持 2 合 1 或 3 合 1且可链式合成至上限等级。
*/
@ccclass('MissionHeroCompComp')
@ecs.register('MissionHeroComp', false)
export class MissionHeroCompComp extends CCComp {
/** 英雄出生时的掉落高度,用于表现从空中落地 */
// ======================== 常量 ========================
/** 英雄出生时的掉落高度(从空中落到地面的像素差) */
private static readonly HERO_DROP_HEIGHT = 260
/** 近战起始出生 X */
/** 近战英雄起始出生 X 坐标 */
private static readonly HERO_SPAWN_START_MELEE_X = -280
/** 远程(含中程)起始出生 X */
/** 远程(含中程)英雄起始出生 X 坐标 */
private static readonly HERO_SPAWN_START_RANGED_X = -280
// ======================== 运行时属性 ========================
/** 预留计时器 */
timer:Timer=new Timer(2)
/** 预留状态:友方是否全部死亡 */
@@ -30,29 +67,32 @@ export class MissionHeroCompComp extends CCComp {
current_hero_uuid:number=0
/** 当前英雄数量缓存 */
current_hero_num:number=-1
/** 合成规则:2 合 1 或 3 合 1 */
/** 合成规则:需要几个同级英雄才能合成2 或 3 */
merge_need_count:number=FightSet.MERGE_NEED
/** 允许合成的最高等级 */
/** 允许合成的最高等级(合成产物不超过此等级) */
merge_max_lv:number=FightSet.MERGE_MAX
/** 是否正在执行一次合成流程 */
/** 是否正在执行一次合成流程(防止并发) */
is_merging:boolean=false
/** 是否正在消费召唤队列防止并发处理 */
/** 是否正在消费召唤队列防止并发 */
is_processing_queue:boolean=false
/** 召唤请求队列保证召唤与合成行 */
/** 召唤请求队列保证召唤与合成按顺序串行执行 */
summon_queue:{ uuid: number; hero_lv: number; pool_lv: number }[]=[]
/** 预留英雄列表 */
heros:any=[]
// ======================== 生命周期 ========================
onLoad(){
/** 节点事件监听 */
// 注册节点事件
this.on(GameEvent.FightReady,this.fight_ready,this)
this.on(GameEvent.Zhaohuan,this.zhao_huan,this)
this.on(GameEvent.MissionEnd,this.clear_heros,this)
/** 全局消息监听 */
// 注册全局消息
oops.message.on(GameEvent.CallHero,this.call_hero,this)
}
onDestroy(){
/** 清理监听,避免节点销毁后仍响应消息 */
// 清理全部监听
oops.message.off(GameEvent.CallHero,this.call_hero,this)
oops.message.off(GameEvent.FightReady,this.fight_ready,this)
oops.message.off(GameEvent.Zhaohuan,this.zhao_huan,this)
@@ -60,29 +100,35 @@ export class MissionHeroCompComp extends CCComp {
}
start() {
// this.test_call()
}
/** 关卡结束时,清理全部存活英雄 */
// ======================== 事件处理 ========================
/** 关卡结束时清理全部存活英雄 ECS 实体 */
clear_heros(){
const heroes = this.getAliveHeroes();
for (let i = 0; i < heroes.length; i++) {
heroes[i].destroy();
}
}
/** 战斗准备阶段重置出战英雄计数 */
/** 战斗准备阶段:重置出战英雄计数 */
fight_ready(){
smc.vmdata.mission_data.hero_num=0
}
// protected update(dt: number): void {
// }
/** 预留:召唤事件扩展入口 */
private zhao_huan(event: string, args: any){
}
/** 召唤请求入口:归一化参数并进入串行队列 */
/**
* 召唤请求入口:
* 从事件参数中提取 uuid / hero_lv / pool_lv放入串行队列。
*
* @param event 事件名
* @param args { uuid, hero_lv, pool_lv }
*/
private async call_hero(event: string, args: any){
const payload = args ?? event;
const uuid = Number(payload?.uuid ?? 1001);
@@ -91,7 +137,19 @@ export class MissionHeroCompComp extends CCComp {
this.summon_queue.push({ uuid, hero_lv, pool_lv });
this.processSummonQueue();
}
/** 添加英雄:固定出生点上方生成,再落至落点 */
// ======================== 英雄生成 ========================
/**
* 生成一个英雄 ECS 实体:
* - 计算出生点(空中)和落点(地面)。
* - 调用 hero.load() 初始化并播放掉落动画。
*
* @param uuid 英雄 UUID
* @param hero_lv 英雄等级
* @param pool_lv 卡池等级
* @returns 创建的 Hero 实体
*/
private addHero(uuid:number=1001,hero_lv:number=1, pool_lv:number=1) {
console.log("addHero uuid:",uuid)
let hero = ecs.getEntity<Hero>(Hero);
@@ -102,6 +160,13 @@ export class MissionHeroCompComp extends CCComp {
return hero;
}
/**
* 计算英雄落点位置。
* Y 坐标来自 HeroPos 配置X 坐标根据英雄类型(近战/远程)决定。
*
* @param uuid 英雄 UUID
* @returns 落点 Vec3
*/
private resolveHeroLandingPos(uuid: number): Vec3 {
const hero_pos = 0;
const baseY = HeroPos[hero_pos].pos.y;
@@ -109,6 +174,11 @@ export class MissionHeroCompComp extends CCComp {
return v3(startX, baseY, 0);
}
/**
* 根据英雄类型决定出生 X 坐标。
* @param uuid 英雄 UUID
* @returns 近战 or 远程的起始 X
*/
private resolveSpawnStartX(uuid: number): number {
const heroType = HeroInfo[uuid]?.type;
return heroType === HType.Melee
@@ -116,7 +186,16 @@ export class MissionHeroCompComp extends CCComp {
: MissionHeroCompComp.HERO_SPAWN_START_RANGED_X;
}
/** 添加合成后的新英雄,并覆盖为聚合后的属性 */
/**
* 生成合成后的高级英雄,并覆盖为聚合后的属性。
*
* @param uuid 英雄 UUID
* @param hero_lv 合成后等级
* @param pool_lv 卡池等级
* @param ap 聚合后攻击力
* @param hp_max 聚合后最大生命值
* @returns 实际生成的英雄等级
*/
private addMergedHero(uuid:number, hero_lv:number, pool_lv:number, ap:number, hp_max:number): number {
const hero = this.addHero(uuid, hero_lv, pool_lv);
const model = hero.get(HeroAttrsComp);
@@ -128,7 +207,9 @@ export class MissionHeroCompComp extends CCComp {
return model.lv;
}
/** 获取当前全部存活友方英雄 */
// ======================== 英雄查询 ========================
/** 获取当前全部存活友方英雄 ECS 实体列表 */
private getAliveHeroes(): Hero[] {
const heroes: Hero[] = [];
ecs.query(ecs.allOf(HeroAttrsComp)).forEach((entity: ecs.Entity) => {
@@ -141,7 +222,15 @@ export class MissionHeroCompComp extends CCComp {
return heroes;
}
/** 挑选可参与本次合成的英雄组 */
/**
* 从存活英雄中挑选可参与本次合成的英雄组。
*
* @param aliveHeroes 存活英雄列表
* @param uuid 目标英雄 UUID
* @param hero_lv 目标等级
* @param needCount 合成需要数量
* @returns 匹配的英雄数组(长度 = needCount 或不足)
*/
private pickMergeHeroes(aliveHeroes: Hero[], uuid: number, hero_lv: number, needCount: number = 3): Hero[] {
const mergeHeroes: Hero[] = [];
for (let i = 0; i < aliveHeroes.length; i++) {
@@ -155,7 +244,7 @@ export class MissionHeroCompComp extends CCComp {
return mergeHeroes;
}
/** 统计满足同 uuid、同等级的可合成英雄数量 */
/** 统计满足同 UUID 同等级的可合成英雄数量 */
private countMergeHeroes(aliveHeroes: Hero[], uuid: number, hero_lv: number): number {
let count = 0;
for (let i = 0; i < aliveHeroes.length; i++) {
@@ -168,17 +257,32 @@ export class MissionHeroCompComp extends CCComp {
return count;
}
/** 读取当前合成需要数量,仅支持 2 或 3 */
// ======================== 合成规则 ========================
/**
* 读取合成所需数量(仅支持 2 或 3
* 由 FightSet.MERGE_NEED 配置。
*/
private getMergeNeedCount(): number {
return this.merge_need_count === 2 ? 2 : 3;
}
/** 判断该等级是否还能继续向上合成 */
/**
* 判断该等级是否还能继续向上合成。
* @param hero_lv 当前等级
* @returns true = 可以合成(未达上限)
*/
private canMergeLevel(hero_lv: number): boolean {
return hero_lv < Math.max(1, this.merge_max_lv);
}
/** 串行消费召唤队列,避免同帧并发触发多次合成导致状态错乱 */
// ======================== 召唤队列 ========================
/**
* 串行消费召唤队列:
* 使用 is_processing_queue 标志防止同帧多次调用。
* 逐个取出队列中的请求并处理。
*/
private async processSummonQueue() {
if (this.is_processing_queue) return;
this.is_processing_queue = true;
@@ -193,7 +297,16 @@ export class MissionHeroCompComp extends CCComp {
}
}
/** 处理单次召唤:先生成,再检测是否触发合成,再尝试链式合成 */
/**
* 处理单次召唤:
* 1. 生成英雄。
* 2. 检测是否满足合成条件。
* 3. 满足则执行合成 + 链式合成。
*
* @param uuid 英雄 UUID
* @param hero_lv 英雄等级
* @param pool_lv 卡池等级
*/
private async handleSingleSummon(uuid: number, hero_lv: number, pool_lv: number = 1) {
this.addHero(uuid, hero_lv, pool_lv);
if (!this.canMergeLevel(hero_lv)) return;
@@ -210,7 +323,15 @@ export class MissionHeroCompComp extends CCComp {
}
}
/** 将一组合成素材向出生点汇聚并销毁,全部完成后返回 */
// ======================== 合成动画 ========================
/**
* 将一组合成素材英雄向出生点汇聚并销毁。
* 所有素材动画完成后 Promise resolve。
*
* @param mergeHeroes 合成素材英雄数组
* @param spawnPos 汇聚目标位置
*/
private mergeDestroyAtBirth(mergeHeroes: Hero[], spawnPos: Vec3): Promise<void> {
return new Promise((resolve) => {
let doneCount = 0;
@@ -231,7 +352,12 @@ export class MissionHeroCompComp extends CCComp {
});
}
/** 播放合成爆点特效,使用 oneCom 控制特效生命周期 */
/**
* 播放合成爆点特效(使用 oneCom 控制生命周期)。
* 延迟 0.4 秒后 resolve。
*
* @param worldPos 特效播放位置
*/
private playMergeBoomFx(worldPos: Vec3): Promise<void> {
return new Promise((resolve) => {
const scene = smc.map?.MapView?.scene;
@@ -257,8 +383,21 @@ export class MissionHeroCompComp extends CCComp {
});
}
/** 执行一次完整合成:聚合属性、销毁素材、播放特效、生成高一级英雄 */
/**
* 执行一次完整合成流程:
* 1. 聚合素材的 AP 和 HP。
* 2. 将素材向出生点汇聚并销毁。
* 3. 播放爆点特效。
* 4. 生成高一级英雄(属性为聚合值)。
*
* @param mergeHeroes 合成素材
* @param uuid 英雄 UUID
* @param hero_lv 素材等级
* @param pool_lv 卡池等级
* @returns 合成产物的实际等级
*/
private async mergeGroupHeroes(mergeHeroes: Hero[], uuid: number, hero_lv: number, pool_lv: number): Promise<number> {
// 聚合属性
let sumAp = 0;
let sumHpMax = 0;
for (let i = 0; i < mergeHeroes.length; i++) {
@@ -267,14 +406,23 @@ export class MissionHeroCompComp extends CCComp {
sumAp += model.ap;
sumHpMax += model.hp_max;
}
// 计算出生点
const landingPos = this.resolveHeroLandingPos(uuid);
const spawnPos:Vec3 = v3(landingPos.x, landingPos.y + MissionHeroCompComp.HERO_DROP_HEIGHT, 0);
// 汇聚 → 特效 → 生成
await this.mergeDestroyAtBirth(mergeHeroes, spawnPos);
await this.playMergeBoomFx(spawnPos);
return this.addMergedHero(uuid, Math.min(this.merge_max_lv, hero_lv + 1), pool_lv, sumAp, sumHpMax);
}
/** 链式合成:当前等级合成完成后,继续尝试更高等级,直到条件不满足 */
/**
* 链式合成:合成完成后继续检测更高等级是否也满足条件。
* 最多循环 20 次作为安全上限。
*
* @param uuid 英雄 UUID
* @param startLv 起始检测等级
* @param pool_lv 卡池等级
*/
private async tryChainMerge(uuid: number, startLv: number, pool_lv: number) {
let checkLv = Math.max(1, startLv);
const needCount = this.getMergeNeedCount();
@@ -300,7 +448,7 @@ export class MissionHeroCompComp extends CCComp {
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件时触发,用于自定义释放逻辑 */
/** ECS 组件移除时触发(当前不销毁节点,保留引用) */
reset() {
// this.node.destroy();
}