/** * Audio System - Звуковая система (Web Audio API) */ class AudioSystem { constructor() { this.context = null; this.enabled = true; this.volume = 0.5; this.musicEnabled = true; this.musicOscillator = null; this.musicGain = null; } // Инициализация аудио контекста init() { try { this.context = new (window.AudioContext || window.webkitAudioContext)(); return true; } catch (e) { console.warn('Audio not supported:', e); return false; } } // Возобновить контекст (нужно после взаимодействия пользователя) resume() { if (this.context && this.context.state === 'suspended') { this.context.resume(); } } // Звук шагов playFootstep() { if (!this.enabled || !this.context) return; const osc = this.context.createOscillator(); const gain = this.context.createGain(); osc.connect(gain); gain.connect(this.context.destination); osc.type = 'square'; osc.frequency.setValueAtTime(80, this.context.currentTime); osc.frequency.exponentialRampToValueAtTime(40, this.context.currentTime + 0.1); gain.gain.setValueAtTime(this.volume * 0.1, this.context.currentTime); gain.gain.exponentialRampToValueAtTime(0.01, this.context.currentTime + 0.1); osc.start(this.context.currentTime); osc.stop(this.context.currentTime + 0.1); } // Звук удара playHit() { if (!this.enabled || !this.context) return; // Шум удара const bufferSize = this.context.sampleRate * 0.1; const buffer = this.context.createBuffer(1, bufferSize, this.context.sampleRate); const data = buffer.getChannelData(0); for (let i = 0; i < bufferSize; i++) { data[i] = (Math.random() * 2 - 1) * (1 - i / bufferSize); } const noise = this.context.createBufferSource(); noise.buffer = buffer; const filter = this.context.createBiquadFilter(); filter.type = 'lowpass'; filter.frequency.value = 1000; const gain = this.context.createGain(); gain.gain.setValueAtTime(this.volume * 0.3, this.context.currentTime); gain.gain.exponentialRampToValueAtTime(0.01, this.context.currentTime + 0.15); noise.connect(filter); filter.connect(gain); gain.connect(this.context.destination); noise.start(); } // Звук убийства playKill() { if (!this.enabled || !this.context) return; // Низкий удар const osc = this.context.createOscillator(); const gain = this.context.createGain(); osc.connect(gain); gain.connect(this.context.destination); osc.type = 'sawtooth'; osc.frequency.setValueAtTime(200, this.context.currentTime); osc.frequency.exponentialRampToValueAtTime(30, this.context.currentTime + 0.3); gain.gain.setValueAtTime(this.volume * 0.4, this.context.currentTime); gain.gain.exponentialRampToValueAtTime(0.01, this.context.currentTime + 0.3); osc.start(this.context.currentTime); osc.stop(this.context.currentTime + 0.3); } // Звукденег playCoin() { if (!this.enabled || !this.context) return; const osc = this.context.createOscillator(); const gain = this.context.createGain(); osc.connect(gain); gain.connect(this.context.destination); osc.type = 'sine'; osc.frequency.setValueAtTime(800, this.context.currentTime); osc.frequency.setValueAtTime(1200, this.context.currentTime + 0.05); osc.frequency.setValueAtTime(1600, this.context.currentTime + 0.1); gain.gain.setValueAtTime(this.volume * 0.2, this.context.currentTime); gain.gain.exponentialRampToValueAtTime(0.01, this.context.currentTime + 0.15); osc.start(this.context.currentTime); osc.stop(this.context.currentTime + 0.15); } // Звук предмета playItem() { if (!this.enabled || !this.context) return; const osc = this.context.createOscillator(); const gain = this.context.createGain(); osc.connect(gain); gain.connect(this.context.destination); osc.type = 'sine'; osc.frequency.setValueAtTime(600, this.context.currentTime); osc.frequency.setValueAtTime(900, this.context.currentTime + 0.08); gain.gain.setValueAtTime(this.volume * 0.15, this.context.currentTime); gain.gain.exponentialRampToValueAtTime(0.01, this.context.currentTime + 0.2); osc.start(this.context.currentTime); osc.stop(this.context.currentTime + 0.2); } // Звук еды playEat() { if (!this.enabled || !this.context) return; const osc = this.context.createOscillator(); const gain = this.context.createGain(); osc.connect(gain); gain.connect(this.context.destination); osc.type = 'triangle'; osc.frequency.setValueAtTime(400, this.context.currentTime); osc.frequency.exponentialRampToValueAtTime(200, this.context.currentTime + 0.15); gain.gain.setValueAtTime(this.volume * 0.2, this.context.currentTime); gain.gain.exponentialRampToValueAtTime(0.01, this.context.currentTime + 0.15); osc.start(this.context.currentTime); osc.stop(this.context.currentTime + 0.15); } // Звук HP playHeal() { if (!this.enabled || !this.context) return; const osc1 = this.context.createOscillator(); const osc2 = this.context.createOscillator(); const gain = this.context.createGain(); osc1.connect(gain); osc2.connect(gain); gain.connect(this.context.destination); osc1.type = 'sine'; osc1.frequency.setValueAtTime(500, this.context.currentTime); osc1.frequency.setValueAtTime(700, this.context.currentTime + 0.1); osc2.type = 'sine'; osc2.frequency.setValueAtTime(750, this.context.currentTime + 0.05); osc2.frequency.setValueAtTime(1000, this.context.currentTime + 0.15); gain.gain.setValueAtTime(this.volume * 0.2, this.context.currentTime); gain.gain.exponentialRampToValueAtTime(0.01, this.context.currentTime + 0.25); osc1.start(this.context.currentTime); osc2.start(this.context.currentTime + 0.05); osc1.stop(this.context.currentTime + 0.2); osc2.stop(this.context.currentTime + 0.25); } // Звук получения урона playDamage() { if (!this.enabled || !this.context) return; const osc = this.context.createOscillator(); const gain = this.context.createGain(); osc.connect(gain); gain.connect(this.context.destination); osc.type = 'sawtooth'; osc.frequency.setValueAtTime(150, this.context.currentTime); osc.frequency.exponentialRampToValueAtTime(50, this.context.currentTime + 0.2); gain.gain.setValueAtTime(this.volume * 0.3, this.context.currentTime); gain.gain.exponentialRampToValueAtTime(0.01, this.context.currentTime + 0.2); osc.start(this.context.currentTime); osc.stop(this.context.currentTime + 0.2); } // Звук UI (кнопка) playUIClick() { if (!this.enabled || !this.context) return; const osc = this.context.createOscillator(); const gain = this.context.createGain(); osc.connect(gain); gain.connect(this.context.destination); osc.type = 'sine'; osc.frequency.setValueAtTime(1000, this.context.currentTime); gain.gain.setValueAtTime(this.volume * 0.1, this.context.currentTime); gain.gain.exponentialRampToValueAtTime(0.01, this.context.currentTime + 0.05); osc.start(this.context.currentTime); osc.stop(this.context.currentTime + 0.05); } // Фоновая музыка (простая мелодия) startMusic() { if (!this.musicEnabled || !this.context) return; // Остановить предыдущую музыку this.stopMusic(); // Создать осциллятор для фоновой музыки this.musicOscillator = this.context.createOscillator(); this.musicGain = this.context.createGain(); this.musicOscillator.connect(this.musicGain); this.musicGain.connect(this.context.destination); this.musicOscillator.type = 'sine'; this.musicOscillator.frequency.value = 220; this.musicGain.gain.value = this.volume * 0.05; // Менять частоту каждые 2 секунды const notes = [220, 262, 294, 330, 349, 392, 440, 392, 349, 330, 294, 262]; let noteIndex = 0; this.musicInterval = setInterval(() => { if (this.musicEnabled && this.musicOscillator) { this.musicOscillator.frequency.value = notes[noteIndex]; noteIndex = (noteIndex + 1) % notes.length; } }, 2000); this.musicOscillator.start(); } // Остановить музыку stopMusic() { if (this.musicInterval) { clearInterval(this.musicInterval); } if (this.musicOscillator) { this.musicOscillator.stop(); this.musicOscillator = null; } } // Переключить звук toggle() { this.enabled = !this.enabled; return this.enabled; } // Переключить музыку toggleMusic() { this.musicEnabled = !this.musicEnabled; if (this.musicEnabled) { this.startMusic(); } else { this.stopMusic(); } return this.musicEnabled; } } // Глобальный экземпляр window.Audio = new AudioSystem();