Files
Some_Projects/Hommie/audio.js

304 lines
11 KiB
JavaScript

/**
* 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();