From b9068e202967415390931f8c2cdad60987066faa Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Tue, 25 Aug 2026 02:17:50 +0000 Subject: [PATCH] Session 17: Sound Toggle (mute/unmute with persistence) Added --- dev-journal.md | 28 ++++++++++++ index.html | 5 +++ js/achievements.js | 4 +- js/game.js | 108 +++++++++++++++++++++++++++++++++++++++------ js/prestige.js | 6 +-- 5 files changed, 133 insertions(+), 18 deletions(-) diff --git a/dev-journal.md b/dev-journal.md index d270502..29fe978 100644 --- a/dev-journal.md +++ b/dev-journal.md @@ -468,3 +468,31 @@ Wrote a headless Node.js test (`/opt/data/idle-game-test/buy-all-buildings-test. - Potential new building tiers or prestige milestones / new prestige upgrades. - Sound variations or background music. - Consider a "Buy Max" toggle (buy one-at-a-time vs bulk) or per-building Buy Max count display. + +--- + +### Session 17 - 2026-08-25 (Morning) +**Status:** ✅ Sound Toggle (mute/unmute with persistence) Added + +#### What was done: +- Followed up on Sessions 14-16's recurring "sound variations / background music" next-goal by adding a **footer Sound toggle button**. The game already had a full Web Audio sound-effect system (click arpeggio, purchase chime, achievement fanfare, prestige whoosh, golden-bloom shimmer in `js/audio.js`), but there was no way to turn it off — once the audio context started on first click, it could never be silenced. This is a real usability gap for, e.g., playing at night or in a shared space. +- Added `soundEnabled: true` to `Game.state` and made **every** sound effect flow through a single new method `Game.playSound(effect)` (effects: 'click', 'purchase', 'achievement', 'prestige', 'goldenBloom'). The method returns early when `soundEnabled` is false, so muting reliably silences all effects. Replaced every direct `Audio.play*()` call site in `game.js`, `prestige.js`, and `achievements.js` with `Game.playSound(...)`. +- Guarded the initial `Audio.init()` on `if (this.state.soundEnabled)` so a muted player's browser never creates an audio context at all. +- Added a footer **Sound** toggle button (`#sound-btn`) next to the existing Autosave toggle, reusing the `.toggle-btn` styling. It shows 🔊/🔇 icons (instead of ON/OFF text), toggles `state.soundEnabled`, persists the preference to `localStorage('cosmicGardenSound')`, shows a notification, and — when unmute-ing — re-initializes/resumes the audio context (a click gesture satisfies the browser's autoplay policy). +- Added `Game.syncSoundButton()` which reflects the current preference on the footer button's visual state; called it at the end of `init()` so a muted player sees a muted button on reload even though the HTML defaults to enabled. +- Restored the persisted sound preference in `loadState()` **outside** the `if (saved)` block so it applies whether or not a per-slot save exists, and preserved `soundEnabled` across `reset()` and the empty-slot branch of `switchSlot()` (mirroring the existing `autoSave` handling). + +#### Files modified: +- `js/game.js` - added `soundEnabled` state; `playSound()` + `syncSoundButton()` methods; guarded `Audio.init()`; sound-toggle event listener; routed all 6 audio call sites through `Game.playSound`; restored pref in `loadState()`; preserved across `reset()`/`switchSlot()` +- `js/prestige.js` - routed prestige + prestige-upgrade sounds through `Game.playSound()` +- `js/achievements.js` - routed achievement sound through `Game.playSound()` +- `index.html` - added Sound toggle button to the footer +- `dev-journal.md` - appended Session 17 entry + +#### Verification: +Wrote a headless Node.js test (`/opt/data/idle-game-test/sound-toggle-test.mjs`) that loads the real `game.js` in-process with DOM/audio/localStorage stubs. **29/29 checks pass**, covering: default-on state, correct effect routing when enabled, total silence for all five effects when muted, unknown-effect safety, toggle button flipping preference + persisting to localStorage + showing notifications + updating 🔊/🔇 icon and `.on` class, restoring the muted/enabled preference from `loadState()` both with and without a save on disk, `reset()` preserving the preference across both states, and `syncSoundButton()` visual state. All existing suites re-ran clean with no regressions: buy-max 6/6, buy-all-upgrades 24/24, golden-bloom 22/22, prestige-buy-max 22/22, slot-preview 22/22, buy-all-buildings 31/31. All modified JS files pass `node --check`. + +#### Next goals: +- Consider adding a mute-state persistence across slots explicitly tested via the UI (currently preserved in state; could add a dedicated test that switches slots and checks the button). +- Potential new building tiers or prestige milestones / new prestige upgrades. +- Background music track or per-effect volume sliders. diff --git a/index.html b/index.html index d7161f5..c9abff9 100644 --- a/index.html +++ b/index.html @@ -125,6 +125,11 @@ Auto: +