I am trying to make a replica of the Simon color game with JavaScript, HTML, and CSS. The colored buttons for the actual game are all SVG paths and thus have event listeners so they can act as buttons. I also have two basic HTML buttons, one to start the game and the other to reset it. I want the listeners to be disabled until the start button is pressed, then disabled again when the reset button is pressed.
Here is a link to my code:
https://jsfiddle.net/NoahLeuthold/xbm63hvu/7/
The console should stay blank, even after clicking the colored buttons, until the start button is clicked. After the start button is clicked and one of the colored buttons are clicked, the console should say which button was pressed.
But when I run my code, nothing happens. The console is blank, even after clicking start, and there aren’t any visual errors on the HTML page (except some sizing errors, but those are the result of a small display window on JSFiddle).
From doing some Googling, my guess is it has something to do with the scope, but I can’t find a way to get anything to work.
I tried putting everything (including the event listeners) inside the play() function, taking everything out of the play() function, putting "play()" inside the event listener, and putting the contents of the play() function inside the event listener instead of "play()".
Like I said, my guess is it has something to do with the scope, but I can’t find any solutions. Is there a quick fix to my problem, or should I scrap this method and try something else? If I should scrap this method, does anyone have any ideas on where to start?
Here is the code:
HTML:
<!DOCTYPE html>
<html>
<head>
<title>Simon Game</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id="board">
<div id="scoreboard">
Score:
<br>
<p id="score">0</p>
</div>
<button id="start">START</button>
<button id="reset">RESET</button>
<div id="rules">
<p id="rulesTitle">Rules</p>
The rules are simple, memorize the pattern shown and repeat it. Every round, the pattern gets longer. If you mess up even once, the game ends.
<p id="goodluck">Good luck!</p>
</div>
<div id="game">
<div id="blackCircle">
<div id="centerCircle"></div>
<svg width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="none">
<path id="yellow" d="
M 5 47.5
Q 10 10, 47.5 5
v 22.5
Q 30 30, 27.5 47.5
Z
"
stroke="darkgray" fill="yellow"/>
<path id="blue" d="
M 52.5 5
Q 90 10, 95 47.5
h -22.5
Q 70 30, 52.5 27.5
Z
"
stroke="darkgray" fill="blue"/>
<path id="green" d="
M 95 52.5
Q 90 90, 52.5 95
v -22.5
Q 70 70, 72.5 52.5
Z
"
stroke="darkgray" fill="green"/>
<path id="red" d="
M 47.5 95
Q 10 90, 5 52.5
h 22.5
Q 30 70, 47.5 72.5
Z
"
stroke="darkgray" fill="red"/>
</svg>
</div>
</div>
</div>
<script type="text/javascript" src="sizing.js"></script>
<script type="text/javascript" src="gamePlay.js"></script>
</body>
</html>
JavaScript:
gamePlay.js
const start = document.getElementById("start");
const reset = document.getElementById("reset");
const yellow = document.getElementById("yellow");
const blue = document.getElementById("blue");
const green = document.getElementById("green");
const red = document.getElementById("red");
var order = [];
var selected = [];
var running;
function play(){
if (running == true){
yellow.addEventListener('click', () => {
console.log("yellow has been clicked");
selected.push("yellow");
});
blue.addEventListener('click', () => {
console.log("blue has been clicked");
selected.push("blue");
});
green.addEventListener('click', () => {
console.log("green has been clicked");
selected.push("green");
});
red.addEventListener('click', () => {
console.log("red has been clicked");
selected.push("red");
});
}
}
start.addEventListener('click', () => {
running = true;
});
reset.addEventListener('click', () => {
running = false;
order = [];
selected = [];
});
play();
sizing.js
const game = document.getElementById("game");
const blackCircle = document.getElementById("blackCircle");
const centerCircle = document.getElementById("centerCircle");
function resizing(){
var gameSTYLE = getComputedStyle(game);
var blackCircleSTYLE = getComputedStyle(blackCircle);
var centerCircleSTYLE = getComputedStyle(centerCircle);
if (gameSTYLE.width > gameSTYLE.height){
blackCircle.style.height = parseInt(gameSTYLE.height) - (parseInt(gameSTYLE.height) * .06) + "px";
blackCircle.style.width = blackCircleSTYLE.height;
blackCircle.style.top = "3%";
blackCircle.style.left = (parseInt(gameSTYLE.width)/2) - (parseInt(blackCircleSTYLE.width)/2) + "px";
} else {
blackCircle.style.width = parseInt(gameSTYLE.width) - (parseInt(gameSTYLE.width) * .06) + "px";
blackCircle.style.height = blackCircle.style.width;
blackCircle.style.left = "3%";
blackCircle.style.top = (parseInt(gameSTYLE.height)/2) - (parseInt(blackCircleSTYLE.height)/2) + "px";
}
centerCircle.style.height = (parseInt(blackCircleSTYLE.height)*.35) + "px";
centerCircle.style.width = (parseInt(blackCircleSTYLE.width)*.35) + "px";
centerCircle.style.top = (parseInt(blackCircleSTYLE.height)/2) - (parseInt(centerCircleSTYLE.height)/2) + "px";
centerCircle.style.left = (parseInt(blackCircleSTYLE.width)/2) - (parseInt(centerCircleSTYLE.width)/2) + "px";
}
var refresh = setInterval(function(){
resizing();
}, .1);
CSS
html {
background: black;
}
body {
width: 100vh;
height: 100vh;
}
#board {
position: absolute;
width: 75%;
height: 85%;
top: 8.5%;
left: 12.5%;
background-color: gray;
}
#scoreboard {
position: absolute;
width: 15%;
height: 17.5%;
top: 5%;
left: 3%;
background-color: lightgray;
text-align: center;
font-size: 150%;
line-height: 150%;
font-weight: bold;
}
#score {
line-height: 0;
font-weight: normal;
}
#start {
position: absolute;
width: 15%;
height: 8%;
top: 27.5%;
left: 3%;
background-color: lightgray;
text-align: center;
font-size: 150%;
line-height: 150%;
font-weight: bold;
}
#start:hover {
background-color: lightgreen;
}
#start:active{
background-color: rgb(98, 161, 98);
}
#reset {
position: absolute;
width: 15%;
height: 8%;
top: 37.5%;
left: 3%;
background-color: lightgray;
text-align: center;
font-size: 150%;
line-height: 150%;
font-weight: bold;
}
#reset:hover {
background-color: lightcoral;
}
#reset:active{
background-color: rgb(202, 99, 99);
}
#rules{
position: absolute;
width: 15%;
height: 45%;
top: 50%;
left: 3%;
background-color: lightgray;
text-align: center;
font-size: 100%;
line-height: 100%;
}
#rulesTitle{
font-size: 125%;
font-weight: bold;
text-decoration: underline;
}
#goodluck{
font-size: 112.5%;
font-weight: bold;
}
#game{
position: absolute;
width: 76%;
height: 90%;
top: 5%;
left: 21%;
background-color: lightgray;
}
#blackCircle {
position: absolute;
border-radius: 50%;
background-color: black;
}
#centerCircle {
position: absolute;
border-radius: 50%;
background-color: gray;
}
#yellow:hover {
fill: darkgoldenrod;
}
#yellow:active {
fill: black;
}
#blue:hover {
fill: darkblue;
}
#blue:active {
fill: black;
}
#green:hover {
fill: darkgreen;
}
#green:active {
fill: black;
}
#red:hover {
fill: darkred;
}
#red:active {
fill: black;
}
>Solution :
Your code that if running then listens for the click event, but you only call play() on start. When the play button clicks, it only set running to true, so if you don’t set running on start, that actually doesn’t listen for buttons click.
Before:
//gamePlay.js
const start = document.getElementById("start");
const reset = document.getElementById("reset");
const yellow = document.getElementById("yellow");
const blue = document.getElementById("blue");
const green = document.getElementById("green");
const red = document.getElementById("red");
var order = [];
var selected = [];
var running;
function play(){
if (running == true){
yellow.addEventListener('click', () => {
console.log("yellow has been clicked");
selected.push("yellow");
});
blue.addEventListener('click', () => {
console.log("blue has been clicked");
selected.push("blue");
});
green.addEventListener('click', () => {
console.log("green has been clicked");
selected.push("green");
});
red.addEventListener('click', () => {
console.log("red has been clicked");
selected.push("red");
});
}
}
start.addEventListener('click', () => {
running = true;
});
reset.addEventListener('click', () => {
running = false;
order = [];
selected = [];
});
play();
///////////////////////////////////////////////////////////////////////////
//sizing.js
const game = document.getElementById("game");
const blackCircle = document.getElementById("blackCircle");
const centerCircle = document.getElementById("centerCircle");
function resizing(){
var gameSTYLE = getComputedStyle(game);
var blackCircleSTYLE = getComputedStyle(blackCircle);
var centerCircleSTYLE = getComputedStyle(centerCircle);
if (gameSTYLE.width > gameSTYLE.height){
blackCircle.style.height = parseInt(gameSTYLE.height) - (parseInt(gameSTYLE.height) * .06) + "px";
blackCircle.style.width = blackCircleSTYLE.height;
blackCircle.style.top = "3%";
blackCircle.style.left = (parseInt(gameSTYLE.width)/2) - (parseInt(blackCircleSTYLE.width)/2) + "px";
} else {
blackCircle.style.width = parseInt(gameSTYLE.width) - (parseInt(gameSTYLE.width) * .06) + "px";
blackCircle.style.height = blackCircle.style.width;
blackCircle.style.left = "3%";
blackCircle.style.top = (parseInt(gameSTYLE.height)/2) - (parseInt(blackCircleSTYLE.height)/2) + "px";
}
centerCircle.style.height = (parseInt(blackCircleSTYLE.height)*.35) + "px";
centerCircle.style.width = (parseInt(blackCircleSTYLE.width)*.35) + "px";
centerCircle.style.top = (parseInt(blackCircleSTYLE.height)/2) - (parseInt(centerCircleSTYLE.height)/2) + "px";
centerCircle.style.left = (parseInt(blackCircleSTYLE.width)/2) - (parseInt(centerCircleSTYLE.width)/2) + "px";
}
var refresh = setInterval(function(){
resizing();
}, .1);
html {
background: black;
}
body {
width: 100vh;
height: 100vh;
}
#board {
position: absolute;
width: 75%;
height: 85%;
top: 8.5%;
left: 12.5%;
background-color: gray;
}
#scoreboard {
position: absolute;
width: 15%;
height: 17.5%;
top: 5%;
left: 3%;
background-color: lightgray;
text-align: center;
font-size: 150%;
line-height: 150%;
font-weight: bold;
}
#score {
line-height: 0;
font-weight: normal;
}
#start {
position: absolute;
width: 15%;
height: 8%;
top: 27.5%;
left: 3%;
background-color: lightgray;
text-align: center;
font-size: 150%;
line-height: 150%;
font-weight: bold;
}
#start:hover {
background-color: lightgreen;
}
#start:active{
background-color: rgb(98, 161, 98);
}
#reset {
position: absolute;
width: 15%;
height: 8%;
top: 37.5%;
left: 3%;
background-color: lightgray;
text-align: center;
font-size: 150%;
line-height: 150%;
font-weight: bold;
}
#reset:hover {
background-color: lightcoral;
}
#reset:active{
background-color: rgb(202, 99, 99);
}
#rules{
position: absolute;
width: 15%;
height: 45%;
top: 50%;
left: 3%;
background-color: lightgray;
text-align: center;
font-size: 100%;
line-height: 100%;
}
#rulesTitle{
font-size: 125%;
font-weight: bold;
text-decoration: underline;
}
#goodluck{
font-size: 112.5%;
font-weight: bold;
}
#game{
position: absolute;
width: 76%;
height: 90%;
top: 5%;
left: 21%;
background-color: lightgray;
}
#blackCircle {
position: absolute;
border-radius: 50%;
background-color: black;
}
#centerCircle {
position: absolute;
border-radius: 50%;
background-color: gray;
}
#yellow:hover {
fill: darkgoldenrod;
}
#yellow:active {
fill: black;
}
#blue:hover {
fill: darkblue;
}
#blue:active {
fill: black;
}
#green:hover {
fill: darkgreen;
}
#green:active {
fill: black;
}
#red:hover {
fill: darkred;
}
#red:active {
fill: black;
}
<!DOCTYPE html>
<html>
<head>
<title>Simon Game</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id="board">
<div id="scoreboard">
Score:
<br>
<p id="score">0</p>
</div>
<button id="start">START</button>
<button id="reset">RESET</button>
<div id="rules">
<p id="rulesTitle">Rules</p>
The rules are simple, memorize the pattern shown and repeat it. Every round, the pattern gets longer. If you mess up even once, the game ends.
<p id="goodluck">Good luck!</p>
</div>
<div id="game">
<div id="blackCircle">
<div id="centerCircle"></div>
<svg width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="none">
<path id="yellow" d="
M 5 47.5
Q 10 10, 47.5 5
v 22.5
Q 30 30, 27.5 47.5
Z
"
stroke="darkgray" fill="yellow"/>
<path id="blue" d="
M 52.5 5
Q 90 10, 95 47.5
h -22.5
Q 70 30, 52.5 27.5
Z
"
stroke="darkgray" fill="blue"/>
<path id="green" d="
M 95 52.5
Q 90 90, 52.5 95
v -22.5
Q 70 70, 72.5 52.5
Z
"
stroke="darkgray" fill="green"/>
<path id="red" d="
M 47.5 95
Q 10 90, 5 52.5
h 22.5
Q 30 70, 47.5 72.5
Z
"
stroke="darkgray" fill="red"/>
</svg>
</div>
</div>
</div>
<script type="text/javascript" src="sizing.js"></script>
<script type="text/javascript" src="gamePlay.js"></script>
</body>
</html>
After:
//gamePlay.js
const start = document.getElementById("start");
const reset = document.getElementById("reset");
const yellow = document.getElementById("yellow");
const blue = document.getElementById("blue");
const green = document.getElementById("green");
const red = document.getElementById("red");
var order = [];
var selected = [];
var running;
function play() {
yellow.addEventListener('click', () => {
if (!running) return;
console.log("yellow has been clicked");
selected.push("yellow");
});
blue.addEventListener('click', () => {
if (!running) return;
console.log("blue has been clicked");
selected.push("blue");
});
green.addEventListener('click', () => {
if (!running) return;
console.log("green has been clicked");
selected.push("green");
});
red.addEventListener('click', () => {
if (!running) return;
console.log("red has been clicked");
selected.push("red");
});
}
start.addEventListener('click', () => {
running = true;
});
reset.addEventListener('click', () => {
running = false;
order = [];
selected = [];
});
play();
///////////////////////////////////////////////////////////////////////////
//sizing.js
const game = document.getElementById("game");
const blackCircle = document.getElementById("blackCircle");
const centerCircle = document.getElementById("centerCircle");
function resizing() {
var gameSTYLE = getComputedStyle(game);
var blackCircleSTYLE = getComputedStyle(blackCircle);
var centerCircleSTYLE = getComputedStyle(centerCircle);
if (gameSTYLE.width > gameSTYLE.height) {
blackCircle.style.height = parseInt(gameSTYLE.height) - (parseInt(gameSTYLE.height) * .06) + "px";
blackCircle.style.width = blackCircleSTYLE.height;
blackCircle.style.top = "3%";
blackCircle.style.left = (parseInt(gameSTYLE.width) / 2) - (parseInt(blackCircleSTYLE.width) / 2) + "px";
} else {
blackCircle.style.width = parseInt(gameSTYLE.width) - (parseInt(gameSTYLE.width) * .06) + "px";
blackCircle.style.height = blackCircle.style.width;
blackCircle.style.left = "3%";
blackCircle.style.top = (parseInt(gameSTYLE.height) / 2) - (parseInt(blackCircleSTYLE.height) / 2) + "px";
}
centerCircle.style.height = (parseInt(blackCircleSTYLE.height) * .35) + "px";
centerCircle.style.width = (parseInt(blackCircleSTYLE.width) * .35) + "px";
centerCircle.style.top = (parseInt(blackCircleSTYLE.height) / 2) - (parseInt(centerCircleSTYLE.height) / 2) + "px";
centerCircle.style.left = (parseInt(blackCircleSTYLE.width) / 2) - (parseInt(centerCircleSTYLE.width) / 2) + "px";
}
var refresh = setInterval(function() {
resizing();
}, .1);
html {
background: black;
}
body {
width: 100vh;
height: 100vh;
}
#board {
position: absolute;
width: 75%;
height: 85%;
top: 8.5%;
left: 12.5%;
background-color: gray;
}
#scoreboard {
position: absolute;
width: 15%;
height: 17.5%;
top: 5%;
left: 3%;
background-color: lightgray;
text-align: center;
font-size: 150%;
line-height: 150%;
font-weight: bold;
}
#score {
line-height: 0;
font-weight: normal;
}
#start {
position: absolute;
width: 15%;
height: 8%;
top: 27.5%;
left: 3%;
background-color: lightgray;
text-align: center;
font-size: 150%;
line-height: 150%;
font-weight: bold;
}
#start:hover {
background-color: lightgreen;
}
#start:active{
background-color: rgb(98, 161, 98);
}
#reset {
position: absolute;
width: 15%;
height: 8%;
top: 37.5%;
left: 3%;
background-color: lightgray;
text-align: center;
font-size: 150%;
line-height: 150%;
font-weight: bold;
}
#reset:hover {
background-color: lightcoral;
}
#reset:active{
background-color: rgb(202, 99, 99);
}
#rules{
position: absolute;
width: 15%;
height: 45%;
top: 50%;
left: 3%;
background-color: lightgray;
text-align: center;
font-size: 100%;
line-height: 100%;
}
#rulesTitle{
font-size: 125%;
font-weight: bold;
text-decoration: underline;
}
#goodluck{
font-size: 112.5%;
font-weight: bold;
}
#game{
position: absolute;
width: 76%;
height: 90%;
top: 5%;
left: 21%;
background-color: lightgray;
}
#blackCircle {
position: absolute;
border-radius: 50%;
background-color: black;
}
#centerCircle {
position: absolute;
border-radius: 50%;
background-color: gray;
}
#yellow:hover {
fill: darkgoldenrod;
}
#yellow:active {
fill: black;
}
#blue:hover {
fill: darkblue;
}
#blue:active {
fill: black;
}
#green:hover {
fill: darkgreen;
}
#green:active {
fill: black;
}
#red:hover {
fill: darkred;
}
#red:active {
fill: black;
}
<!DOCTYPE html>
<html>
<head>
<title>Simon Game</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id="board">
<div id="scoreboard">
Score:
<br>
<p id="score">0</p>
</div>
<button id="start">START</button>
<button id="reset">RESET</button>
<div id="rules">
<p id="rulesTitle">Rules</p>
The rules are simple, memorize the pattern shown and repeat it. Every round, the pattern gets longer. If you mess up even once, the game ends.
<p id="goodluck">Good luck!</p>
</div>
<div id="game">
<div id="blackCircle">
<div id="centerCircle"></div>
<svg width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="none">
<path id="yellow" d="
M 5 47.5
Q 10 10, 47.5 5
v 22.5
Q 30 30, 27.5 47.5
Z
"
stroke="darkgray" fill="yellow"/>
<path id="blue" d="
M 52.5 5
Q 90 10, 95 47.5
h -22.5
Q 70 30, 52.5 27.5
Z
"
stroke="darkgray" fill="blue"/>
<path id="green" d="
M 95 52.5
Q 90 90, 52.5 95
v -22.5
Q 70 70, 72.5 52.5
Z
"
stroke="darkgray" fill="green"/>
<path id="red" d="
M 47.5 95
Q 10 90, 5 52.5
h 22.5
Q 30 70, 47.5 72.5
Z
"
stroke="darkgray" fill="red"/>
</svg>
</div>
</div>
</div>
<script type="text/javascript" src="sizing.js"></script>
<script type="text/javascript" src="gamePlay.js"></script>
</body>
</html>
Another thing:
I think there’s some way to optimize your code, but this isn’t the problem of this question.