SkillButtonAnimator.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import { _decorator, Component, Node, Vec3, tween, find, Sprite, Color, Tween } from 'cc';
  2. const { ccclass, property } = _decorator;
  3. /**
  4. * SkillButtonAnimator
  5. * 负责技能按钮的缩放 / 移动动画和星星闪烁效果。
  6. * 提供 playShrink 接口供外部调用。
  7. */
  8. @ccclass('SkillButtonAnimator')
  9. export class SkillButtonAnimator extends Component {
  10. @property({ type: [Node], tooltip: '星星节点数组 (xx-1 到 xx-5)' })
  11. starNodes: Node[] = [];
  12. private _origScale: Vec3 = new Vec3();
  13. private _origPos: Vec3 = new Vec3();
  14. private _blinkTween: Tween<Node> | null = null;
  15. private _blinkTweenTarget: Node | null = null;
  16. private _origStarScale: Vec3 | null = null;
  17. // 星星颜色配置
  18. private readonly STAR_ACTIVE_COLOR = new Color(255, 255, 255, 255); // 亮起的星星
  19. private readonly STAR_INACTIVE_COLOR = new Color(58, 37, 37, 255); // 未亮起的星星 (3A2525)
  20. onLoad() {
  21. // 记录初始位置、缩放,用于恢复
  22. this._origScale.set(this.node.scale);
  23. this._origPos.set(this.node.position);
  24. }
  25. /**
  26. * 设置技能等级并更新星星显示
  27. * @param currentLevel 当前等级 (0-5)
  28. */
  29. public setSkillLevel(currentLevel: number) {
  30. // 停止之前的闪烁动画
  31. this.stopBlinkAnimation();
  32. // 更新星星显示
  33. this.starNodes.forEach((starNode, index) => {
  34. const sprite = starNode.getComponent(Sprite);
  35. if (sprite) {
  36. if (index < currentLevel) {
  37. // 已获得等级的星星 - 常亮
  38. sprite.color = this.STAR_ACTIVE_COLOR;
  39. } else if (index === currentLevel && currentLevel < 5) {
  40. // 下一等级的星星 - 设置为未亮起状态,稍后开始闪烁
  41. sprite.color = this.STAR_INACTIVE_COLOR;
  42. } else {
  43. // 剩余星星 - 不亮
  44. sprite.color = this.STAR_INACTIVE_COLOR;
  45. }
  46. }
  47. });
  48. // 如果当前等级小于最大等级,开始闪烁下一颗星星(即将获得的等级)
  49. if (currentLevel < 5) {
  50. this.startBlinkAnimation(currentLevel);
  51. }
  52. }
  53. /**
  54. * 开始星星闪烁动画
  55. * @param nextStarIndex 下一颗要闪烁的星星索引 (0-4)
  56. */
  57. private startBlinkAnimation(nextStarIndex: number) {
  58. if (nextStarIndex >= this.starNodes.length) return;
  59. const nextStar = this.starNodes[nextStarIndex];
  60. const sprite = nextStar.getComponent(Sprite);
  61. if (!sprite) return;
  62. // 直接使用补间动画控制星星缩放闪烁(不依赖组件)
  63. if (this._blinkTween) {
  64. this._blinkTween.stop();
  65. this._blinkTween = null;
  66. }
  67. const origScale = nextStar.scale.clone();
  68. const targetScale = new Vec3(origScale.x * 1.3, origScale.y * 1.3, origScale.z);
  69. this._blinkTweenTarget = nextStar;
  70. this._origStarScale = origScale.clone();
  71. this._blinkTween = tween(nextStar)
  72. .to(0.15, { scale: targetScale }, { easing: 'sineOut' })
  73. .to(0.15, { scale: origScale }, { easing: 'sineIn' })
  74. .union()
  75. .repeatForever()
  76. .start();
  77. }
  78. /**
  79. * 停止星星闪烁动画
  80. */
  81. private stopBlinkAnimation() {
  82. if (this._blinkTween) {
  83. this._blinkTween.stop();
  84. this._blinkTween = null;
  85. }
  86. // 恢复被闪烁星星的原始缩放
  87. if (this._blinkTweenTarget && this._blinkTweenTarget.isValid && this._origStarScale) {
  88. this._blinkTweenTarget.setScale(this._origStarScale);
  89. }
  90. this._blinkTweenTarget = null;
  91. this._origStarScale = null;
  92. }
  93. /**
  94. * 播放缩小并(可选)移动到指定目标位置的动画。
  95. * @param duration 动画时长(秒)
  96. * @param targetPos 目标位置(节点本地坐标系),不传则保持原位置
  97. * @param onComplete 完成回调
  98. */
  99. public playShrink(duration: number = 0.3, targetPos?: Vec3, onComplete?: () => void) {
  100. // 停止闪烁动画
  101. this.stopBlinkAnimation();
  102. // 若目标位置存在,则先 tween 到该位置;否则只缩放
  103. const props: any = { scale: new Vec3(0, 0, 0) };
  104. if (targetPos) {
  105. props.position = targetPos;
  106. }
  107. tween(this.node)
  108. .to(duration, props, { easing: 'quadIn' })
  109. .call(() => {
  110. // 动画结束后隐藏节点,但允许后续 resetState 恢复
  111. this.node.active = false;
  112. if (onComplete) onComplete();
  113. })
  114. .start();
  115. this.node.setPosition(this._origPos);
  116. }
  117. public resetState() {
  118. // 停止闪烁动画
  119. this.stopBlinkAnimation();
  120. // Reset scale, position, opacity, etc. as needed
  121. this.node.setScale(Vec3.ONE);
  122. this.node.active = true;
  123. this.node.setPosition(this._origPos);
  124. // 重置星星显示为0级状态
  125. this.setSkillLevel(0);
  126. }
  127. onDestroy() {
  128. // 清理闪烁动画
  129. this.stopBlinkAnimation();
  130. }
  131. }
  132. export default SkillButtonAnimator;