Fix pterodactyl duck hitbox and prevent duplicate leaderboard submits

This commit is contained in:
OpenClaw Engineer 2026-03-03 22:23:41 -06:00
parent 4470266234
commit d433141ccb

View File

@ -63,6 +63,15 @@ function createInitialState() {
let state = createInitialState(); let state = createInitialState();
let saveEligible = false; let saveEligible = false;
let scoreSavedThisRun = false; let scoreSavedThisRun = false;
let saveInFlight = false;
const saveScoreBtnEl = saveScoreFormEl.querySelector('button[type="submit"]');
function setSaveFormBusy(isBusy) {
saveInFlight = isBusy;
playerNameEl.disabled = isBusy;
if (saveScoreBtnEl) saveScoreBtnEl.disabled = isBusy;
}
window.addEventListener('keydown', (e) => { window.addEventListener('keydown', (e) => {
if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.key)) e.preventDefault(); if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.key)) e.preventDefault();
@ -81,23 +90,33 @@ restartBtnEl.addEventListener('click', () => {
saveScoreFormEl.classList.add('hidden'); saveScoreFormEl.classList.add('hidden');
saveEligible = false; saveEligible = false;
scoreSavedThisRun = false; scoreSavedThisRun = false;
setSaveFormBusy(false);
}); });
saveScoreFormEl.addEventListener('submit', async (e) => { saveScoreFormEl.addEventListener('submit', async (e) => {
e.preventDefault(); e.preventDefault();
if (!saveEligible) return; if (!saveEligible || saveInFlight || scoreSavedThisRun) return;
const name = playerNameEl.value.trim() || 'Anonymous'; const name = playerNameEl.value.trim() || 'Anonymous';
await fetch('api/scores.php', { setSaveFormBusy(true);
method: 'POST', try {
headers: { 'Content-Type': 'application/json' }, const res = await fetch('api/scores.php', {
body: JSON.stringify({ name, score: state.score }) method: 'POST',
}); headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name, score: state.score })
});
saveEligible = false; if (!res.ok) throw new Error('Score save failed');
scoreSavedThisRun = true;
saveScoreFormEl.classList.add('hidden'); saveEligible = false;
await populateLeaderboard(); scoreSavedThisRun = true;
saveScoreFormEl.classList.add('hidden');
await populateLeaderboard();
} catch (err) {
console.error(err);
} finally {
setSaveFormBusy(false);
}
}); });
function drawBackground() { function drawBackground() {
@ -177,7 +196,7 @@ async function populateLeaderboard() {
}); });
const qualifies = scores.length < 10 || state.score > (scores[scores.length - 1]?.score ?? -1); const qualifies = scores.length < 10 || state.score > (scores[scores.length - 1]?.score ?? -1);
saveEligible = qualifies && !scoreSavedThisRun; saveEligible = qualifies && !scoreSavedThisRun && !saveInFlight;
saveScoreFormEl.classList.toggle('hidden', !saveEligible); saveScoreFormEl.classList.toggle('hidden', !saveEligible);
} }
@ -234,10 +253,23 @@ const PTERODACTYL_LANES = [
function getPterodactylHitbox(flyer) { function getPterodactylHitbox(flyer) {
return { return {
x: flyer.x + 6, x: flyer.x + 8,
y: flyer.y + 5, y: flyer.y + 6,
width: flyer.width - 12, width: flyer.width - 16,
height: flyer.height - 10 height: flyer.height - 12
};
}
function getPlayerHitboxForAirHazards(player) {
const widthInset = player.ducking ? 8 : 6;
const topInset = player.ducking ? 8 : 4;
const bottomInset = 2;
return {
x: player.x + widthInset,
y: player.y + topInset,
width: player.width - widthInset * 2,
height: player.height - topInset - bottomInset
}; };
} }
@ -258,9 +290,10 @@ function updatePterodactyls(dt) {
} }
const p = state.player; const p = state.player;
const playerHitbox = getPlayerHitboxForAirHazards(p);
for (const flyer of state.pterodactyls) { for (const flyer of state.pterodactyls) {
flyer.x += flyer.vx * dt; flyer.x += flyer.vx * dt;
if (intersects(p, getPterodactylHitbox(flyer))) applyHit('Pterodactyl collision. Duck next time!'); if (intersects(playerHitbox, getPterodactylHitbox(flyer))) applyHit('Pterodactyl collision. Duck next time!');
} }
state.pterodactyls = state.pterodactyls.filter((f) => f.x + f.width > state.cameraX - 150); state.pterodactyls = state.pterodactyls.filter((f) => f.x + f.width > state.cameraX - 150);
} }