summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--quickdraw-game.html381
1 files changed, 323 insertions, 58 deletions
diff --git a/quickdraw-game.html b/quickdraw-game.html
index 77191c3..7d7b9e4 100644
--- a/quickdraw-game.html
+++ b/quickdraw-game.html
@@ -1,112 +1,377 @@
<!DOCTYPE html>
<html>
<head>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
+ font-family: sans-serif;
}
html {
height: 100vh;
width: 100vw;
background-color: #161616;
+ font-size: 24px;
+ overflow-x: hidden;
}
body {
display: flex;
+ flex-direction: column;
+ align-items: center;
justify-content: center;
+ height: 100vh;
+ width: 100vw;
}
- #target {
+ #frame {
+ width: 60%;
+ height: 75%;
+ /** border: 1px solid white; */
+ }
+ #center {
+ height: 20px;
+ width: 20px;
+ background-color: red;
+ position: absolute;
+ }
+
+ .target {
height: 20px;
width: 20px;
background-color: red;
position: absolute;
}
- #frame {
- width: 75%;
- height: 100vh;
- border: 1px solid white;
+
+ .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>
</head>
<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>
<script>
+ let gameBorderWidth = 1;
+ let targetWidth = 20;
+ let targetHeight = 20;
- const gameBorderWidth = 1;
- const targetWidth = 20;
- const targetHeight = 20;
+ let pageHeight;
+ let pageWidth;
- let pageWidth = window.innerWidth;
- let pageHeight = window.innerHeight;
+ let frameElement;
+ let frameRect;
+ let frameHeight;
+ let frameWidth;
- const frameElement = document.getElementById("frame");
- let frameHeight = frameElement.offsetHeight;
- let frameWidth = frameElement.offsetWidth;
-
- let target;
+ let center;
+ let ratio;
+ let xFrameAdjustment;
+ let yFrameAdjustment;
- window.addEventListener("resize", (e) => {
- 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 hovering = false;
- let k, r, x, y;
- let radians;
+ let hoverCount = 0;
+
+ let currentRound = 0;
+ let countingDown = false;
- let ratio = frameHeight / frameWidth;
+ // text elements
+ let intro1 = document.getElementById("intro1");
+ let intro2 = document.getElementById("intro2");
+ let instructions = document.getElementById("instructions");
- let xFrameAdjustment = ((pageWidth - frameWidth) * 2) - (targetWidth / 2);
- let yFrameAdjustment = (frameHeight / 2) - (targetWidth / 2);
+ let one = document.getElementById("countdown1");
+ let two = document.getElementById("countdown2");
+ let three = document.getElementById("countdown3");
- generateTarget(xFrameAdjustment, yFrameAdjustment)
+ let draw = document.getElementById("draw");
- for (let i = 0; i < 360; i++) {
- r = (frameWidth / 2) - (targetWidth / 2);
+ window.addEventListener("load", initGame);
- radians = degreesToRadians(i);
+ function setParameters(event) {
+ pageHeight = window.innerHeight;
+ pageWidth = window.innerWidth;
- x = ((r * 1 * Math.cos(radians)) + xFrameAdjustment);
- y = ((r * ratio * Math.sin(radians)) + yFrameAdjustment);
- console.log(x + ', ' + y);
+ frameElement = document.getElementById("frame");
+ frameRect = frameElement.getBoundingClientRect();
+ frameHeight = frameElement.offsetHeight;
+ frameWidth = frameElement.offsetWidth;
- generateTarget(x, y);
- }
+ // 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();
- function degreesToRadians(degrees) {
- return degrees * (Math.PI / 180)
- }
-
-
- function generateTarget(x, y) {
- const target = document.createElement("div");
- target.id = "target";
- target.style.top = y +'px';
- target.style.left = x + 'px';
- // console.log(target);
- document.getElementById("frame").insertAdjacentElement("afterbegin", target);
- }
+ 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);
- 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
+ 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 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);
+
+ if (animate) await sleep(15);
}
+ }
+
+ function sleep(ms) {
+ return new Promise(resolve => setTimeout(resolve, ms));
+ }
+
+ function degreesToRadians(degrees) {
+ return degrees * (Math.PI / 180)
+ }
+
+
+ function generateTarget(x, y) {
+ 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 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>
</body>
</html>