normal mode lowk working

This commit is contained in:
simon-ec
2026-07-02 00:32:00 -04:00
parent e4d7bd675a
commit 8eec483788
+280 -179
View File
@@ -42,6 +42,10 @@
width: 20px; width: 20px;
background-color: red; background-color: red;
position: absolute; position: absolute;
border-radius: 25%;
}
.target:active {
background-color: orange;
} }
.hidden { .hidden {
@@ -62,10 +66,11 @@
flex-direction: row; flex-direction: row;
align-content: end; align-content: end;
justify-content: space-evenly; justify-content: space-evenly;
text-align: center;
color: red; color: red;
width: 100%; width: 100%;
min-height: 2rem; min-height: 2rem;
line-height: 2rem; line-height: 1rem;
margin-top: 2rem; margin-top: 2rem;
} }
@@ -85,243 +90,329 @@
</head> </head>
<body> <body>
<div id="frame"></div> <div id="frame">
<!-- where the targets + bullseye are drawn -->
</div>
<!-- where we place text + buttons -->
<div id="text-box"> <div id="text-box">
<!-- intro related -->
<span id="intro1" class="hidden title">QUICK</span> <span id="intro1" class="hidden title">QUICK</span>
<span id="intro2" class="hidden title">DRAW</span> <span id="intro2" class="hidden title">DRAW</span>
<span id="instructions" class="hidden fade">hover on bullseye to start</span> <!-- gamemode menu button-->
<div id="game-modes" class="hidden fade">
<button id="normal" onclick="handleNormalMode()">normal mode</button>
<button id="infinite">infinite mode</button>
<button id="countdown">countdown mode</button>
</div>
<!-- pre-round text -->
<span id="gameText" class="hidden fade"></span>
<!-- post round text -->
<span id="round-end" class="hidden fade"></span>
<!-- countdown text -->
<span id="countdown3" class="hidden title">3</span> <span id="countdown3" class="hidden title">3</span>
<span id="countdown2" class="hidden title">2</span> <span id="countdown2" class="hidden title">2</span>
<span id="countdown1" class="hidden title">1</span> <span id="countdown1" class="hidden title">1</span>
<div id="game-modes" class="hidden fade">
<button id="normal" onclick="handleNormalMode">normal mode</button>
<button id="normal">infinite mode</button>
<button id="normal">countdown mode</button>
</div>
<span id="draw" class="hidden title">DRAW!</span> <span id="draw" class="hidden title">DRAW!</span>
</div> </div>
<script> <script>
let gameBorderWidth = 1; let gameBorderWidth = 1;
let targetWidth = 20; let targetWidth = 20;
let targetHeight = 20; let targetHeight = 20;
let pageHeight; let pageHeight;
let pageWidth; let pageWidth;
let frameElement; let frameElement;
let frameRect; let frameRect;
let frameHeight; let frameHeight;
let frameWidth; let frameWidth;
let center; let center;
let ratio; let ratio;
let xFrameAdjustment; let xFrameAdjustment;
let yFrameAdjustment; let yFrameAdjustment;
let hovering = false; let hovering = false;
let hoverCount = 0; let hoverCount = 0; // number of times the cursor has hovered over bullseye. used to cleanly handle round starting / cancelling
let currentRound = 0; let targetsClickedThisRound = 0;
let countingDown = false; let gamemode = ""; // can be: "normal", "countdown", "infinite"
let roundmode = ""; // if gamemode is "countdown" or "infinite", can be: "rounds" or "frenzy"
// text elements let currentRound = 0;
let intro1 = document.getElementById("intro1"); let countingDown = false;
let intro2 = document.getElementById("intro2");
let instructions = document.getElementById("instructions");
let one = document.getElementById("countdown1"); let roundTimeStart = 0;
let two = document.getElementById("countdown2"); let roundTimeEnd = 0;
let three = document.getElementById("countdown3"); let roundSeconds = 0.0;
let draw = document.getElementById("draw"); // text elements
let intro1 = document.getElementById("intro1");
let intro2 = document.getElementById("intro2");
let gameText = document.getElementById("gameText");
window.addEventListener("load", initGame); let one = document.getElementById("countdown1");
let two = document.getElementById("countdown2");
let three = document.getElementById("countdown3");
function setParameters(event) { let draw = document.getElementById("draw");
pageHeight = window.innerHeight;
pageWidth = window.innerWidth;
frameElement = document.getElementById("frame"); window.addEventListener("load", initGame);
frameRect = frameElement.getBoundingClientRect();
frameHeight = frameElement.offsetHeight;
frameWidth = frameElement.offsetWidth;
// ratio = (frameHeight - (gameBorderWidth*2)) / (frameWidth - (gameBorderWidth*2)); function setParameters(event) {
ratio = frameHeight / frameWidth; pageHeight = window.innerHeight;
pageWidth = window.innerWidth;
// adjustments to find center of frame in absolute coords (for origin of target cirlce) frameElement = document.getElementById("frame");
xFrameAdjustment = ((frameWidth / 2) + frameRect.left) - (targetWidth / 2); frameRect = frameElement.getBoundingClientRect();
yFrameAdjustment = ((frameHeight / 2) + frameRect.top) - (targetWidth / 2); frameHeight = frameElement.offsetHeight;
frameWidth = frameElement.offsetWidth;
// init logs: // ratio = (frameHeight - (gameBorderWidth*2)) / (frameWidth - (gameBorderWidth*2));
console.log('page: ' + pageWidth + ' x ' + pageHeight); ratio = frameHeight / frameWidth;
console.log('frame: ' + frameWidth + ' x ' + frameHeight);
}
async function initGame() { // adjustments to find center of frame in absolute coords (for origin of target cirlce)
setParameters(); xFrameAdjustment = ((frameWidth / 2) + frameRect.left) - (targetWidth / 2);
yFrameAdjustment = ((frameHeight / 2) + frameRect.top) - (targetWidth / 2);
center = generateTarget(xFrameAdjustment, yFrameAdjustment); // init logs:
center.id = "center"; console.log('page: ' + pageWidth + ' x ' + pageHeight);
document.body.insertAdjacentElement("afterbegin", center); console.log('frame: ' + frameWidth + ' x ' + frameHeight);
}
await drawTargetsInCircle(true); async function initGame() {
setParameters();
// insert intro elements into document flow center = generateTarget(xFrameAdjustment, yFrameAdjustment);
intro1.style.display = "inline"; center.id = "center";
intro2.style.display = "inline"; document.body.insertAdjacentElement("afterbegin", center);
// reveal intro elements await drawTargetsInCircle(false);
intro1.style.opacity = "100";
await sleep(500);
intro2.style.opacity = "100";
await sleep(1500);
intro1.classList.add("fade"); // insert intro elements into document flow
intro2.classList.add("fade"); intro1.style.display = "inline";
intro2.style.display = "inline";
intro1.style.opacity = "0"; // reveal intro elements
intro2.style.opacity = "0"; intro1.style.opacity = "100";
await sleep(500);
intro2.style.opacity = "100";
await sleep(1500);
await sleep(1000); intro1.classList.add("fade");
intro2.classList.add("fade");
intro1.style.display = "none"; intro1.style.opacity = "0";
intro2.style.display = "none"; intro2.style.opacity = "0";
window.addEventListener("resize", handleResize); await sleep(1000);
document.getElementById("game-modes").style.display = "inline"; intro1.style.display = "none";
await sleep(500); intro2.style.display = "none";
document.getElementById("game-modes").style.opacity = "100";
}
function handleNormalMode(e) { window.addEventListener("resize", handlePageResize);
center.addEventListener("mouseover", handleHoverStart);
center.addEventListener("mouseleave", handleHoverEnd);
// instructions.style.display = "inline"; document.getElementById("game-modes").style.display = "inline";
// instructions.style.opacity = "100"; await sleep(500);
} document.getElementById("game-modes").style.opacity = "100";
}
function handleHoverStart(e) { function handleNormalMode(e) {
e.target.style.backgroundColor = "green"; gamemode = "normal";
if (currentRound == 0) return; console.log("game mode: " + gamemode);
hovering = true; currentRound = 1;
hoverCount++;
frameElement.replaceChildren(); center.addEventListener("mouseover", handleHoverStart);
center.addEventListener("mouseleave", handleHoverEnd);
intro1.style.display = "none"; document.getElementById("game-modes").style.display = "none";
intro2.style.display = "none";
instructions.style.display = "none";
// if (infinityMode) intro1.style.display = "none";
intro2.style.display = "none";
if (currentRound == 0) { startRoundOne(); } gameText.innerText = "click the targets as quickly as possible!\nhover on bullseye to start.";
} gameText.style.display = "inline";
gameText.style.opacity = "100";
async function startRoundOne() { }
if (!await startCountdown(hoverCount)) {
// if user canceled hover, don't continue round
return;
}
console.log('success');
}
async function startCountdown(hoverNumber) { async function handleHoverStart(e) {
instructions.style.display = "none"; e.target.style.backgroundColor = "green";
countingDown = true; hovering = true;
await sleep(1000); hoverCount++;
one.style.opacity = "0"; console.log('hover count: ' + hoverCount);
two.style.opacity = "0"; console.log('current round: ' + currentRound);
three.style.opacity = "0";
// this check prevents countdown from continuing if user removes / reapplies hover while we're sleeping frameElement.replaceChildren();
if (!hovering || hoverNumber != hoverCount) return false;
one.style.display = "inline";
two.style.display = "inline";
three.style.display = "inline";
three.style.opacity = "100"; // intro1.style.display = "none";
await sleep(1000); // intro2.style.display = "none";
gameText.style.display = "none";
two.style.opacity = "100"; if (gamemode == "normal") {
await sleep(1000); if (currentRound > 3) {
console.log("hover attempt after round 3");
return;
}
await startNormalRound(currentRound);
}
// if (infinityMode)
one.style.opacity = "100"; }
await sleep(1000);
if (!hovering || hoverNumber != hoverCount) return false; async function startNormalRound(roundNumber) {
one.style.display = "none"; if (!await startCountdown(hoverCount)) {
two.style.display = "none"; // if user canceled hover, don't continue round
three.style.display = "none"; console.log("player canceled coundown");
return;
}
one.style.opacity = "0"; console.log("starting round " + roundNumber);
two.style.opacity = "0";
three.style.opacity = "0";
draw.style.display = "inline"; targetsClickedThisRound = 0;
draw.style.opacity = "100"; let numTargets = 0;
countingDown = false; if (roundNumber == 1) {
setTimeout(() => {draw.style.display = "none"; draw.style.opacity = "0"; }, 1000); numTargets = 1;
return true; }
} else if (roundNumber == 2) {
numTargets = 3;
}
else if (roundNumber == 3) {
numTargets = 5;
}
else { alert("max number of rounds hit. should not be seeing this"); }
function handleHoverEnd(e) { // effectively begin the round
hovering = false; roundTimeStart = Date.now();
e.target.style.backgroundColor = "red"; placeTarget(numTargets);
while (targetsClickedThisRound < numTargets) {
await sleep(10);
if (targetsClickedThisRound == numTargets) break;
}
roundTimeEnd = Date.now();
roundSeconds = (roundTimeEnd - roundTimeStart) / 1000;
if (countingDown) { currentRound++;
one.style.display = "none";
two.style.display = "none";
three.style.display = "none";
draw.style.display = "none";
one.style.opacity = "0"; console.log('ROUND ' + currentRound + ' TIME: ' + roundSeconds);
two.style.opacity = "0"; gameText.innerText = "TIME: " + roundSeconds + "\nhover on bullseye to start round " + currentRound;
three.style.opacity = "0"; gameText.style.display = "inline";
gameText.style.opacity = "100";
draw.style.opacity = "0"; return;
}
instructions.style.display = "inline";
countingDown = false;
}
}
function handleResize(event) {
frameElement.replaceChildren();
setParameters();
document.getElementById("center").remove(); async function startCountdown(hoverNumber) {
center = generateTarget(xFrameAdjustment, yFrameAdjustment); gameText.style.display = "none";
center.id = "center";
document.body.insertAdjacentElement("afterbegin", center);
center.addEventListener("mouseover", handleHoverStart);
center.addEventListener("mouseleave", handleHoverEnd);
if (currentRound == 0) { countingDown = true;
drawTargetsInCircle(false); await sleep(1000);
}
console.log('page: ' + pageWidth + ' x ' + pageHeight); // this check prevents countdown from continuing if user removes / reapplies hover while we're sleeping
console.log('frame: ' + frameWidth + ' x ' + frameHeight); if (!hovering || hoverNumber != hoverCount) return false;
one.style.opacity = "0";
two.style.opacity = "0";
three.style.opacity = "0";
if (!hovering || hoverNumber != hoverCount) return false;
one.style.display = "inline";
two.style.display = "inline";
three.style.display = "inline";
if (!hovering || hoverNumber != hoverCount) return false;
three.style.opacity = "100";
await sleep(1000);
if (!hovering || hoverNumber != hoverCount) return false;
two.style.opacity = "100";
await sleep(1000);
if (!hovering || hoverNumber != hoverCount) return false;
one.style.opacity = "100";
await sleep(1000);
if (!hovering || hoverNumber != hoverCount) return false;
one.style.display = "none";
two.style.display = "none";
three.style.display = "none";
one.style.opacity = "0";
two.style.opacity = "0";
three.style.opacity = "0";
draw.style.display = "inline";
draw.style.opacity = "100";
countingDown = false;
setTimeout(() => {draw.style.display = "none"; draw.style.opacity = "0"; }, 1000);
return true;
}
function handleHoverEnd(e) {
hovering = false;
e.target.style.backgroundColor = "red";
if (countingDown) {
one.style.display = "none";
two.style.display = "none";
three.style.display = "none";
draw.style.display = "none";
one.style.opacity = "0";
two.style.opacity = "0";
three.style.opacity = "0";
draw.style.opacity = "0";
if (currentRound == 1) {
gameText.innerText = "click the targets as quickly as possible!\nhover on bullseye to start.";
}
else {
gameText.innerText = "TIME: " + roundSeconds + "\nhover on bullseye to start round " + currentRound;
}
gameText.style.display = "inline";
countingDown = false;
}
}
function handleTargetClick(e) {
targetsClickedThisRound++;
e.target.remove();
}
function handlePageResize(event) {
frameElement.replaceChildren();
setParameters();
document.getElementById("center").remove();
center = generateTarget(xFrameAdjustment, yFrameAdjustment);
center.id = "center";
document.body.insertAdjacentElement("afterbegin", center);
center.addEventListener("mouseover", handleHoverStart);
center.addEventListener("mouseleave", handleHoverEnd);
if (currentRound == 0) {
drawTargetsInCircle(false);
}
console.log('page: ' + pageWidth + ' x ' + pageHeight);
console.log('frame: ' + frameWidth + ' x ' + frameHeight);
} }
async function drawTargetsInCircle(animate) { async function drawTargetsInCircle(animate) {
@@ -330,17 +421,10 @@
let target; let target;
for (let i = 0; i < 360; i = i + 2) { for (let i = 0; i < 360; i = i + 2) {
r = (frameWidth / 2) - (targetWidth / 2) - (gameBorderWidth * 2); r = (frameWidth / 2) - (targetWidth / 2) - (gameBorderWidth * 2);
// r = (frameWidth / 2) - (targetWidth / 2);
radians = degreesToRadians(i); radians = degreesToRadians(i);
x = (r * 1 * Math.cos(radians)) + xFrameAdjustment; x = (r * 1 * Math.cos(radians)) + xFrameAdjustment;
y = (r * ratio * Math.sin(radians)) + yFrameAdjustment; y = (r * ratio * Math.sin(radians)) + yFrameAdjustment;
// console.log(x + ', ' + y);
// console.log(ratio);
// console.log(xFrameAdjustment + 'adj, ' + yFrameAdjustment + 'adj');
target = generateTarget(x, y); target = generateTarget(x, y);
document.getElementById("frame").insertAdjacentElement("afterbegin", target); document.getElementById("frame").insertAdjacentElement("afterbegin", target);
@@ -348,14 +432,28 @@
} }
} }
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function degreesToRadians(degrees) { function degreesToRadians(degrees) {
return degrees * (Math.PI / 180) return degrees * (Math.PI / 180)
} }
// function to place a target somewhere random on the circle
function placeTarget(numTargets) {
let radians, radius
let x, y;
let target;
for (let i = 0; i < numTargets; i++){
radians = degreesToRadians(getRandomInt(0, 360));
radius = (frameWidth / 2) - (targetWidth / 2) - (gameBorderWidth * 2);
x = (radius * 1 * Math.cos(radians)) + xFrameAdjustment;
y = (radius * ratio * Math.sin(radians)) + yFrameAdjustment;
target = generateTarget(x, y);
target.classList.add("target");
target.addEventListener("click", handleTargetClick);
document.getElementById("frame").insertAdjacentElement("afterbegin", target);
}
}
function generateTarget(x, y) { function generateTarget(x, y) {
const target = document.createElement("div"); const target = document.createElement("div");
@@ -366,12 +464,15 @@
return target; return target;
} }
function getRandomInt(min, max) { function getRandomInt(min, max) {
const minCeiled = Math.ceil(min); const minCeiled = Math.ceil(min);
const maxFloored = Math.floor(max); const maxFloored = Math.floor(max);
return Math.floor(Math.random() * (maxFloored - minCeiled) + minCeiled); // The maximum is exclusive and the minimum is inclusive return Math.floor(Math.random() * (maxFloored - minCeiled) + minCeiled); // The maximum is exclusive and the minimum is inclusive
} }
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
</script> </script>
</body> </body>
</html> </html>