feat(sfx): wire Howler.js SFX audio into renderer #86
Reference in New Issue
Block a user
Delete Branch "feat/sfx-audio"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
public/index.htmlsowindow.Howlis available in the browserpublic/renderer/audio.js— a factory module wrapping Howler with graceful load-error handling and aNOOP_AUDIOfallbackaudio.playSfx()intoobjection(),holdIt(), andtakeThat()composite cues ineffects.jscreateCourtRendererand exposes the handle on the returned renderer object for DevTools inspectionassets/sfx/README.mddocumenting the 5 required MP3 files and suggested CC0 sourcesTest Plan
npm run lintpasses (no TypeScript changes)[Audio] Loaded N SFX(or graceful per-file warnings if files absent)courtRenderer.effects.objection()plays audio + shows OBJECTION! stampcourtRenderer.effects.holdIt()plays audio + shows HOLD IT! stampcourtRenderer.effects.takeThat()plays audio + shows TAKE THAT! stampcourtRenderer.effects.trigger('unknown_cue')→ no crash, no audiorender_directivewitheffect: 'objection'fires the stingerCloses #73
🤖 Generated with Claude Code
Pull request overview
This PR wires SFX playback into the browser renderer by introducing a Howler-backed audio module, initializing it in the renderer bootstrap, and triggering SFX during key composite effect cues (OBJECTION/HOLD IT/TAKE THAT).
Changes:
Howlglobally in the browser.public/renderer/audio.jsand initialize/load SFX increateCourtRenderer, passing an audio handle into the effects layer.objection(),holdIt(), andtakeThat()cues; add documentation for required SFX files.Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.
Show a summary per file
audioon renderer.loadSFXandplaySfxwith graceful error handling.💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
DEFAULT_SFX_CONFIGpoints at/assets/sfx/..., which is served frompublic/assets/sfx(since onlypublic/is mounted viaexpress.static). This README instructs placing MP3s under repo-rootassets/sfx, which won’t be reachable by the browser; either move this doc (and any SFX assets) topublic/assets/sfx/or change the URLs/config to match the served directory.This PR is scoped to wiring Howler SFX into the renderer, but it also adds a large Twitch bot integration plan doc. If the Twitch plan isn’t required for the SFX feature/issue #73, consider moving it to a separate PR to keep changesets focused and reduce review noise.
@@ -546,6 +546,7 @@</aside>Loading Howler from a third-party CDN without Subresource Integrity (SRI) or a self-hosted fallback increases supply-chain risk. If this project already accepts CDN scripts, consider at least adding
integrity/crossoriginattributes (or vendoring Howler underpublic/like other static assets) to reduce the impact of a compromised CDN.@@ -0,0 +53,4 @@resolve();},});} catch (err) {On
onloaderror, theHowlis still stored insounds, so[Audio] Loaded ${sounds.size} SFXcounts failed loads and laterplaySfxwill attempt to play entries that never loaded. Consider only adding tosoundsafter a successfulonload, or deleting the entry insideonloaderrorso the map reflects playable sounds and the log is accurate.@@ -0,0 +74,4 @@const sound = sounds.get(name);if (sound) {sound.play();}playSfxcurrently returns early whenreadyis false, which means effects triggered beforeloadSFX()finishes will never play audio even if the requested sound has already loaded. Consider allowing playback whenever aHowlinstance exists (optionally callingsound.play()and letting Howler handle lazy loading), and reservereadyonly for logging/metrics.@copilot open a new pull request to apply changes based on the comments in this thread
@PatrickFanella I've opened a new pull request, #88, to work on those changes. Once the pull request is ready, I'll request review from you.