improvfmeents
This commit is contained in:
@@ -39,6 +39,17 @@ window.FaraonFx = (function () {
|
||||
return audioCtx;
|
||||
}
|
||||
|
||||
// Automatické prebudenie AudioContextu pri prvom kliknutí používateľa kdekoľvek
|
||||
if (typeof window !== 'undefined') {
|
||||
const unlockAudio = () => {
|
||||
getAudioContext();
|
||||
window.removeEventListener('pointerdown', unlockAudio);
|
||||
window.removeEventListener('keydown', unlockAudio);
|
||||
};
|
||||
window.addEventListener('pointerdown', unlockAudio, { passive: true });
|
||||
window.addEventListener('keydown', unlockAudio, { passive: true });
|
||||
}
|
||||
|
||||
// --- PROCEDURAL SOUND GENERATORS ---
|
||||
function playCardSnap() {
|
||||
if (isMuted) return;
|
||||
@@ -386,6 +397,182 @@ window.FaraonFx = (function () {
|
||||
});
|
||||
}
|
||||
|
||||
function playCardWhoosh() {
|
||||
if (isMuted) return;
|
||||
const ctx = getAudioContext();
|
||||
if (!ctx) return;
|
||||
const now = ctx.currentTime;
|
||||
const bufferSize = Math.floor(ctx.sampleRate * 0.22);
|
||||
const buffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate);
|
||||
const data = buffer.getChannelData(0);
|
||||
for (let i = 0; i < bufferSize; i++) {
|
||||
data[i] = (Math.random() * 2 - 1) * Math.sin((i / bufferSize) * Math.PI);
|
||||
}
|
||||
const noise = ctx.createBufferSource();
|
||||
noise.buffer = buffer;
|
||||
const filter = ctx.createBiquadFilter();
|
||||
filter.type = 'bandpass';
|
||||
filter.frequency.setValueAtTime(450, now);
|
||||
filter.frequency.exponentialRampToValueAtTime(1200, now + 0.1);
|
||||
filter.frequency.exponentialRampToValueAtTime(350, now + 0.22);
|
||||
filter.Q.value = 2.5;
|
||||
|
||||
const gain = ctx.createGain();
|
||||
gain.gain.setValueAtTime(0.3, now);
|
||||
gain.gain.exponentialRampToValueAtTime(0.001, now + 0.22);
|
||||
|
||||
noise.connect(filter);
|
||||
filter.connect(gain);
|
||||
gain.connect(ctx.destination);
|
||||
noise.start(now);
|
||||
}
|
||||
|
||||
function playBotPersonalitySfx(personalityId, emotion) {
|
||||
if (isMuted) return;
|
||||
const ctx = getAudioContext();
|
||||
if (!ctx) return;
|
||||
const now = ctx.currentTime;
|
||||
const pId = (personalityId || 'fox').toLowerCase();
|
||||
const emo = (emotion || 'thinking').toLowerCase();
|
||||
|
||||
// Mierny posun tóniny podľa emócie
|
||||
let pitchMul = 1.0;
|
||||
if (emo === 'shocked' || emo === 'desperate') pitchMul = 0.82;
|
||||
else if (emo === 'confident' || emo === 'celebrating') pitchMul = 1.22;
|
||||
else if (emo === 'freezing') pitchMul = 1.45;
|
||||
else if (emo === 'angry') pitchMul = 0.92;
|
||||
|
||||
switch (pId) {
|
||||
case 'fox': { // Lišiak Filip - sly playful rising arpeggio
|
||||
const baseFreqs = [440, 554.37, 659.25, 880];
|
||||
baseFreqs.forEach((freq, i) => {
|
||||
const osc = ctx.createOscillator();
|
||||
const gain = ctx.createGain();
|
||||
const t = now + i * 0.045;
|
||||
osc.type = 'triangle';
|
||||
osc.frequency.setValueAtTime(freq * pitchMul, t);
|
||||
gain.gain.setValueAtTime(0.28, t);
|
||||
gain.gain.exponentialRampToValueAtTime(0.001, t + 0.18);
|
||||
osc.connect(gain);
|
||||
gain.connect(ctx.destination);
|
||||
osc.start(t);
|
||||
osc.stop(t + 0.19);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'queen': { // Kráľovná Alžbeta - regal royal chime / bell chords
|
||||
const baseFreqs = [523.25, 659.25, 783.99, 1046.50];
|
||||
baseFreqs.forEach((freq, i) => {
|
||||
const osc = ctx.createOscillator();
|
||||
const gain = ctx.createGain();
|
||||
const t = now + i * 0.055;
|
||||
osc.type = 'sine';
|
||||
osc.frequency.setValueAtTime(freq * pitchMul, t);
|
||||
gain.gain.setValueAtTime(0.32, t);
|
||||
gain.gain.exponentialRampToValueAtTime(0.001, t + 0.42);
|
||||
osc.connect(gain);
|
||||
gain.connect(ctx.destination);
|
||||
osc.start(t);
|
||||
osc.stop(t + 0.43);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'robot': { // Kyber-Robo - 8-bit digital synth crunch
|
||||
const tones = [880, 1320, 660, 1760];
|
||||
tones.forEach((freq, i) => {
|
||||
const osc = ctx.createOscillator();
|
||||
const gain = ctx.createGain();
|
||||
const t = now + i * 0.04;
|
||||
osc.type = 'square';
|
||||
osc.frequency.setValueAtTime(freq * pitchMul, t);
|
||||
gain.gain.setValueAtTime(0.22, t);
|
||||
gain.gain.exponentialRampToValueAtTime(0.001, t + 0.06);
|
||||
osc.connect(gain);
|
||||
gain.connect(ctx.destination);
|
||||
osc.start(t);
|
||||
osc.stop(t + 0.065);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'grandpa': { // Dedo Jozef - warm vintage harmonic bell
|
||||
const osc = ctx.createOscillator();
|
||||
const gain = ctx.createGain();
|
||||
osc.type = 'sine';
|
||||
osc.frequency.setValueAtTime(987.77 * pitchMul, now);
|
||||
gain.gain.setValueAtTime(0.35, now);
|
||||
gain.gain.exponentialRampToValueAtTime(0.001, now + 0.55);
|
||||
osc.connect(gain);
|
||||
gain.connect(ctx.destination);
|
||||
osc.start(now);
|
||||
osc.stop(now + 0.56);
|
||||
break;
|
||||
}
|
||||
case 'cyberkid': { // Hacker Miško - futuristic laser zap
|
||||
const osc = ctx.createOscillator();
|
||||
const gain = ctx.createGain();
|
||||
osc.type = 'sawtooth';
|
||||
osc.frequency.setValueAtTime(1500 * pitchMul, now);
|
||||
osc.frequency.exponentialRampToValueAtTime(180 * pitchMul, now + 0.18);
|
||||
gain.gain.setValueAtTime(0.3, now);
|
||||
gain.gain.exponentialRampToValueAtTime(0.001, now + 0.18);
|
||||
osc.connect(gain);
|
||||
gain.connect(ctx.destination);
|
||||
osc.start(now);
|
||||
osc.stop(now + 0.19);
|
||||
break;
|
||||
}
|
||||
case 'cat': { // Mačka Minda - playful synth meow
|
||||
const osc = ctx.createOscillator();
|
||||
const gain = ctx.createGain();
|
||||
osc.type = 'sine';
|
||||
osc.frequency.setValueAtTime(580 * pitchMul, now);
|
||||
osc.frequency.exponentialRampToValueAtTime(980 * pitchMul, now + 0.11);
|
||||
osc.frequency.exponentialRampToValueAtTime(680 * pitchMul, now + 0.28);
|
||||
gain.gain.setValueAtTime(0.32, now);
|
||||
gain.gain.exponentialRampToValueAtTime(0.001, now + 0.30);
|
||||
osc.connect(gain);
|
||||
gain.connect(ctx.destination);
|
||||
osc.start(now);
|
||||
osc.stop(now + 0.31);
|
||||
break;
|
||||
}
|
||||
case 'wizard': { // Čarodejník Baltazár - mystical shimmering chord
|
||||
[392.00, 587.33, 880.00, 1174.66].forEach((freq, i) => {
|
||||
const osc = ctx.createOscillator();
|
||||
const gain = ctx.createGain();
|
||||
const t = now + i * 0.035;
|
||||
osc.type = 'sine';
|
||||
osc.frequency.setValueAtTime(freq * pitchMul, t);
|
||||
gain.gain.setValueAtTime(0.24, t);
|
||||
gain.gain.exponentialRampToValueAtTime(0.001, t + 0.45);
|
||||
osc.connect(gain);
|
||||
gain.connect(ctx.destination);
|
||||
osc.start(t);
|
||||
osc.stop(t + 0.46);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'bear': { // Medveď Mišo - deep bass growl thud
|
||||
const osc = ctx.createOscillator();
|
||||
const gain = ctx.createGain();
|
||||
osc.type = 'sawtooth';
|
||||
osc.frequency.setValueAtTime(95 * pitchMul, now);
|
||||
osc.frequency.exponentialRampToValueAtTime(38 * pitchMul, now + 0.35);
|
||||
gain.gain.setValueAtTime(0.42, now);
|
||||
gain.gain.exponentialRampToValueAtTime(0.001, now + 0.35);
|
||||
osc.connect(gain);
|
||||
gain.connect(ctx.destination);
|
||||
osc.start(now);
|
||||
osc.stop(now + 0.36);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
playCardSnap();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- SCREEN SHAKE ---
|
||||
function triggerScreenShake(intensity = 5) {
|
||||
const board = document.getElementById('game-table-container');
|
||||
@@ -1197,6 +1384,8 @@ window.FaraonFx = (function () {
|
||||
animateCardPlay,
|
||||
animateCardDraw,
|
||||
animateTurnTransition,
|
||||
playCardWhoosh,
|
||||
playBotPersonalitySfx,
|
||||
setSpeedLevel,
|
||||
toggleMute
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user