diff --git a/assets/script/game/map/ChipComp.ts b/assets/script/game/map/ChipComp.ts index d4ace829..7c5e61da 100644 --- a/assets/script/game/map/ChipComp.ts +++ b/assets/script/game/map/ChipComp.ts @@ -3,34 +3,28 @@ * @description 英雄图鉴卡预制体组件(UI 视图层·精简版) * * 职责: - * 1. 根据卡牌配置渲染 **图标**(英雄卡为 idle 动画,其他卡为静态图集帧)。 - * 2. 根据 card_lv / kind 渲染 **背景底框**。 + * 1. 根据英雄 UUID 渲染 **图标**(idle 动画)。 + * 2. 根据 HeroInfo.card_lv 切换 **背景底框颜色**(BG_node 下的 green/blue/purple/yellow/red 子节点)。 * * 说明: - * - 仅保留图标与背景渲染能力,名称、费用、等级等展示由外部组件负责。 + * - 仅处理英雄展示,数据源为 heroSet 的 HeroInfo,不依赖 CardSet。 * - 通过 iconVisualToken 防止异步动画加载竞态。 - * - * 依赖: - * - CardConfig / CardType / CKind / CardPoolList(CardSet) - * - HeroInfo(heroSet)、SkillSet(SkillSet) - * - smc —— 全局单例,访问图标图集缓存 */ 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 { CardConfig, CardType, CKind, CardPoolList } from "../common/config/CardSet"; -import { CardBgComp } from "./CardBgComp"; import { HeroInfo } from "../common/config/heroSet"; -import { SkillSet } from "../common/config/SkillSet"; -import { smc } from "../common/SingletonModuleComp"; const { ccclass, property } = _decorator; +/** card_lv → BG_node 子节点(颜色)名映射:1=green 2=blue 3=purple 4=yellow 5=red */ +const BG_COLORS = ["green", "blue", "purple", "yellow", "red"]; + /** - * ChipComp —— 单张卡牌图标/背景视图组件 + * ChipComp —— 单张英雄卡图标/背景视图组件 * - * 挂载在图鉴卡预制体上,仅负责图标与背景的渲染。 + * 挂载在图鉴卡预制体上,仅负责英雄图标(idle 动画)与背景底框的渲染。 */ @ccclass('ChipComp') @ecs.register('ChipComp', false) @@ -47,165 +41,53 @@ export class ChipComp extends CCComp { // ======================== 运行时状态 ======================== card_uuid: number = 0 - card_type: CardType = CardType.Hero - private cardData: CardConfig | null = null; private iconVisualToken: number = 0; - // ======================== 生命周期 ======================== - - onLoad() { - if (!this.cardData) { - this.applyEmptyUI(); - } - } - // ======================== 对外接口 ======================== /** - * 设置卡牌数据并渲染图标与背景。 - * @param data 卡牌配置数据 + * 通过英雄 UUID 渲染英雄卡(idle 动画图标 + 背景底框)。 + * @param uuid 英雄 UUID(须存在于 HeroInfo) */ - setData(data: CardConfig) { - if (!data) return; - this.cardData = data; - this.card_uuid = data.uuid; - this.card_type = data.type; - this.node.active = true; - this.applyCardUI(); - mLogger.log(this.debugMode, "ChipComp", "setData", { - uuid: this.card_uuid, - type: this.card_type - }); - } - - /** - * 通过英雄 UUID 直接渲染英雄图标(自动播放 idle 动画并应用背景)。 - * 适用于碎片、头像、图鉴等纯展示场景。 - * @param uuid 英雄 UUID - */ - setHeroIconByUuid(uuid: number) { + setHeroByUuid(uuid: number) { const hero = HeroInfo[uuid]; if (!hero) return; - this.cardData = null; this.card_uuid = uuid; - this.card_type = CardType.Hero; this.node.active = true; this.iconVisualToken += 1; - // 背景:按 HeroInfo.card_lv 应用英雄底框样式 + // 背景:按 card_lv 切换颜色底框(green/blue/purple/yellow/red) if (this.BG_node) { - const cardLv = hero.card_lv ?? 1; - const kindName = CKind[CKind.Hero]; - this.BG_node.children.forEach(child => { - child.active = (child.name === kindName); - const bg = child.getComponent(CardBgComp); - if (bg) child.active ? bg.apply(cardLv) : bg.clear(); - }); + const color = 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 动画(带镜像翻转) + // 图标:idle 动画(镜像翻转,原图朝右,卡面需朝左) if (this.icon_node) { - this.icon_node.setScale(new Vec3(-1.5, 1.5, 1)); this.updateHeroAnimation(this.icon_node, uuid, this.iconVisualToken); } + mLogger.log(this.debugMode, "ChipComp", "setHeroByUuid", { uuid }); } - /** 清空卡牌数据并重置 UI */ + /** 清空并重置 UI */ clear() { - this.cardData = null; this.card_uuid = 0; - this.card_type = CardType.Hero; - this.applyEmptyUI(); - this.node.active = false; - } - - // ======================== UI 渲染 ======================== - - /** 渲染图标与背景 */ - private applyCardUI() { - if (!this.cardData) { - this.applyEmptyUI(); - return; - } - - this.iconVisualToken += 1; - const kindName = CKind[this.cardData.kind]; - - // 背景:按 kind 显示对应底框,按 card_lv 应用等级样式 - if (this.BG_node) { - const bgLv = this.cardData.base_card_lv ?? this.cardData.card_lv; - this.BG_node.children.forEach(child => { - child.active = (child.name === kindName); - const bg = child.getComponent(CardBgComp); - if (bg) child.active ? bg.apply(bgLv) : bg.clear(); - }); - } - - // 图标:英雄卡播放 idle 动画,其他卡使用静态图集帧 - if (this.icon_node) { - const iconNode = this.icon_node; - if (this.card_type === CardType.Hero) { - // 英雄图标做镜像翻转(原图朝右,卡面需朝左) - iconNode.setScale(new Vec3(-1.5, 1.5, 1)); - this.updateHeroAnimation(iconNode, this.card_uuid, this.iconVisualToken); - return; - } - iconNode.setScale(new Vec3(1, 1, 1)); - this.clearIconAnimation(iconNode); - const iconId = this.resolveCardIconId(this.card_type, this.card_uuid); - if (iconId) { - this.updateIcon(iconNode, iconId); - } else { - const sprite = iconNode.getComponent(Sprite) || iconNode.getComponentInChildren(Sprite); - if (sprite) sprite.spriteFrame = null; - } - } - } - - /** 渲染空槽状态:清空图标与背景 */ - private applyEmptyUI() { this.iconVisualToken += 1; if (this.BG_node) { - this.BG_node.children.forEach(child => { - child.active = false; - const bg = child.getComponent(CardBgComp); - if (bg) bg.clear(); - }); + this.BG_node.children.forEach(child => child.active = false); } if (this.icon_node) { - this.icon_node.setScale(new Vec3(1, 1, 1)); 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; } - // ======================== 工具方法 ======================== - - /** 更新图标:从全局缓存图集中获取对应帧 */ - private updateIcon(node: Node, iconId: string) { - if (!node || !iconId) return; - const sprite = node.getComponent(Sprite) || node.getComponentInChildren(Sprite); - if (!sprite) return; - if (smc.uiconsAtlas) { - const frame = smc.uiconsAtlas.getSpriteFrame(iconId); - sprite.spriteFrame = frame || null; - } - } - - /** 根据卡牌类型和 UUID 解析出图标 ID(在 SpriteAtlas 中的帧名) */ - private resolveCardIconId(type: CardType, uuid: number): string { - if (type === CardType.Skill) { - return SkillSet[uuid]?.icon || `${uuid}`; - } - if (type === CardType.Hero) { - return HeroInfo[uuid]?.icon || `${uuid}`; - } - return `${uuid}`; - } + // ======================== 动画 ======================== /** - * 为英雄卡图标加载并播放 idle 动画。 + * 为英雄图标加载并播放 idle 动画。 * 使用 token 做竞态保护,确保异步回调时不会覆盖已更新的图标。 */ private updateHeroAnimation(node: Node, uuid: number, token: number) { @@ -221,7 +103,7 @@ export class ChipComp extends CCComp { mLogger.log(this.debugMode, "ChipComp", `load hero animation failed ${uuid}`, err); return; } - if (token !== this.iconVisualToken || !this.cardData || this.card_type !== CardType.Hero || this.card_uuid !== uuid) { + if (token !== this.iconVisualToken || this.card_uuid !== uuid) { return; } this.clearAnimationClips(anim);