submodes for normal mode

This commit is contained in:
2026-08-02 20:15:55 -05:00
parent 61a98ca89d
commit 88c8dca057
+180 -156
View File
@@ -112,9 +112,10 @@
margin-top: 2rem; margin-top: 2rem;
} }
#game-modes { .button-container {
display: flex; /** display: flex; */
align-content: center; align-content: center;
align-items: center;
justify-content: center; justify-content: center;
width: 100%; width: 100%;
gap: 1rem; gap: 1rem;
@@ -122,8 +123,6 @@
#game-over-buttons { #game-over-buttons {
gap: 2rem; gap: 2rem;
align-items: center;
justify-content: center;
} }
button { button {
@@ -182,17 +181,23 @@
</div> </div>
<!-- gamemode menu buttons--> <!-- gamemode menu buttons-->
<div id="game-modes" class="hidden fade"> <div id="game-modes" class="button-container hidden fade">
<button id="normal" onclick="handleNormalMode()">normal</button> <button id="normal" onclick="handleNormalMode()">normal</button>
<button id="countdown" onclick="handleCountdownMode()">countdown</button> <button id="countdown" onclick="handleCountdownMode()">countdown</button>
<!-- <button id="infinite">infinite</button> --> <!-- <button id="infinite">infinite</button> -->
</div> </div>
<div id="normal-sub-modes" class="button-container hidden fade">
<button id="normal-3-rounds" onclick="setNormalRounds(3)">3 rounds</button>
<button id="normal-6-rounds" onclick="setNormalRounds(6)">6 rounds</button>
<button id="normal-10-rounds" onclick="setNormalRounds(10)">10 rounds</button>
</div>
<!-- pre-round text --> <!-- pre-round text -->
<span id="game-text" class="hidden fade"></span> <span id="game-text" class="hidden fade"></span>
<!-- post game buttons --> <!-- post game buttons -->
<div id="game-over-buttons" class="hidden fade"> <div id="game-over-buttons" class="button-container hidden fade">
<button id="play-again" onclick="handlePlayAgain()">play again</button> <button id="play-again" onclick="handlePlayAgain()">play again</button>
<button id="reset-game" onclick="handleReset()">back to main menu</button> <button id="reset-game" onclick="handleReset()">back to main menu</button>
</div> </div>
@@ -260,6 +265,10 @@
let title2 = document.getElementById("title2"); let title2 = document.getElementById("title2");
let gameModes = document.getElementById("game-modes"); let gameModes = document.getElementById("game-modes");
let normalSubModes = document.getElementById("normal-sub-modes");
let countdownSubModes = document.getElementById("countdown-sub-modes");
let gameText = document.getElementById("game-text"); let gameText = document.getElementById("game-text");
let gameOverButtons = document.getElementById("game-over-buttons"); let gameOverButtons = document.getElementById("game-over-buttons");
@@ -318,40 +327,30 @@
console.log('frame: ' + frameWidth + ' x ' + frameHeight); console.log('frame: ' + frameWidth + ' x ' + frameHeight);
} }
async function handlePlayAgain(e) {
// hide game over buttons
gameOverButtons.style.display = "none";
gameOverButtons.style.opacity = "0";
// remove game text from DOM flow
gameText.style.display = "none";
gameText.style.opacity = "0";
setParameters();
center = generateTarget(xFrameAdjustment, yFrameAdjustment);
center.id = "center";
document.body.insertAdjacentElement("afterbegin", center);
if (gamemode == "normal") {
handleNormalMode(e);
}
else if (gamemode == "countdown") {
handleCountdownMode(e);
}
else {
alert("cannot play again, gamemode does not exit?");
}
}
async function handleNormalMode(e) { async function handleNormalMode(e) {
gamemode = "normal"; gamemode = "normal";
// setup mode parameters // ensure mode parameters are reset
currentRound = 1; currentRound = 1;
totalTime = 0; totalTime = 0;
await fadeMainMenuOut(); await fadeMainMenuOut();
normalSubModes.style.display = "flex";
normalSubModes.style.opacity = "100";
}
function setNormalRounds(numRounds) {
// fade buttons out
normalSubModes.style.opacity = "0";
sleep(500);
normalSubModes.style.display = "none";
maxNormalRounds = numRounds;
beginNormalMode();
}
async function beginNormalMode() {
// set game instruction text + fade it in // set game instruction text + fade it in
gameText.innerText = "hover on middle circle to start the countdown,\nthen click the targets as fast as possible!"; gameText.innerText = "hover on middle circle to start the countdown,\nthen click the targets as fast as possible!";
gameText.style.opacity = "0"; gameText.style.opacity = "0";
@@ -365,6 +364,96 @@
center.addEventListener("touchend", handleHoverEnd); center.addEventListener("touchend", handleHoverEnd);
} }
async function startNormalRound(roundNumber) {
if (roundNumber > maxNormalRounds) {
handleReset({});
return;
}
// if user cancels hover countdown, don't start round
if (!await drawCountdown(hoverCount)) {
console.log("player canceled coundown");
return;
}
if (roundNumber == maxNormalRounds) {
numTargets = roundNumber * 2;
}
else {
numTargets = roundNumber;
}
// effectively begin the round
console.log("starting round " + roundNumber);
center.remove();
targetsClicked = 0;
roundTimeStart = Date.now();
randomTargetGenerator(numTargets);
while (targetsClicked < numTargets) {
await sleep(10);
if (targetsClicked == numTargets) break;
}
roundTimeEnd = Date.now();
roundSeconds = (roundTimeEnd - roundTimeStart) / 1000;
totalTime += roundSeconds;
currentRound++;
// auto-reset bullseye if page gets resized at all
if (needsResizeAdjustment) {
handlePageResize();
}
// ensure "DRAW" isn't still lingering on screen after round
draw.style.display = "none";
draw.style.opacity = "0";
// GAME OVER STUFF
if (roundNumber == maxNormalRounds) {
if (totalTime < bestNormalTime || bestNormalTime == 0) {
if (bestNormalTime == 0) {
alert("NEW FASTEST TIME!!! congratulations cowboy.");
}
else {
alert("NEW FASTEST TIME!!! previous best: " + bestNormalTime.toFixed(3) + "s. congratulations cowboy.");
}
bestNormalTime = totalTime;
localStorage.setItem("bestNormalTime", bestNormalTime);
}
gameText.innerText = "ROUND: " + roundSeconds.toFixed(3) +
"s\nTOTAL: " + totalTime.toFixed(3) +
"s\nBEST SCORE: " + bestNormalTime.toFixed(3);
numTargets = 0;
targetsClicked =0;
gameOverButtons.style.display = "flex";
gameOverButtons.style.opacity = "100";
}
// NORMAL END OF ROUND STUFF
else {
center = generateTarget(xFrameAdjustment, yFrameAdjustment);
center.id = "center";
document.body.insertAdjacentElement("afterbegin", center);
console.log("ROUND: " + roundSeconds.toFixed(3) + "s\nTOTAL: " + totalTime.toFixed(3) + "\nhover on circle to start round " + currentRound);
gameText.innerText = "ROUND: " + roundSeconds.toFixed(3) + "s\nTOTAL: " + totalTime.toFixed(3) + "s\nhover on circle to start round " + currentRound;
center.addEventListener("mouseover", handleHoverStart);
center.addEventListener("mouseleave", handleHoverEnd);
center.addEventListener("touchend", handleHoverEnd);
}
gameText.style.display = "inline";
gameText.style.opacity = "100";
return;
}
async function handleCountdownMode(e) { async function handleCountdownMode(e) {
gamemode = "countdown"; gamemode = "countdown";
countdownBullseyeNeeded = true; countdownBullseyeNeeded = true;
@@ -383,36 +472,6 @@
center.addEventListener("touchend", handleHoverEnd); center.addEventListener("touchend", handleHoverEnd);
} }
async function handleReset(e) {
// bullseye won't be on screen after a game
setParameters();
center = generateTarget(xFrameAdjustment, yFrameAdjustment);
center.id = "center";
document.body.insertAdjacentElement("afterbegin", center);
// refresh game state variables
gamemode = "";
currentRound = 0;
// hide buttons
gameOverButtons.style.display = "none";
gameOverButtons.style.opacity = "0";
// remove game text from DOM flow
gameText.style.display = "none";
gameText.style.opacity = "0";
// reintroduce main menu elements into DOM flow
await sleep(800);
await drawCircle(2);
await fadeMainMenuIn();
// auto-reset bullseye if page was resized during animation
if (needsResizeAdjustment) {
handlePageResize();
}
}
async function handleHoverStart(e) { async function handleHoverStart(e) {
hovering = true; hovering = true;
hoverCount++; hoverCount++;
@@ -436,7 +495,7 @@
async function startCountdownMode() { async function startCountdownMode() {
// if user cancels hover countdown, don't start round // if user cancels hover countdown, don't start round
if (!await normalModeRoundCountdown(hoverCount)) { if (!await drawCountdown(hoverCount)) {
console.log("player canceled coundown"); console.log("player canceled coundown");
return; return;
} }
@@ -498,101 +557,10 @@
gameOverButtons.style.opacity = "100"; gameOverButtons.style.opacity = "100";
} }
async function startNormalRound(roundNumber) {
if (roundNumber > 3) {
handleReset({});
return;
}
// if user cancels hover countdown, don't start round
if (!await normalModeRoundCountdown(hoverCount)) {
console.log("player canceled coundown");
return;
}
if (roundNumber == 1) { /** HELPER TO KICK-OFF COUNTDOWNS FROM HOVER */
numTargets = 1; async function drawCountdown(hoverNumber) {
}
else if (roundNumber == 2) {
numTargets = 3;
}
else if (roundNumber == 3) {
numTargets = 5;
}
// effectively begin the round
console.log("starting round " + roundNumber);
center.remove();
targetsClicked = 0;
roundTimeStart = Date.now();
randomTargetGenerator(numTargets);
while (targetsClicked < numTargets) {
await sleep(10);
if (targetsClicked == numTargets) break;
}
roundTimeEnd = Date.now();
roundSeconds = (roundTimeEnd - roundTimeStart) / 1000;
totalTime += roundSeconds;
currentRound++;
// auto-reset bullseye if page gets resized at all
if (needsResizeAdjustment) {
handlePageResize();
}
// even if no resize, bring bullseye back to screen
// ensure "DRAW" isn't still lingering on screen after round
draw.style.display = "none";
draw.style.opacity = "0";
// GAME OVER STUFF
if (roundNumber == 3) {
if (totalTime < bestNormalTime || bestNormalTime == 0) {
if (bestNormalTime == 0) {
alert("NEW FASTEST TIME!!! congratulations cowboy.");
}
else {
alert("NEW FASTEST TIME!!! previous best: " + bestNormalTime.toFixed(3) + "s. congratulations cowboy.");
}
bestNormalTime = totalTime;
localStorage.setItem("bestNormalTime", bestNormalTime);
}
gameText.innerText = "ROUND: " + roundSeconds.toFixed(3) +
"s\nTOTAL: " + totalTime.toFixed(3) +
"s\nBEST SCORE: " + bestNormalTime.toFixed(3);
numTargets = 0;
targetsClicked =0;
gameOverButtons.style.display = "flex";
gameOverButtons.style.opacity = "100";
}
// NORMAL END OF ROUND STUFF
else {
center = generateTarget(xFrameAdjustment, yFrameAdjustment);
center.id = "center";
document.body.insertAdjacentElement("afterbegin", center);
console.log("ROUND: " + roundSeconds.toFixed(3) + "s\nTOTAL: " + totalTime.toFixed(3) + "\nhover on circle to start round " + currentRound);
gameText.innerText = "ROUND: " + roundSeconds.toFixed(3) + "s\nTOTAL: " + totalTime.toFixed(3) + "s\nhover on circle to start round " + currentRound;
center.addEventListener("mouseover", handleHoverStart);
center.addEventListener("mouseleave", handleHoverEnd);
center.addEventListener("touchend", handleHoverEnd);
}
gameText.style.display = "inline";
gameText.style.opacity = "100";
return;
}
/**
* HELPER TO KICK-OFF COUNTDOWNS FROM HOVER
*/
async function normalModeRoundCountdown(hoverNumber) {
gameText.style.display = "none"; gameText.style.display = "none";
countingDown = true; countingDown = true;
@@ -682,6 +650,62 @@
} }
} }
async function handlePlayAgain(e) {
// hide game over buttons
gameOverButtons.style.display = "none";
gameOverButtons.style.opacity = "0";
// remove game text from DOM flow
gameText.style.display = "none";
gameText.style.opacity = "0";
setParameters();
center = generateTarget(xFrameAdjustment, yFrameAdjustment);
center.id = "center";
document.body.insertAdjacentElement("afterbegin", center);
if (gamemode == "normal") {
handleNormalMode(e);
}
else if (gamemode == "countdown") {
handleCountdownMode(e);
}
else {
alert("cannot play again, gamemode does not exit?");
}
}
async function handleReset(e) {
// bullseye won't be on screen after a game
setParameters();
center = generateTarget(xFrameAdjustment, yFrameAdjustment);
center.id = "center";
document.body.insertAdjacentElement("afterbegin", center);
// refresh game state variables
gamemode = "";
currentRound = 0;
// hide buttons
gameOverButtons.style.display = "none";
gameOverButtons.style.opacity = "0";
// remove game text from DOM flow
gameText.style.display = "none";
gameText.style.opacity = "0";
// reintroduce main menu elements into DOM flow
await sleep(800);
await drawCircle(2);
await fadeMainMenuIn();
// auto-reset bullseye if page was resized during animation
if (needsResizeAdjustment) {
handlePageResize();
}
}
function handleTargetClick(e) { function handleTargetClick(e) {
targetsClicked++; targetsClicked++;
e.target.remove(); e.target.remove();