summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--quickdraw-game.html471
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>