| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- import { _decorator, Component, Node, Vec3, find, sp, Color } from 'cc';
- import { BundleLoader } from '../../Core/BundleLoader';
- import { Audio } from '../../AudioManager/AudioManager';
- const { ccclass, property } = _decorator;
- /**
- * 武器特效管理器
- * 负责处理敌人武器的击中特效、轨迹特效、音效等
- * 挂载到Canvas/GameLevelUI/EnemyController上使用
- */
- @ccclass('WeaponEffectManager')
- export class WeaponEffectManager extends Component {
-
- // 当前播放中的特效节点列表
- private activeEffects: Node[] = [];
-
- // 特效缓存
- private effectCache: Map<string, sp.SkeletonData> = new Map();
-
- onLoad() {
- console.log('[WeaponEffectManager] 武器特效管理器已加载');
- }
-
- onDestroy() {
- this.clearAllEffects();
- }
-
- /**
- * 播放武器特效
- * @param weaponEffects 武器特效配置
- * @param position 特效播放位置
- * @param attackType 攻击类型
- */
- public async playWeaponEffects(weaponEffects: any, position: Vec3, attackType: string) {
- if (!weaponEffects) {
- return;
- }
-
- // 播放击中特效
- if (weaponEffects.hitEffect) {
- await this.playHitEffect(weaponEffects.hitEffect, position, weaponEffects.visualScale || 1.0);
- }
-
- // 播放轨迹特效(主要用于远程攻击)
- if (weaponEffects.trailEffect && (attackType === 'magic_projectile' || attackType === 'arrow_projectile')) {
- await this.playTrailEffect(weaponEffects.trailEffect, position, weaponEffects.visualScale || 1.0);
- }
-
- // 播放音效
- if (weaponEffects.impactSound) {
- this.playImpactSound(weaponEffects.impactSound);
- }
- }
-
- /**
- * 播放击中特效
- * @param effectName 特效名称
- * @param position 播放位置
- * @param scale 缩放比例
- */
- private async playHitEffect(effectName: string, position: Vec3, scale: number = 1.0) {
- const effectPath = this.getEffectPath(effectName);
- if (!effectPath) {
- console.warn(`[WeaponEffectManager] 未知的击中特效: ${effectName}`);
- return;
- }
-
- await this.createAndPlayEffect(effectPath, position, scale, false);
- }
-
- /**
- * 播放轨迹特效
- * @param effectName 特效名称
- * @param position 播放位置
- * @param scale 缩放比例
- */
- private async playTrailEffect(effectName: string, position: Vec3, scale: number = 1.0) {
- const effectPath = this.getEffectPath(effectName);
- if (!effectPath) {
- console.warn(`[WeaponEffectManager] 未知的轨迹特效: ${effectName}`);
- return;
- }
-
- await this.createAndPlayEffect(effectPath, position, scale, false);
- }
-
- /**
- * 播放撞击音效
- * @param soundName 音效名称
- */
- private playImpactSound(soundName: string) {
- const soundPath = this.getSoundPath(soundName);
- if (soundPath) {
- Audio.playWeaponSound(soundPath);
- } else {
- console.warn(`[WeaponEffectManager] 未知的撞击音效: ${soundName}`);
- }
- }
-
- /**
- * 获取特效路径
- * @param effectName 特效名称
- */
- private getEffectPath(effectName: string): string | null {
- const effectPaths: { [key: string]: string } = {
- 'blood_splash': 'WeaponTx/tx0001/tx0001',
- 'magic_burst': 'WeaponTx/tx0002/tx0002',
- 'arrow_impact': 'WeaponTx/tx0003/tx0003',
- 'weapon_clash': 'WeaponTx/tx0004/tx0004',
- 'fire_explosion': 'WeaponTx/tx0005/tx0005',
- 'ice_shatter': 'WeaponTx/tx0006/tx0006',
- 'lightning_strike': 'WeaponTx/tx0007/tx0007',
- 'dark_energy': 'WeaponTx/tx0008/tx0008'
- };
-
- return effectPaths[effectName] || null;
- }
-
- /**
- * 获取音效路径
- * @param soundName 音效名称
- */
- private getSoundPath(soundName: string): string | null {
- const soundPaths: { [key: string]: string } = {
- 'melee_hit': 'data/弹球音效/melee_hit',
- 'magic_impact': 'data/弹球音效/magic_impact',
- 'arrow_hit': 'data/弹球音效/arrow_hit',
- 'weapon_clash': 'data/弹球音效/weapon_clash',
- 'explosion': 'data/弹球音效/explosion',
- 'ice_break': 'data/弹球音效/ice_break',
- 'lightning': 'data/弹球音效/lightning',
- 'dark_magic': 'data/弹球音效/dark_magic'
- };
-
- return soundPaths[soundName] || null;
- }
-
- /**
- * 创建并播放特效
- * @param effectPath 特效路径
- * @param position 播放位置
- * @param scale 缩放比例
- * @param loop 是否循环播放
- */
- private async createAndPlayEffect(effectPath: string, position: Vec3, scale: number = 1.0, loop: boolean = false) {
- try {
- // 尝试从缓存获取特效数据
- let skeletonData = this.effectCache.get(effectPath);
-
- if (!skeletonData) {
- // 从Bundle加载特效数据
- skeletonData = await BundleLoader.loadSkeletonData(effectPath);
- if (!skeletonData) {
- console.warn(`[WeaponEffectManager] 加载特效失败: ${effectPath}`);
- return;
- }
-
- // 缓存特效数据
- this.effectCache.set(effectPath, skeletonData);
- }
-
- // 创建特效节点
- const effectNode = new Node('WeaponEffect');
- const skeleton = effectNode.addComponent(sp.Skeleton);
- skeleton.skeletonData = skeletonData;
- skeleton.premultipliedAlpha = false;
-
- // 设置动画
- skeleton.setAnimation(0, 'animation', loop);
-
- // 设置完成监听器(非循环动画)
- if (!loop) {
- skeleton.setCompleteListener(() => {
- this.removeEffect(effectNode);
- });
- }
-
- // 添加到Canvas并设置位置和缩放
- const canvas = find('Canvas');
- if (canvas) {
- canvas.addChild(effectNode);
- effectNode.setWorldPosition(position);
- effectNode.setScale(scale, scale, 1);
-
- // 设置特效颜色(增加亮度)
- const color = new Color(255, 255, 255, 255);
- color.r = Math.min(255, color.r * 1.2);
- color.g = Math.min(255, color.g * 1.2);
- color.b = Math.min(255, color.b * 1.2);
- skeleton.color = color;
-
- // 添加到活动特效列表
- this.activeEffects.push(effectNode);
-
- console.log(`[WeaponEffectManager] 播放武器特效: ${effectPath}`);
- } else {
- effectNode.destroy();
- console.warn('[WeaponEffectManager] 未找到Canvas节点,无法播放特效');
- }
-
- } catch (error) {
- console.error(`[WeaponEffectManager] 播放特效失败: ${effectPath}`, error);
- }
- }
-
- /**
- * 移除特效节点
- * @param effectNode 要移除的特效节点
- */
- private removeEffect(effectNode: Node) {
- // 从活动特效列表中移除
- const index = this.activeEffects.indexOf(effectNode);
- if (index !== -1) {
- this.activeEffects.splice(index, 1);
- }
-
- // 销毁节点
- if (effectNode && effectNode.isValid) {
- effectNode.destroy();
- }
- }
-
- /**
- * 清理所有活动的特效
- */
- public clearAllEffects() {
- for (const effect of this.activeEffects) {
- if (effect && effect.isValid) {
- effect.destroy();
- }
- }
- this.activeEffects = [];
- console.log('[WeaponEffectManager] 清理所有武器特效');
- }
-
- /**
- * 清理特效缓存
- */
- public clearEffectCache() {
- this.effectCache.clear();
- console.log('[WeaponEffectManager] 清理特效缓存');
- }
- }
|