import { _decorator, Component, Node, Vec3, tween, find, Camera } from 'cc'; const { ccclass, property } = _decorator; /** * 画面震动管理器 * 负责管理整个游戏画面的震动效果 */ export class ScreenShakeManager { private static instance: ScreenShakeManager = null; // 相机节点 private cameraNode: Node = null; // 震动相关属性 private originalCameraPosition: Vec3 = new Vec3(); private isShaking: boolean = false; private currentShakeTween: any = null; // 震动设置 private vibrationEnabled: boolean = true; private constructor() { // 私有构造函数,确保单例模式 } /** * 获取单例实例 */ public static getInstance(): ScreenShakeManager { if (!ScreenShakeManager.instance) { ScreenShakeManager.instance = new ScreenShakeManager(); } return ScreenShakeManager.instance; } /** * 初始化相机节点 * @param cameraNode 相机节点引用 */ public initialize(cameraNode: Node): void { this.cameraNode = cameraNode; if (this.cameraNode) { this.originalCameraPosition = this.cameraNode.position.clone(); console.log('[ScreenShakeManager] 相机节点初始化完成'); } else { console.warn('[ScreenShakeManager] 相机节点为空,画面震动功能将不可用'); } } /** * 播放画面震动效果 * @param intensity 震动强度 (像素) * @param duration 震动持续时间 (秒) * @param frequency 震动频率 (次数) */ public playScreenShake(intensity: number = 10, duration: number = 0.5, frequency: number = 8): void { // 检查震动是否启用 if (!this.vibrationEnabled) { console.log('[ScreenShakeManager] 震动已禁用,跳过画面震动'); return; } // 检查相机节点是否存在 if (!this.cameraNode) { console.warn('[ScreenShakeManager] 相机节点不存在,无法播放画面震动'); return; } // 如果正在震动,先停止当前震动 this.stopScreenShake(); console.log(`[ScreenShakeManager] 开始画面震动 - 强度: ${intensity}, 持续时间: ${duration}s, 频率: ${frequency}`); // 标记为正在震动 this.isShaking = true; // 保存当前位置作为原始位置 this.originalCameraPosition = this.cameraNode.position.clone(); // 创建震动序列 let shakeTween = tween(this.cameraNode); const singleShakeTime = duration / frequency; for (let i = 0; i < frequency; i++) { // 计算震动强度衰减 const currentIntensity = intensity * (1 - i / frequency); // 随机方向震动 const randomAngle = Math.random() * Math.PI * 2; const offsetX = Math.cos(randomAngle) * currentIntensity; const offsetY = Math.sin(randomAngle) * currentIntensity; const targetPosition = this.originalCameraPosition.clone(); targetPosition.x += offsetX; targetPosition.y += offsetY; shakeTween = shakeTween.to(singleShakeTime, { position: targetPosition }, { easing: 'sineInOut' }); } // 最后回到原始位置 shakeTween = shakeTween.to(singleShakeTime * 0.5, { position: this.originalCameraPosition }, { easing: 'sineOut' }).call(() => { this.isShaking = false; this.currentShakeTween = null; console.log('[ScreenShakeManager] 画面震动结束'); }); this.currentShakeTween = shakeTween; this.currentShakeTween.start(); } /** * 停止画面震动 */ public stopScreenShake(): void { if (this.currentShakeTween) { this.currentShakeTween.stop(); this.currentShakeTween = null; } if (this.isShaking && this.cameraNode) { // 立即回到原始位置 this.cameraNode.position = this.originalCameraPosition.clone(); this.isShaking = false; console.log('[ScreenShakeManager] 画面震动已停止'); } } /** * 检查是否正在震动 */ public isScreenShaking(): boolean { return this.isShaking; } /** * 设置震动启用状态 */ public setVibrationEnabled(enabled: boolean): void { this.vibrationEnabled = enabled; console.log(`[ScreenShakeManager] 震动设置: ${enabled ? '启用' : '禁用'}`); // 如果禁用震动且正在震动,立即停止 if (!enabled && this.isShaking) { this.stopScreenShake(); } } /** * 获取震动启用状态 */ public getVibrationEnabled(): boolean { return this.vibrationEnabled; } /** * 播放轻微震动(用于普通攻击) */ public playLightShake(): void { this.playScreenShake(6, 0.3, 6); } /** * 播放中等震动(用于重击) */ public playMediumShake(): void { this.playScreenShake(10, 0.5, 8); } /** * 播放强烈震动(用于爆炸或特殊攻击) */ public playHeavyShake(): void { this.playScreenShake(15, 0.8, 12); } /** * 根据攻击类型播放对应的震动效果 */ public playShakeByAttackType(attackType: string, intensity?: number): void { switch (attackType.toLowerCase()) { case 'light': case 'normal': case 'melee': this.playLightShake(); break; case 'heavy': case 'strong': this.playMediumShake(); break; case 'explosive': case 'critical': case 'special': this.playHeavyShake(); break; default: // 如果指定了强度,使用自定义震动 if (intensity !== undefined) { this.playScreenShake(intensity, 0.5, 8); } else { this.playLightShake(); } break; } } onDestroy() { // 清理震动效果 this.stopScreenShake(); // 清除单例引用 if (ScreenShakeManager.instance === this) { ScreenShakeManager.instance = null; } } }