Browse Source

音乐音效

181404010226 1 month ago
parent
commit
4786739162

File diff suppressed because it is too large
+ 218 - 131
assets/Scenes/GameLevel.scene


+ 5 - 1
assets/scripts/Ads/AdManager.ts

@@ -259,7 +259,11 @@ export class AdManager {
                 console.log('[AdManager] 用户完整观看广告,给予奖励');
                 onReward();
             } else {
-                console.log('[AdManager] 用户未完整观看广告,不给予奖励');
+                console.log('[AdManager] 用户未完整观看广告,视为取消,不给予奖励');
+                // 用户主动关闭或未看完,通知上层进行状态重置
+                if (onError) {
+                    onError({ errCode: 'USER_CANCELLED', message: '用户取消观看激励视频广告', isEnded: false });
+                }
             }
         };
         

+ 66 - 10
assets/scripts/AudioManager/AudioManager.ts

@@ -1,6 +1,7 @@
-import { _decorator, Component, AudioClip, AudioSource, resources, Node, find, director } from 'cc';
+import { _decorator, Component, AudioClip, AudioSource, resources, Node, find, director, sys } from 'cc';
 import { GameManager } from '../LevelSystem/GameManager';
 import { BundleLoader } from '../Core/BundleLoader';
+import { SaveDataManager } from '../LevelSystem/SaveDataManager';
 const { ccclass, property } = _decorator;
 
 @ccclass('AudioManager')
