normal mode lowk working
This commit is contained in:
+280
-179
@@ -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>
|
||||
|
||||
|
||||
<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;
|
||||
let gameBorderWidth = 1;
|
||||
let targetWidth = 20;
|
||||
let targetHeight = 20;
|
||||
|
||||
let pageHeight;
|
||||
let pageWidth;
|
||||
let pageHeight;
|
||||
let pageWidth;
|
||||
|
||||
let frameElement;
|
||||
let frameRect;
|
||||
let frameHeight;
|
||||
let frameWidth;
|
||||
let frameElement;
|
||||
let frameRect;
|
||||
let frameHeight;
|
||||
let frameWidth;
|
||||
|
||||
let center;
|
||||
let ratio;
|
||||
let center;
|
||||
let ratio;
|
||||
|
||||
let xFrameAdjustment;
|
||||
let yFrameAdjustment;
|
||||
let xFrameAdjustment;
|
||||
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 countingDown = false;
|
||||
let targetsClickedThisRound = 0;
|
||||
let gamemode = ""; // can be: "normal", "countdown", "infinite"
|
||||
let roundmode = ""; // if gamemode is "countdown" or "infinite", can be: "rounds" or "frenzy"
|
||||
|
||||
// text elements
|
||||
let intro1 = document.getElementById("intro1");
|
||||
let intro2 = document.getElementById("intro2");
|
||||
let instructions = document.getElementById("instructions");
|
||||
let currentRound = 0;
|
||||
let countingDown = false;
|
||||
|
||||
let one = document.getElementById("countdown1");
|
||||
let two = document.getElementById("countdown2");
|
||||
let three = document.getElementById("countdown3");
|
||||
let roundTimeStart = 0;
|
||||
let roundTimeEnd = 0;
|
||||
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) {
|
||||
pageHeight = window.innerHeight;
|
||||
pageWidth = window.innerWidth;
|
||||
let draw = document.getElementById("draw");
|
||||
|
||||
frameElement = document.getElementById("frame");
|
||||
frameRect = frameElement.getBoundingClientRect();
|
||||
frameHeight = frameElement.offsetHeight;
|
||||
frameWidth = frameElement.offsetWidth;
|
||||
window.addEventListener("load", initGame);
|
||||
|
||||
// ratio = (frameHeight - (gameBorderWidth*2)) / (frameWidth - (gameBorderWidth*2));
|
||||
ratio = frameHeight / frameWidth;
|
||||
function setParameters(event) {
|
||||
pageHeight = window.innerHeight;
|
||||
pageWidth = window.innerWidth;
|
||||
|
||||
// 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);
|
||||
frameElement = document.getElementById("frame");
|
||||
frameRect = frameElement.getBoundingClientRect();
|
||||
frameHeight = frameElement.offsetHeight;
|
||||
frameWidth = frameElement.offsetWidth;
|
||||
|
||||
// init logs:
|
||||
console.log('page: ' + pageWidth + ' x ' + pageHeight);
|
||||
console.log('frame: ' + frameWidth + ' x ' + frameHeight);
|
||||
}
|
||||
// ratio = (frameHeight - (gameBorderWidth*2)) / (frameWidth - (gameBorderWidth*2));
|
||||
ratio = frameHeight / frameWidth;
|
||||
|
||||
async function initGame() {
|
||||
setParameters();
|
||||
// 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);
|
||||
|
||||
center = generateTarget(xFrameAdjustment, yFrameAdjustment);
|
||||
center.id = "center";
|
||||
document.body.insertAdjacentElement("afterbegin", center);
|
||||
// init logs:
|
||||
console.log('page: ' + pageWidth + ' x ' + pageHeight);
|
||||
console.log('frame: ' + frameWidth + ' x ' + frameHeight);
|
||||
}
|
||||
|
||||
await drawTargetsInCircle(true);
|
||||
async function initGame() {
|
||||
setParameters();
|
||||
|
||||
// insert intro elements into document flow
|
||||
intro1.style.display = "inline";
|
||||
intro2.style.display = "inline";
|
||||
center = generateTarget(xFrameAdjustment, yFrameAdjustment);
|
||||
center.id = "center";
|
||||
document.body.insertAdjacentElement("afterbegin", center);
|
||||
|
||||
// reveal intro elements
|
||||
intro1.style.opacity = "100";
|
||||
await sleep(500);
|
||||
intro2.style.opacity = "100";
|
||||
await sleep(1500);
|
||||
await drawTargetsInCircle(false);
|
||||
|
||||
intro1.classList.add("fade");
|
||||
intro2.classList.add("fade");
|
||||
// insert intro elements into document flow
|
||||
intro1.style.display = "inline";
|
||||
intro2.style.display = "inline";
|
||||
|
||||
intro1.style.opacity = "0";
|
||||
intro2.style.opacity = "0";
|
||||
// reveal intro elements
|
||||
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";
|
||||
intro2.style.display = "none";
|
||||
intro1.style.opacity = "0";
|
||||
intro2.style.opacity = "0";
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
await sleep(1000);
|
||||
|
||||
document.getElementById("game-modes").style.display = "inline";
|
||||
await sleep(500);
|
||||
document.getElementById("game-modes").style.opacity = "100";
|
||||
}
|
||||
intro1.style.display = "none";
|
||||
intro2.style.display = "none";
|
||||
|
||||
function handleNormalMode(e) {
|
||||
center.addEventListener("mouseover", handleHoverStart);
|
||||
center.addEventListener("mouseleave", handleHoverEnd);
|
||||
window.addEventListener("resize", handlePageResize);
|
||||
|
||||
// instructions.style.display = "inline";
|
||||
// instructions.style.opacity = "100";
|
||||
}
|
||||
document.getElementById("game-modes").style.display = "inline";
|
||||
await sleep(500);
|
||||
document.getElementById("game-modes").style.opacity = "100";
|
||||
}
|
||||
|
||||
function handleHoverStart(e) {
|
||||
e.target.style.backgroundColor = "green";
|
||||
if (currentRound == 0) return;
|
||||
function handleNormalMode(e) {
|
||||
gamemode = "normal";
|
||||
console.log("game mode: " + gamemode);
|
||||
|
||||
hovering = true;
|
||||
hoverCount++;
|
||||
currentRound = 1;
|
||||
|
||||
frameElement.replaceChildren();
|
||||
center.addEventListener("mouseover", handleHoverStart);
|
||||
center.addEventListener("mouseleave", handleHoverEnd);
|
||||
|
||||
intro1.style.display = "none";
|
||||
intro2.style.display = "none";
|
||||
instructions.style.display = "none";
|
||||
document.getElementById("game-modes").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) {
|
||||
instructions.style.display = "none";
|
||||
async function handleHoverStart(e) {
|
||||
e.target.style.backgroundColor = "green";
|
||||
|
||||
countingDown = true;
|
||||
await sleep(1000);
|
||||
hovering = true;
|
||||
hoverCount++;
|
||||
|
||||
one.style.opacity = "0";
|
||||
two.style.opacity = "0";
|
||||
three.style.opacity = "0";
|
||||
console.log('hover count: ' + hoverCount);
|
||||
console.log('current round: ' + currentRound);
|
||||
|
||||
// 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";
|
||||
frameElement.replaceChildren();
|
||||
|
||||
three.style.opacity = "100";
|
||||
await sleep(1000);
|
||||
// intro1.style.display = "none";
|
||||
// intro2.style.display = "none";
|
||||
gameText.style.display = "none";
|
||||
|
||||
two.style.opacity = "100";
|
||||
await sleep(1000);
|
||||
if (gamemode == "normal") {
|
||||
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;
|
||||
one.style.display = "none";
|
||||
two.style.display = "none";
|
||||
three.style.display = "none";
|
||||
async function startNormalRound(roundNumber) {
|
||||
if (!await startCountdown(hoverCount)) {
|
||||
// if user canceled hover, don't continue round
|
||||
console.log("player canceled coundown");
|
||||
return;
|
||||
}
|
||||
|
||||
one.style.opacity = "0";
|
||||
two.style.opacity = "0";
|
||||
three.style.opacity = "0";
|
||||
console.log("starting round " + roundNumber);
|
||||
|
||||
draw.style.display = "inline";
|
||||
draw.style.opacity = "100";
|
||||
targetsClickedThisRound = 0;
|
||||
let numTargets = 0;
|
||||
|
||||
countingDown = false;
|
||||
setTimeout(() => {draw.style.display = "none"; draw.style.opacity = "0"; }, 1000);
|
||||
return true;
|
||||
}
|
||||
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"); }
|
||||
|
||||
function handleHoverEnd(e) {
|
||||
hovering = false;
|
||||
e.target.style.backgroundColor = "red";
|
||||
// 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;
|
||||
|
||||
if (countingDown) {
|
||||
one.style.display = "none";
|
||||
two.style.display = "none";
|
||||
three.style.display = "none";
|
||||
draw.style.display = "none";
|
||||
currentRound++;
|
||||
|
||||
one.style.opacity = "0";
|
||||
two.style.opacity = "0";
|
||||
three.style.opacity = "0";
|
||||
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";
|
||||
|
||||
draw.style.opacity = "0";
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
async function startCountdown(hoverNumber) {
|
||||
gameText.style.display = "none";
|
||||
|
||||
if (currentRound == 0) {
|
||||
drawTargetsInCircle(false);
|
||||
}
|
||||
countingDown = true;
|
||||
await sleep(1000);
|
||||
|
||||
console.log('page: ' + pageWidth + ' x ' + pageHeight);
|
||||
console.log('frame: ' + frameWidth + ' x ' + frameHeight);
|
||||
// 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";
|
||||
|
||||
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) {
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user