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:
dilgenfritz 2025-10-28 08:07:13 -05:00
parent 5861c07bab
commit 66bee4821b
3 changed files with 58 additions and 10 deletions

View File

@ -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);

View File

@ -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`);

View File

@ -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);
}
}