168 lines
4.7 KiB
JavaScript
168 lines
4.7 KiB
JavaScript
/**
|
|
* Cosmic Garden - Audio System
|
|
* Sound effects using Web Audio API (no external assets needed)
|
|
*/
|
|
|
|
const Audio = {
|
|
ctx: null,
|
|
|
|
/**
|
|
* Initialize audio context
|
|
*/
|
|
init() {
|
|
try {
|
|
this.ctx = new (window.AudioContext || window.webkitAudioContext)();
|
|
} catch (e) {
|
|
console.log('Web Audio API not supported');
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Resume audio context (needed for some browsers)
|
|
*/
|
|
resume() {
|
|
if (this.ctx && this.ctx.state === 'suspended') {
|
|
this.ctx.resume();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Play click sound - rising C-major arpeggio
|
|
*/
|
|
playClick() {
|
|
if (!this.ctx) return;
|
|
this.resume();
|
|
|
|
const now = this.ctx.currentTime;
|
|
const notes = [523.25, 659.25, 783.99]; // C5, E5, G5
|
|
|
|
notes.forEach((freq, i) => {
|
|
const osc = this.ctx.createOscillator();
|
|
const gain = this.ctx.createGain();
|
|
|
|
osc.connect(gain);
|
|
gain.connect(this.ctx.destination);
|
|
|
|
osc.frequency.value = freq;
|
|
osc.type = 'sine';
|
|
|
|
gain.gain.setValueAtTime(0.1, now + i * 0.05);
|
|
gain.gain.exponentialRampToValueAtTime(0.01, now + i * 0.05 + 0.15);
|
|
|
|
osc.start(now + i * 0.05);
|
|
osc.stop(now + i * 0.05 + 0.15);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Play purchase sound - descending chime
|
|
*/
|
|
playPurchase() {
|
|
if (!this.ctx) return;
|
|
this.resume();
|
|
|
|
const now = this.ctx.currentTime;
|
|
const notes = [783.99, 659.25, 523.25]; // G5, E5, C5
|
|
|
|
notes.forEach((freq, i) => {
|
|
const osc = this.ctx.createOscillator();
|
|
const gain = this.ctx.createGain();
|
|
|
|
osc.connect(gain);
|
|
gain.connect(this.ctx.destination);
|
|
|
|
osc.frequency.value = freq;
|
|
osc.type = 'triangle';
|
|
|
|
gain.gain.setValueAtTime(0.15, now + i * 0.08);
|
|
gain.gain.exponentialRampToValueAtTime(0.01, now + i * 0.08 + 0.2);
|
|
|
|
osc.start(now + i * 0.08);
|
|
osc.stop(now + i * 0.08 + 0.2);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Play achievement sound - ascending chord fanfare
|
|
*/
|
|
playAchievement() {
|
|
if (!this.ctx) return;
|
|
this.resume();
|
|
|
|
const now = this.ctx.currentTime;
|
|
const chords = [
|
|
[523.25, 659.25, 783.99], // C major
|
|
[659.25, 783.99, 987.77], // E major
|
|
[783.99, 987.77, 1174.66] // G major
|
|
];
|
|
|
|
chords.forEach((chord, chordIndex) => {
|
|
chord.forEach(freq => {
|
|
const osc = this.ctx.createOscillator();
|
|
const gain = this.ctx.createGain();
|
|
|
|
osc.connect(gain);
|
|
gain.connect(this.ctx.destination);
|
|
|
|
osc.frequency.value = freq;
|
|
osc.type = 'sine';
|
|
|
|
const startTime = now + chordIndex * 0.15;
|
|
gain.gain.setValueAtTime(0.12, startTime);
|
|
gain.gain.exponentialRampToValueAtTime(0.01, startTime + 0.3);
|
|
|
|
osc.start(startTime);
|
|
osc.stop(startTime + 0.3);
|
|
});
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Play prestige sound - ethereal whoosh
|
|
*/
|
|
playPrestige() {
|
|
if (!this.ctx) return;
|
|
this.resume();
|
|
|
|
const now = this.ctx.currentTime;
|
|
|
|
// Rising sweep
|
|
const osc = this.ctx.createOscillator();
|
|
const gain = this.ctx.createGain();
|
|
|
|
osc.connect(gain);
|
|
gain.connect(this.ctx.destination);
|
|
|
|
osc.type = 'sine';
|
|
osc.frequency.setValueAtTime(200, now);
|
|
osc.frequency.exponentialRampToValueAtTime(800, now + 0.5);
|
|
|
|
gain.gain.setValueAtTime(0.2, now);
|
|
gain.gain.exponentialRampToValueAtTime(0.01, now + 0.8);
|
|
|
|
osc.start(now);
|
|
osc.stop(now + 0.8);
|
|
|
|
// Sparkle overlay
|
|
for (let i = 0; i < 5; i++) {
|
|
const sparkle = this.ctx.createOscillator();
|
|
const sparkleGain = this.ctx.createGain();
|
|
|
|
sparkle.connect(sparkleGain);
|
|
sparkleGain.connect(this.ctx.destination);
|
|
|
|
sparkle.frequency.value = 1200 + Math.random() * 800;
|
|
sparkle.type = 'sine';
|
|
|
|
const startTime = now + 0.1 + i * 0.1;
|
|
sparkleGain.gain.setValueAtTime(0.08, startTime);
|
|
sparkleGain.gain.exponentialRampToValueAtTime(0.01, startTime + 0.2);
|
|
|
|
sparkle.start(startTime);
|
|
sparkle.stop(startTime + 0.2);
|
|
}
|
|
}
|
|
};
|
|
|
|
window.Audio = Audio;
|