MatchMaster/assets/win/script/WinPanel.ts
2026-09-18 14:02:07 +08:00

119 lines
4.2 KiB
TypeScript

const { ccclass } = cc._decorator;
type WinPanelAction = (event?: cc.Event, customEventData?: string) => void;
interface WinPanelActions {
[name: string]: WinPanelAction;
}
/** Win prefab 内部按钮入口;具体游戏流程由 Map 在实例化后注入。 */
@ccclass
export default class WinPanel extends cc.Component {
private actions: WinPanelActions = null;
private rainbowStars: cc.Node[] = [];
private starTime = 0;
private avatarFrame: cc.SpriteFrame = null;
bind(actions: WinPanelActions) {
this.actions = actions || {};
}
initRainbowWinStreak(count: number) {
const streak = this.node.getChildByName("WinStreak2");
if (!streak) return;
count = Math.max(0, Math.min(10, count));
const reward = streak.getChildByName("reward");
const avatar = streak.getChildByName("avatar");
const milestone = count > 0 ? streak.getChildByName("hammer").getChildByName(String(count))
: streak.getChildByName("progress");
if (milestone) {
const position = milestone.convertToWorldSpaceAR(cc.v2());
[reward, avatar].forEach(node => {
if (node) node.x = node.parent.convertToNodeSpaceAR(position).x;
});
}
this.rainbowStars = reward ? reward.children.filter(node => node.name === "star") : [];
this.starTime = 0;
this.update(0);
const mask = avatar && avatar.getChildByName("mask");
if (!mask) return;
const icon = mask.getChildByName("icon");
const spine = mask.getChildByName("sp");
const selected = cc.fx.GameConfig.GM_INFO.useravatarIcon || "icon_0";
const remote = selected.length > 10;
icon.active = remote;
spine.active = !remote;
if (remote) {
icon.getComponent(cc.Sprite).spriteFrame = null;
cc.assetManager.loadRemote(selected, { ext: '.png' }, (err, texture: cc.Texture2D) => {
if (err || !texture || !cc.isValid(this, true) || !cc.isValid(icon, true)
|| cc.fx.GameConfig.GM_INFO.useravatarIcon !== selected) return;
if (!this.avatarFrame) this.avatarFrame = new cc.SpriteFrame(texture);
else this.avatarFrame.setTexture(texture);
icon.getComponent(cc.Sprite).spriteFrame = this.avatarFrame;
});
} else {
cc.fx.GameTool.loadSpineSimple(spine, cc.fx.GameTool.getActionName(selected));
}
}
update(dt: number) {
if (!this.rainbowStars.length) return;
this.starTime = (this.starTime + dt) % 1.8;
this.rainbowStars.forEach((star, index) => {
const phase = (this.starTime / 1.8 - index / this.rainbowStars.length) * Math.PI * 2;
star.opacity = 40 + (Math.cos(phase) + 1) * 107.5;
});
}
setSpecialTipsVisible(visible: boolean) {
const specialTips = this.node.getChildByName("specialTips");
if (specialTips) {
specialTips.active = visible;
}
}
openPosition(event?: cc.Event, customEventData?: string) {
this.invoke("openPosition", event, customEventData);
}
winMaxLevelShowClose() {
this.setSpecialTipsVisible(false);
}
winLevel(event?: cc.Event, customEventData?: string) {
this.invoke("winLevel", event, customEventData);
}
winLevel2(event?: cc.Event, customEventData?: string) {
this.invoke("winLevel2", event, customEventData);
}
returnHome(event?: cc.Event, customEventData?: string) {
this.invoke("returnHome", event, customEventData);
}
returnHomeScene(event?: cc.Event, customEventData?: string) {
this.invoke("returnHomeScene", event, customEventData);
}
showDoubleCoin(event?: cc.Event, customEventData?: string) {
this.invoke("showDoubleCoin", event, customEventData);
}
private invoke(name: string, event?: cc.Event, customEventData?: string) {
const action = this.actions && this.actions[name];
if (action) {
action(event, customEventData);
return;
}
cc.warn("WinPanel action is not bound:", name);
}
onDestroy() {
if (this.avatarFrame) this.avatarFrame.destroy();
this.actions = null;
}
}