Files
pixelheros/assets/script/game/map/ChipComp.ts
panFD 41842f2b67 refactor(config,map): 统一抽离卡片背景颜色配置
将多处硬编码的卡片等级背景颜色数组移至公共配置文件,
同时重构英雄列表组件的等级显示逻辑,替换为标签直接赋值。
2026-08-23 23:52:20 +08:00

135 lines
4.9 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 ChipComp.ts
* @description 英雄图鉴卡预制体组件UI 视图层·精简版)
*
* 职责:
* 1. 根据英雄 UUID 渲染 **图标**idle 动画)。
* 2. 根据 HeroInfo.card_lv 切换 **背景底框颜色**BG_node 下的 green/blue/purple/yellow/red 子节点)。
*
* 说明:
* - 仅处理英雄展示,数据源为 heroSet 的 HeroInfo不依赖 CardSet。
* - 通过 iconVisualToken 防止异步动画加载竞态。
*/
import { mLogger } from "../common/Logger";
import { _decorator, Animation, AnimationClip, Node, Sprite, Vec3, resources } 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 { HeroInfo } from "../common/config/heroSet";
import { CARD_LV_BG_COLORS } from "../common/config/GameSet";
const { ccclass, property } = _decorator;
/**
* ChipComp —— 单张英雄卡图标/背景视图组件
*
* 挂载在图鉴卡预制体上仅负责英雄图标idle 动画)与背景底框的渲染。
*/
@ccclass('ChipComp')
@ecs.register('ChipComp', false)
export class ChipComp extends CCComp {
private debugMode: boolean = false;
// ======================== 编辑器绑定节点 ========================
@property(Node)
icon_node: Node = null!
@property(Node)
BG_node: Node = null!
// ======================== 运行时状态 ========================
card_uuid: number = 0
private iconVisualToken: number = 0;
// ======================== 对外接口 ========================
/**
* 通过英雄 UUID 渲染英雄卡idle 动画图标 + 背景底框)。
* @param uuid 英雄 UUID须存在于 HeroInfo
*/
setHeroByUuid(uuid: number) {
const hero = HeroInfo[uuid];
if (!hero) return;
this.card_uuid = uuid;
this.node.active = true;
this.iconVisualToken += 1;
// 背景:按 card_lv 切换颜色底框green/blue/purple/yellow/red
if (this.BG_node) {
const color = CARD_LV_BG_COLORS[Math.min(Math.max(hero.card_lv ?? 1, 1), 5) - 1];
this.BG_node.children.forEach(child => child.active = (child.name === color));
}
// 图标idle 动画(镜像翻转,原图朝右,卡面需朝左)
if (this.icon_node) {
this.updateHeroAnimation(this.icon_node, uuid, this.iconVisualToken);
}
mLogger.log(this.debugMode, "ChipComp", "setHeroByUuid", { uuid });
}
/** 清空并重置 UI */
clear() {
this.card_uuid = 0;
this.iconVisualToken += 1;
if (this.BG_node) {
this.BG_node.children.forEach(child => child.active = false);
}
if (this.icon_node) {
this.clearIconAnimation(this.icon_node);
const sprite = this.icon_node.getComponent(Sprite) || this.icon_node.getComponentInChildren(Sprite);
if (sprite) sprite.spriteFrame = null;
}
this.node.active = false;
}
// ======================== 动画 ========================
/**
* 为英雄图标加载并播放 idle 动画。
* 使用 token 做竞态保护,确保异步回调时不会覆盖已更新的图标。
*/
private updateHeroAnimation(node: Node, uuid: number, token: number) {
const sprite = node?.getComponent(Sprite) || node?.getComponentInChildren(Sprite);
if (sprite) sprite.spriteFrame = null;
const hero = HeroInfo[uuid];
if (!hero) return;
const anim = node.getComponent(Animation) || node.addComponent(Animation);
this.clearAnimationClips(anim);
const path = `game/heros/hero/${hero.path}/idle`;
resources.load(path, AnimationClip, (err, clip) => {
if (err || !clip) {
mLogger.log(this.debugMode, "ChipComp", `load hero animation failed ${uuid}`, err);
return;
}
if (token !== this.iconVisualToken || this.card_uuid !== uuid) {
return;
}
this.clearAnimationClips(anim);
anim.addClip(clip);
anim.play("idle");
});
}
/** 清除图标节点上的动画(停止播放并移除所有 clip */
private clearIconAnimation(node: Node) {
const anim = node?.getComponent(Animation);
if (!anim) return;
anim.stop();
this.clearAnimationClips(anim);
}
/** 移除 Animation 组件上的全部 AnimationClip */
private clearAnimationClips(anim: Animation) {
const clips = anim.clips as AnimationClip[] | undefined;
if (!clips || clips.length === 0) return;
[...clips].forEach(clip => anim.removeClip(clip, true));
}
// ======================== 生命周期钩子 ========================
/** ECS 组件移除时的释放钩子:销毁节点 */
reset() {
this.node.destroy();
}
}