SkillButtonController.ts 6.2 KB

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