GameEnd.ts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. import { _decorator, Component, Node, Label, Button } from 'cc';
  2. import { SaveDataManager } from '../LevelSystem/SaveDataManager';
  3. import { InGameManager, GameState } from '../LevelSystem/IN_game';
  4. import EventBus, { GameEvents } from '../Core/EventBus';
  5. const { ccclass, property } = _decorator;
  6. /**
  7. * 游戏结算界面管理器
  8. * 负责处理游戏结束后的奖励显示和双倍奖励功能
  9. */
  10. @ccclass('GameEnd')
  11. export class GameEnd extends Component {
  12. // === UI节点引用 ===
  13. @property({
  14. type: Button,
  15. tooltip: '双倍奖励按钮 (Canvas/GameEnd/double)'
  16. })
  17. public doubleButton: Button = null;
  18. @property({
  19. type: Label,
  20. tooltip: '钞票数量显示 '
  21. })
  22. public moneyLabel: Label = null;
  23. @property({
  24. type: Label,
  25. tooltip: '钻石数量显示 '
  26. })
  27. public diamondLabel: Label = null;
  28. @property({
  29. type: Button,
  30. tooltip: '继续按钮 (Canvas/GameEnd/Continue)'
  31. })
  32. public continueButton: Button = null;
  33. @property({
  34. type: InGameManager,
  35. tooltip: '游戏管理器组件'
  36. })
  37. public inGameManager: InGameManager = null;
  38. // 动画相关属性已移除,现在由MoneyAni组件负责处理奖励动画
  39. // === 私有属性 ===
  40. private saveDataManager: SaveDataManager = null;
  41. public currentRewards: {money: number, diamonds: number};
  42. private hasDoubledReward: boolean = false;
  43. private isGameSuccess: boolean = false;
  44. start() {
  45. console.log('[GameEnd] start方法被调用');
  46. // start方法只在节点首次激活时调用一次
  47. // 如果节点初始状态为false,start不会被调用
  48. }
  49. onEnable() {
  50. console.log('[GameEnd] onEnable方法被调用,节点已激活');
  51. // 初始化管理器
  52. this.initializeManagers();
  53. // UI节点已通过装饰器挂载,无需自动查找
  54. // 绑定按钮事件
  55. this.bindButtonEvents();
  56. // 监听游戏事件
  57. this.setupEventListeners();
  58. // 初始化UI状态
  59. this.initializeUI();
  60. // 检查当前游戏状态并处理奖励(解决时序问题)
  61. this.checkAndHandleGameState();
  62. }
  63. /**
  64. * 初始化管理器
  65. */
  66. private initializeManagers() {
  67. this.saveDataManager = SaveDataManager.getInstance();
  68. // InGameManager已通过装饰器挂载,无需查找
  69. }
  70. /**
  71. * 绑定按钮事件
  72. */
  73. private bindButtonEvents() {
  74. if (this.doubleButton) {
  75. this.doubleButton.node.on(Button.EventType.CLICK, this.onDoubleButtonClick, this);
  76. }
  77. if (this.continueButton) {
  78. this.continueButton.node.on(Button.EventType.CLICK, this.onContinueButtonClick, this);
  79. }
  80. }
  81. /**
  82. * 设置事件监听器
  83. */
  84. private setupEventListeners() {
  85. console.log('[GameEnd] 开始设置事件监听器');
  86. const eventBus = EventBus.getInstance();
  87. // 监听游戏成功事件
  88. eventBus.on(GameEvents.GAME_SUCCESS, this.onGameSuccess, this);
  89. console.log('[GameEnd] 已注册GAME_SUCCESS事件监听器');
  90. // 监听游戏失败事件
  91. eventBus.on(GameEvents.GAME_DEFEAT, this.onGameDefeat, this);
  92. console.log('[GameEnd] 已注册GAME_DEFEAT事件监听器');
  93. // 监听UI重置事件
  94. eventBus.on(GameEvents.RESET_UI_STATES, this.onResetUI, this);
  95. console.log('[GameEnd] 事件监听器设置完成');
  96. }
  97. /**
  98. * 初始化UI状态
  99. */
  100. private initializeUI() {
  101. // 不强制隐藏面板,让UIStateManager控制面板显示状态
  102. // this.node.active = false;
  103. // 重置状态
  104. this.hasDoubledReward = false;
  105. this.currentRewards = {money: 0, diamonds: 0};
  106. console.log('[GameEnd] UI状态初始化完成,面板状态由UIStateManager控制');
  107. }
  108. /**
  109. * 检查当前游戏状态并处理奖励(解决时序问题)
  110. */
  111. private checkAndHandleGameState() {
  112. console.log('[GameEnd] 检查当前游戏状态');
  113. if (!this.inGameManager) {
  114. console.log('[GameEnd] InGameManager未初始化,无法检查游戏状态');
  115. return;
  116. }
  117. const currentState = this.inGameManager.getCurrentState();
  118. console.log('[GameEnd] 当前游戏状态:', currentState);
  119. // 如果游戏已经结束,主动处理奖励
  120. if (currentState === GameState.SUCCESS) {
  121. console.log('[GameEnd] 检测到游戏成功状态,主动处理奖励');
  122. this.isGameSuccess = true;
  123. this.calculateAndShowRewards();
  124. } else if (currentState === GameState.DEFEAT) {
  125. console.log('[GameEnd] 检测到游戏失败状态,主动处理奖励');
  126. this.isGameSuccess = false;
  127. this.calculateAndShowRewards();
  128. }
  129. }
  130. /**
  131. * 处理游戏成功事件
  132. */
  133. private onGameSuccess() {
  134. console.log('[GameEnd] 接收到GAME_SUCCESS事件');
  135. console.log('[GameEnd] 游戏成功,准备显示奖励');
  136. this.isGameSuccess = true;
  137. this.calculateAndShowRewards();
  138. }
  139. /**
  140. * 处理游戏失败事件
  141. */
  142. private onGameDefeat() {
  143. console.log('[GameEnd] 接收到GAME_DEFEAT事件');
  144. console.log('[GameEnd] 游戏失败,准备显示奖励');
  145. this.isGameSuccess = false;
  146. this.calculateAndShowRewards();
  147. }
  148. /**
  149. * 计算并显示奖励
  150. */
  151. private async calculateAndShowRewards() {
  152. console.log('[GameEnd] 开始计算并显示奖励');
  153. if (!this.saveDataManager) {
  154. console.error('[GameEnd] SaveDataManager未初始化');
  155. return;
  156. }
  157. const currentLevel = this.saveDataManager.getCurrentLevel();
  158. console.log(`[GameEnd] 当前关卡: ${currentLevel}, 游戏成功: ${this.isGameSuccess}`);
  159. try {
  160. if (this.isGameSuccess) {
  161. // 游戏成功,给予完整奖励
  162. console.log('[GameEnd] 准备给予成功奖励');
  163. await this.saveDataManager.giveCompletionRewards(currentLevel);
  164. console.log('[GameEnd] 已给予成功奖励');
  165. } else {
  166. // 游戏失败,给予按比例奖励
  167. const totalWaves = this.inGameManager?.levelWaves?.length || 1;
  168. const completedWaves = this.inGameManager ? Math.max(0, this.inGameManager.getCurrentWave() - 1) : 0;
  169. console.log(`[GameEnd] 准备给予失败奖励,完成波数: ${completedWaves}/${totalWaves}`);
  170. await this.saveDataManager.giveFailureRewards(currentLevel, completedWaves, totalWaves);
  171. console.log(`[GameEnd] 已给予失败奖励,完成波数: ${completedWaves}/${totalWaves}`);
  172. }
  173. // 获取奖励数据并显示
  174. this.currentRewards = this.saveDataManager.getLastRewards();
  175. console.log('[GameEnd] 获取到的奖励数据:', this.currentRewards);
  176. this.updateRewardDisplay();
  177. // 显示结算面板
  178. this.showEndPanel();
  179. } catch (error) {
  180. console.error('[GameEnd] 计算奖励时出错:', error);
  181. }
  182. }
  183. /**
  184. * 更新奖励显示
  185. */
  186. private updateRewardDisplay() {
  187. if (this.moneyLabel) {
  188. this.moneyLabel.string = this.currentRewards.money.toString();
  189. }
  190. if (this.diamondLabel) {
  191. this.diamondLabel.string = this.currentRewards.diamonds.toString();
  192. }
  193. console.log(`[GameEnd] 更新奖励显示 - 钞票: ${this.currentRewards.money}, 钻石: ${this.currentRewards.diamonds}`);
  194. }
  195. /**
  196. * 显示结算面板
  197. */
  198. private showEndPanel() {
  199. this.node.active = true;
  200. // 重置双倍奖励状态
  201. this.hasDoubledReward = false;
  202. if (this.doubleButton) {
  203. this.doubleButton.interactable = true;
  204. }
  205. console.log('[GameEnd] 结算面板已显示');
  206. }
  207. /**
  208. * 双倍按钮点击事件
  209. */
  210. private onDoubleButtonClick() {
  211. if (this.hasDoubledReward) {
  212. console.log('[GameEnd] 已经获得过双倍奖励');
  213. return;
  214. }
  215. console.log('[GameEnd] 点击双倍奖励按钮');
  216. // 这里可以添加观看广告的逻辑
  217. // 暂时直接给予双倍奖励
  218. this.giveDoubleReward();
  219. }
  220. /**
  221. * 给予双倍奖励
  222. */
  223. private giveDoubleReward() {
  224. if (!this.saveDataManager || this.hasDoubledReward) {
  225. return;
  226. }
  227. // 计算双倍奖励
  228. const doubleMoney = this.currentRewards.money;
  229. const doubleDiamonds = this.currentRewards.diamonds;
  230. // 添加额外奖励到玩家账户
  231. if (doubleMoney > 0) {
  232. this.saveDataManager.addMoney(doubleMoney, 'double_reward');
  233. }
  234. if (doubleDiamonds > 0) {
  235. this.saveDataManager.addDiamonds(doubleDiamonds, 'double_reward');
  236. }
  237. // 更新当前奖励显示(显示双倍后的数值)
  238. this.currentRewards.money += doubleMoney;
  239. this.currentRewards.diamonds += doubleDiamonds;
  240. this.updateRewardDisplay();
  241. // 标记已获得双倍奖励
  242. this.hasDoubledReward = true;
  243. // 禁用双倍按钮
  244. if (this.doubleButton) {
  245. this.doubleButton.interactable = false;
  246. }
  247. console.log(`[GameEnd] 双倍奖励已给予 - 额外钞票: ${doubleMoney}, 额外钻石: ${doubleDiamonds}`);
  248. // 触发货币变化事件
  249. EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
  250. }
  251. /**
  252. * 继续按钮点击事件
  253. */
  254. private onContinueButtonClick() {
  255. console.log('[GameEnd] 点击继续按钮');
  256. // 派发事件给MoneyAni播放奖励动画
  257. const rewards = this.saveDataManager.getLastRewards();
  258. console.log('[GameEnd] 派发奖励动画事件,奖励数据:', rewards);
  259. EventBus.getInstance().emit('PLAY_REWARD_ANIMATION', {
  260. money: rewards.money,
  261. diamonds: rewards.diamonds
  262. });
  263. // 触发返回主菜单事件
  264. EventBus.getInstance().emit('CONTINUE_CLICK');
  265. // 隐藏结算面板
  266. this.hideEndPanel();
  267. }
  268. /**
  269. * 隐藏结算面板
  270. */
  271. private hideEndPanel() {
  272. this.node.active = false;
  273. console.log('[GameEnd] 结算面板已隐藏');
  274. }
  275. /**
  276. * 重置UI状态
  277. */
  278. private onResetUI() {
  279. console.log('[GameEnd] 重置UI状态');
  280. this.hideEndPanel();
  281. this.hasDoubledReward = false;
  282. this.currentRewards = {money: 0, diamonds: 0};
  283. }
  284. /**
  285. * 获取当前奖励信息(用于外部查询)
  286. */
  287. public getCurrentRewards(): {money: number, diamonds: number} {
  288. return {...this.currentRewards};
  289. }
  290. /**
  291. * 检查是否已获得双倍奖励
  292. */
  293. public hasGotDoubleReward(): boolean {
  294. return this.hasDoubledReward;
  295. }
  296. onDisable() {
  297. console.log('[GameEnd] onDisable方法被调用,节点已禁用');
  298. // 清理事件监听
  299. const eventBus = EventBus.getInstance();
  300. eventBus.off(GameEvents.GAME_SUCCESS, this.onGameSuccess, this);
  301. eventBus.off(GameEvents.GAME_DEFEAT, this.onGameDefeat, this);
  302. eventBus.off(GameEvents.RESET_UI_STATES, this.onResetUI, this);
  303. console.log('[GameEnd] 事件监听器已清理');
  304. }
  305. protected onDestroy() {
  306. // 清理事件监听
  307. const eventBus = EventBus.getInstance();
  308. eventBus.off(GameEvents.GAME_SUCCESS, this.onGameSuccess, this);
  309. eventBus.off(GameEvents.GAME_DEFEAT, this.onGameDefeat, this);
  310. eventBus.off(GameEvents.RESET_UI_STATES, this.onResetUI, this);
  311. // 清理按钮事件
  312. if (this.doubleButton) {
  313. this.doubleButton.node.off(Button.EventType.CLICK, this.onDoubleButtonClick, this);
  314. }
  315. if (this.continueButton) {
  316. this.continueButton.node.off(Button.EventType.CLICK, this.onContinueButtonClick, this);
  317. }
  318. }
  319. }