feat(sasch40): major overhaul with doodle jump, party bunker, and guitar hero
- Add global settings & pause modal (gear icon) with mute and reset, removing obsolete bag button - Extend Prologue with Flo Maier (castle fire game over & Löschzug restart) and Viktor (vampire bite game over & Knoblauch restart) - Rebuild Akt II as 3-level vertical Doodle Jump climber to rescue sisters Saskia, Maja, and Miriam with custom pixel portraits - Update Akt III Schankraum with seamless oak floor, double-tap 'Luke zum Party Bunker', duel intro modals, and Hansi's departure in Hinterland - Rebuild Akt IV as 3-lane medieval Guitar Hero rock concert with live crowd meter, combo multipliers, and Hansi duo - Update AGENTS.md architectural documentation and playtest test suite
This commit is contained in:
@@ -162,6 +162,116 @@ class SoundEngine {
|
||||
})
|
||||
}
|
||||
|
||||
// SFX: Sister Rescue Fanfare (bright sweet jingle)
|
||||
public playRescueFanfare() {
|
||||
if (this.isMuted) return
|
||||
this.initCtx()
|
||||
if (!this.ctx) return
|
||||
|
||||
const notes = [523.25, 659.25, 783.99, 1046.50] // C5, E5, G5, C6
|
||||
notes.forEach((freq, idx) => {
|
||||
if (!this.ctx) return
|
||||
const now = this.ctx.currentTime + idx * 0.1
|
||||
const osc = this.ctx.createOscillator()
|
||||
const gain = this.ctx.createGain()
|
||||
|
||||
osc.type = 'sine'
|
||||
osc.frequency.setValueAtTime(freq, now)
|
||||
|
||||
gain.gain.setValueAtTime(0.25, now)
|
||||
gain.gain.exponentialRampToValueAtTime(0.001, now + 0.35)
|
||||
|
||||
osc.connect(gain)
|
||||
gain.connect(this.ctx.destination)
|
||||
|
||||
osc.start(now)
|
||||
osc.stop(now + 0.35)
|
||||
})
|
||||
}
|
||||
|
||||
// SFX: Spring / Trampoline Bounce (Doodle Jump super bounce)
|
||||
public playSpringBounce() {
|
||||
if (this.isMuted) return
|
||||
this.initCtx()
|
||||
if (!this.ctx) return
|
||||
|
||||
const now = this.ctx.currentTime
|
||||
const osc = this.ctx.createOscillator()
|
||||
const gain = this.ctx.createGain()
|
||||
|
||||
osc.type = 'triangle'
|
||||
osc.frequency.setValueAtTime(220, now)
|
||||
osc.frequency.exponentialRampToValueAtTime(880, now + 0.25)
|
||||
|
||||
gain.gain.setValueAtTime(0.3, now)
|
||||
gain.gain.exponentialRampToValueAtTime(0.01, now + 0.3)
|
||||
|
||||
osc.connect(gain)
|
||||
gain.connect(this.ctx.destination)
|
||||
|
||||
osc.start(now)
|
||||
osc.stop(now + 0.3)
|
||||
}
|
||||
|
||||
// SFX: Hit / Impact / Thud
|
||||
public playBoarHit() {
|
||||
if (this.isMuted) return
|
||||
this.initCtx()
|
||||
if (!this.ctx) return
|
||||
|
||||
const now = this.ctx.currentTime
|
||||
const osc = this.ctx.createOscillator()
|
||||
const gain = this.ctx.createGain()
|
||||
|
||||
osc.type = 'sawtooth'
|
||||
osc.frequency.setValueAtTime(160, now)
|
||||
osc.frequency.exponentialRampToValueAtTime(40, now + 0.2)
|
||||
|
||||
gain.gain.setValueAtTime(0.3, now)
|
||||
gain.gain.exponentialRampToValueAtTime(0.01, now + 0.2)
|
||||
|
||||
osc.connect(gain)
|
||||
gain.connect(this.ctx.destination)
|
||||
|
||||
osc.start(now)
|
||||
osc.stop(now + 0.2)
|
||||
}
|
||||
|
||||
// SFX: Medieval Lute Hero Note (String Index 0: Low, 1: Mid, 2: High)
|
||||
public playLuteNote(lane: number, success: boolean = true) {
|
||||
if (this.isMuted) return
|
||||
this.initCtx()
|
||||
if (!this.ctx) return
|
||||
|
||||
const now = this.ctx.currentTime
|
||||
const osc = this.ctx.createOscillator()
|
||||
const gain = this.ctx.createGain()
|
||||
|
||||
if (!success) {
|
||||
// Missed clunk / muted buzz
|
||||
osc.type = 'sawtooth'
|
||||
osc.frequency.setValueAtTime(90, now)
|
||||
gain.gain.setValueAtTime(0.12, now)
|
||||
gain.gain.exponentialRampToValueAtTime(0.001, now + 0.12)
|
||||
} else {
|
||||
// Resonant lute string twang
|
||||
const freqs = [293.66, 392.00, 587.33] // D4, G4, D5
|
||||
const freq = freqs[lane % 3] || 440
|
||||
osc.type = 'triangle'
|
||||
osc.frequency.setValueAtTime(freq, now)
|
||||
|
||||
gain.gain.setValueAtTime(0.28, now)
|
||||
gain.gain.exponentialRampToValueAtTime(0.001, now + 0.32)
|
||||
}
|
||||
|
||||
osc.connect(gain)
|
||||
gain.connect(this.ctx.destination)
|
||||
|
||||
osc.start(now)
|
||||
osc.stop(now + (success ? 0.32 : 0.12))
|
||||
}
|
||||
|
||||
|
||||
// 135 BPM Medieval Techno Chiptune Beat
|
||||
public startBGM() {
|
||||
if (this.isMuted || this.bgmPlaying) return
|
||||
|
||||
Reference in New Issue
Block a user