GameBlockSelection.ts 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. import { _decorator, Component, Node, Button, Label, find, UITransform, Sprite, Color } from 'cc';
  2. import { LevelSessionManager } from '../../Core/LevelSessionManager';
  3. import { BallController } from '../BallController';
  4. import { BlockManager } from '../BlockManager';
  5. import { GameStartMove } from '../../Animations/GameStartMove';
  6. const { ccclass, property } = _decorator;
  7. @ccclass('GameBlockSelection')
  8. export class GameBlockSelection extends Component {
  9. @property({
  10. type: Node,
  11. tooltip: '拖拽BlockSelectionUI/diban/ann001按钮节点到这里'
  12. })
  13. public addBallButton: Node = null;
  14. @property({
  15. type: Node,
  16. tooltip: '拖拽BlockSelectionUI/diban/ann002按钮节点到这里'
  17. })
  18. public addCoinButton: Node = null;
  19. @property({
  20. type: Node,
  21. tooltip: '拖拽BlockSelectionUI/diban/ann003按钮节点到这里'
  22. })
  23. public refreshButton: Node = null;
  24. @property({
  25. type: Node,
  26. tooltip: '拖拽Canvas-001/TopArea/CoinNode/CoinLabel节点到这里'
  27. })
  28. public coinLabelNode: Node = null;
  29. @property({
  30. type: Node,
  31. tooltip: '拖拽Canvas/InsufficientCoinsUI节点到这里'
  32. })
  33. public insufficientCoinsUI: Node = null;
  34. @property({
  35. type: Node,
  36. tooltip: '拖拽Canvas/GameLevelUI/BallController节点到这里'
  37. })
  38. public ballControllerNode: Node = null;
  39. @property({
  40. type: Node,
  41. tooltip: '拖拽Canvas/GameLevelUI/BlockController节点到这里'
  42. })
  43. public blockManagerNode: Node = null;
  44. @property({
  45. type: Node,
  46. tooltip: '拖拽Canvas/Camera节点到这里'
  47. })
  48. public cameraNode: Node = null;
  49. @property({
  50. type: Node,
  51. tooltip: '拖拽Canvas/GameLevelUI/GameArea/GridContainer节点到这里'
  52. })
  53. public gridContainer: Node = null;
  54. @property({
  55. type: Node,
  56. tooltip: '拖拽confirm按钮节点到这里'
  57. })
  58. public confirmButton: Node = null;
  59. // 按钮费用配置
  60. private readonly ADD_BALL_COST = 80;
  61. private readonly ADD_COIN_AMOUNT = 80;
  62. private readonly REFRESH_COST = 5;
  63. private session: LevelSessionManager = null;
  64. private ballController: BallController = null;
  65. private blockManager: BlockManager = null;
  66. private gameStartMove: GameStartMove = null;
  67. // 回调函数,用于通知GameManager
  68. public onConfirmCallback: () => void = null;
  69. start() {
  70. // 获取管理器实例
  71. this.session = LevelSessionManager.inst;
  72. // 获取BallController
  73. if (this.ballControllerNode) {
  74. this.ballController = this.ballControllerNode.getComponent(BallController);
  75. } else {
  76. console.warn('BallController节点未绑定,请在Inspector中拖拽Canvas/GameLevelUI/BallController节点');
  77. }
  78. // 获取BlockManager
  79. if (this.blockManagerNode) {
  80. this.blockManager = this.blockManagerNode.getComponent(BlockManager);
  81. } else {
  82. console.warn('BlockManager节点未绑定,请在Inspector中拖拽Canvas/GameLevelUI/BlockController节点');
  83. }
  84. // 获取GameStartMove组件
  85. if (this.cameraNode) {
  86. this.gameStartMove = this.cameraNode.getComponent(GameStartMove);
  87. }
  88. // 如果没有指定coinLabelNode,尝试找到它
  89. if (!this.coinLabelNode) {
  90. this.coinLabelNode = find('Canvas-001/TopArea/CoinNode/CoinLabel');
  91. }
  92. // 绑定按钮事件
  93. this.bindButtonEvents();
  94. }
  95. // 绑定按钮事件
  96. private bindButtonEvents() {
  97. // 绑定新增小球按钮
  98. if (this.addBallButton) {
  99. const btn = this.addBallButton.getComponent(Button);
  100. if (btn) {
  101. this.addBallButton.on(Button.EventType.CLICK, this.onAddBallClicked, this);
  102. } else {
  103. this.addBallButton.on(Node.EventType.TOUCH_END, this.onAddBallClicked, this);
  104. }
  105. }
  106. // 绑定增加金币按钮
  107. if (this.addCoinButton) {
  108. const btn = this.addCoinButton.getComponent(Button);
  109. if (btn) {
  110. this.addCoinButton.on(Button.EventType.CLICK, this.onAddCoinClicked, this);
  111. } else {
  112. this.addCoinButton.on(Node.EventType.TOUCH_END, this.onAddCoinClicked, this);
  113. }
  114. }
  115. // 绑定刷新方块按钮
  116. if (this.refreshButton) {
  117. const btn = this.refreshButton.getComponent(Button);
  118. if (btn) {
  119. this.refreshButton.on(Button.EventType.CLICK, this.onRefreshClicked, this);
  120. } else {
  121. this.refreshButton.on(Node.EventType.TOUCH_END, this.onRefreshClicked, this);
  122. }
  123. }
  124. // 绑定确认按钮
  125. if (this.confirmButton) {
  126. const btn = this.confirmButton.getComponent(Button);
  127. if (btn) {
  128. this.confirmButton.on(Button.EventType.CLICK, this.onConfirmButtonClicked, this);
  129. } else {
  130. this.confirmButton.on(Node.EventType.TOUCH_END, this.onConfirmButtonClicked, this);
  131. }
  132. }
  133. }
  134. // 新增小球按钮点击
  135. private onAddBallClicked() {
  136. if (!this.canSpendCoins(this.ADD_BALL_COST)) {
  137. this.showInsufficientCoinsUI();
  138. return;
  139. }
  140. // 扣除金币
  141. if (this.session.spendCoins(this.ADD_BALL_COST)) {
  142. this.updateCoinDisplay();
  143. // 创建新的小球
  144. if (this.ballController) {
  145. this.ballController.createBall();
  146. console.log(`新增小球成功,扣除${this.ADD_BALL_COST}金币`);
  147. } else {
  148. console.error('找不到BallController,无法创建小球');
  149. }
  150. }
  151. }
  152. // 增加金币按钮点击
  153. private onAddCoinClicked() {
  154. this.session.addCoins(this.ADD_COIN_AMOUNT);
  155. this.updateCoinDisplay();
  156. console.log(`增加${this.ADD_COIN_AMOUNT}金币`);
  157. }
  158. // 刷新方块按钮点击
  159. private onRefreshClicked() {
  160. if (!this.canSpendCoins(this.REFRESH_COST)) {
  161. this.showInsufficientCoinsUI();
  162. return;
  163. }
  164. // 扣除金币
  165. if (this.session.spendCoins(this.REFRESH_COST)) {
  166. this.updateCoinDisplay();
  167. // 刷新方块
  168. if (this.blockManager) {
  169. this.blockManager.refreshBlocks();
  170. console.log(`刷新方块成功,扣除${this.REFRESH_COST}金币`);
  171. } else {
  172. console.error('找不到BlockManager,无法刷新方块');
  173. }
  174. }
  175. }
  176. // 确认按钮点击(从GameManager迁移的onConfirmButtonClicked)
  177. public onConfirmButtonClicked() {
  178. // 执行相机动画和UI关闭
  179. if (this.gameStartMove) {
  180. this.gameStartMove.slideDibanDownAndHide();
  181. } else {
  182. // Fallback: 若未挂载 GameStartMove,直接关闭
  183. this.node.active = false;
  184. }
  185. // Camera move back up with smooth animation
  186. if (this.gameStartMove) {
  187. this.gameStartMove.moveUpSmooth();
  188. }
  189. // 显示GridContainer
  190. if (this.gridContainer) {
  191. this.gridContainer.active = true;
  192. }
  193. // 保存已放置的方块
  194. this.preservePlacedBlocks();
  195. // 回调通知GameManager
  196. if (this.onConfirmCallback) {
  197. this.onConfirmCallback();
  198. }
  199. }
  200. // 保存已放置的方块(从GameManager迁移)
  201. private preservePlacedBlocks() {
  202. if (this.blockManager) {
  203. this.blockManager.onGameStart();
  204. }
  205. }
  206. // 检查是否有足够金币
  207. private canSpendCoins(amount: number): boolean {
  208. return this.session.getCoins() >= amount;
  209. }
  210. // 更新金币显示
  211. private updateCoinDisplay() {
  212. if (this.coinLabelNode) {
  213. const label = this.coinLabelNode.getComponent(Label);
  214. if (label) {
  215. label.string = this.session.getCoins().toString();
  216. }
  217. }
  218. }
  219. // 显示金币不足UI
  220. private showInsufficientCoinsUI() {
  221. if (!this.insufficientCoinsUI) {
  222. console.error('金币不足UI节点未绑定,请在Inspector中拖拽Canvas/InsufficientCoinsUI节点');
  223. return;
  224. }
  225. // 显示金币不足UI
  226. this.insufficientCoinsUI.active = true;
  227. // 3秒后自动隐藏
  228. this.scheduleOnce(() => {
  229. if (this.insufficientCoinsUI && this.insufficientCoinsUI.isValid) {
  230. this.insufficientCoinsUI.active = false;
  231. }
  232. }, 3.0);
  233. console.log('金币不足!');
  234. }
  235. // === 公共方法:供GameManager调用 ===
  236. // 显示方块选择UI(用于游戏开始或下一波)
  237. public showBlockSelection(isNextWave: boolean = false) {
  238. this.node.active = true;
  239. if (this.gridContainer) {
  240. this.gridContainer.active = true;
  241. }
  242. console.log(isNextWave ? '显示下一波方块选择UI' : '显示游戏开始方块选择UI');
  243. }
  244. // 隐藏方块选择UI
  245. public hideBlockSelection() {
  246. this.node.active = false;
  247. if (this.gridContainer) {
  248. this.gridContainer.active = false;
  249. }
  250. console.log('隐藏方块选择UI');
  251. }
  252. // 设置确认回调
  253. public setConfirmCallback(callback: () => void) {
  254. this.onConfirmCallback = callback;
  255. }
  256. }