fix: Prevent audio from continuing after game completion
PROBLEM: - Task audio and punishment audio would continue playing after completing games - Interactive task manager had delayed completions that could trigger after endGame() - AudioManager didn't check game state before playing new audio SOLUTION: Enhanced endGame() method with multiple audio stop attempts Added game state check in AudioManager.playAudio() to prevent new audio after game ends Modified AudioManager constructor to accept game instance for state checking Added game state validation in all interactive task completion methods Enhanced cleanupInteractiveTask() to explicitly stop audio categories Added safeguards in completeInteractiveTask(), giveUpInteractiveTask(), resumeFromCamera() TECHNICAL DETAILS: - endGame() now calls stopAllImmediate() twice (immediate + 100ms delay) - AudioManager checks if game.gameState.isRunning before playing any new audio - Interactive task manager validates game state before calling completeTask() - All delayed completions now verify game is still running before proceeding - Interactive task cleanup now explicitly stops 'tasks' and 'punishments' audio Audio will now properly stop when games end and won't restart from delayed task completions!
This commit is contained in:
parent
5861c07bab
commit
66bee4821b
|
|
@ -56,7 +56,7 @@ class TaskChallengeGame {
|
|||
this.aiTaskManager = new AITaskManager(this.dataManager);
|
||||
|
||||
// Initialize Audio Management System
|
||||
this.audioManager = new AudioManager(this.dataManager);
|
||||
this.audioManager = new AudioManager(this.dataManager, this);
|
||||
|
||||
// Initialize Game Mode Manager
|
||||
this.gameModeManager = new GameModeManager();
|
||||
|
|
@ -4791,10 +4791,16 @@ ${usagePercent > 85 ? '⚠️ Storage getting full - consider deleting some imag
|
|||
this.popupImageManager.stopPeriodicPopups();
|
||||
}
|
||||
|
||||
// Stop all audio immediately when game ends
|
||||
console.log('Game ended - stopping all audio');
|
||||
// Stop all audio immediately when game ends - multiple attempts to ensure it stops
|
||||
console.log('Game ended - stopping all audio immediately');
|
||||
this.audioManager.stopAllImmediate();
|
||||
|
||||
// Additional safeguard - stop all audio again after a brief delay
|
||||
setTimeout(() => {
|
||||
console.log('Game ended - secondary audio stop to ensure silence');
|
||||
this.audioManager.stopAllImmediate();
|
||||
}, 100);
|
||||
|
||||
// Show photo gallery if any photos were taken during the game
|
||||
this.showGamePhotoGallery(() => {
|
||||
this.showFinalStats(reason);
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@
|
|||
* Handles multiple audio categories with volume controls and fade effects
|
||||
*/
|
||||
class AudioManager {
|
||||
constructor(dataManager) {
|
||||
constructor(dataManager, game = null) {
|
||||
this.dataManager = dataManager;
|
||||
this.game = game; // Reference to game instance for state checking
|
||||
this.audioContext = null;
|
||||
this.masterGain = null;
|
||||
|
||||
|
|
@ -234,6 +235,12 @@ class AudioManager {
|
|||
console.warn('AudioManager not initialized yet');
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if the game is still running - prevent audio after game ends
|
||||
if (this.game && this.game.gameState && !this.game.gameState.isRunning) {
|
||||
console.log(`Game is not running - blocking audio playback for ${category}/${subcategory}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!this.isCategoryEnabled(category)) {
|
||||
console.log(`Audio category ${category} is disabled`);
|
||||
|
|
|
|||
|
|
@ -205,6 +205,12 @@ class InteractiveTaskManager {
|
|||
*/
|
||||
async completeInteractiveTask() {
|
||||
if (!this.currentInteractiveTask) return;
|
||||
|
||||
// Check if game is still running - prevent completion after game has ended
|
||||
if (!this.game.gameState.isRunning) {
|
||||
console.log('Interactive task completion cancelled - game no longer running');
|
||||
return;
|
||||
}
|
||||
|
||||
const taskType = this.taskTypes.get(this.currentInteractiveTask.interactiveType);
|
||||
|
||||
|
|
@ -215,8 +221,11 @@ class InteractiveTaskManager {
|
|||
// Task completed successfully
|
||||
this.showFeedback('success', 'Challenge completed successfully! 🎉');
|
||||
setTimeout(() => {
|
||||
this.cleanupInteractiveTask();
|
||||
this.game.completeTask();
|
||||
// Double-check game is still running before proceeding
|
||||
if (this.game.gameState.isRunning) {
|
||||
this.cleanupInteractiveTask();
|
||||
this.game.completeTask();
|
||||
}
|
||||
}, 1500);
|
||||
} else {
|
||||
// Task failed validation
|
||||
|
|
@ -230,10 +239,19 @@ class InteractiveTaskManager {
|
|||
* Give up on interactive task (counts as skip)
|
||||
*/
|
||||
giveUpInteractiveTask() {
|
||||
// Check if game is still running
|
||||
if (!this.game.gameState.isRunning) {
|
||||
console.log('Interactive task give up cancelled - game no longer running');
|
||||
return;
|
||||
}
|
||||
|
||||
this.showFeedback('warning', 'Challenge abandoned. This counts as a skip.');
|
||||
setTimeout(() => {
|
||||
this.cleanupInteractiveTask();
|
||||
this.game.skipTask();
|
||||
// Double-check game is still running before proceeding
|
||||
if (this.game.gameState.isRunning) {
|
||||
this.cleanupInteractiveTask();
|
||||
this.game.skipTask();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
|
|
@ -303,6 +321,13 @@ class InteractiveTaskManager {
|
|||
* Clean up interactive task elements
|
||||
*/
|
||||
cleanupInteractiveTask() {
|
||||
// Stop any audio that might be playing before cleanup
|
||||
if (this.game && this.game.audioManager) {
|
||||
console.log('Interactive task cleanup - stopping audio');
|
||||
this.game.audioManager.stopCategory('tasks', 0);
|
||||
this.game.audioManager.stopCategory('punishments', 0);
|
||||
}
|
||||
|
||||
// Remove interactive container
|
||||
const container = document.getElementById('interactive-task-container');
|
||||
if (container) {
|
||||
|
|
@ -891,7 +916,8 @@ class InteractiveTaskManager {
|
|||
|
||||
// Mark current task as completed after a delay (but don't use completeInteractiveTask to avoid container issues)
|
||||
setTimeout(() => {
|
||||
if (this.currentInteractiveTask) {
|
||||
// Check if game is still running before completing
|
||||
if (this.currentInteractiveTask && this.game.gameState.isRunning) {
|
||||
this.cleanupInteractiveTask();
|
||||
this.game.completeTask();
|
||||
}
|
||||
|
|
@ -904,6 +930,12 @@ class InteractiveTaskManager {
|
|||
resumeFromCamera() {
|
||||
console.log('📱 Resuming from camera to task interface');
|
||||
|
||||
// Check if game is still running
|
||||
if (!this.game.gameState.isRunning) {
|
||||
console.log('Resume from camera cancelled - game no longer running');
|
||||
return;
|
||||
}
|
||||
|
||||
// Show completion message and progress to next task
|
||||
if (this.currentInteractiveTask) {
|
||||
// Mark task as completed without trying to show feedback in missing containers
|
||||
|
|
@ -916,7 +948,10 @@ class InteractiveTaskManager {
|
|||
|
||||
// Complete the task directly
|
||||
setTimeout(() => {
|
||||
this.game.completeTask();
|
||||
// Double-check game is still running
|
||||
if (this.game.gameState.isRunning) {
|
||||
this.game.completeTask();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue