SkillButtonController.ts 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import { _decorator, Component, Node, Button, Label, Sprite, resources, SpriteFrame } from 'cc';
  2. import { SkillManager, SkillData } from './SkillManager';
  3. import { SkillButtonAnimator } from './SkillButtonAnimator';
  4. import { Audio } from '../../AudioManager/AudioManager';
  5. const { ccclass, property } = _decorator;
  6. /**
  7. * SkillButtonController
  8. * 单个技能按钮的控制器,负责显示技能信息和处理点击事件
  9. * 配合预制体使用,提高代码复用性和维护性
  10. */
  11. @ccclass('SkillButtonController')
  12. export class SkillButtonController extends Component {
  13. @property({ type: Node, tooltip: '技能图标节点' })
  14. public skillSpriteNode: Node = null!;
  15. @property({ type: Node, tooltip: '技能名称节点' })
  16. public skillNameNode: Node = null!;
  17. @property({ type: Node, tooltip: '技能介绍节点' })
  18. public skillIntroduceNode: Node = null!;
  19. // 当前技能数据
  20. private _skillData: SkillData | null = null;
  21. // 按钮组件
  22. private _button: Button | null = null;
  23. // 动画组件
  24. private _animator: SkillButtonAnimator | null = null;
  25. // 点击回调
  26. private _onClickCallback: ((skillButton: SkillButtonController) => void) | null = null;
  27. protected onLoad() {
  28. this._button = this.getComponent(Button);
  29. this._animator = this.getComponent(SkillButtonAnimator);
  30. // 如果没有手动设置节点引用,尝试自动查找
  31. if (!this.skillSpriteNode) {
  32. this.skillSpriteNode = this.node.getChildByName('SkillSprite');
  33. }
  34. if (!this.skillNameNode) {
  35. this.skillNameNode = this.node.getChildByName('SkillName');
  36. }
  37. if (!this.skillIntroduceNode && this.skillNameNode) {
  38. this.skillIntroduceNode = this.skillNameNode.getChildByName('SkillIntroduce');
  39. }
  40. }
  41. protected start() {
  42. if (this._button) {
  43. this._button.node.on(Button.EventType.CLICK, this.onButtonClick, this);
  44. }
  45. }
  46. protected onDestroy() {
  47. if (this._button) {
  48. this._button.node.off(Button.EventType.CLICK, this.onButtonClick, this);
  49. }
  50. }
  51. /**
  52. * 设置技能数据并更新UI显示
  53. */
  54. public setSkillData(skillData: SkillData) {
  55. this._skillData = skillData;
  56. this.updateUI();
  57. }
  58. /**
  59. * 获取当前技能数据
  60. */
  61. public getSkillData(): SkillData | null {
  62. return this._skillData;
  63. }
  64. /**
  65. * 设置点击回调
  66. */
  67. public setClickCallback(callback: (skillButton: SkillButtonController) => void) {
  68. this._onClickCallback = callback;
  69. }
  70. /**
  71. * 更新UI显示
  72. */
  73. private updateUI() {
  74. if (!this._skillData) {
  75. this.node.active = false;
  76. return;
  77. }
  78. this.node.active = true;
  79. // 更新技能图标
  80. this.updateSkillIcon();
  81. // 更新技能名称
  82. this.updateSkillName();
  83. // 更新技能介绍
  84. this.updateSkillDescription();
  85. // 更新星级显示
  86. this.updateSkillLevel();
  87. }
  88. /**
  89. * 更新技能图标
  90. */
  91. private updateSkillIcon() {
  92. if (!this.skillSpriteNode || !this._skillData) return;
  93. const sprite = this.skillSpriteNode.getComponent(Sprite);
  94. if (sprite) {
  95. const framePath = `${this._skillData.iconPath}/spriteFrame`;
  96. resources.load(framePath, SpriteFrame, (err, spriteFrame) => {
  97. if (!err && spriteFrame && sprite && sprite.isValid) {
  98. sprite.spriteFrame = spriteFrame;
  99. console.log(`技能图标加载成功: ${this._skillData!.iconPath}`);
  100. } else if (err) {
  101. console.warn(`加载技能图标失败: ${this._skillData!.iconPath}`, err);
  102. }
  103. });
  104. }
  105. }
  106. /**
  107. * 更新技能名称
  108. */
  109. private updateSkillName() {
  110. if (!this.skillNameNode || !this._skillData) return;
  111. const label = this.skillNameNode.getComponent(Label);
  112. if (label) {
  113. label.string = this._skillData.name;
  114. }
  115. }
  116. /**
  117. * 更新技能介绍
  118. */
  119. private updateSkillDescription() {
  120. if (!this.skillIntroduceNode || !this._skillData) return;
  121. const label = this.skillIntroduceNode.getComponent(Label);
  122. if (label) {
  123. const skillManager = SkillManager.getInstance();
  124. if (skillManager) {
  125. // 检查技能是否满级
  126. if (skillManager.isSkillMaxLevel(this._skillData.id)) {
  127. label.string = "技能等级已满";
  128. } else {
  129. // 获取当前技能等级的描述
  130. const currentLevel = skillManager.getSkillLevel(this._skillData.id);
  131. const description = skillManager.getSkillDescription(this._skillData.id, currentLevel);
  132. label.string = description;
  133. }
  134. } else {
  135. label.string = this._skillData.description;
  136. }
  137. }
  138. }
  139. /**
  140. * 更新技能等级显示
  141. */
  142. private updateSkillLevel() {
  143. if (!this._animator || !this._skillData) return;
  144. const skillManager = SkillManager.getInstance();
  145. const actualLevel = skillManager ? skillManager.getSkillLevel(this._skillData.id) : 0;
  146. this._animator.setSkillLevel(actualLevel);
  147. console.log(`设置技能 ${this._skillData.name} 星级: ${actualLevel}`);
  148. }
  149. /**
  150. * 刷新技能等级显示(用于技能升级后的UI更新)
  151. */
  152. public refreshSkillLevel() {
  153. this.updateSkillLevel();
  154. this.updateSkillDescription(); // 同时更新描述
  155. }
  156. /**
  157. * 按钮点击事件
  158. */
  159. private onButtonClick() {
  160. Audio.playUISound('data/弹球音效/level up 2');
  161. if (this._onClickCallback) {
  162. this._onClickCallback(this);
  163. }
  164. }
  165. /**
  166. * 播放收缩动画
  167. */
  168. public playShrinkAnimation(duration: number, targetPos?: any, onComplete?: () => void) {
  169. if (this._animator) {
  170. this._animator.playShrink(duration, targetPos, onComplete);
  171. } else if (onComplete) {
  172. onComplete();
  173. }
  174. }
  175. /**
  176. * 重置动画状态
  177. */
  178. public resetAnimationState() {
  179. if (this._animator) {
  180. this._animator.resetState();
  181. }
  182. }
  183. /**
  184. * 设置按钮交互状态
  185. */
  186. public setInteractable(interactable: boolean) {
  187. if (this._button) {
  188. this._button.interactable = interactable;
  189. }
  190. }
  191. }