/* ------------------------ 2. AUDIO MANAGER ------------------------ */ const audio = { bg: new Audio("Background_Music.mp3"), pop: new Audio("Pop.mp3"), merge: new Audio("Merge.mp3") }; audio.bg.loop = true; // Update audio volumes based on state & sliders function updateAudioVolumes() { audio.bg.volume = soundState.bg ? (volumeState.music / 100) : 0; audio.pop.volume = soundState.pop ? (volumeState.pop / 100) : 0; audio.merge.volume = soundState.merge ? (volumeState.merge / 100) : 0; } function tryPlayBg() { if (!soundState.bg || volumeState.music === 0) return; audio.bg.play().catch(() => { const unlock = () => { if (soundState.bg && volumeState.music > 0) audio.bg.play().catch(()=>{}); window.removeEventListener("keydown", unlock); window.removeEventListener("click", unlock); }; window.addEventListener("keydown", unlock, { once: true }); window.addEventListener("click", unlock, { once: true }); }); } /* Safe playSound with mute check */ function playSound(soundObj) { try { if (soundObj === audio.pop && (!soundState.pop || volumeState.pop === 0)) return; if (soundObj === audio.merge && (!soundState.merge || volumeState.merge === 0)) return; if (soundObj === audio.bg && (!soundState.bg || volumeState.music === 0)) return; soundObj.currentTime = 0; soundObj.play().catch(() => {}); } catch (e) {} } // Initialize Volume Sliders function initVolumeControl() { updateAudioVolumes(); const musicSlider = document.getElementById('vol-music'); const popSlider = document.getElementById('vol-pop'); const mergeSlider = document.getElementById('vol-merge'); if (musicSlider) { musicSlider.value = volumeState.music; updateSliderFill(musicSlider, volumeState.music); document.getElementById('vol-music-display').textContent = volumeState.music + '%'; musicSlider.addEventListener('input', (e) => { const val = parseInt(e.target.value); volumeState.music = val; audio.bg.volume = val / 100; // Direct update localStorage.setItem('vol_music', val); document.getElementById('vol-music-display').textContent = val + '%'; updateSliderFill(e.target, val); updateMainSoundIcon(); if (val > 0 && audio.bg.paused && soundState.bg) { tryPlayBg(); } else if (val === 0) { audio.bg.pause(); } }); } if (popSlider) { popSlider.value = volumeState.pop; updateSliderFill(popSlider, volumeState.pop); document.getElementById('vol-pop-display').textContent = volumeState.pop + '%'; popSlider.addEventListener('input', (e) => { const val = parseInt(e.target.value); volumeState.pop = val; audio.pop.volume = val / 100; localStorage.setItem('vol_pop', val); document.getElementById('vol-pop-display').textContent = val + '%'; updateSliderFill(e.target, val); updateMainSoundIcon(); }); } if (mergeSlider) { mergeSlider.value = volumeState.merge; updateSliderFill(mergeSlider, volumeState.merge); document.getElementById('vol-merge-display').textContent = volumeState.merge + '%'; mergeSlider.addEventListener('input', (e) => { const val = parseInt(e.target.value); volumeState.merge = val; audio.merge.volume = val / 100; localStorage.setItem('vol_merge', val); document.getElementById('vol-merge-display').textContent = val + '%'; updateSliderFill(e.target, val); updateMainSoundIcon(); }); } updateMainSoundIcon(); setupVolumePanelEvents(); } function setupVolumePanelEvents() { const btnSoundMain = document.getElementById('btn-sound-main'); const volumePanel = document.getElementById('volume-panel'); const volumeBackdrop = document.getElementById('volume-backdrop'); if (btnSoundMain && volumePanel) { btnSoundMain.addEventListener('click', (e) => { e.stopPropagation(); const isActive = volumePanel.classList.contains('active'); if (isActive) { volumePanel.classList.remove('active'); if (volumeBackdrop) volumeBackdrop.classList.remove('active'); inputLocked = false; // 🔓 buka panel -> input kembali } else { volumePanel.classList.add('active'); if (volumeBackdrop) volumeBackdrop.classList.add('active'); inputLocked = true; // 🔒 panel sound aktif -> swipe & keyboard mati } }); // Close when clicking backdrop volumeBackdrop.addEventListener('click', () => { volumePanel.classList.remove('active'); volumeBackdrop.classList.remove('active'); inputLocked = false; // 🔓 unlock }); // Close when clicking outside (desktop) document.addEventListener('click', (e) => { if (!volumePanel.contains(e.target) && !btnSoundMain.contains(e.target) && (!volumeBackdrop || !volumeBackdrop.contains(e.target))) { volumePanel.classList.remove('active'); if (volumeBackdrop) volumeBackdrop.classList.remove('active'); inputLocked = false; // 🔓 unlock input } }); volumePanel.addEventListener('click', (e) => { e.stopPropagation(); }); } } function updateSliderFill(slider, value) { slider.style.setProperty('--value', value + '%'); } function updateMainSoundIcon() { const btnMain = document.getElementById('btn-sound-main'); if (!btnMain) return; const iconFull = btnMain.querySelector('.sound-full'); const iconMedium = btnMain.querySelector('.sound-medium'); const iconLow = btnMain.querySelector('.sound-low'); const iconMuted = btnMain.querySelector('.sound-muted'); const totalVolume = volumeState.music + volumeState.pop + volumeState.merge; const avgVolume = totalVolume / 3; if (iconFull) iconFull.style.display = 'none'; if (iconMedium) iconMedium.style.display = 'none'; if (iconLow) iconLow.style.display = 'none'; if (iconMuted) iconMuted.style.display = 'none'; if (totalVolume === 0) { if (iconMuted) iconMuted.style.display = 'block'; btnMain.classList.add('all-muted'); } else { btnMain.classList.remove('all-muted'); if (avgVolume >= 60) { if (iconFull) iconFull.style.display = 'block'; } else if (avgVolume >= 30) { if (iconMedium) iconMedium.style.display = 'block'; } else { if (iconLow) iconLow.style.display = 'block'; } } }