kelompok06-2048/Audio_2048.js
Jevinca Marvella e4c4a3795f 2048
2025-12-02 20:19:55 +07:00

188 lines
6.2 KiB
JavaScript

/* ------------------------
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');
} else {
volumePanel.classList.add('active');
if (volumeBackdrop) volumeBackdrop.classList.add('active');
}
});
// Close when clicking backdrop
if (volumeBackdrop) {
volumeBackdrop.addEventListener('click', () => {
volumePanel.classList.remove('active');
volumeBackdrop.classList.remove('active');
});
}
// 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');
}
});
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';
}
}
}