@@ -54,6 +55,8 @@ export class AudioManager extends Component {
         
         this.bundleLoader = BundleLoader.getInstance();
         this.initializeAudioSources();
+        // 初始化后尝试应用存档中的音频设置
+        this.applyPersistedSettings();
     }
     
     public static getInstance(): AudioManager {
@@ -109,6 +112,60 @@ export class AudioManager extends Component {
         // 设置初始音量
         this.updateAllVolumes();
     }
+
+    // 从存档或本地 audioSettings 恢复音量与开关状态
+    private applyPersistedSettings() {
+        try {
+            const sdm = SaveDataManager.getInstance();
+            let musicEnabled: boolean | undefined = undefined;
+            let soundEnabled: boolean | undefined = undefined;
+            let musicVolume: number | undefined = undefined;
+            let soundVolume: number | undefined = undefined;
+
+            if (sdm && typeof sdm.getSetting === 'function') {
+                musicEnabled = sdm.getSetting('musicEnabled');
+                soundEnabled = sdm.getSetting('soundEnabled');
+                musicVolume = sdm.getSetting('musicVolume');
+                soundVolume = sdm.getSetting('soundVolume');
+            }
+
+            // 兼容旧的本地键 audioSettings(如果存档未初始化或缺值)
+            if (musicEnabled === undefined || soundEnabled === undefined || musicVolume === undefined || soundVolume === undefined) {
+                const raw = sys?.localStorage?.getItem('audioSettings');
+                if (raw) {
+                    try {
+                        const parsed = JSON.parse(raw);
+                        musicEnabled = musicEnabled ?? parsed?.musicEnabled;
+                        soundEnabled = soundEnabled ?? parsed?.soundEffectEnabled;
+                        musicVolume = musicVolume ?? parsed?.musicVolume;
+                        soundVolume = soundVolume ?? parsed?.soundEffectVolume;
+                    } catch (e) {
+                        // 无需处理解析错误
+                    }
+                }
+            }
+
+            // 默认值与裁剪
+            const finalMusicEnabled = musicEnabled !== false;
+            const finalSoundEnabled = soundEnabled !== false;
+            const finalMusicVolume = typeof musicVolume === 'number' ? Math.max(0, Math.min(1, musicVolume)) : this.musicVolume;
+            const finalSoundVolume = typeof soundVolume === 'number' ? Math.max(0, Math.min(1, soundVolume)) : this.soundEffectVolume;
+
+            // 应用到管理器内部状态
+            this.musicVolume = finalMusicEnabled ? finalMusicVolume : 0;
+            this.soundEffectVolume = finalSoundEnabled ? finalSoundVolume : 0;
+            this.uiSoundVolume = this.soundEffectVolume;
+            this.enemySoundVolume = this.soundEffectVolume;
+            this.environmentSoundVolume = this.soundEffectVolume;
+            this.weaponSoundVolume = this.soundEffectVolume;
+
+            this.updateAllVolumes();
+            console.log(`[AudioManager] 从存档恢复音量:music=${this.musicVolume}, sfx=${this.soundEffectVolume}`);
+        } catch (err) {
+            // 安静失败,不影响后续逻辑
+            console.warn('[AudioManager] 恢复音频设置失败,使用默认值');
+        }
+    }
     
     public async playMusic(musicPath: string, loop: boolean = true) {
         if (!this.musicAudioSource) {
@@ -591,15 +648,14 @@ export class Audio {
                 isInGame = !!(gameUI && (gameUI as Node).activeInHierarchy);
             }
 
-            Audio.stopMusic();
-            Audio.setMusicVolume(0.8);
-            if (isInGame) {
-                Audio.playMusic('data/弹球音效/fight bgm', true);
-                console.log('[Audio] 切换到游戏战斗音乐');
-            } else {
-                Audio.playMusic('data/弹球音效/ui bgm', true);
-                console.log('[Audio] 切换到主界面背景音乐');
-            }
+            // 保持用户设置的音量,不重置为固定值
+            Audio.setMusicVolume(manager.getMusicVolume());
+
+            // 仅当目标曲目与当前不同或未播放时才切换;
+            // playMusic 内部已防重,若同曲且正在播放会直接忽略。
+            const targetPath = isInGame ? 'data/弹球音效/fight bgm' : 'data/弹球音效/ui bgm';
+            Audio.playMusic(targetPath, true);
+            console.log(isInGame ? '[Audio] 维持/切换到游戏战斗音乐' : '[Audio] 维持/切换到主界面背景音乐');
         } catch (err) {
             console.error('[Audio] updateBGMByTopUI 失败:', err);
         }

+ 2 - 10
assets/scripts/AudioManager/EnemyAudios.ts

@@ -80,12 +80,8 @@ export class EnemyAudios extends Component {
         if (!soundPath || soundPath === 'Null' || soundPath === 'nan' || soundPath === '') {
             soundPath = 'data/弹球音效/hammer1'; // 默认攻击音效
         }
-        
-        // 获取音量设置
-        const volume = enemyConfig.audioConfig?.volume || 1.0;
-        
         console.log(`[EnemyAudios] 播放攻击音效: ${soundPath}`);
-        this.audioManager.playEnemySound(soundPath, volume);
+        this.audioManager.playEnemySound(soundPath);
     }
     
     /**
@@ -107,12 +103,8 @@ export class EnemyAudios extends Component {
         if (!soundPath || soundPath === 'Null' || soundPath === 'nan' || soundPath === '') {
             soundPath = 'data/弹球音效/normal zombie die 1'; // 默认死亡音效
         }
-        
-        // 获取音量设置
-        const volume = enemyConfig.audioConfig?.volume || 1.0;
-        
         console.log(`[EnemyAudios] 播放死亡音效: ${soundPath}`);
-        this.audioManager.playEnemySound(soundPath, volume);
+        this.audioManager.playEnemySound(soundPath);
     }
     
     onDestroy() {

+ 1 - 1
assets/scripts/CombatSystem/GameEnd.ts

@@ -69,7 +69,7 @@ export class GameEnd extends Component {
 
     // === 弹窗冷却控制 ===
     private static lastPopupTimestamp: number = 0; // 最近一次弹出时间戳
-    private static readonly popupCooldownMs: number = 2000; // 弹窗冷却时长(毫秒)
+    private static readonly popupCooldownMs: number = 1; // 弹窗冷却时长(毫秒)
 
     private isInCooldown(): boolean {
         const now = Date.now();

+ 0 - 3
assets/scripts/CombatSystem/GamePause.ts

@@ -193,9 +193,6 @@ export class GamePause extends Component {
         console.log('[GamePause] 设置游戏状态为成功');
         this.currentState = GameState.SUCCESS;
         this.bulletFireEnabled = false;
-
-        // 派发游戏成功事件,让GameManager处理具体动作
-        EventBus.getInstance().emit(GameEvents.GAME_SUCCESS);
     }
 
     /**

+ 45 - 16
assets/scripts/CombatSystem/MenuSystem/SoundController.ts

@@ -275,7 +275,7 @@ export class SoundController extends Component {
     private applySoundEffectVolume(volume: number) {
         const audioManager = AudioManager.getInstance();
         if (audioManager) {
-            audioManager.setSoundEffectVolume(volume);
+            audioManager.setAllSoundVolume(volume);
         }
         //console.log(`[SoundController] 设置音效音量: ${volume}`);
     }
@@ -302,34 +302,59 @@ export class SoundController extends Component {
             musicVolume: this.savedMusicVolume
         };
         
+        // 兼容已有的本地键(微信端也可用)
         localStorage.setItem('audioSettings', JSON.stringify(settings));
+
+        // 写入到 SaveDataManager 的玩家设置,保证随存档持久化
+        const sdm = SaveDataManager.getInstance();
+        if (sdm && typeof sdm.updateSetting === 'function') {
+            sdm.updateSetting('soundEnabled', this.soundEffectEnabled);
+            sdm.updateSetting('musicEnabled', this.musicEnabled);
+            sdm.updateSetting('soundVolume', this.savedSoundEffectVolume);
+            sdm.updateSetting('musicVolume', this.savedMusicVolume);
+        }
     }
     
     /**
      * 从本地存储加载设置
      */
     private loadSettings() {
-        const savedSettings = localStorage.getItem('audioSettings');
-        if (savedSettings) {
+        const sdm = SaveDataManager.getInstance();
+        let loadedFromSDM = false;
+        if (sdm && typeof sdm.getSetting === 'function' && sdm.getPlayerData()) {
             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();
+                this.soundEffectEnabled = sdm.getSetting('soundEnabled') ?? true;
+                this.musicEnabled = sdm.getSetting('musicEnabled') ?? true;
+                this.savedSoundEffectVolume = sdm.getSetting('soundVolume') ?? 0.8;
+                this.savedMusicVolume = sdm.getSetting('musicVolume') ?? 0.6;
+                loadedFromSDM = true;
             } catch (e) {
-                console.warn('[SoundController] 加载音频设置失败:', e);
+                // 读取失败则走本地兜底
             }
         }
-        
+
+        if (!loadedFromSDM) {
+            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.6;
+                } catch (e) {
+                    console.warn('[SoundController] 加载音频设置失败:', e);
+                }
+            }
+        }
+
         // 从SaveDataManager加载震动设置
-        const saveDataManager = SaveDataManager.getInstance();
-        if (saveDataManager) {
-            this.vibrationEnabled = saveDataManager.getSetting('vibrationEnabled');
+        if (sdm) {
+            this.vibrationEnabled = sdm.getSetting('vibrationEnabled');
         }
+
+        // 更新UI显示
+        this.updateUI();
     }
     
     /**
@@ -348,11 +373,15 @@ export class SoundController extends Component {
         if (this.soundEffectSlider) {
             this.soundEffectSlider.progress = this.soundEffectEnabled ? this.savedSoundEffectVolume : 0;
             this.updateProgressBar(this.soundEffectProgressBar, this.soundEffectSlider.progress);
+            // 应用当前滑条音量到音频系统(初始化时也生效)
+            this.applySoundEffectVolume(this.soundEffectSlider.progress);
         }
         
         if (this.musicSlider) {
             this.musicSlider.progress = this.musicEnabled ? this.savedMusicVolume : 0;
             this.updateProgressBar(this.musicProgressBar, this.musicSlider.progress);
+            // 应用当前滑条音量到音频系统(初始化时也生效)
+            this.applyMusicVolume(this.musicSlider.progress);
         }
         
         // 更新震动滑动按钮位置(不使用动画,直接设置位置)

+ 1 - 10
assets/scripts/LevelSystem/GameManager.ts

@@ -831,20 +831,11 @@ export class GameManager extends Component {
         console.log('[GameManager] 游戏重启事件已发送');
     }
 
-    public forceGameSuccess() {
-        this.triggerGameSuccess();
-    }
-
     public forceGameDefeat() {
         this.triggerGameDefeat();
     }
 
-    // === 触发游戏成功 ===
-    private triggerGameSuccess() {
-        console.log('[GameManager] 触发游戏成功');
-        const eventBus = EventBus.getInstance();
-        eventBus.emit(GameEvents.GAME_SUCCESS);
-    }
+ 
 
     // === 触发游戏失败 ===
     private triggerGameDefeat() {

+ 26 - 10
assets/scripts/LevelSystem/IN_game.ts

@@ -353,11 +353,13 @@ export class InGameManager extends Component {
             console.log('[InGameManager] 技能选择完成,现在播放diban动画');
             this.pendingBlockSelection = false;
             
-            if (this.currentWave < (this.levelWaves?.length || 1)) {
+            const totalWaves = this.levelWaves?.length || 1;
+            if (this.currentWave < totalWaves) {
                 this.playDibanAnimationForNextWave();
             } else {
-                console.log('[InGameManager] 最后一波结束,触发游戏胜利');
-                this.triggerGameSuccess();
+                console.log('[InGameManager] 最后一波结束,直接进入下一波事件以判定胜利');
+                // 统一在 nextWave 中进行胜利判定
+                this.nextWave();
             }
         } else if (this.shouldPlayDibanAnimation()) {
             this.playDibanAnimationForNextWave();
@@ -472,18 +474,16 @@ export class InGameManager extends Component {
         
         if (isWaveEnd) {
             console.log(`[InGameManager] 波次结束检测: remaining=${remaining}`);
+            console.log(`[InGameManager]当前波次: remaining=${this.currentWave}`);
 
-            const isLastWave = this.currentWave >= (this.levelWaves?.length || 1);
-            if (isLastWave) {
-                // 最后一波结束,立即触发胜利(不受能量满影响)
-                this.triggerGameSuccess();
-            } else if (energyWillBeFull) {
-                // 非最后一波且能量已满,进入方块选择并准备下一波
+            // 不在击杀事件中判断游戏胜利;后续胜利判定在进入下一波事件中进行
+            if (energyWillBeFull) {
+                // 进入方块选择并准备下一波
                 this.pendingBlockSelection = true;
                 this.preparingNextWave = true;
                 this.currentState = GameState.BLOCK_SELECTION;
             } else {
-                // 非最后一波且能量未满,显示下一波提示
+                // 显示下一波提示(内部会在播放提示前判断是否还有后续波次)
                 this.showNextWavePrompt();
             }
         } else if (energyWillBeFull) {
@@ -519,6 +519,14 @@ export class InGameManager extends Component {
      * 显示下一波提示
      */
     private showNextWavePrompt() {
+        // 在播放下一波提示之前,先判断是否还有后续波次
+        const totalWaves = this.levelWaves?.length ?? -1;
+        if (totalWaves > 0 && this.currentWave >= totalWaves) {
+            console.log('[InGameManager] 已经没有后续波次,直接进入下一波事件以判定胜利(不播放提示与diban动画)');
+            this.nextWave();
+            return;
+        }
+
         // 设置准备下一波的状态
         this.preparingNextWave = true;
         this.pendingBlockSelection = true;
@@ -790,6 +798,14 @@ export class InGameManager extends Component {
      * 进入下一波
      */
     public nextWave() {
+        const totalWaves = this.levelWaves?.length ?? -1;
+        // 仅当总波次有效且没有下一波时触发胜利
+        if (totalWaves > 0 && this.currentWave >= totalWaves) {
+            console.log('[InGameManager] 没有下一波,触发游戏胜利');
+            this.triggerGameSuccess();
+            return;
+        }
+
         this.currentWave++;
 
         // 根据关卡配置获取下一波敌人数

Some files were not shown because too many files changed in this diff