feat(card): 完善卡牌图标显示与锁定功能
- 为英雄卡牌添加动画图标显示,根据配置加载对应动画 - 修复锁定按钮显示逻辑,现在正确显示锁定/解锁状态 - 为技能、buff、英雄等卡牌类型添加图标解析功能 - 更新卡牌预制体,调整图标尺寸和锁定图标 - 删除未使用的动画资源文件 - 优化资源图集配置,调整精灵帧位置
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
import { mLogger } from "../common/Logger";
|
||||
import { _decorator, EventTouch, Label, Node, NodeEventType, Sprite, SpriteAtlas, Tween, tween, UIOpacity, Vec3 } from "cc";
|
||||
import { _decorator, Animation, AnimationClip, EventTouch, Label, Node, NodeEventType, Sprite, SpriteAtlas, Tween, tween, UIOpacity, 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 } from "../common/config/CardSet";
|
||||
import { CardUseComp } from "./CardUseComp";
|
||||
import { HeroInfo } from "../common/config/heroSet";
|
||||
import { BuffsList, SkillSet } from "../common/config/SkillSet";
|
||||
|
||||
|
||||
|
||||
@@ -46,6 +48,7 @@ export class CardComp extends CCComp {
|
||||
private restPosition: Vec3 = new Vec3();
|
||||
private opacityComp: UIOpacity | null = null;
|
||||
private cardUseComp: CardUseComp | null = null;
|
||||
private iconVisualToken: number = 0;
|
||||
|
||||
onLoad() {
|
||||
/** 初始阶段只做UI状态准备,不触发业务逻辑 */
|
||||
@@ -86,7 +89,31 @@ export class CardComp extends CCComp {
|
||||
}
|
||||
|
||||
private updateIcon(node: Node, iconId: string) {
|
||||
|
||||
if (!node || !iconId) return;
|
||||
const sprite = node.getComponent(Sprite) || node.getComponentInChildren(Sprite);
|
||||
if (!sprite) return;
|
||||
if (this.uiconsAtlas) {
|
||||
const frame = this.uiconsAtlas.getSpriteFrame(iconId);
|
||||
if (frame) {
|
||||
sprite.spriteFrame = frame;
|
||||
} else {
|
||||
sprite.spriteFrame = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
resources.load("gui/uicons", SpriteAtlas, (err, atlas) => {
|
||||
if (err || !atlas) {
|
||||
mLogger.log(this.debugMode, "CardComp", "load uicons atlas failed", err);
|
||||
return;
|
||||
}
|
||||
this.uiconsAtlas = atlas;
|
||||
const frame = atlas.getSpriteFrame(iconId);
|
||||
if (frame) {
|
||||
sprite.spriteFrame = frame;
|
||||
} else {
|
||||
sprite.spriteFrame = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** 兼容旧接口:按索引更新卡牌(当前由 MissionCardComp 顺序分发) */
|
||||
@@ -264,7 +291,7 @@ export class CardComp extends CCComp {
|
||||
}
|
||||
|
||||
/** 点击锁控件:切换锁态;空槽不允许锁定 */
|
||||
private onToggleLock(event?: Event) {
|
||||
private onToggleLock(event?: EventTouch) {
|
||||
if (!this.cardData) return;
|
||||
this.isLocked = !this.isLocked;
|
||||
this.updateLockUI();
|
||||
@@ -272,13 +299,16 @@ export class CardComp extends CCComp {
|
||||
uuid: this.card_uuid,
|
||||
locked: this.isLocked
|
||||
});
|
||||
event?.stopPropagation();
|
||||
const stopPropagation = (event as any)?.stopPropagation;
|
||||
if (typeof stopPropagation === "function") {
|
||||
stopPropagation.call(event);
|
||||
}
|
||||
}
|
||||
|
||||
/** 根据锁态刷新 Lock / unLock 显示 */
|
||||
/** 根据锁态刷新 Lock / unLock 显示(Lock=可点击上锁,unLock=可点击解锁) */
|
||||
private updateLockUI() {
|
||||
if (this.Lock) this.Lock.active = this.isLocked;
|
||||
if (this.unLock) this.unLock.active = !this.isLocked;
|
||||
if (this.Lock) this.Lock.active = !this.isLocked;
|
||||
if (this.unLock) this.unLock.active = this.isLocked;
|
||||
}
|
||||
|
||||
/** 根据当前 cardData 渲染卡面文字与图标 */
|
||||
@@ -287,13 +317,26 @@ export class CardComp extends CCComp {
|
||||
this.applyEmptyUI();
|
||||
return;
|
||||
}
|
||||
this.iconVisualToken += 1;
|
||||
if (this.opacityComp) this.opacityComp.opacity = 255;
|
||||
this.node.setPosition(this.restPosition);
|
||||
this.setLabel(this.name_node, `${CardType[this.card_type]}-${this.card_uuid}`);
|
||||
this.setLabel(this.cost_node, `${this.card_cost}`);
|
||||
if (this.ap_node) this.ap_node.active = false;
|
||||
if (this.hp_node) this.hp_node.active = false;
|
||||
this.updateIcon(this.icon_node, `${this.card_uuid}`);
|
||||
const iconNode = this.icon_node as Node;
|
||||
if (this.card_type === CardType.Hero) {
|
||||
this.updateHeroAnimation(iconNode, this.card_uuid, this.iconVisualToken);
|
||||
return;
|
||||
}
|
||||
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 playRefreshAnim() {
|
||||
@@ -337,11 +380,13 @@ export class CardComp extends CCComp {
|
||||
|
||||
/** 渲染空槽状态 */
|
||||
private applyEmptyUI() {
|
||||
this.iconVisualToken += 1;
|
||||
this.setLabel(this.name_node, "");
|
||||
this.setLabel(this.cost_node, "");
|
||||
if (this.ap_node) this.ap_node.active = false;
|
||||
if (this.hp_node) this.hp_node.active = false;
|
||||
const sprite = this.icon_node?.getComponent(Sprite);
|
||||
this.clearIconAnimation(this.icon_node as Node);
|
||||
const sprite = this.icon_node?.getComponent(Sprite) || this.icon_node?.getComponentInChildren(Sprite);
|
||||
if (sprite) sprite.spriteFrame = null;
|
||||
}
|
||||
|
||||
@@ -363,6 +408,54 @@ export class CardComp extends CCComp {
|
||||
return null;
|
||||
}
|
||||
|
||||
private resolveCardIconId(type: CardType, uuid: number): string {
|
||||
if (type === CardType.Skill) {
|
||||
return SkillSet[uuid]?.icon || `${uuid}`;
|
||||
}
|
||||
if (type === CardType.Buff || type === CardType.Debuff) {
|
||||
return BuffsList[uuid]?.icon || `${uuid}`;
|
||||
}
|
||||
if (type === CardType.Hero) {
|
||||
return HeroInfo[uuid]?.icon || `${uuid}`;
|
||||
}
|
||||
return `${uuid}`;
|
||||
}
|
||||
|
||||
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, "CardComp", `load hero animation failed ${uuid}`, err);
|
||||
return;
|
||||
}
|
||||
if (token !== this.iconVisualToken || !this.cardData || this.card_type !== CardType.Hero || this.card_uuid !== uuid) {
|
||||
return;
|
||||
}
|
||||
this.clearAnimationClips(anim);
|
||||
anim.addClip(clip);
|
||||
anim.play("idle");
|
||||
});
|
||||
}
|
||||
|
||||
private clearIconAnimation(node: Node) {
|
||||
const anim = node?.getComponent(Animation);
|
||||
if (!anim) return;
|
||||
anim.stop();
|
||||
this.clearAnimationClips(anim);
|
||||
}
|
||||
|
||||
private clearAnimationClips(anim: Animation) {
|
||||
const clips = (anim as any).clips as AnimationClip[] | undefined;
|
||||
if (!clips || clips.length === 0) return;
|
||||
[...clips].forEach(clip => anim.removeClip(clip, true));
|
||||
}
|
||||
|
||||
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
|
||||
reset() {
|
||||
this.node.destroy();
|
||||
|
||||
Reference in New Issue
Block a user