game mode selection ui created

This commit is contained in:
simon-ec
2026-06-29 09:46:36 -04:00
parent ff51e386c6
commit e4d7bd675a
+324 -59
View File
@@ -1,112 +1,377 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style> <style>
* { * {
box-sizing: border-box; box-sizing: border-box;
margin: 0; margin: 0;
padding: 0; padding: 0;
font-family: sans-serif;
} }
html { html {
height: 100vh; height: 100vh;
width: 100vw; width: 100vw;
background-color: #161616; background-color: #161616;
font-size: 24px;
overflow-x: hidden;
} }
body { body {
display: flex; display: flex;
flex-direction: column;
align-items: center;
justify-content: center; justify-content: center;
height: 100vh;
width: 100vw;
} }
#target { #frame {
width: 60%;
height: 75%;
/** border: 1px solid white; */
}
#center {
height: 20px; height: 20px;
width: 20px; width: 20px;
background-color: red; background-color: red;
position: absolute; position: absolute;
} }
#frame {
width: 75%; .target {
height: 100vh; height: 20px;
border: 1px solid white; width: 20px;
background-color: red;
position: absolute;
} }
.hidden {
display: none;
opacity: 0;
}
.fade {
transition: opacity 1s;
}
.title {
font-weight: bold;
font-size: 2rem;
}
#text-box {
display: flex;
flex-direction: row;
align-content: end;
justify-content: space-evenly;
color: red;
width: 100%;
min-height: 2rem;
line-height: 2rem;
margin-top: 2rem;
}
@media screen and (max-width: 750px) {
html {
font-size: 32px;
}
#text-box {
flex-direction: column;
align-items: center;
}
.text { font-size: .5rem; }
.title { font-size: 2rem; }
}
</style> </style>
</head> </head>
<body> <body>
<div id="frame"> <div id="frame"></div>
<div id="text-box">
<span id="intro1" class="hidden title">QUICK</span>
<span id="intro2" class="hidden title">DRAW</span>
<span id="instructions" class="hidden fade">hover on bullseye to start</span>
<span id="countdown3" class="hidden title">3</span>
<span id="countdown2" class="hidden title">2</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>
</div> </div>
<script> <script>
let gameBorderWidth = 1;
let targetWidth = 20;
let targetHeight = 20;
const gameBorderWidth = 1; let pageHeight;
const targetWidth = 20; let pageWidth;
const targetHeight = 20;
let pageWidth = window.innerWidth; let frameElement;
let pageHeight = window.innerHeight; let frameRect;
let frameHeight;
let frameWidth;
const frameElement = document.getElementById("frame"); let center;
let frameHeight = frameElement.offsetHeight; let ratio;
let frameWidth = frameElement.offsetWidth;
let target; let xFrameAdjustment;
let yFrameAdjustment;
let hovering = false;
window.addEventListener("resize", (e) => { let hoverCount = 0;
this.pageWidth = window.innerWidth;
this.pageHeight = window.innerHeight;
this.frameHeight = frameElement.offsetHeight - targetHeight;
this.frameWidth = frameElement.offsetWidth - targetWidth;
console.log('page: ' + this.pageWidth + ' x ' + this.pageHeight);
console.log('frame: ' + this.frameWidth + ' x ' + this.frameHeight);
});
let k, r, x, y; let currentRound = 0;
let countingDown = false;
// text elements
let intro1 = document.getElementById("intro1");
let intro2 = document.getElementById("intro2");
let instructions = document.getElementById("instructions");
let one = document.getElementById("countdown1");
let two = document.getElementById("countdown2");
let three = document.getElementById("countdown3");
let draw = document.getElementById("draw");
window.addEventListener("load", initGame);
function setParameters(event) {
pageHeight = window.innerHeight;
pageWidth = window.innerWidth;
frameElement = document.getElementById("frame");
frameRect = frameElement.getBoundingClientRect();
frameHeight = frameElement.offsetHeight;
frameWidth = frameElement.offsetWidth;
// ratio = (frameHeight - (gameBorderWidth*2)) / (frameWidth - (gameBorderWidth*2));
ratio = frameHeight / frameWidth;
// adjustments to find center of frame in absolute coords (for origin of target cirlce)
xFrameAdjustment = ((frameWidth / 2) + frameRect.left) - (targetWidth / 2);
yFrameAdjustment = ((frameHeight / 2) + frameRect.top) - (targetWidth / 2);
// init logs:
console.log('page: ' + pageWidth + ' x ' + pageHeight);
console.log('frame: ' + frameWidth + ' x ' + frameHeight);
}
async function initGame() {
setParameters();
center = generateTarget(xFrameAdjustment, yFrameAdjustment);
center.id = "center";
document.body.insertAdjacentElement("afterbegin", center);
await drawTargetsInCircle(true);
// insert intro elements into document flow
intro1.style.display = "inline";
intro2.style.display = "inline";
// reveal intro elements
intro1.style.opacity = "100";
await sleep(500);
intro2.style.opacity = "100";
await sleep(1500);
intro1.classList.add("fade");
intro2.classList.add("fade");
intro1.style.opacity = "0";
intro2.style.opacity = "0";
await sleep(1000);
intro1.style.display = "none";
intro2.style.display = "none";
window.addEventListener("resize", handleResize);
document.getElementById("game-modes").style.display = "inline";
await sleep(500);
document.getElementById("game-modes").style.opacity = "100";
}
function handleNormalMode(e) {
center.addEventListener("mouseover", handleHoverStart);
center.addEventListener("mouseleave", handleHoverEnd);
// instructions.style.display = "inline";
// instructions.style.opacity = "100";
}
function handleHoverStart(e) {
e.target.style.backgroundColor = "green";
if (currentRound == 0) return;
hovering = true;
hoverCount++;
frameElement.replaceChildren();
intro1.style.display = "none";
intro2.style.display = "none";
instructions.style.display = "none";
// if (infinityMode)
if (currentRound == 0) { startRoundOne(); }
}
async function startRoundOne() {
if (!await startCountdown(hoverCount)) {
// if user canceled hover, don't continue round
return;
}
console.log('success');
}
async function startCountdown(hoverNumber) {
instructions.style.display = "none";
countingDown = true;
await sleep(1000);
one.style.opacity = "0";
two.style.opacity = "0";
three.style.opacity = "0";
// this check prevents countdown from continuing if user removes / reapplies hover while we're sleeping
if (!hovering || hoverNumber != hoverCount) return false;
one.style.display = "inline";
two.style.display = "inline";
three.style.display = "inline";
three.style.opacity = "100";
await sleep(1000);
two.style.opacity = "100";
await sleep(1000);
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";
instructions.style.display = "inline";
countingDown = false;
}
}
function handleResize(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) {
let r, x, y;
let radians; let radians;
let target;
let ratio = frameHeight / frameWidth; for (let i = 0; i < 360; i = i + 2) {
r = (frameWidth / 2) - (targetWidth / 2) - (gameBorderWidth * 2);
let xFrameAdjustment = ((pageWidth - frameWidth) * 2) - (targetWidth / 2); // r = (frameWidth / 2) - (targetWidth / 2);
let yFrameAdjustment = (frameHeight / 2) - (targetWidth / 2);
generateTarget(xFrameAdjustment, yFrameAdjustment)
for (let i = 0; i < 360; i++) {
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);
generateTarget(x, y); // console.log(x + ', ' + y);
// console.log(ratio);
// console.log(xFrameAdjustment + 'adj, ' + yFrameAdjustment + 'adj');
target = generateTarget(x, y);
document.getElementById("frame").insertAdjacentElement("afterbegin", target);
if (animate) await sleep(15);
} }
}
// init logs: function sleep(ms) {
console.log('page: ' + pageWidth + ' x ' + pageHeight); return new Promise(resolve => setTimeout(resolve, ms));
console.log('frame: ' + frameWidth + ' x ' + frameHeight); }
function degreesToRadians(degrees) {
return degrees * (Math.PI / 180)
}
function degreesToRadians(degrees) { function generateTarget(x, y) {
return degrees * (Math.PI / 180) const target = document.createElement("div");
} target.classList.add("target");
target.style.top = y +'px';
target.style.left = x + 'px';
// console.log(target);
return target;
}
function generateTarget(x, y) { function getRandomInt(min, max) {
const target = document.createElement("div"); const minCeiled = Math.ceil(min);
target.id = "target"; const maxFloored = Math.floor(max);
target.style.top = y +'px'; return Math.floor(Math.random() * (maxFloored - minCeiled) + minCeiled); // The maximum is exclusive and the minimum is inclusive
target.style.left = x + 'px'; }
// console.log(target);
document.getElementById("frame").insertAdjacentElement("afterbegin", target);
}
function getRandomInt(min, max) {
const minCeiled = Math.ceil(min);
const maxFloored = Math.floor(max);
return Math.floor(Math.random() * (maxFloored - minCeiled) + minCeiled); // The maximum is exclusive and the minimum is inclusive
}
</script> </script>
</body> </body>
</html> </html>