Загрузить файлы в «Prehistorik»
This commit is contained in:
76
Prehistorik/audio.js
Normal file
76
Prehistorik/audio.js
Normal file
@@ -0,0 +1,76 @@
|
||||
'use strict';
|
||||
|
||||
let audioCtx = null;
|
||||
|
||||
function getAudio() {
|
||||
if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)();
|
||||
return audioCtx;
|
||||
}
|
||||
|
||||
function beep(freq, freq2, dur, type = 'sine', vol = 0.3) {
|
||||
try {
|
||||
const ac = getAudio();
|
||||
const o = ac.createOscillator();
|
||||
const g = ac.createGain();
|
||||
o.type = type;
|
||||
o.connect(g); g.connect(ac.destination);
|
||||
o.frequency.setValueAtTime(freq, ac.currentTime);
|
||||
if (freq2 && freq2 !== freq) o.frequency.exponentialRampToValueAtTime(freq2, ac.currentTime + dur);
|
||||
g.gain.setValueAtTime(vol, ac.currentTime);
|
||||
g.gain.exponentialRampToValueAtTime(0.001, ac.currentTime + dur);
|
||||
o.start(ac.currentTime);
|
||||
o.stop(ac.currentTime + dur + 0.01);
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
const SFX = {
|
||||
jump: () => beep(280, 560, 0.18, 'sine', 0.25),
|
||||
attack: () => beep(140, 70, 0.12, 'sawtooth', 0.30),
|
||||
stomp: () => { beep(200, 80, 0.1, 'square', 0.35); beep(400, 400, 0.08, 'sine', 0.2); },
|
||||
hurt: () => beep(180, 90, 0.28, 'square', 0.40),
|
||||
die: () => beep(380, 50, 0.80, 'square', 0.40),
|
||||
collect: () => beep(550, 880, 0.10, 'sine', 0.20),
|
||||
heart: () => { beep(660, 660, 0.06, 'sine', 0.2); setTimeout(() => beep(880, 880, 0.12, 'sine', 0.2), 70); },
|
||||
killEnemy: () => beep(260, 100, 0.25, 'sawtooth', 0.28),
|
||||
combo: (n) => beep(440 + n * 40, 550 + n * 40, 0.08, 'sine', 0.18),
|
||||
levelUp: () => {
|
||||
[523, 659, 784, 1047].forEach((f, i) =>
|
||||
setTimeout(() => beep(f, f, i === 3 ? 0.25 : 0.08, 'sine', 0.28), i * 100)
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
// ─── Background Music ─────────────────────────────────────────────────────────
|
||||
let _musicTimer = null;
|
||||
let _musicStep = 0;
|
||||
|
||||
const MUSIC = {
|
||||
menu: { bpm: 112, notes: [392,0,523,0,659,523,392,330, 392,0,523,659,784,659,523,0] },
|
||||
grass: { bpm: 132, notes: [523,0,659,0,784,659,523,0, 440,0,523,0,659,523,440,0] },
|
||||
cave: { bpm: 96, notes: [294,0,330,0,262,0,294,0, 220,0,247,0,262,0,220,0] },
|
||||
ice: { bpm: 108, notes: [440,0,494,523,587,0,523,494, 440,0,392,0,440,494,523,0] },
|
||||
};
|
||||
|
||||
function startMusic(theme) {
|
||||
stopMusic();
|
||||
try { getAudio(); } catch(e) { return; }
|
||||
const pat = MUSIC[theme] || MUSIC.menu;
|
||||
const beatMs = (60000 / pat.bpm) / 2; // eighth-note duration
|
||||
_musicStep = 0;
|
||||
|
||||
const tick = () => {
|
||||
const freq = pat.notes[_musicStep % pat.notes.length];
|
||||
if (freq > 0) {
|
||||
beep(freq / 2, freq / 2, beatMs / 1000 * 0.75, 'square', 0.04);
|
||||
if (_musicStep % 2 === 0) beep(freq, freq, beatMs / 1000 * 0.55, 'triangle', 0.05);
|
||||
}
|
||||
_musicStep++;
|
||||
_musicTimer = setTimeout(tick, beatMs);
|
||||
};
|
||||
_musicTimer = setTimeout(tick, 0);
|
||||
}
|
||||
|
||||
function stopMusic() {
|
||||
if (_musicTimer) { clearTimeout(_musicTimer); _musicTimer = null; }
|
||||
_musicStep = 0;
|
||||
}
|
||||
Reference in New Issue
Block a user