This commit is contained in:
2025-12-07 21:31:44 +01:00
parent 4a0ca267ea
commit 974141c08c
52 changed files with 2485 additions and 397 deletions

View File

@@ -117,6 +117,111 @@ class SoundManager {
osc.stop(ctx.currentTime + 0.2);
}
beepAttack() {
if (!this.scene.sound.context) return;
const ctx = this.scene.sound.context;
const osc = ctx.createOscillator();
const gain = ctx.createGain();
osc.connect(gain);
gain.connect(ctx.destination);
osc.frequency.setValueAtTime(400, ctx.currentTime);
osc.frequency.exponentialRampToValueAtTime(100, ctx.currentTime + 0.08);
osc.type = 'sawtooth';
gain.gain.setValueAtTime(0.2, ctx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.01, ctx.currentTime + 0.08);
osc.start();
osc.stop(ctx.currentTime + 0.08);
}
beepHit() {
if (!this.scene.sound.context) return;
const ctx = this.scene.sound.context;
const osc = ctx.createOscillator();
const gain = ctx.createGain();
osc.connect(gain);
gain.connect(ctx.destination);
osc.frequency.value = 80;
osc.type = 'square';
gain.gain.setValueAtTime(0.25, ctx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.01, ctx.currentTime + 0.05);
osc.start();
osc.stop(ctx.currentTime + 0.05);
}
beepFootstep() {
if (!this.scene.sound.context) return;
const ctx = this.scene.sound.context;
const osc = ctx.createOscillator();
const gain = ctx.createGain();
osc.connect(gain);
gain.connect(ctx.destination);
osc.frequency.value = 120 + Math.random() * 20;
osc.type = 'sine';
gain.gain.setValueAtTime(0.05, ctx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.01, ctx.currentTime + 0.03);
osc.start();
osc.stop(ctx.currentTime + 0.03);
}
beepDeath() {
if (!this.scene.sound.context) return;
const ctx = this.scene.sound.context;
const osc = ctx.createOscillator();
const gain = ctx.createGain();
osc.connect(gain);
gain.connect(ctx.destination);
osc.frequency.setValueAtTime(300, ctx.currentTime);
osc.frequency.exponentialRampToValueAtTime(50, ctx.currentTime + 0.5);
osc.type = 'sawtooth';
gain.gain.setValueAtTime(0.2, ctx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.01, ctx.currentTime + 0.5);
osc.start();
osc.stop(ctx.currentTime + 0.5);
}
startRainNoise() {
if (!this.scene.sound.context || this.rainNode) return;
const ctx = this.scene.sound.context;
// Create noise buffer
const bufferSize = 2 * ctx.sampleRate;
const buffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate);
const output = buffer.getChannelData(0);
for (let i = 0; i < bufferSize; i++) {
output[i] = Math.random() * 2 - 1;
}
this.rainNode = ctx.createBufferSource();
this.rainNode.buffer = buffer;
this.rainNode.loop = true;
// Lowpass filter for rain sound
const filter = ctx.createBiquadFilter();
filter.type = 'lowpass';
filter.frequency.value = 800;
this.rainGain = ctx.createGain();
this.rainGain.gain.value = 0.05 * this.sfxVolume;
this.rainNode.connect(filter);
filter.connect(this.rainGain);
this.rainGain.connect(ctx.destination);
this.rainNode.start();
}
stopRainNoise() {
if (this.rainNode) {
this.rainNode.stop();
this.rainNode.disconnect();
this.rainNode = null;
}
if (this.rainGain) {
this.rainGain.disconnect();
this.rainGain = null;
}
}
playAmbient(key, loop = true) {
if (this.isMuted) return;
if (this.currentAmbient) this.currentAmbient.stop();
@@ -132,6 +237,55 @@ class SoundManager {
}
}
startMusic() {
if (!this.scene.sound.context || this.musicInterval) return;
console.log('🎵 Starting Ambient Music...');
// Simple C Minor Pentatonic: C3, Eb3, F3, G3, Bb3
const scale = [130.81, 155.56, 174.61, 196.00, 233.08, 261.63];
// Loop every 3-5 seconds play a note
this.musicInterval = setInterval(() => {
if (this.isMuted) return;
// 40% chance to play a note
if (Math.random() > 0.6) {
const freq = scale[Math.floor(Math.random() * scale.length)];
this.playProceduralNote(freq);
}
}, 2000);
}
stopMusic() {
if (this.musicInterval) {
clearInterval(this.musicInterval);
this.musicInterval = null;
}
}
playProceduralNote(freq) {
if (!this.scene.sound.context) return;
const ctx = this.scene.sound.context;
const osc = ctx.createOscillator();
const gain = ctx.createGain();
osc.connect(gain);
gain.connect(ctx.destination);
osc.frequency.value = freq;
osc.type = 'sine'; // Soft tone
const now = ctx.currentTime;
const duration = 2.0; // Long decay like reverb/pad
gain.gain.setValueAtTime(0, now);
gain.gain.linearRampToValueAtTime(0.05 * this.musicVolume, now + 0.5); // Slow attack
gain.gain.exponentialRampToValueAtTime(0.001, now + duration); // Long release
osc.start(now);
osc.stop(now + duration);
}
toggleMute() {
this.isMuted = !this.isMuted;
this.scene.sound.mute = this.isMuted;
@@ -143,6 +297,10 @@ class SoundManager {
playHarvest() { this.playSFX('harvest'); }
playBuild() { this.playSFX('build'); }
playPickup() { this.playSFX('pickup'); }
playRainSound() { this.playAmbient('rain_loop'); }
stopRainSound() { this.stopAmbient(); }
playAttack() { this.beepAttack(); }
playHit() { this.beepHit(); }
playFootstep() { this.beepFootstep(); }
playDeath() { this.beepDeath(); }
playRainSound() { this.startRainNoise(); }
stopRainSound() { this.stopRainNoise(); }
}