Files
pixelheros/assets/script/game/map/MissionCardComp.ts
walkpan fcc2aaf0a0 refactor(界面): 移除物品购买逻辑并调整卡片组件
- 删除MissionCardComp中与物品购买相关的代码逻辑
- 调整card.prefab的宽度和精灵图集引用
- 简化卡片选择逻辑,统一处理物品使用事件
2026-01-06 17:01:57 +08:00

371 lines
12 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.
import { _decorator, Label, Node, tween, Vec3, Color, Sprite, Tween } 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 { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
import { GameEvent } from "../common/config/GameEvent";
import { talConf, ItalConf } from "../common/config/TalSet";
import { CanSelectHeros, HeroInfo } from "../common/config/heroSet";
import { CanSelectSkills, SkillSet } from "../common/config/SkillSet";
import { ItemSet } from "../common/config/ItemSet";
import { smc } from "../common/SingletonModuleComp";
import { CardType } from "../common/config/GameSet";
const { ccclass, property } = _decorator;
/** 视图层对象 */
@ccclass('MissionCardComp')
@ecs.register('MissionCard', false)
export class MissionCardComp extends CCComp {
/** 视图层逻辑代码分离演示 */
@property(Node)
card1:Node = null!
@property(Node)
card2:Node = null!
@property(Node)
card3:Node = null!
@property(Node)
card4:Node = null!
@property(Node)
btnClose: Node = null!
@property(Node)
Lock: Node = null!
card1_data:any = null!
card2_data:any = null!
card3_data:any = null!
card4_data:any = null!
// 当前卡片类型
curCardType: CardType = CardType.Talent;
// 是否处于锁定状态
private isLocked: boolean = true;
onLoad() {
if (this.btnClose) {
this.btnClose.on(Node.EventType.TOUCH_END, this.onGiveUp, this);
}
oops.message.on(GameEvent.TalentSelect, this.onTalentSelect, this);
oops.message.on(GameEvent.HeroSkillSelect, this.onHeroSkillSelect, this);
oops.message.on(GameEvent.ShopOpen, this.onShopOpen, this);
oops.message.on(GameEvent.MissionStart, this.onMissionStart, this);
oops.message.on(GameEvent.MissionEnd, this.onMissionEnd, this);
oops.message.on(GameEvent.ToCallFriend, this.onCallFriend, this);
}
onDestroy() {
if (this.btnClose) {
this.btnClose.off(Node.EventType.TOUCH_END, this.onGiveUp, this);
}
oops.message.off(GameEvent.TalentSelect, this.onTalentSelect, this);
oops.message.off(GameEvent.HeroSkillSelect, this.onHeroSkillSelect, this);
oops.message.off(GameEvent.ShopOpen, this.onShopOpen, this);
oops.message.off(GameEvent.MissionStart, this.onMissionStart, this);
oops.message.off(GameEvent.MissionEnd, this.onMissionEnd, this);
oops.message.off(GameEvent.ToCallFriend, this.onCallFriend, this);
this.ent.destroy();
}
init(){
this.onMissionStart();
}
/** 游戏开始初始化 */
onMissionStart() {
this.isLocked = true;
if (this.Lock) this.Lock.active = false; // 初始不显示,等待 showCardType
this.eventQueue = [];
}
/** 游戏结束清理 */
onMissionEnd() {
this.eventQueue = [];
this.node.active = false;
this.hasSelected = false;
// 停止所有卡片动画
const cards = [this.card1, this.card2, this.card3, this.card4];
cards.forEach(card => {
if (card) {
Tween.stopAllByTarget(card);
const selected = card.getChildByName("selected");
if (selected) Tween.stopAllByTarget(selected);
}
});
}
start() {
// 初始隐藏或显示逻辑
this.node.active = false;
this.resetCardStates();
}
private resetCardStates() {
const cards = [this.card1, this.card2, this.card3, this.card4];
cards.forEach(card => {
if (card) {
const selected = card.getChildByName("selected");
if (selected) selected.active = false;
// 恢复缩放和颜色
card.setScale(1, 1, 1);
const sprite = card.getComponent(Sprite);
if (sprite) sprite.color = new Color(255, 255, 255);
}
});
}
// 是否已经选择了天赋
private hasSelected: boolean = false;
// 事件队列
private eventQueue: CardType[] = [];
private onShopOpen(event: string, args: any) {
this.eventQueue.push(CardType.Potion);
this.checkQueue();
}
private onTalentSelect(event: string, args: any) {
this.eventQueue.push(CardType.Talent);
this.checkQueue();
}
private onHeroSkillSelect(event: string, args: any) {
this.eventQueue.push(CardType.Skill);
this.checkQueue();
}
private onCallFriend(event: string, args: any) {
this.eventQueue.push(CardType.Partner);
this.checkQueue();
}
private checkQueue() {
if (this.node.active) return;
if (this.eventQueue.length === 0) return;
const type = this.eventQueue.shift();
if (type) {
this.showCardType(type);
}
}
private showCardType(type: CardType) {
this.node.active = true;
this.hasSelected = false;
this.curCardType = type;
// 根据锁定状态显示 Lock 节点
if (this.Lock) {
this.Lock.active = this.isLocked;
}
this.resetCardStates();
this.refCards();
this.playShowAnimation();
}
private playShowAnimation() {
const cards = [this.card1, this.card2, this.card3, this.card4];
cards.forEach((card, index) => {
if (card) {
card.setScale(Vec3.ZERO);
tween(card)
.delay(index * 0.1)
.to(0.4, { scale: new Vec3(1, 1, 1) }, { easing: 'backOut' })
.start();
}
});
}
refCards(){
// 根据当前类型获取数据
let allData: any[] = [];
if (this.curCardType === CardType.Talent) {
allData = Object.values(talConf);
} else if (this.curCardType === CardType.Skill) {
// 过滤掉怪物技能 (uuid >= 6200)
// allData = Object.values(SkillSet).filter((s:any) => s.uuid < 6200);
allData = CanSelectSkills.map(id => SkillSet[id]);
} else if (this.curCardType === CardType.Partner) {
allData = CanSelectHeros.map(id => HeroInfo[id]);
} else if (this.curCardType === CardType.Potion) {
allData = Object.values(ItemSet);
}
// 后续扩展其他类型
// else if (this.curCardType === CardType.Skill) { ... }
const result: any[] = [];
const temp = [...allData];
// 简单的随机抽取算法
for (let i = 0; i < 4 && temp.length > 0; i++) {
const index = Math.floor(Math.random() * temp.length);
result.push(temp[index]);
temp.splice(index, 1);
}
// 更新卡片
if (result.length > 0) this.updateCardData(1, result[0]);
if (result.length > 1) this.updateCardData(2, result[1]);
if (result.length > 2) this.updateCardData(3, result[2]);
if (result.length > 3) this.updateCardData(4, result[3]);
}
updateCardInfo(card:Node, data:any){
if(!card) return
card.active = true;
// 隐藏选中状态
const selected = card.getChildByName("selected");
if(selected) selected.active = false;
let name = card.getChildByName("name")
if(name){
name.getComponent(Label)!.string = data.name
}
let info = card.getChildByName("info")?.getChildByName("Label")
if(info){
// 根据类型显示不同描述目前天赋用desc
let desc = "";
if (this.curCardType === CardType.Talent) {
desc = data.desc || "";
} else if (this.curCardType === CardType.Skill) {
desc = data.info || "";
} else if (this.curCardType === CardType.Partner) {
desc = data.info || "";
} else {
desc = data.desc || "";
}
info.getComponent(Label)!.string = desc;
}
}
updateCardData(index: number, data: any) {
// 使用动态属性访问,简化 switch 冗余代码
(this as any)[`card${index}_data`] = data;
this.updateCardInfo((this as any)[`card${index}`], data);
}
selectCard(e: any, index: string) {
console.log("selectCard", index)
let _index = parseInt(index);
// 如果已经选择过,则不再处理
if (this.hasSelected) return;
// 动态获取数据和节点,简化 switch 逻辑
let selectedData: any = (this as any)[`card${_index}_data`];
let selectedCardNode: Node | null = (this as any)[`card${_index}`];
if (selectedData && selectedCardNode) {
this.hasSelected = true;
console.log("选择卡片:", selectedData.name, "类型:", this.curCardType);
// 未选中的卡片缩小
const cards = [this.card1, this.card2, this.card3, this.card4];
cards.forEach(card => {
if (card && card !== selectedCardNode) {
tween(card).to(0.2, { scale: Vec3.ZERO }).start();
}
});
// 显示当前选中的 selected 节点
const selected = selectedCardNode.getChildByName("selected");
if(selected) {
selected.active = true;
selected.setScale(Vec3.ZERO);
tween(selected).to(0.2, { scale: new Vec3(1, 1, 1) }, { easing: 'backOut' }).start();
}
// 选中卡片动效后触发逻辑
tween(selectedCardNode)
.to(0.1, { scale: new Vec3(1.1, 1.1, 1.1) })
.to(0.1, { scale: new Vec3(1, 1, 1) })
.delay(0.5)
.call(() => {
// 根据类型发送不同事件
if (this.curCardType === CardType.Talent) {
smc.addTalentRecord(selectedData.uuid);
oops.message.dispatchEvent(GameEvent.UseTalentCard, selectedData.uuid);
} else if (this.curCardType === CardType.Skill) {
smc.addSkillRecord(selectedData.uuid);
oops.message.dispatchEvent(GameEvent.UseSkillCard, selectedData.uuid);
} else if (this.curCardType === CardType.Partner) {
oops.message.dispatchEvent(GameEvent.CallFriend, { uuid: selectedData.uuid });
} else if (this.curCardType === CardType.Potion) {
oops.message.dispatchEvent(GameEvent.UseItemCard, selectedData.id);
}
// 后续扩展其他类型事件
this.close();
})
.start();
}
}
/** 看广告关闭 Lock */
watchAdCloseLock() {
// TODO: 此处接入 IAA 广告 SDK
console.log("播放激励视频广告...");
// 模拟广告播放成功回调
this.isLocked = false;
if (this.Lock) {
this.Lock.active = false;
oops.gui.toast("解锁成功");
}
}
/** 放弃选择 */
onGiveUp() {
if (this.hasSelected) return;
this.hasSelected = true;
// 隐藏关闭按钮
if (this.btnClose) {
this.btnClose.active = false;
}
const cards = [this.card1, this.card2, this.card3, this.card4];
let delayTime = 0.2;
cards.forEach(card => {
if (card && card.active) {
tween(card).to(delayTime, { scale: Vec3.ZERO }).start();
}
});
// 动画结束后关闭
this.scheduleOnce(() => {
this.close();
}, delayTime);
}
/**
* 关闭界面
*/
close() {
this.node.active = false;
// 关闭时隐藏按钮,避免下次打开其他类型时闪烁
if (this.btnClose) {
this.btnClose.active = false;
}
// 关闭时隐藏 Lock 节点
if (this.Lock) {
this.Lock.active = false;
}
this.checkQueue();
}
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
reset() {
this.node.destroy();
}
}