|
|
@@ -0,0 +1,490 @@
|
|
|
+import { _decorator, Component, Node, Slider, Button, Sprite, SpriteFrame, ProgressBar, resources, tween, Vec3 } from 'cc';
|
|
|
+import { AudioManager } from '../../Core/AudioManager';
|
|
|
+import { SaveDataManager } from '../../LevelSystem/SaveDataManager';
|
|
|
+const { ccclass, property } = _decorator;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 音频控制器
|
|
|
+ * 管理音效和音乐的音量控制以及开关状态
|
|
|
+ */
|
|
|
+@ccclass('SoundController')
|
|
|
+export class SoundController extends Component {
|
|
|
+ // 音效控制组件
|
|
|
+ @property({ type: Slider, tooltip: '音效音量滑动条' })
|
|
|
+ public soundEffectSlider: Slider = null;
|
|
|
+
|
|
|
+ @property({ type: Button, tooltip: '音效开关按钮' })
|
|
|
+ public soundEffectCheckbox: Button = null;
|
|
|
+
|
|
|
+ @property({ type: Node, tooltip: '音效勾选标记节点' })
|
|
|
+ public soundEffectCheck: Node = null;
|
|
|
+
|
|
|
+ @property({ type: ProgressBar, tooltip: '音效进度条' })
|
|
|
+ public soundEffectProgressBar: ProgressBar = null;
|
|
|
+
|
|
|
+ // 音乐控制组件
|
|
|
+ @property({ type: Slider, tooltip: '音乐音量滑动条' })
|
|
|
+ public musicSlider: Slider = null;
|
|
|
+
|
|
|
+ @property({ type: Button, tooltip: '音乐开关按钮' })
|
|
|
+ public musicCheckbox: Button = null;
|
|
|
+
|
|
|
+ @property({ type: Node, tooltip: '音乐勾选标记节点' })
|
|
|
+ public musicCheck: Node = null;
|
|
|
+
|
|
|
+ @property({ type: ProgressBar, tooltip: '音乐进度条' })
|
|
|
+ public musicProgressBar: ProgressBar = null;
|
|
|
+
|
|
|
+ // 震动控制组件
|
|
|
+ @property({ type: Button, tooltip: '震动开关按钮' })
|
|
|
+ public vibrationOnButton: Button = null;
|
|
|
+
|
|
|
+ @property({ type: Button, tooltip: '震动关闭按钮' })
|
|
|
+ public vibrationOffButton: Button = null;
|
|
|
+
|
|
|
+ @property({ type: Node, tooltip: '震动滑动节点' })
|
|
|
+ public vibrationSlideNode: Node = null;
|
|
|
+
|
|
|
+ // 音量状态
|
|
|
+ private soundEffectEnabled: boolean = true;
|
|
|
+ private musicEnabled: boolean = true;
|
|
|
+ private savedSoundEffectVolume: number = 0.5;
|
|
|
+ private savedMusicVolume: number = 0.5;
|
|
|
+ private vibrationEnabled: boolean = true;
|
|
|
+
|
|
|
+ onLoad() {
|
|
|
+ this.initializeSliders();
|
|
|
+ this.bindEvents();
|
|
|
+ this.loadSettings();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化滑动条
|
|
|
+ */
|
|
|
+ private initializeSliders() {
|
|
|
+ if (this.soundEffectSlider) {
|
|
|
+ this.soundEffectSlider.progress = this.savedSoundEffectVolume;
|
|
|
+ this.updateProgressBar(this.soundEffectProgressBar, this.soundEffectSlider.progress);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.musicSlider) {
|
|
|
+ this.musicSlider.progress = this.savedMusicVolume;
|
|
|
+ this.updateProgressBar(this.musicProgressBar, this.musicSlider.progress);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 绑定事件
|
|
|
+ */
|
|
|
+ private bindEvents() {
|
|
|
+ // 音效滑动条事件
|
|
|
+ if (this.soundEffectSlider) {
|
|
|
+ this.soundEffectSlider.node.on('slide', this.onSoundEffectSliderChange, this);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 音乐滑动条事件
|
|
|
+ if (this.musicSlider) {
|
|
|
+ this.musicSlider.node.on('slide', this.onMusicSliderChange, this);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 音效开关按钮事件
|
|
|
+ if (this.soundEffectCheckbox) {
|
|
|
+ this.soundEffectCheckbox.node.on(Button.EventType.CLICK, this.onSoundEffectCheckboxClick, this);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 音乐开关按钮事件
|
|
|
+ if (this.musicCheckbox) {
|
|
|
+ this.musicCheckbox.node.on(Button.EventType.CLICK, this.onMusicCheckboxClick, this);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 震动开关按钮事件
|
|
|
+ if (this.vibrationOnButton) {
|
|
|
+ this.vibrationOnButton.node.on(Button.EventType.CLICK, this.onVibrationOnClick, this);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.vibrationOffButton) {
|
|
|
+ this.vibrationOffButton.node.on(Button.EventType.CLICK, this.onVibrationOffClick, this);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 音效滑动条变化事件
|
|
|
+ */
|
|
|
+ private onSoundEffectSliderChange(slider: Slider) {
|
|
|
+ if (this.soundEffectEnabled) {
|
|
|
+ this.savedSoundEffectVolume = slider.progress;
|
|
|
+ this.updateProgressBar(this.soundEffectProgressBar, slider.progress);
|
|
|
+ // TODO: 应用音效音量到音频系统
|
|
|
+ this.applySoundEffectVolume(slider.progress);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 音乐滑动条变化事件
|
|
|
+ */
|
|
|
+ private onMusicSliderChange(slider: Slider) {
|
|
|
+ if (this.musicEnabled) {
|
|
|
+ this.savedMusicVolume = slider.progress;
|
|
|
+ this.updateProgressBar(this.musicProgressBar, slider.progress);
|
|
|
+ // TODO: 应用音乐音量到音频系统
|
|
|
+ this.applyMusicVolume(slider.progress);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 音效开关按钮点击事件
|
|
|
+ */
|
|
|
+ private onSoundEffectCheckboxClick() {
|
|
|
+ this.soundEffectEnabled = !this.soundEffectEnabled;
|
|
|
+
|
|
|
+ if (this.soundEffectEnabled) {
|
|
|
+ // 开启音效:恢复之前保存的音量
|
|
|
+ this.soundEffectSlider.progress = this.savedSoundEffectVolume;
|
|
|
+ this.updateProgressBar(this.soundEffectProgressBar, this.savedSoundEffectVolume);
|
|
|
+ this.applySoundEffectVolume(this.savedSoundEffectVolume);
|
|
|
+ } else {
|
|
|
+ // 关闭音效:保存当前音量并设置为0
|
|
|
+ this.savedSoundEffectVolume = this.soundEffectSlider.progress;
|
|
|
+ this.soundEffectSlider.progress = 0;
|
|
|
+ this.updateProgressBar(this.soundEffectProgressBar, 0);
|
|
|
+ this.applySoundEffectVolume(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新勾选标记显示
|
|
|
+ if (this.soundEffectCheck) {
|
|
|
+ this.soundEffectCheck.active = this.soundEffectEnabled;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.saveSettings();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 音乐开关按钮点击事件
|
|
|
+ */
|
|
|
+ private onMusicCheckboxClick() {
|
|
|
+ this.musicEnabled = !this.musicEnabled;
|
|
|
+
|
|
|
+ if (this.musicEnabled) {
|
|
|
+ // 开启音乐:恢复之前保存的音量
|
|
|
+ this.musicSlider.progress = this.savedMusicVolume;
|
|
|
+ this.updateProgressBar(this.musicProgressBar, this.savedMusicVolume);
|
|
|
+ this.applyMusicVolume(this.savedMusicVolume);
|
|
|
+ } else {
|
|
|
+ // 关闭音乐:保存当前音量并设置为0
|
|
|
+ this.savedMusicVolume = this.musicSlider.progress;
|
|
|
+ this.musicSlider.progress = 0;
|
|
|
+ this.updateProgressBar(this.musicProgressBar, 0);
|
|
|
+ this.applyMusicVolume(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新勾选标记显示
|
|
|
+ if (this.musicCheck) {
|
|
|
+ this.musicCheck.active = this.musicEnabled;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.saveSettings();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 震动开启按钮点击事件
|
|
|
+ */
|
|
|
+ private onVibrationOnClick() {
|
|
|
+ this.vibrationEnabled = true;
|
|
|
+ this.updateVibrationSlideButton();
|
|
|
+ this.saveVibrationSetting();
|
|
|
+
|
|
|
+ // 开启音效和音乐
|
|
|
+ this.enableSoundEffectAndMusic();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 震动关闭按钮点击事件
|
|
|
+ */
|
|
|
+ private onVibrationOffClick() {
|
|
|
+ this.vibrationEnabled = false;
|
|
|
+ this.updateVibrationSlideButton();
|
|
|
+ this.saveVibrationSetting();
|
|
|
+
|
|
|
+ // 关闭音效和音乐
|
|
|
+ this.disableSoundEffectAndMusic();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新震动滑动按钮位置
|
|
|
+ */
|
|
|
+ private updateVibrationSlideButton() {
|
|
|
+ if (!this.vibrationSlideNode || !this.vibrationOnButton || !this.vibrationOffButton) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取目标按钮的位置
|
|
|
+ const targetButton = this.vibrationEnabled ? this.vibrationOnButton : this.vibrationOffButton;
|
|
|
+ const targetPosition = targetButton.node.position.clone();
|
|
|
+
|
|
|
+ // 使用缓动动画移动滑动节点
|
|
|
+ tween(this.vibrationSlideNode)
|
|
|
+ .to(0.3, { position: targetPosition }, { easing: 'sineInOut' })
|
|
|
+ .start();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存震动设置
|
|
|
+ */
|
|
|
+ private saveVibrationSetting() {
|
|
|
+ const saveDataManager = SaveDataManager.getInstance();
|
|
|
+ if (saveDataManager) {
|
|
|
+ saveDataManager.updateSetting('vibrationEnabled', this.vibrationEnabled);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 立即更新震动滑动按钮位置(不使用动画)
|
|
|
+ */
|
|
|
+ private updateVibrationSlideButtonImmediate() {
|
|
|
+ if (!this.vibrationSlideNode || !this.vibrationOnButton || !this.vibrationOffButton) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取目标按钮的位置
|
|
|
+ const targetButton = this.vibrationEnabled ? this.vibrationOnButton : this.vibrationOffButton;
|
|
|
+ const targetPosition = targetButton.node.position.clone();
|
|
|
+
|
|
|
+ // 直接设置位置,不使用动画
|
|
|
+ this.vibrationSlideNode.position = targetPosition;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新进度条显示
|
|
|
+ */
|
|
|
+ private updateProgressBar(progressBar: ProgressBar, progress: number) {
|
|
|
+ if (!progressBar) return;
|
|
|
+
|
|
|
+ // 直接设置ProgressBar的进度值
|
|
|
+ // ProgressBar会自动处理背景和前景的显示,保持黑色背景不变
|
|
|
+ progressBar.progress = progress;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 应用音效音量到音频系统
|
|
|
+ */
|
|
|
+ private applySoundEffectVolume(volume: number) {
|
|
|
+ const audioManager = AudioManager.getInstance();
|
|
|
+ if (audioManager) {
|
|
|
+ audioManager.setSoundEffectVolume(volume);
|
|
|
+ }
|
|
|
+ //console.log(`[SoundController] 设置音效音量: ${volume}`);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 应用音乐音量到音频系统
|
|
|
+ */
|
|
|
+ private applyMusicVolume(volume: number) {
|
|
|
+ const audioManager = AudioManager.getInstance();
|
|
|
+ if (audioManager) {
|
|
|
+ audioManager.setMusicVolume(volume);
|
|
|
+ }
|
|
|
+ //console.log(`[SoundController] 设置音乐音量: ${volume}`);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存设置到本地存储
|
|
|
+ */
|
|
|
+ private saveSettings() {
|
|
|
+ const settings = {
|
|
|
+ soundEffectEnabled: this.soundEffectEnabled,
|
|
|
+ musicEnabled: this.musicEnabled,
|
|
|
+ soundEffectVolume: this.savedSoundEffectVolume,
|
|
|
+ musicVolume: this.savedMusicVolume
|
|
|
+ };
|
|
|
+
|
|
|
+ localStorage.setItem('audioSettings', JSON.stringify(settings));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从本地存储加载设置
|
|
|
+ */
|
|
|
+ private loadSettings() {
|
|
|
+ const savedSettings = localStorage.getItem('audioSettings');
|
|
|
+ if (savedSettings) {
|
|
|
+ try {
|
|
|
+ const settings = JSON.parse(savedSettings);
|
|
|
+ this.soundEffectEnabled = settings.soundEffectEnabled ?? true;
|
|
|
+ this.musicEnabled = settings.musicEnabled ?? true;
|
|
|
+ this.savedSoundEffectVolume = settings.soundEffectVolume ?? 0.8;
|
|
|
+ this.savedMusicVolume = settings.musicVolume ?? 0.8;
|
|
|
+
|
|
|
+ // 更新UI显示
|
|
|
+ this.updateUI();
|
|
|
+ } catch (e) {
|
|
|
+ console.warn('[SoundController] 加载音频设置失败:', e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从SaveDataManager加载震动设置
|
|
|
+ const saveDataManager = SaveDataManager.getInstance();
|
|
|
+ if (saveDataManager) {
|
|
|
+ this.vibrationEnabled = saveDataManager.getSetting('vibrationEnabled');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新UI显示
|
|
|
+ */
|
|
|
+ private updateUI() {
|
|
|
+ // 更新勾选标记
|
|
|
+ if (this.soundEffectCheck) {
|
|
|
+ this.soundEffectCheck.active = this.soundEffectEnabled;
|
|
|
+ }
|
|
|
+ if (this.musicCheck) {
|
|
|
+ this.musicCheck.active = this.musicEnabled;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新滑动条和进度条
|
|
|
+ if (this.soundEffectSlider) {
|
|
|
+ this.soundEffectSlider.progress = this.soundEffectEnabled ? this.savedSoundEffectVolume : 0;
|
|
|
+ this.updateProgressBar(this.soundEffectProgressBar, this.soundEffectSlider.progress);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.musicSlider) {
|
|
|
+ this.musicSlider.progress = this.musicEnabled ? this.savedMusicVolume : 0;
|
|
|
+ this.updateProgressBar(this.musicProgressBar, this.musicSlider.progress);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新震动滑动按钮位置(不使用动画,直接设置位置)
|
|
|
+ this.updateVibrationSlideButtonImmediate();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前音效音量
|
|
|
+ */
|
|
|
+ public getSoundEffectVolume(): number {
|
|
|
+ return this.soundEffectEnabled ? this.savedSoundEffectVolume : 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前音乐音量
|
|
|
+ */
|
|
|
+ public getMusicVolume(): number {
|
|
|
+ return this.musicEnabled ? this.savedMusicVolume : 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置音效音量
|
|
|
+ */
|
|
|
+ public setSoundEffectVolume(volume: number) {
|
|
|
+ this.savedSoundEffectVolume = Math.max(0, Math.min(1, volume));
|
|
|
+ if (this.soundEffectEnabled && this.soundEffectSlider) {
|
|
|
+ this.soundEffectSlider.progress = this.savedSoundEffectVolume;
|
|
|
+ this.updateProgressBar(this.soundEffectProgressBar, this.savedSoundEffectVolume);
|
|
|
+ this.applySoundEffectVolume(this.savedSoundEffectVolume);
|
|
|
+ }
|
|
|
+ this.saveSettings();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置音乐音量
|
|
|
+ */
|
|
|
+ public setMusicVolume(volume: number) {
|
|
|
+ this.savedMusicVolume = Math.max(0, Math.min(1, volume));
|
|
|
+ if (this.musicEnabled && this.musicSlider) {
|
|
|
+ this.musicSlider.progress = this.savedMusicVolume;
|
|
|
+ this.updateProgressBar(this.musicProgressBar, this.savedMusicVolume);
|
|
|
+ this.applyMusicVolume(this.savedMusicVolume);
|
|
|
+ }
|
|
|
+ this.saveSettings();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前震动状态
|
|
|
+ */
|
|
|
+ public getVibrationEnabled(): boolean {
|
|
|
+ return this.vibrationEnabled;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置震动状态
|
|
|
+ */
|
|
|
+ public setVibrationEnabled(enabled: boolean) {
|
|
|
+ this.vibrationEnabled = enabled;
|
|
|
+ this.updateVibrationSlideButton();
|
|
|
+ this.saveVibrationSetting();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 开启音效和音乐
|
|
|
+ */
|
|
|
+ private enableSoundEffectAndMusic() {
|
|
|
+ // 如果音效未开启,则开启音效
|
|
|
+ if (!this.soundEffectEnabled) {
|
|
|
+ this.soundEffectEnabled = true;
|
|
|
+
|
|
|
+ // 恢复之前保存的音量或使用默认值0.5
|
|
|
+ const volumeToRestore = this.savedSoundEffectVolume > 0 ? this.savedSoundEffectVolume : 0.5;
|
|
|
+ this.soundEffectSlider.progress = volumeToRestore;
|
|
|
+ this.updateProgressBar(this.soundEffectProgressBar, volumeToRestore);
|
|
|
+ this.applySoundEffectVolume(volumeToRestore);
|
|
|
+
|
|
|
+ // 更新勾选标记显示
|
|
|
+ if (this.soundEffectCheck) {
|
|
|
+ this.soundEffectCheck.active = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果音乐未开启,则开启音乐
|
|
|
+ if (!this.musicEnabled) {
|
|
|
+ this.musicEnabled = true;
|
|
|
+
|
|
|
+ // 恢复之前保存的音量或使用默认值0.5
|
|
|
+ const volumeToRestore = this.savedMusicVolume > 0 ? this.savedMusicVolume : 0.5;
|
|
|
+ this.musicSlider.progress = volumeToRestore;
|
|
|
+ this.updateProgressBar(this.musicProgressBar, volumeToRestore);
|
|
|
+ this.applyMusicVolume(volumeToRestore);
|
|
|
+
|
|
|
+ // 更新勾选标记显示
|
|
|
+ if (this.musicCheck) {
|
|
|
+ this.musicCheck.active = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.saveSettings();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭音效和音乐
|
|
|
+ */
|
|
|
+ private disableSoundEffectAndMusic() {
|
|
|
+ // 关闭音效
|
|
|
+ if (this.soundEffectEnabled) {
|
|
|
+ this.soundEffectEnabled = false;
|
|
|
+
|
|
|
+ // 保存当前音量并设置为0
|
|
|
+ this.savedSoundEffectVolume = this.soundEffectSlider.progress;
|
|
|
+ this.soundEffectSlider.progress = 0;
|
|
|
+ this.updateProgressBar(this.soundEffectProgressBar, 0);
|
|
|
+ this.applySoundEffectVolume(0);
|
|
|
+
|
|
|
+ // 更新勾选标记显示
|
|
|
+ if (this.soundEffectCheck) {
|
|
|
+ this.soundEffectCheck.active = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 关闭音乐
|
|
|
+ if (this.musicEnabled) {
|
|
|
+ this.musicEnabled = false;
|
|
|
+
|
|
|
+ // 保存当前音量并设置为0
|
|
|
+ this.savedMusicVolume = this.musicSlider.progress;
|
|
|
+ this.musicSlider.progress = 0;
|
|
|
+ this.updateProgressBar(this.musicProgressBar, 0);
|
|
|
+ this.applyMusicVolume(0);
|
|
|
+
|
|
|
+ // 更新勾选标记显示
|
|
|
+ if (this.musicCheck) {
|
|
|
+ this.musicCheck.active = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.saveSettings();
|
|
|
+ }
|
|
|
+}
|