docs: 为游戏地图模块添加详细的代码注释
为游戏地图模块的脚本文件添加全面的注释,说明每个组件的职责、关键设计、依赖关系和使用方式。注释覆盖了英雄信息面板、技能卡槽位管理器、排行榜弹窗、卡牌控制器、背景滚动组件等核心功能模块,提高了代码的可读性和维护性。 同时修复了英雄预制体的激活状态和技能效果预制体的尺寸参数。
This commit is contained in:
@@ -1,3 +1,24 @@
|
||||
/**
|
||||
* @file IBoxComp.ts
|
||||
* @description 英雄信息弹窗组件(IBox,UI 视图层)
|
||||
*
|
||||
* 职责:
|
||||
* 1. 作为全局弹窗,展示某个英雄的 **详细技能信息**。
|
||||
* 2. 通过 onAdded(args) 接收英雄 UUID、等级和运行时技能数据。
|
||||
* 3. 自动计算技能行数并动态调整弹窗背景高度和名称位置。
|
||||
* 4. 点击弹窗任意区域关闭自身。
|
||||
*
|
||||
* 关键设计:
|
||||
* - Line1~Line5 为预设的 5 行技能节点,按需显示/隐藏。
|
||||
* - 每行包含技能名、等级、CD、描述文本和类型图标(近战/远程/辅助)。
|
||||
* - 背景高度 = baseHeight + (行数 - 1) × extraLineHeight。
|
||||
* - 若传入 args.skills(运行时技能),优先使用;否则回退到英雄静态配置。
|
||||
*
|
||||
* 依赖:
|
||||
* - HeroInfo(heroSet)—— 英雄静态配置
|
||||
* - SkillSet / IType(SkillSet)—— 技能静态配置
|
||||
* - UIID —— 在 oops.gui 系统中注册的弹窗 ID
|
||||
*/
|
||||
import { _decorator, Label, Node, NodeEventType, UITransform } from "cc";
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||
@@ -6,9 +27,16 @@ import { IType, SkillSet } from "../common/config/SkillSet";
|
||||
import { oops } from "db://oops-framework/core/Oops";
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/**
|
||||
* IBoxComp —— 英雄信息弹窗视图组件
|
||||
*
|
||||
* 通过 oops.gui.open(UIID.IBox, { heroUuid, heroLv, skills? }) 打开。
|
||||
* 展示英雄技能列表,支持最多 5 行。
|
||||
*/
|
||||
@ccclass('IBoxComp')
|
||||
@ecs.register('IBoxComp', false)
|
||||
export class IBoxComp extends CCComp {
|
||||
// ======================== 编辑器绑定节点(5 行技能) ========================
|
||||
@property(Node)
|
||||
Line1: Node = null!
|
||||
@property(Node)
|
||||
@@ -19,11 +47,23 @@ export class IBoxComp extends CCComp {
|
||||
Line4: Node = null!
|
||||
@property(Node)
|
||||
Line5: Node = null!
|
||||
|
||||
// ======================== 布局常量 ========================
|
||||
/** 弹窗背景基础高度(只有 1 行技能时的高度) */
|
||||
private readonly baseHeight: number = 100;
|
||||
/** 每增加一行技能,背景增加的高度 */
|
||||
private readonly extraLineHeight: number = 50;
|
||||
/** 英雄名称标签的基准 Y 坐标 */
|
||||
private readonly nameBaseY: number = 50;
|
||||
/** 每增加一行技能,名称标签额外上移的 Y 偏移 */
|
||||
private readonly nameExtraLineOffsetY: number = 25;
|
||||
|
||||
/**
|
||||
* ECS 实体挂载回调:接收外部传入的英雄参数并渲染。
|
||||
* @param args.heroUuid 英雄 UUID
|
||||
* @param args.heroLv 英雄当前等级
|
||||
* @param args.skills (可选)运行时技能数据,若无则使用英雄静态配置
|
||||
*/
|
||||
onAdded(args: {
|
||||
heroUuid?: number;
|
||||
heroLv?: number;
|
||||
@@ -32,18 +72,32 @@ export class IBoxComp extends CCComp {
|
||||
this.renderHeroInfo(args);
|
||||
}
|
||||
|
||||
/** 绑定点击关闭事件 */
|
||||
onLoad() {
|
||||
this.node.on(NodeEventType.TOUCH_END, this.onTapClose, this);
|
||||
}
|
||||
|
||||
/** 解绑点击事件 */
|
||||
onDestroy() {
|
||||
this.node.off(NodeEventType.TOUCH_END, this.onTapClose, this);
|
||||
}
|
||||
|
||||
/** ECS 组件移除时销毁节点 */
|
||||
reset() {
|
||||
this.node.destroy();
|
||||
}
|
||||
|
||||
// ======================== 渲染逻辑 ========================
|
||||
|
||||
/**
|
||||
* 主渲染方法:解析英雄数据并填充技能行。
|
||||
*
|
||||
* 流程:
|
||||
* 1. 从 args 中取英雄 UUID 和等级。
|
||||
* 2. 优先使用运行时技能数据(args.skills),否则回退英雄静态配置。
|
||||
* 3. 将每个技能映射为 { text, iType },过滤无效项。
|
||||
* 4. 调用 applyLineData 渲染到 Line1~Line5。
|
||||
*/
|
||||
private renderHeroInfo(args: {
|
||||
heroUuid?: number;
|
||||
heroLv?: number;
|
||||
@@ -58,13 +112,18 @@ export class IBoxComp extends CCComp {
|
||||
return;
|
||||
}
|
||||
this.setHeroName(hero.name);
|
||||
|
||||
// 运行时技能 vs 静态配置
|
||||
const runtimeSkills = args?.skills ? Object.values(args.skills) : [];
|
||||
const sourceSkills = runtimeSkills.length > 0 ? runtimeSkills : Object.values(hero.skills ?? {});
|
||||
|
||||
// 将每个技能转换为显示数据
|
||||
const lineData = sourceSkills.map(skill => {
|
||||
const skillId = Math.floor(skill?.uuid ?? 0);
|
||||
if (!skillId) return null;
|
||||
const config = SkillSet[skillId];
|
||||
if (!config) return null;
|
||||
// 运行时技能直接使用其等级;静态配置的技能等级需叠加英雄等级修正
|
||||
const runtimeLv = runtimeSkills.length > 0 ? Math.max(0, Math.floor(skill.lv ?? 0)) : Math.max(0, Math.floor((skill.lv ?? 1) + heroLv - 2));
|
||||
const cd = Number(skill?.cd ?? 0);
|
||||
return {
|
||||
@@ -72,9 +131,18 @@ export class IBoxComp extends CCComp {
|
||||
iType: config.IType
|
||||
};
|
||||
}).filter(item => !!item) as Array<{ text: string; iType: IType }>;
|
||||
|
||||
this.applyLineData(lineData.length > 0 ? lineData : [{ text: "暂无技能信息" }]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将技能数据应用到 Line1~Line5:
|
||||
* 1. 按顺序填充文本和类型图标。
|
||||
* 2. 超出的行隐藏。
|
||||
* 3. 根据显示行数调整弹窗高度和名称位置。
|
||||
*
|
||||
* @param skillLines 技能行数据数组
|
||||
*/
|
||||
private applyLineData(skillLines: Array<{ text: string; iType?: IType }>) {
|
||||
const lines = [this.Line1, this.Line2, this.Line3, this.Line4, this.Line5];
|
||||
const showCount = Math.max(1, Math.min(lines.length, skillLines.length));
|
||||
@@ -86,16 +154,24 @@ export class IBoxComp extends CCComp {
|
||||
if (!active) continue;
|
||||
const data = skillLines[i];
|
||||
const text = data?.text ?? "";
|
||||
// 查找技能文本节点并设置内容
|
||||
const noteNode = line.getChildByName("note");
|
||||
const label = noteNode?.getComponent(Label) || noteNode?.getComponentInChildren(Label) || line.getComponentInChildren(Label);
|
||||
if (label) label.string = text;
|
||||
// 更新类型图标
|
||||
this.updateLineTypeIcon(line, data?.iType);
|
||||
}
|
||||
// 动态调整弹窗背景高度
|
||||
const targetHeight = this.baseHeight + Math.max(0, showCount - 1) * this.extraLineHeight;
|
||||
this.updateIBoxHeight(targetHeight);
|
||||
// 动态调整名称位置
|
||||
this.updateNamePosition(showCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置弹窗背景 Bg 节点的高度
|
||||
* @param height 目标高度
|
||||
*/
|
||||
private updateIBoxHeight(height: number) {
|
||||
const bgNode = this.node.getChildByName("Bg");
|
||||
const bgTransform = bgNode?.getComponent(UITransform);
|
||||
@@ -104,6 +180,10 @@ export class IBoxComp extends CCComp {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置英雄名称标签
|
||||
* @param name 英雄名称
|
||||
*/
|
||||
private setHeroName(name: string) {
|
||||
const bgNode = this.node.getChildByName("Bg");
|
||||
const nameNode = bgNode?.getChildByName("name");
|
||||
@@ -114,6 +194,12 @@ export class IBoxComp extends CCComp {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据显示行数调整名称节点的 Y 坐标。
|
||||
* 行数越多,名称越往上移,保持视觉居中。
|
||||
*
|
||||
* @param showCount 当前显示的技能行数
|
||||
*/
|
||||
private updateNamePosition(showCount: number) {
|
||||
const bgNode = this.node.getChildByName("Bg");
|
||||
const nameNode = bgNode?.getChildByName("name");
|
||||
@@ -123,6 +209,11 @@ export class IBoxComp extends CCComp {
|
||||
nameNode.setPosition(current.x, targetY, current.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新技能行的类型图标(互斥显示)。
|
||||
* @param line 技能行节点
|
||||
* @param iType 技能类型(近战 / 远程 / 辅助)
|
||||
*/
|
||||
private updateLineTypeIcon(line: Node, iType?: IType) {
|
||||
const meleeNode = line.getChildByName("Melee");
|
||||
const remoteNode = line.getChildByName("remote");
|
||||
@@ -132,6 +223,7 @@ export class IBoxComp extends CCComp {
|
||||
if (supportNode) supportNode.active = iType === IType.support;
|
||||
}
|
||||
|
||||
/** 点击弹窗任意区域关闭自身 */
|
||||
private onTapClose() {
|
||||
oops.gui.removeByNode(this.node);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user