import { _decorator, Component, Node, Tween, tween, Vec3, Material, Sprite, resources, Label, JsonAsset } from 'cc'; import { Audio } from '../../AudioManager/AudioManager'; const { ccclass, property } = _decorator; /** * 植物升级动画控制器 * 负责管理植物升级相关的动画效果 */ @ccclass('UpgradeAni') export class UpgradeAni extends Component { @property(Node) weaponSpriteNode: Node = null; @property(Node) upgradeBtnNode: Node = null; // Canvas/UpgradePanel/UpgradeBtn/UP节点 @property(Label) currentDamageLabel: Label = null; // Canvas/UpgradePanel/NumberBack/CurrentDamage节点 private blinkTween: Tween = null; // 闪烁动画的引用 private weaponsConfig: any = null; // 武器配置数据 /** * 植物升级成功动画 * 播放植物图标的放大缩小动画,并在升级期间应用扫描效果材质,同时播放升级音效 * @param weaponIconNode 植物图标节点 */ public playWeaponUpgradeAnimation(weaponIconNode: Node): Promise { return new Promise((resolve) => { if (!weaponIconNode) { resolve(); return; } // 停止之前的动画,防止快速点击时动画冲突 Tween.stopAllByTarget(weaponIconNode); // 重置到原始缩放状态,确保动画从正确的状态开始 weaponIconNode.setScale(Vec3.ONE); // 保存原始缩放值 const originalScale = Vec3.ONE.clone(); let weaponSprite: Sprite = null; let originalMaterial: Material = null; console.log('[UpgradeAni] 开始武器升级动画,weaponSpriteNode:', this.weaponSpriteNode); // 播放植物升级音效 Audio.playUISound('data/弹球音效/equipment level up finish'); // 使用装饰器引用的WeaponSprite节点,获取其Sprite组件并保存原始材质 if (this.weaponSpriteNode) { console.log('[UpgradeAni] 找到weaponSpriteNode,开始获取Sprite组件'); weaponSprite = this.weaponSpriteNode.getComponent(Sprite); if (weaponSprite) { console.log('[UpgradeAni] 找到Sprite组件,开始加载材质'); // 保存原始材质,优先保存customMaterial,如果没有则保存当前material originalMaterial = weaponSprite.customMaterial || weaponSprite.material; console.log('[UpgradeAni] 原始材质:', originalMaterial); // 加载并应用扫描效果材质 resources.load('shaders/scan-effect', Material, (err, scanMaterial) => { console.log('[UpgradeAni] 材质加载回调,err:', err, 'scanMaterial:', scanMaterial); if (!err && scanMaterial && weaponSprite) { weaponSprite.material = scanMaterial; console.log('[UpgradeAni] 应用扫描效果材质成功'); } else { console.warn('[UpgradeAni] 加载扫描效果材质失败:', err); } }); } else { console.warn('[UpgradeAni] weaponSpriteNode上没有找到Sprite组件'); } } else { console.warn('[UpgradeAni] weaponSpriteNode为null,请在编辑器中设置'); } // 创建缩放动画:放大到1.5倍再立即缩小回原始大小 const scaleAnimation = tween(weaponIconNode) .to(0.25, { scale: new Vec3(originalScale.x * 1.5, originalScale.y * 1.5, originalScale.z) }, { easing: 'sineOut' }) .to(0.25, { scale: originalScale }, { easing: 'sineIn' }) .call(() => { // 动画结束后恢复原始材质 if (weaponSprite && originalMaterial) { // 如果原始材质是customMaterial,则恢复customMaterial if (weaponSprite.customMaterial === originalMaterial) { weaponSprite.material = weaponSprite.customMaterial; } else { weaponSprite.material = originalMaterial; } console.log('[UpgradeAni] 恢复原始材质成功'); } else if (weaponSprite) { // 如果没有保存的原始材质,尝试恢复到customMaterial if (weaponSprite.customMaterial) { weaponSprite.material = weaponSprite.customMaterial; console.log('[UpgradeAni] 恢复到customMaterial'); } else { weaponSprite.material = null; console.log('[UpgradeAni] 恢复到默认材质'); } } resolve(); }); // 播放缩放动画 scaleAnimation.start(); }); } /** * 显示升级面板动画 */ public showPanel(): Promise { return new Promise((resolve) => { const panel = this.node; if (!panel) { resolve(); return; } // 确保面板激活 panel.active = true; // 停止之前的动画 Tween.stopAllByTarget(panel); // 设置初始状态:缩放为0 panel.setScale(Vec3.ZERO); // 播放弹出动画 tween(panel) .to(0.3, { scale: Vec3.ONE }, { easing: 'backOut' }) .call(() => { resolve(); }) .start(); }); } /** * 隐藏升级面板动画 */ public hidePanel(): Promise { return new Promise((resolve) => { const panel = this.node; if (!panel) { resolve(); return; } // 停止之前的动画 Tween.stopAllByTarget(panel); // 播放缩小动画 tween(panel) .to(0.2, { scale: Vec3.ZERO }, { easing: 'backIn' }) .call(() => { // 动画结束后隐藏面板 panel.active = false; resolve(); }) .start(); }); } /** * 立即隐藏面板(无动画) */ public hidePanelImmediate(): void { const panel = this.node; if (panel) { // 停止所有动画 Tween.stopAllByTarget(panel); // 立即隐藏 panel.active = false; panel.setScale(Vec3.ONE); } } /** * 开始升级按钮闪烁动画 * 当钞票足够升级时调用此方法 */ public startUpgradeBtnBlink(): void { if (!this.upgradeBtnNode) { console.warn('[UpgradeAni] upgradeBtnNode为null,请在编辑器中设置Canvas/UpgradePanel/UpgradeBtn/UP节点'); return; } // 停止之前的闪烁动画 this.stopUpgradeBtnBlink(); // 重置到原始缩放状态 this.upgradeBtnNode.setScale(Vec3.ONE); // 创建循环闪烁动画:放大到1.5倍再缩小回原始大小,无限循环 this.blinkTween = tween(this.upgradeBtnNode) .to(0.5, { scale: new Vec3(1.5, 1.5, 1) }, { easing: 'sineInOut' }) .to(0.5, { scale: Vec3.ONE }, { easing: 'sineInOut' }) .union() // 将上面的动画组合成一个整体 .repeatForever(); // 无限循环 this.blinkTween.start(); console.log('[UpgradeAni] 开始升级按钮闪烁动画'); } /** * 停止升级按钮闪烁动画 * 当钞票不够升级时调用此方法 */ public stopUpgradeBtnBlink(): void { if (this.blinkTween) { this.blinkTween.stop(); this.blinkTween = null; } if (this.upgradeBtnNode) { // 停止节点上的所有动画 Tween.stopAllByTarget(this.upgradeBtnNode); // 恢复到原始缩放状态 this.upgradeBtnNode.setScale(Vec3.ONE); } console.log('[UpgradeAni] 停止升级按钮闪烁动画'); } /** * 检查升级按钮是否正在闪烁 * @returns 是否正在闪烁 */ public isUpgradeBtnBlinking(): boolean { return this.blinkTween !== null; } /** * 加载武器配置数据 */ public async loadWeaponsConfig(): Promise { return new Promise((resolve, reject) => { resources.load('data/weapons', JsonAsset, (err, weaponsData) => { if (err) { console.error('[UpgradeAni] 加载武器配置失败:', err); reject(err); return; } this.weaponsConfig = weaponsData.json || weaponsData; console.log('[UpgradeAni] 武器配置加载成功'); resolve(); }); }); } /** * 从JSON配置中获取武器在指定等级的伤害值 * @param weaponId 武器ID * @param level 武器等级 * @returns 伤害值 */ public getWeaponDamageFromConfig(weaponId: string, level: number): number { if (!this.weaponsConfig || !this.weaponsConfig.weapons) { console.warn('[UpgradeAni] 武器配置未加载'); return 0; } const weaponConfig = this.weaponsConfig.weapons.find((w: any) => w.id === weaponId); if (!weaponConfig) { console.warn(`[UpgradeAni] 未找到武器配置: ${weaponId}`); return 0; } if (level === 0) { return 0; // 未解锁武器伤害为0 } // 优先从upgradeConfig中获取伤害值 if (weaponConfig.upgradeConfig && weaponConfig.upgradeConfig.levels) { const levelConfig = weaponConfig.upgradeConfig.levels[level.toString()]; if (levelConfig && typeof levelConfig.damage === 'number') { return levelConfig.damage; } } // 如果upgradeConfig中没有伤害值,使用基础伤害 + 等级加成 const baseDamage = weaponConfig.stats?.damage || 0; return baseDamage + (level - 1); } /** * 更新当前伤害显示 * @param weaponId 武器ID * @param level 武器等级 */ public updateCurrentDamageDisplay(weaponId: string, level: number): void { if (!this.currentDamageLabel) { console.warn('[UpgradeAni] currentDamageLabel未设置,请在编辑器中设置Canvas/UpgradePanel/NumberBack/CurrentDamage节点'); return; } const damage = this.getWeaponDamageFromConfig(weaponId, level); this.currentDamageLabel.string = damage.toString(); console.log(`[UpgradeAni] 更新伤害显示: ${weaponId} 等级${level} 伤害${damage}`); } }