|
|
@@ -0,0 +1,127 @@
|
|
|
+import { _decorator, Component, Node, Label, Sprite, Button } from 'cc';
|
|
|
+import EventBus, { GameEvents } from '../Core/EventBus';
|
|
|
+import { JsonConfigLoader } from '../Core/JsonConfigLoader';
|
|
|
+import { BundleLoader } from '../Core/BundleLoader';
|
|
|
+
|
|
|
+const { ccclass, property } = _decorator;
|
|
|
+
|
|
|
+@ccclass('GainUI')
|
|
|
+export class GainUI extends Component {
|
|
|
+ @property(Node) panel: Node = null; // 弹窗根节点
|
|
|
+ @property(Label) titleLabel: Label = null; // 标题,如“新武器”
|
|
|
+ @property(Sprite) iconSprite: Sprite = null; // 武器图标
|
|
|
+ @property(Label) nameLabel: Label = null; // 武器名称
|
|
|
+ @property(Button) confirmBtn: Button = null; // 确认按钮
|
|
|
+
|
|
|
+ private weaponsConfig: any = null;
|
|
|
+ private bundleLoader: BundleLoader = null;
|
|
|
+
|
|
|
+ // 等待展示的武器名称队列(来自 UpgradeController 派发的 NEW_WEAPONS_UNLOCKED)
|
|
|
+ private pendingWeapons: string[] = [];
|
|
|
+ // 是否已经完成奖励动画(由 MoneyAni 派发 REWARD_ANIMATION_COMPLETED)
|
|
|
+ private rewardAnimationCompleted = false;
|
|
|
+ // 当前是否正在显示弹窗
|
|
|
+ private showing = false;
|
|
|
+
|
|
|
+ async onLoad() {
|
|
|
+ this.bundleLoader = BundleLoader.getInstance();
|
|
|
+ // 默认隐藏弹窗
|
|
|
+ if (this.panel) this.panel.active = false;
|
|
|
+
|
|
|
+ // 绑定事件
|
|
|
+ EventBus.getInstance().on(GameEvents.NEW_WEAPONS_UNLOCKED, this.onNewWeaponsUnlocked, this);
|
|
|
+ EventBus.getInstance().on(GameEvents.REWARD_ANIMATION_COMPLETED, this.onRewardAnimationCompleted, this);
|
|
|
+
|
|
|
+ // 绑定确认按钮
|
|
|
+ this.confirmBtn?.node.on(Button.EventType.CLICK, this.onConfirm, this);
|
|
|
+ }
|
|
|
+
|
|
|
+ async start() {
|
|
|
+ // 预加载武器配置,便于查找图标与名称
|
|
|
+ try {
|
|
|
+ this.weaponsConfig = await JsonConfigLoader.getInstance().loadConfig('weapons');
|
|
|
+ } catch (err) {
|
|
|
+ console.warn('[GainUI] 加载武器配置失败:', err);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ onDestroy() {
|
|
|
+ EventBus.getInstance().off(GameEvents.NEW_WEAPONS_UNLOCKED, this.onNewWeaponsUnlocked, this);
|
|
|
+ EventBus.getInstance().off(GameEvents.REWARD_ANIMATION_COMPLETED, this.onRewardAnimationCompleted, this);
|
|
|
+ this.confirmBtn?.node.off(Button.EventType.CLICK, this.onConfirm, this);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理新武器解锁事件
|
|
|
+ private onNewWeaponsUnlocked = (weaponNames: string[]) => {
|
|
|
+ if (!weaponNames || weaponNames.length === 0) return;
|
|
|
+ this.pendingWeapons.push(...weaponNames);
|
|
|
+ this.tryShowPopup();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理奖励动画完成事件
|
|
|
+ private onRewardAnimationCompleted = () => {
|
|
|
+ this.rewardAnimationCompleted = true;
|
|
|
+ this.tryShowPopup();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 在满足条件时显示弹窗:需要奖励动画已完成且队列非空
|
|
|
+ private async tryShowPopup() {
|
|
|
+ if (this.showing) return;
|
|
|
+ if (!this.rewardAnimationCompleted) return;
|
|
|
+ if (this.pendingWeapons.length === 0) return;
|
|
|
+
|
|
|
+ const nextName = this.pendingWeapons.shift();
|
|
|
+ await this.renderWeapon(nextName);
|
|
|
+ this.panel.active = true;
|
|
|
+ this.showing = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 确认按钮逻辑:继续展示队列中的下一个或关闭弹窗
|
|
|
+ private async onConfirm() {
|
|
|
+ if (this.pendingWeapons.length > 0) {
|
|
|
+ const nextName = this.pendingWeapons.shift();
|
|
|
+ await this.renderWeapon(nextName);
|
|
|
+ } else {
|
|
|
+ this.panel.active = false;
|
|
|
+ this.showing = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 根据武器名称渲染弹窗内容(标题、图标、名称)
|
|
|
+ private async renderWeapon(weaponName: string) {
|
|
|
+ if (this.titleLabel) this.titleLabel.string = '新武器';
|
|
|
+ if (this.nameLabel) this.nameLabel.string = weaponName || '';
|
|
|
+
|
|
|
+ // 查找武器配置,加载图标
|
|
|
+ const config = this.findWeaponConfigByName(weaponName);
|
|
|
+ if (config && config.visualConfig && config.visualConfig.weaponSprites) {
|
|
|
+ let spritePath: string;
|
|
|
+ const sprites = config.visualConfig.weaponSprites;
|
|
|
+ if (typeof sprites === 'string') {
|
|
|
+ spritePath = sprites;
|
|
|
+ } else {
|
|
|
+ spritePath = sprites['I'] || sprites['H-I'] || sprites['L'] || sprites['S'] || sprites['D-T'];
|
|
|
+ }
|
|
|
+ if (spritePath && this.iconSprite) {
|
|
|
+ await this.loadWeaponSprite(this.iconSprite, spritePath);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private findWeaponConfigByName(name: string) {
|
|
|
+ if (!this.weaponsConfig || !this.weaponsConfig.weapons) return null;
|
|
|
+ return this.weaponsConfig.weapons.find((w: any) => w.name === name);
|
|
|
+ }
|
|
|
+
|
|
|
+ private async loadWeaponSprite(sprite: Sprite, spritePath: string) {
|
|
|
+ const bundlePath = spritePath.replace(/^images\//, '');
|
|
|
+ try {
|
|
|
+ const spriteFrame = await this.bundleLoader.loadSpriteFrame(bundlePath + '/spriteFrame');
|
|
|
+ if (spriteFrame && sprite && sprite.isValid) {
|
|
|
+ sprite.spriteFrame = spriteFrame;
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ console.warn(`[GainUI] 加载武器图标失败: ${spritePath}`, err);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|