diff options
Diffstat (limited to 'quickdraw-game.html')
| -rw-r--r-- | quickdraw-game.html | 471 |
1 files changed, 286 insertions, 185 deletions
diff --git a/quickdraw-game.html b/quickdraw-game.html index 7d7b9e4..cf175ad 100644 --- a/quickdraw-game.html +++ b/quickdraw-game.html @@ -42,6 +42,10 @@ width: 20px; background-color: red; position: absolute; + border-radius: 25%; + } + .target:active { + background-color: orange; } .hidden { @@ -62,10 +66,11 @@ flex-direction: row; align-content: end; justify-content: space-evenly; + text-align: center; color: red; width: 100%; min-height: 2rem; - line-height: 2rem; + line-height: 1rem; margin-top: 2rem; } @@ -85,243 +90,329 @@ </head> <body> - <div id="frame"></div> - - + <div id="frame"> + <!-- where the targets + bullseye are drawn --> + </div> + <!-- where we place text + buttons --> <div id="text-box"> + + <!-- intro related --> <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> + <!-- 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="countdown2" class="hidden title">2</span> <span id="countdown1" class="hidden title">1</span> + <span id="draw" class="hidden title">DRAW!</span> + </div> - <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> + <script> + let gameBorderWidth = 1; + let targetWidth = 20; + let targetHeight = 20; + let pageHeight; + let pageWidth; - <span id="draw" class="hidden title">DRAW!</span> - </div> + let frameElement; + let frameRect; + let frameHeight; + let frameWidth; - <script> - let gameBorderWidth = 1; - let targetWidth = 20; - let targetHeight = 20; + let center; + let ratio; - let pageHeight; - let pageWidth; + let xFrameAdjustment; + let yFrameAdjustment; - let frameElement; - let frameRect; - let frameHeight; - let frameWidth; + let hovering = false; - let center; - let ratio; + let hoverCount = 0; // number of times the cursor has hovered over bullseye. used to cleanly handle round starting / cancelling - let xFrameAdjustment; - let yFrameAdjustment; + let targetsClickedThisRound = 0; + let gamemode = ""; // can be: "normal", "countdown", "infinite" + let roundmode = ""; // if gamemode is "countdown" or "infinite", can be: "rounds" or "frenzy" + + let currentRound = 0; + let countingDown = false; - let hovering = false; + let roundTimeStart = 0; + let roundTimeEnd = 0; + let roundSeconds = 0.0; - let hoverCount = 0; - - let currentRound = 0; - let countingDown = false; + // text elements + let intro1 = document.getElementById("intro1"); + let intro2 = document.getElementById("intro2"); + let gameText = document.getElementById("gameText"); - // 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 one = document.getElementById("countdown1"); - let two = document.getElementById("countdown2"); - let three = document.getElementById("countdown3"); + let draw = document.getElementById("draw"); - let draw = document.getElementById("draw"); + window.addEventListener("load", initGame); - window.addEventListener("load", initGame); + function setParameters(event) { + pageHeight = window.innerHeight; + pageWidth = window.innerWidth; - function setParameters(event) { - pageHeight = window.innerHeight; - pageWidth = window.innerWidth; + frameElement = document.getElementById("frame"); + frameRect = frameElement.getBoundingClientRect(); + frameHeight = frameElement.offsetHeight; + frameWidth = frameElement.offsetWidth; - 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); - // 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); + } - // init logs: - console.log('page: ' + pageWidth + ' x ' + pageHeight); - console.log('frame: ' + frameWidth + ' x ' + frameHeight); - } + async function initGame() { + setParameters(); - async function initGame() { - setParameters(); + center = generateTarget(xFrameAdjustment, yFrameAdjustment); + center.id = "center"; + document.body.insertAdjacentElement("afterbegin", center); - center = generateTarget(xFrameAdjustment, yFrameAdjustment); - center.id = "center"; - document.body.insertAdjacentElement("afterbegin", center); + await drawTargetsInCircle(false); - await drawTargetsInCircle(true); + // insert intro elements into document flow + intro1.style.display = "inline"; + intro2.style.display = "inline"; - // 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); - // 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.classList.add("fade"); - intro2.classList.add("fade"); + intro1.style.opacity = "0"; + intro2.style.opacity = "0"; - intro1.style.opacity = "0"; - intro2.style.opacity = "0"; + await sleep(1000); - await sleep(1000); + intro1.style.display = "none"; + intro2.style.display = "none"; - intro1.style.display = "none"; - intro2.style.display = "none"; + window.addEventListener("resize", handlePageResize); - window.addEventListener("resize", handleResize); + document.getElementById("game-modes").style.display = "inline"; + await sleep(500); + document.getElementById("game-modes").style.opacity = "100"; + } + + function handleNormalMode(e) { + gamemode = "normal"; + console.log("game mode: " + gamemode); + + currentRound = 1; + + center.addEventListener("mouseover", handleHoverStart); + center.addEventListener("mouseleave", handleHoverEnd); + + document.getElementById("game-modes").style.display = "none"; + + intro1.style.display = "none"; + intro2.style.display = "none"; + + gameText.innerText = "click the targets as quickly as possible!\nhover on bullseye to start."; + gameText.style.display = "inline"; + gameText.style.opacity = "100"; + + } - document.getElementById("game-modes").style.display = "inline"; - await sleep(500); - document.getElementById("game-modes").style.opacity = "100"; - } + async function handleHoverStart(e) { + e.target.style.backgroundColor = "green"; - function handleNormalMode(e) { - center.addEventListener("mouseover", handleHoverStart); - center.addEventListener("mouseleave", handleHoverEnd); + hovering = true; + hoverCount++; - // instructions.style.display = "inline"; - // instructions.style.opacity = "100"; - } + console.log('hover count: ' + hoverCount); + console.log('current round: ' + currentRound); + + frameElement.replaceChildren(); + + // intro1.style.display = "none"; + // intro2.style.display = "none"; + gameText.style.display = "none"; + + if (gamemode == "normal") { + if (currentRound > 3) { + console.log("hover attempt after round 3"); + return; + } + await startNormalRound(currentRound); + } + // if (infinityMode) + + } + + async function startNormalRound(roundNumber) { + if (!await startCountdown(hoverCount)) { + // if user canceled hover, don't continue round + console.log("player canceled coundown"); + return; + } + + console.log("starting round " + roundNumber); - function handleHoverStart(e) { - e.target.style.backgroundColor = "green"; - if (currentRound == 0) return; + targetsClickedThisRound = 0; + let numTargets = 0; + + if (roundNumber == 1) { + numTargets = 1; + } + else if (roundNumber == 2) { + numTargets = 3; + } + else if (roundNumber == 3) { + numTargets = 5; + } + else { alert("max number of rounds hit. should not be seeing this"); } - hovering = true; - hoverCount++; + // effectively begin the round + roundTimeStart = Date.now(); + placeTarget(numTargets); + while (targetsClickedThisRound < numTargets) { + await sleep(10); + if (targetsClickedThisRound == numTargets) break; + } + roundTimeEnd = Date.now(); + roundSeconds = (roundTimeEnd - roundTimeStart) / 1000; - frameElement.replaceChildren(); + currentRound++; - intro1.style.display = "none"; - intro2.style.display = "none"; - instructions.style.display = "none"; + console.log('ROUND ' + currentRound + ' TIME: ' + roundSeconds); + gameText.innerText = "TIME: " + roundSeconds + "\nhover on bullseye to start round " + currentRound; + gameText.style.display = "inline"; + gameText.style.opacity = "100"; - // if (infinityMode) + return; + } - 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"; + async function startCountdown(hoverNumber) { + gameText.style.display = "none"; - countingDown = true; - await sleep(1000); + countingDown = true; + await sleep(1000); + + // this check prevents countdown from continuing if user removes / reapplies hover while we're sleeping + if (!hovering || hoverNumber != hoverCount) return false; + one.style.opacity = "0"; + two.style.opacity = "0"; + three.style.opacity = "0"; - 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"; - // 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"; + 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); - 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"; - 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"; - one.style.opacity = "0"; - two.style.opacity = "0"; - three.style.opacity = "0"; + draw.style.display = "inline"; + draw.style.opacity = "100"; - draw.style.display = "inline"; - draw.style.opacity = "100"; + countingDown = false; + setTimeout(() => {draw.style.display = "none"; draw.style.opacity = "0"; }, 1000); + return true; + } - countingDown = false; - setTimeout(() => {draw.style.display = "none"; draw.style.opacity = "0"; }, 1000); - return true; - } + function handleHoverEnd(e) { + hovering = false; + e.target.style.backgroundColor = "red"; - 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"; - 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"; - 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; + } + } - draw.style.opacity = "0"; - - instructions.style.display = "inline"; - countingDown = false; - } - } + function handleTargetClick(e) { + targetsClickedThisRound++; + e.target.remove(); + } - 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); - } + 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); + console.log('page: ' + pageWidth + ' x ' + pageHeight); + console.log('frame: ' + frameWidth + ' x ' + frameHeight); } async function drawTargetsInCircle(animate) { @@ -330,17 +421,10 @@ let target; for (let i = 0; i < 360; i = i + 2) { r = (frameWidth / 2) - (targetWidth / 2) - (gameBorderWidth * 2); - // r = (frameWidth / 2) - (targetWidth / 2); - radians = degreesToRadians(i); - x = (r * 1 * Math.cos(radians)) + xFrameAdjustment; y = (r * ratio * Math.sin(radians)) + yFrameAdjustment; - // console.log(x + ', ' + y); - // console.log(ratio); - // console.log(xFrameAdjustment + 'adj, ' + yFrameAdjustment + 'adj'); - target = generateTarget(x, y); document.getElementById("frame").insertAdjacentElement("afterbegin", target); @@ -348,14 +432,28 @@ } } - function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); - } function degreesToRadians(degrees) { 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) { const target = document.createElement("div"); @@ -366,12 +464,15 @@ return 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 } + + function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } </script> </body> </html> |
