|
|
@@ -0,0 +1,412 @@
|
|
|
+import { _decorator, Component, Node, Label, Button } from 'cc';
|
|
|
+import { SaveDataManager } from '../LevelSystem/SaveDataManager';
|
|
|
+import { InGameManager, GameState } from '../LevelSystem/IN_game';
|
|
|
+import EventBus, { GameEvents } from '../Core/EventBus';
|
|
|
+const { ccclass, property } = _decorator;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 游戏结算界面管理器
|
|
|
+ * 负责处理游戏结束后的奖励显示和双倍奖励功能
|
|
|
+ */
|
|
|
+@ccclass('GameEnd')
|
|
|
+export class GameEnd extends Component {
|
|
|
+
|
|
|
+ // === UI节点引用 ===
|
|
|
+ @property({
|
|
|
+ type: Button,
|
|
|
+ tooltip: '双倍奖励按钮 (Canvas/GameEnd/double)'
|
|
|
+ })
|
|
|
+ public doubleButton: Button = null;
|
|
|
+
|
|
|
+ @property({
|
|
|
+ type: Label,
|
|
|
+ tooltip: '钞票数量显示 '
|
|
|
+ })
|
|
|
+ public moneyLabel: Label = null;
|
|
|
+
|
|
|
+ @property({
|
|
|
+ type: Label,
|
|
|
+ tooltip: '钻石数量显示 '
|
|
|
+ })
|
|
|
+ public diamondLabel: Label = null;
|
|
|
+
|
|
|
+ @property({
|
|
|
+ type: Button,
|
|
|
+ tooltip: '继续按钮 (Canvas/GameEnd/Continue)'
|
|
|
+ })
|
|
|
+ public continueButton: Button = null;
|
|
|
+
|
|
|
+ @property({
|
|
|
+ type: InGameManager,
|
|
|
+ tooltip: '游戏管理器组件'
|
|
|
+ })
|
|
|
+ public inGameManager: InGameManager = null;
|
|
|
+
|
|
|
+ // 动画相关属性已移除,现在由MoneyAni组件负责处理奖励动画
|
|
|
+
|
|
|
+ // === 私有属性 ===
|
|
|
+ private saveDataManager: SaveDataManager = null;
|
|
|
+ public currentRewards: {money: number, diamonds: number};
|
|
|
+ private hasDoubledReward: boolean = false;
|
|
|
+ private isGameSuccess: boolean = false;
|
|
|
+
|
|
|
+ start() {
|
|
|
+ console.log('[GameEnd] start方法被调用');
|
|
|
+ // start方法只在节点首次激活时调用一次
|
|
|
+ // 如果节点初始状态为false,start不会被调用
|
|
|
+ }
|
|
|
+
|
|
|
+ onEnable() {
|
|
|
+ console.log('[GameEnd] onEnable方法被调用,节点已激活');
|
|
|
+
|
|
|
+ // 初始化管理器
|
|
|
+ this.initializeManagers();
|
|
|
+
|
|
|
+ // UI节点已通过装饰器挂载,无需自动查找
|
|
|
+
|
|
|
+ // 绑定按钮事件
|
|
|
+ this.bindButtonEvents();
|
|
|
+
|
|
|
+ // 监听游戏事件
|
|
|
+ this.setupEventListeners();
|
|
|
+
|
|
|
+ // 初始化UI状态
|
|
|
+ this.initializeUI();
|
|
|
+
|
|
|
+ // 检查当前游戏状态并处理奖励(解决时序问题)
|
|
|
+ this.checkAndHandleGameState();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化管理器
|
|
|
+ */
|
|
|
+ private initializeManagers() {
|
|
|
+ this.saveDataManager = SaveDataManager.getInstance();
|
|
|
+ // InGameManager已通过装饰器挂载,无需查找
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 绑定按钮事件
|
|
|
+ */
|
|
|
+ private bindButtonEvents() {
|
|
|
+ if (this.doubleButton) {
|
|
|
+ this.doubleButton.node.on(Button.EventType.CLICK, this.onDoubleButtonClick, this);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.continueButton) {
|
|
|
+ this.continueButton.node.on(Button.EventType.CLICK, this.onContinueButtonClick, this);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置事件监听器
|
|
|
+ */
|
|
|
+ private setupEventListeners() {
|
|
|
+ console.log('[GameEnd] 开始设置事件监听器');
|
|
|
+ const eventBus = EventBus.getInstance();
|
|
|
+
|
|
|
+ // 监听游戏成功事件
|
|
|
+ eventBus.on(GameEvents.GAME_SUCCESS, this.onGameSuccess, this);
|
|
|
+ console.log('[GameEnd] 已注册GAME_SUCCESS事件监听器');
|
|
|
+
|
|
|
+ // 监听游戏失败事件
|
|
|
+ eventBus.on(GameEvents.GAME_DEFEAT, this.onGameDefeat, this);
|
|
|
+ console.log('[GameEnd] 已注册GAME_DEFEAT事件监听器');
|
|
|
+
|
|
|
+ // 监听UI重置事件
|
|
|
+ eventBus.on(GameEvents.RESET_UI_STATES, this.onResetUI, this);
|
|
|
+ console.log('[GameEnd] 事件监听器设置完成');
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化UI状态
|
|
|
+ */
|
|
|
+ private initializeUI() {
|
|
|
+ // 不强制隐藏面板,让UIStateManager控制面板显示状态
|
|
|
+ // this.node.active = false;
|
|
|
+
|
|
|
+ // 重置状态
|
|
|
+ this.hasDoubledReward = false;
|
|
|
+ this.currentRewards = {money: 0, diamonds: 0};
|
|
|
+
|
|
|
+ console.log('[GameEnd] UI状态初始化完成,面板状态由UIStateManager控制');
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查当前游戏状态并处理奖励(解决时序问题)
|
|
|
+ */
|
|
|
+ private checkAndHandleGameState() {
|
|
|
+ console.log('[GameEnd] 检查当前游戏状态');
|
|
|
+
|
|
|
+ if (!this.inGameManager) {
|
|
|
+ console.log('[GameEnd] InGameManager未初始化,无法检查游戏状态');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const currentState = this.inGameManager.getCurrentState();
|
|
|
+ console.log('[GameEnd] 当前游戏状态:', currentState);
|
|
|
+
|
|
|
+ // 如果游戏已经结束,主动处理奖励
|
|
|
+ if (currentState === GameState.SUCCESS) {
|
|
|
+ console.log('[GameEnd] 检测到游戏成功状态,主动处理奖励');
|
|
|
+ this.isGameSuccess = true;
|
|
|
+ this.calculateAndShowRewards();
|
|
|
+ } else if (currentState === GameState.DEFEAT) {
|
|
|
+ console.log('[GameEnd] 检测到游戏失败状态,主动处理奖励');
|
|
|
+ this.isGameSuccess = false;
|
|
|
+ this.calculateAndShowRewards();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理游戏成功事件
|
|
|
+ */
|
|
|
+ private onGameSuccess() {
|
|
|
+ console.log('[GameEnd] 接收到GAME_SUCCESS事件');
|
|
|
+ console.log('[GameEnd] 游戏成功,准备显示奖励');
|
|
|
+ this.isGameSuccess = true;
|
|
|
+ this.calculateAndShowRewards();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理游戏失败事件
|
|
|
+ */
|
|
|
+ private onGameDefeat() {
|
|
|
+ console.log('[GameEnd] 接收到GAME_DEFEAT事件');
|
|
|
+ console.log('[GameEnd] 游戏失败,准备显示奖励');
|
|
|
+ this.isGameSuccess = false;
|
|
|
+ this.calculateAndShowRewards();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算并显示奖励
|
|
|
+ */
|
|
|
+ private async calculateAndShowRewards() {
|
|
|
+ console.log('[GameEnd] 开始计算并显示奖励');
|
|
|
+
|
|
|
+ if (!this.saveDataManager) {
|
|
|
+ console.error('[GameEnd] SaveDataManager未初始化');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const currentLevel = this.saveDataManager.getCurrentLevel();
|
|
|
+ console.log(`[GameEnd] 当前关卡: ${currentLevel}, 游戏成功: ${this.isGameSuccess}`);
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (this.isGameSuccess) {
|
|
|
+ // 游戏成功,给予完整奖励
|
|
|
+ console.log('[GameEnd] 准备给予成功奖励');
|
|
|
+ await this.saveDataManager.giveCompletionRewards(currentLevel);
|
|
|
+ console.log('[GameEnd] 已给予成功奖励');
|
|
|
+ } else {
|
|
|
+ // 游戏失败,给予按比例奖励
|
|
|
+ const totalWaves = this.inGameManager?.levelWaves?.length || 1;
|
|
|
+ const completedWaves = this.inGameManager ? Math.max(0, this.inGameManager.getCurrentWave() - 1) : 0;
|
|
|
+
|
|
|
+ console.log(`[GameEnd] 准备给予失败奖励,完成波数: ${completedWaves}/${totalWaves}`);
|
|
|
+ await this.saveDataManager.giveFailureRewards(currentLevel, completedWaves, totalWaves);
|
|
|
+ console.log(`[GameEnd] 已给予失败奖励,完成波数: ${completedWaves}/${totalWaves}`);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取奖励数据并显示
|
|
|
+ this.currentRewards = this.saveDataManager.getLastRewards();
|
|
|
+ console.log('[GameEnd] 获取到的奖励数据:', this.currentRewards);
|
|
|
+ this.updateRewardDisplay();
|
|
|
+
|
|
|
+ // 显示结算面板
|
|
|
+ this.showEndPanel();
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('[GameEnd] 计算奖励时出错:', error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新奖励显示
|
|
|
+ */
|
|
|
+ private updateRewardDisplay() {
|
|
|
+ if (this.moneyLabel) {
|
|
|
+ this.moneyLabel.string = this.currentRewards.money.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.diamondLabel) {
|
|
|
+ this.diamondLabel.string = this.currentRewards.diamonds.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log(`[GameEnd] 更新奖励显示 - 金币: ${this.currentRewards.money}, 钻石: ${this.currentRewards.diamonds}`);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 显示结算面板
|
|
|
+ */
|
|
|
+ private showEndPanel() {
|
|
|
+ this.node.active = true;
|
|
|
+
|
|
|
+ // 重置双倍奖励状态
|
|
|
+ this.hasDoubledReward = false;
|
|
|
+ if (this.doubleButton) {
|
|
|
+ this.doubleButton.interactable = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('[GameEnd] 结算面板已显示');
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 双倍按钮点击事件
|
|
|
+ */
|
|
|
+ private onDoubleButtonClick() {
|
|
|
+ if (this.hasDoubledReward) {
|
|
|
+ console.log('[GameEnd] 已经获得过双倍奖励');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('[GameEnd] 点击双倍奖励按钮');
|
|
|
+
|
|
|
+ // 这里可以添加观看广告的逻辑
|
|
|
+ // 暂时直接给予双倍奖励
|
|
|
+ this.giveDoubleReward();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 给予双倍奖励
|
|
|
+ */
|
|
|
+ private giveDoubleReward() {
|
|
|
+ if (!this.saveDataManager || this.hasDoubledReward) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算双倍奖励
|
|
|
+ const doubleMoney = this.currentRewards.money;
|
|
|
+ const doubleDiamonds = this.currentRewards.diamonds;
|
|
|
+
|
|
|
+ // 添加额外奖励到玩家账户
|
|
|
+ if (doubleMoney > 0) {
|
|
|
+ this.saveDataManager.addMoney(doubleMoney, 'double_reward');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (doubleDiamonds > 0) {
|
|
|
+ this.saveDataManager.addDiamonds(doubleDiamonds, 'double_reward');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新当前奖励显示(显示双倍后的数值)
|
|
|
+ this.currentRewards.money += doubleMoney;
|
|
|
+ this.currentRewards.diamonds += doubleDiamonds;
|
|
|
+ this.updateRewardDisplay();
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // 标记已获得双倍奖励
|
|
|
+ this.hasDoubledReward = true;
|
|
|
+
|
|
|
+ // 禁用双倍按钮
|
|
|
+ if (this.doubleButton) {
|
|
|
+ this.doubleButton.interactable = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log(`[GameEnd] 双倍奖励已给予 - 额外金币: ${doubleMoney}, 额外钻石: ${doubleDiamonds}`);
|
|
|
+
|
|
|
+ // 触发货币变化事件
|
|
|
+ EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 继续按钮点击事件
|
|
|
+ */
|
|
|
+ private onContinueButtonClick() {
|
|
|
+ console.log('[GameEnd] 点击继续按钮');
|
|
|
+
|
|
|
+ // 派发事件给MoneyAni播放奖励动画
|
|
|
+ const rewards = this.saveDataManager.getLastRewards();
|
|
|
+ console.log('[GameEnd] 派发奖励动画事件,奖励数据:', rewards);
|
|
|
+ EventBus.getInstance().emit('PLAY_REWARD_ANIMATION', {
|
|
|
+ money: rewards.money,
|
|
|
+ diamonds: rewards.diamonds
|
|
|
+ });
|
|
|
+
|
|
|
+ // 触发返回主菜单事件
|
|
|
+ EventBus.getInstance().emit('CONTINUE_CLICK');
|
|
|
+
|
|
|
+ // 隐藏结算面板
|
|
|
+ this.hideEndPanel();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 隐藏结算面板
|
|
|
+ */
|
|
|
+ private hideEndPanel() {
|
|
|
+ this.node.active = false;
|
|
|
+ console.log('[GameEnd] 结算面板已隐藏');
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 重置UI状态
|
|
|
+ */
|
|
|
+ private onResetUI() {
|
|
|
+ console.log('[GameEnd] 重置UI状态');
|
|
|
+ this.hideEndPanel();
|
|
|
+ this.hasDoubledReward = false;
|
|
|
+ this.currentRewards = {money: 0, diamonds: 0};
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前奖励信息(用于外部查询)
|
|
|
+ */
|
|
|
+ public getCurrentRewards(): {money: number, diamonds: number} {
|
|
|
+ return {...this.currentRewards};
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查是否已获得双倍奖励
|
|
|
+ */
|
|
|
+ public hasGotDoubleReward(): boolean {
|
|
|
+ return this.hasDoubledReward;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ onDisable() {
|
|
|
+ console.log('[GameEnd] onDisable方法被调用,节点已禁用');
|
|
|
+ // 清理事件监听
|
|
|
+ const eventBus = EventBus.getInstance();
|
|
|
+ eventBus.off(GameEvents.GAME_SUCCESS, this.onGameSuccess, this);
|
|
|
+ eventBus.off(GameEvents.GAME_DEFEAT, this.onGameDefeat, this);
|
|
|
+ eventBus.off(GameEvents.RESET_UI_STATES, this.onResetUI, this);
|
|
|
+ console.log('[GameEnd] 事件监听器已清理');
|
|
|
+ }
|
|
|
+
|
|
|
+ protected onDestroy() {
|
|
|
+ // 清理事件监听
|
|
|
+ const eventBus = EventBus.getInstance();
|
|
|
+ eventBus.off(GameEvents.GAME_SUCCESS, this.onGameSuccess, this);
|
|
|
+ eventBus.off(GameEvents.GAME_DEFEAT, this.onGameDefeat, this);
|
|
|
+ eventBus.off(GameEvents.RESET_UI_STATES, this.onResetUI, this);
|
|
|
+
|
|
|
+ // 清理按钮事件
|
|
|
+ if (this.doubleButton) {
|
|
|
+ this.doubleButton.node.off(Button.EventType.CLICK, this.onDoubleButtonClick, this);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.continueButton) {
|
|
|
+ this.continueButton.node.off(Button.EventType.CLICK, this.onContinueButtonClick, this);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|