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

同时修复了英雄预制体的激活状态和技能效果预制体的尺寸参数。
2026-04-07 19:00:30 +08:00

271 lines
9.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file SkillBoxComp.ts
* @description 单个技能卡效果控制组件UI 视图层 + 逻辑层)
*
* 职责:
* 1. 表示一张已使用的技能卡在战场上的 **可视化实体**。
* 2. 管理技能的 **触发逻辑**:即时触发 vs 定时触发(战斗中按间隔触发)。
* 3. 显示技能图标和剩余触发次数。
* 4. 触发结束后自动销毁。
*
* 关键设计:
* - is_instant=true即时技能init 时立即触发一次,播放后延迟销毁。
* - is_instant=false持续技能战斗中每隔 trigger_interval 秒触发一次,
* 共触发 trigger_times 次后销毁。
* - 新一波NewWave时如果持续技能的次数已用完则销毁。
* - 销毁时通过 GameEvent.RemoveSkillBox 通知 MissSkillsComp 回收槽位。
*
* 触发技能的方式:
* - 通过 GameEvent.TriggerSkill 事件,将技能 UUID、卡牌等级、
* 触发位置等信息分发给技能系统。
*
* 依赖:
* - CardPoolListCardSet—— 查询技能卡的触发配置t_times / t_inv / is_inst
* - SkillSet —— 技能静态配置icon 字段)
* - GameEvent —— 各类游戏事件
* - smc.mission —— 游戏运行状态
*/
import { mLogger } from "../common/Logger";
import { _decorator, Node, Prefab, Sprite, Label, Vec3, resources, SpriteAtlas } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
import { CardPoolList } from "../common/config/CardSet";
import { SkillSet } from "../common/config/SkillSet";
import { oops } from "db://oops-framework/core/Oops";
import { GameEvent } from "../common/config/GameEvent";
import { smc } from "../common/SingletonModuleComp";
const { ccclass, property } = _decorator;
/**
* SkillBoxComp —— 单个技能卡效果视图 + 逻辑组件
*
* 由 MissSkillsComp.addSkill() 实例化并初始化。
* 在战场上以图标 + 剩余次数的形式呈现。
*/
@ccclass('SkillBoxComp')
@ecs.register('SkillBoxComp', false)
export class SkillBoxComp extends CCComp {
/** 调试日志开关 */
private debugMode: boolean = true;
/** 技能图标节点 */
@property({type: Node})
private icon_node:Node= null;
/** 剩余次数标签 */
@property(Label)
private info_label: Label = null;
// ======================== 技能配置 ========================
/** 技能 UUID */
private s_uuid: number = 0;
/** 卡牌等级 */
private card_lv: number = 1;
/** 是否为即时技能true=使用后立即触发false=战斗中定时触发) */
private is_instant: boolean = true;
/** 总触发次数 */
private trigger_times: number = 1;
/** 触发间隔(秒,仅持续技能有效) */
private trigger_interval: number = 0;
// ======================== 运行时状态 ========================
/** 已触发次数 */
private current_trigger_times: number = 0;
/** 当前计时器(秒) */
private timer: number = 0;
/** 是否处于战斗中(仅战斗中持续技能才计时) */
private in_combat: boolean = false;
/** 是否已初始化 */
private initialized: boolean = false;
// ======================== 生命周期 ========================
/** 注册战斗开始、任务结束、新一波等事件 */
onLoad() {
oops.message.on(GameEvent.FightStart, this.onFightStart, this);
oops.message.on(GameEvent.MissionEnd, this.onMissionEnd, this);
this.node.on(GameEvent.NewWave, this.onNewWave, this);
oops.message.on(GameEvent.NewWave, this.onNewWaveGlobal, this);
}
/** 销毁时移除所有事件监听并通知槽位管理器回收 */
onDestroy() {
oops.message.off(GameEvent.FightStart, this.onFightStart, this);
oops.message.off(GameEvent.MissionEnd, this.onMissionEnd, this);
this.node.off(GameEvent.NewWave, this.onNewWave, this);
oops.message.off(GameEvent.NewWave, this.onNewWaveGlobal, this);
// 通知 MissSkillsComp 回收该节点占用的槽位
oops.message.dispatchEvent(GameEvent.RemoveSkillBox, this.node);
}
/**
* 初始化技能卡效果:
* 1. 从 CardPoolList 查询技能卡的触发配置。
* 2. 更新 UI 显示(图标 + 次数)。
* 3. 即时技能立即触发一次;若次数已满则延迟销毁。
*
* @param uuid 技能 UUID
* @param card_lv 技能卡等级
*/
init(uuid: number, card_lv: number) {
this.s_uuid = uuid;
this.card_lv = card_lv;
// 查询触发配置
const config = CardPoolList.find(c => c.uuid === uuid);
if (config) {
this.is_instant = config.is_inst ?? true;
this.trigger_times = config.t_times ?? 1;
this.trigger_interval = config.t_inv ?? 0;
}
this.current_trigger_times = 0;
this.timer = 0;
this.initialized = true;
this.updateUI();
if (this.is_instant) {
// 即时技能:立即触发
this.triggerSkill();
this.current_trigger_times++;
if (this.current_trigger_times >= this.trigger_times) {
// 次数已满 → 延迟 1 秒后销毁(保留短暂视觉反馈)
this.scheduleOnce(() => {
this.node.destroy();
}, 1.0);
}
}
}
/**
* 更新 UI
* - 图标:从 uicons 图集获取。
* - 剩余次数:持续技能显示剩余数字,即时技能不显示。
*/
updateUI() {
// 加载技能图标
if (this.icon_node) {
const iconId = SkillSet[this.s_uuid]?.icon || `${this.s_uuid}`;
resources.load("gui/uicons", SpriteAtlas, (err, atlas) => {
if (err || !atlas) return;
const frame = atlas.getSpriteFrame(iconId);
if (frame && this.icon_node && this.icon_node.isValid) {
const sprite = this.icon_node.getComponent(Sprite) || this.icon_node.addComponent(Sprite);
sprite.spriteFrame = frame;
}
});
}
// 更新剩余次数标签
if (this.info_label) {
if (!this.is_instant) {
const remain = Math.max(0, this.trigger_times - this.current_trigger_times);
this.info_label.string = `${remain}`;
} else {
this.info_label.string = "";
}
}
}
// ======================== 战斗状态事件 ========================
/** 战斗开始:标记进入战斗状态,持续技能开始计时 */
private onFightStart() {
if (!this.initialized) return;
this.in_combat = true;
if (!this.is_instant) {
this.timer = 0; // 重置计时器
}
}
/** 节点级新一波事件处理 */
private onNewWave() {
this.handleNewWave();
}
/** 全局级新一波事件处理 */
private onNewWaveGlobal() {
this.handleNewWave();
}
/**
* 新一波:退出战斗状态。
* 持续技能:若总次数已用完则销毁。
*/
private handleNewWave() {
if (!this.initialized) return;
this.in_combat = false;
if (!this.is_instant) {
if (this.current_trigger_times >= this.trigger_times) {
this.node.destroy();
}
}
}
/** 任务结束:强制销毁 */
private onMissionEnd() {
this.node.destroy();
}
// ======================== 帧更新 ========================
/**
* 每帧更新(仅对持续技能生效):
* - 累加计时器,达到 trigger_interval 时触发一次技能。
* - 触发后重置计时器并更新 UI。
* - 总次数用完后延迟销毁。
*/
update(dt: number) {
if (!this.initialized || !this.in_combat || this.is_instant) return;
if (!smc.mission.play || smc.mission.pause) return;
if (this.current_trigger_times < this.trigger_times) {
this.timer += dt;
if (this.timer >= this.trigger_interval) {
this.timer = 0;
this.triggerSkill();
this.current_trigger_times++;
this.updateUI();
// 次数用完 → 延迟销毁
if (this.current_trigger_times >= this.trigger_times) {
this.scheduleOnce(() => {
if (this.node.isValid) this.node.destroy();
}, 0.5);
}
}
}
}
// ======================== 技能触发 ========================
/**
* 触发技能效果:
* - 计算触发位置(节点局部坐标 + 父节点偏移)。
* - 通过 GameEvent.TriggerSkill 事件将技能数据分发给技能系统。
*/
private triggerSkill() {
let targetPos = new Vec3();
const localPos = this.node.position;
const parentPos = this.node.parent ? this.node.parent.position : new Vec3(0, 0, 0);
targetPos.set(parentPos.x + localPos.x, parentPos.y + localPos.y, 0);
oops.message.dispatchEvent(GameEvent.TriggerSkill, {
s_uuid: this.s_uuid,
isCardSkill: true, // 标记为卡牌技能(区别于英雄自身技能)
card_lv: this.card_lv,
targetPos: targetPos
});
}
/** ECS 组件移除时销毁节点 */
reset() {
this.node.destroy();
}
}