168 lines
5.6 KiB
JavaScript
168 lines
5.6 KiB
JavaScript
document.addEventListener('DOMContentLoaded', () => {
|
|
const slapImage = document.getElementById('slap-image');
|
|
const hand = document.getElementById('hand');
|
|
const fist = document.getElementById('fist');
|
|
const slapSound = document.getElementById('slap-sound');
|
|
const punchSound = document.getElementById('punch-sound');
|
|
const scoreDisplay = document.getElementById('score');
|
|
const saveScoreBtn = document.getElementById('save-score');
|
|
const leaderboard = document.getElementById('leaderboard');
|
|
const modalOverlay = document.getElementById('modal-overlay');
|
|
const modal = document.getElementById('modal');
|
|
const nameInput = document.getElementById('name-input');
|
|
const submitScoreBtn = document.getElementById('submit-score');
|
|
const cancelScoreBtn = document.getElementById('cancel-score');
|
|
|
|
let score = 0;
|
|
let pressTimer = null;
|
|
|
|
const initialHandRight = 20;
|
|
const initialFistRight = 20;
|
|
|
|
hand.style.right = `${initialHandRight}px`;
|
|
fist.style.right = `${initialFistRight}px`;
|
|
|
|
|
|
/*
|
|
* Slap Ryan with the hand or fist.
|
|
*/
|
|
function doAction(emoji, x, y) {
|
|
console.log('doAction called');
|
|
emoji.style.right = 'auto'; /* Unset right property. */
|
|
emoji.style.left = `${x - emoji.offsetWidth / 2}px`;
|
|
emoji.style.top = `${y - emoji.offsetHeight / 2}px`;
|
|
|
|
if (emoji === hand) {
|
|
slapSound.currentTime = 0;
|
|
slapSound.play();
|
|
} else {
|
|
punchSound.currentTime = 0;
|
|
punchSound.play();
|
|
}
|
|
|
|
score++;
|
|
scoreDisplay.textContent = score;
|
|
console.log('Score:', score);
|
|
|
|
/* Move the emoji back to a ready position. */
|
|
setTimeout(() => {
|
|
console.log('Moving emoji back');
|
|
emoji.style.left = 'auto'; /* Unset left property. */
|
|
if (emoji === hand) {
|
|
emoji.style.right = `${initialHandRight}px`;
|
|
emoji.style.top = '50%';
|
|
} else {
|
|
emoji.style.right = `${initialFistRight}px`;
|
|
emoji.style.top = 'calc(50% + 150px)';
|
|
}
|
|
}, 500);
|
|
}
|
|
|
|
/*
|
|
* Handle mouse events.
|
|
*/
|
|
slapImage.addEventListener('mousedown', (event) => {
|
|
if (event.button === 0) { // Left mouse button
|
|
/* Start a timer to detect a long press. */
|
|
pressTimer = setTimeout(() => {
|
|
doAction(fist, event.clientX, event.clientY);
|
|
pressTimer = null;
|
|
}, 500);
|
|
} else if (event.button === 2) { // Right mouse button
|
|
doAction(fist, event.clientX, event.clientY);
|
|
}
|
|
});
|
|
|
|
slapImage.addEventListener('mouseup', (event) => {
|
|
if (pressTimer && event.button === 0) {
|
|
/* If the timer is still running, it was a short press. */
|
|
clearTimeout(pressTimer);
|
|
doAction(hand, event.clientX, event.clientY);
|
|
}
|
|
});
|
|
|
|
/* Prevent the context menu on right-click. */
|
|
slapImage.addEventListener('contextmenu', (event) => {
|
|
event.preventDefault();
|
|
});
|
|
|
|
/*
|
|
* Handle touch events.
|
|
*/
|
|
slapImage.addEventListener('touchstart', (event) => {
|
|
/* Start a timer to detect a long press. */
|
|
pressTimer = setTimeout(() => {
|
|
doAction(fist, event.touches[0].clientX, event.touches[0].clientY);
|
|
pressTimer = null;
|
|
}, 500);
|
|
});
|
|
|
|
slapImage.addEventListener('touchend', (event) => {
|
|
if (pressTimer) {
|
|
/* If the timer is still running, it was a short press. */
|
|
clearTimeout(pressTimer);
|
|
doAction(hand, event.changedTouches[0].clientX, event.changedTouches[0].clientY);
|
|
}
|
|
});
|
|
|
|
slapImage.addEventListener('touchmove', (event) => {
|
|
/* Cancel the long press if the user moves their finger. */
|
|
clearTimeout(pressTimer);
|
|
});
|
|
|
|
const fetchScores = async () => {
|
|
try {
|
|
console.log('Fetching scores...');
|
|
const response = await fetch('/api/scores');
|
|
console.log('Scores response:', response);
|
|
const scores = await response.json();
|
|
console.log('Scores data:', scores);
|
|
leaderboard.innerHTML = '';
|
|
scores.forEach(score => {
|
|
const li = document.createElement('li');
|
|
li.textContent = `${score.name}: ${score.score}`;
|
|
leaderboard.appendChild(li);
|
|
});
|
|
} catch (error) {
|
|
console.error('Error fetching scores:', error);
|
|
}
|
|
};
|
|
|
|
saveScoreBtn.addEventListener('click', () => {
|
|
modalOverlay.style.display = 'flex';
|
|
});
|
|
|
|
submitScoreBtn.addEventListener('click', async () => {
|
|
const name = nameInput.value;
|
|
if (name) {
|
|
try {
|
|
const response = await fetch('/api/scores', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({ name, score })
|
|
});
|
|
|
|
if (response.ok) {
|
|
score = 0;
|
|
scoreDisplay.textContent = score;
|
|
fetchScores();
|
|
}
|
|
|
|
modalOverlay.style.display = 'none';
|
|
nameInput.value = '';
|
|
} catch (error) {
|
|
console.error('Error saving score:', error);
|
|
}
|
|
}
|
|
});
|
|
|
|
cancelScoreBtn.addEventListener('click', () => {
|
|
modalOverlay.style.display = 'none';
|
|
nameInput.value = '';
|
|
});
|
|
|
|
fetchScores();
|
|
});
|