UpgradeAni.ts 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import { _decorator, Component, Node, Tween, tween, Vec3, Material, Sprite, resources } from 'cc';
  2. import { Audio } from '../../AudioManager/AudioManager';
  3. const { ccclass, property } = _decorator;
  4. /**
  5. * 植物升级动画控制器
  6. * 负责管理植物升级相关的动画效果
  7. */
  8. @ccclass('UpgradeAni')
  9. export class UpgradeAni extends Component {
  10. @property(Node)
  11. weaponSpriteNode: Node = null;
  12. /**
  13. * 植物升级成功动画
  14. * 播放植物图标的放大缩小动画,并在升级期间应用扫描效果材质,同时播放升级音效
  15. * @param weaponIconNode 植物图标节点
  16. */
  17. public playWeaponUpgradeAnimation(weaponIconNode: Node): Promise<void> {
  18. return new Promise((resolve) => {
  19. if (!weaponIconNode) {
  20. resolve();
  21. return;
  22. }
  23. // 停止之前的动画,防止快速点击时动画冲突
  24. Tween.stopAllByTarget(weaponIconNode);
  25. // 重置到原始缩放状态,确保动画从正确的状态开始
  26. weaponIconNode.setScale(Vec3.ONE);
  27. // 保存原始缩放值
  28. const originalScale = Vec3.ONE.clone();
  29. let weaponSprite: Sprite = null;
  30. let originalMaterial: Material = null;
  31. console.log('[UpgradeAni] 开始武器升级动画,weaponSpriteNode:', this.weaponSpriteNode);
  32. // 播放植物升级音效
  33. Audio.playUISound('data/弹球音效/equipment level up finish');
  34. // 使用装饰器引用的WeaponSprite节点,获取其Sprite组件并保存原始材质
  35. if (this.weaponSpriteNode) {
  36. console.log('[UpgradeAni] 找到weaponSpriteNode,开始获取Sprite组件');
  37. weaponSprite = this.weaponSpriteNode.getComponent(Sprite);
  38. if (weaponSprite) {
  39. console.log('[UpgradeAni] 找到Sprite组件,开始加载材质');
  40. // 保存原始材质,优先保存customMaterial,如果没有则保存当前material
  41. originalMaterial = weaponSprite.customMaterial || weaponSprite.material;
  42. console.log('[UpgradeAni] 原始材质:', originalMaterial);
  43. // 加载并应用扫描效果材质
  44. resources.load('shaders/scan-effect', Material, (err, scanMaterial) => {
  45. console.log('[UpgradeAni] 材质加载回调,err:', err, 'scanMaterial:', scanMaterial);
  46. if (!err && scanMaterial && weaponSprite) {
  47. weaponSprite.material = scanMaterial;
  48. console.log('[UpgradeAni] 应用扫描效果材质成功');
  49. } else {
  50. console.warn('[UpgradeAni] 加载扫描效果材质失败:', err);
  51. }
  52. });
  53. } else {
  54. console.warn('[UpgradeAni] weaponSpriteNode上没有找到Sprite组件');
  55. }
  56. } else {
  57. console.warn('[UpgradeAni] weaponSpriteNode为null,请在编辑器中设置');
  58. }
  59. // 创建缩放动画:放大到1.5倍再立即缩小回原始大小
  60. const scaleAnimation = tween(weaponIconNode)
  61. .to(0.25, { scale: new Vec3(originalScale.x * 1.5, originalScale.y * 1.5, originalScale.z) }, {
  62. easing: 'sineOut'
  63. })
  64. .to(0.25, { scale: originalScale }, {
  65. easing: 'sineIn'
  66. })
  67. .call(() => {
  68. // 动画结束后恢复原始材质
  69. if (weaponSprite && originalMaterial) {
  70. // 如果原始材质是customMaterial,则恢复customMaterial
  71. if (weaponSprite.customMaterial === originalMaterial) {
  72. weaponSprite.material = weaponSprite.customMaterial;
  73. } else {
  74. weaponSprite.material = originalMaterial;
  75. }
  76. console.log('[UpgradeAni] 恢复原始材质成功');
  77. } else if (weaponSprite) {
  78. // 如果没有保存的原始材质,尝试恢复到customMaterial
  79. if (weaponSprite.customMaterial) {
  80. weaponSprite.material = weaponSprite.customMaterial;
  81. console.log('[UpgradeAni] 恢复到customMaterial');
  82. } else {
  83. weaponSprite.material = null;
  84. console.log('[UpgradeAni] 恢复到默认材质');
  85. }
  86. }
  87. resolve();
  88. });
  89. // 播放缩放动画
  90. scaleAnimation.start();
  91. });
  92. }
  93. /**
  94. * 显示升级面板动画
  95. */
  96. public showPanel(): Promise<void> {
  97. return new Promise((resolve) => {
  98. const panel = this.node;
  99. if (!panel) {
  100. resolve();
  101. return;
  102. }
  103. // 确保面板激活
  104. panel.active = true;
  105. // 停止之前的动画
  106. Tween.stopAllByTarget(panel);
  107. // 设置初始状态:缩放为0
  108. panel.setScale(Vec3.ZERO);
  109. // 播放弹出动画
  110. tween(panel)
  111. .to(0.3, { scale: Vec3.ONE }, {
  112. easing: 'backOut'
  113. })
  114. .call(() => {
  115. resolve();
  116. })
  117. .start();
  118. });
  119. }
  120. /**
  121. * 隐藏升级面板动画
  122. */
  123. public hidePanel(): Promise<void> {
  124. return new Promise((resolve) => {
  125. const panel = this.node;
  126. if (!panel) {
  127. resolve();
  128. return;
  129. }
  130. // 停止之前的动画
  131. Tween.stopAllByTarget(panel);
  132. // 播放缩小动画
  133. tween(panel)
  134. .to(0.2, { scale: Vec3.ZERO }, {
  135. easing: 'backIn'
  136. })
  137. .call(() => {
  138. // 动画结束后隐藏面板
  139. panel.active = false;
  140. resolve();
  141. })
  142. .start();
  143. });
  144. }
  145. /**
  146. * 立即隐藏面板(无动画)
  147. */
  148. public hidePanelImmediate(): void {
  149. const panel = this.node;
  150. if (panel) {
  151. // 停止所有动画
  152. Tween.stopAllByTarget(panel);
  153. // 立即隐藏
  154. panel.active = false;
  155. panel.setScale(Vec3.ONE);
  156. }
  157. }
  158. }