I am working on an HTML5 game of memory called SIMON in which there is a board with 4 colored pads (green, red, yellow and blue), an ignition switch and 2 buttons to play in different modes.
The user must click on the number of pads that are indicated according to the round and in the correct order, if not, the round must be repeated. I have not finished the JS section yet.
My question is this: I have written a function that illuminates and reproduces the corresponding pad and verifies the click, but only for the first round. I'm confused about how to do it for the next rounds (10 or 15 rounds maximum) where the function runs several times and there must be a delay / wait for the user to click.
I've been in this for a couple of months, but I have not been able to capture it. Should I use recursive functions to define the main function of the game? Store the clicks in an array / object? Do several small functions as modules to call later and simplify the code?
This is my code (also available at CodePen ):
$(document).ready(function() {
var randColors = [];
var player = [];
var normalClicks = [];
//This variable will be used to check
//if the game is powered on or off
var powerCheck = 0;
// This objects are going to be useful
// to identify and shorten many things.
var greenPad = {
color: "green",
gradColor: "green-grad",
audio: document.getElementById("audio1"),
item: "greenCanvas"
},
redPad = {
color: "red",
gradColor: "red-grad",
audio: document.getElementById("audio2"),
item: "redCanvas"
},
yellowPad = {
color: "yellow",
gradColor: "yellow-grad",
audio: document.getElementById("audio3"),
item: "yellowCanvas"
},
bluePad = {
color: "blue",
gradColor: "blue-grad",
audio: document.getElementById("audio4"),
item: "blueCanvas"
};
// Illuminate and play a pad's sound
function illuminate (col) {
if (col === "green") {
console.log("color was green");
greenPad.audio.play();
$("#green").addClass("green-grad");
setTimeout(function() {
$("#green").removeClass("green-grad");
}, 500);
}
if (col === "blue") {
console.log("color was blue");
bluePad.audio.play();
$("#blue").addClass("blue-grad");
setTimeout(function() {
$("#blue").removeClass("blue-grad");
}, 500);
}
if (col === "red") {
console.log("color was red");
redPad.audio.play();
$("#red").addClass("red-grad");
setTimeout(function() {
$("#red").removeClass("red-grad");
}, 500);
}
if (col === "yellow") {
console.log("color was yellow");
yellowPad.audio.play();
$("#yellow").addClass("yellow-grad");
setTimeout(function() {
$("#yellow").removeClass("yellow-grad");
}, 500);
}
}
$( ".onoffswitch-label" ).click( function() {
powerCheck = powerCheck + 1;
console.log( "powerCheck = " + powerCheck );
// If powerCheck is an odd number, it means
// that the game has been powered on,
// and now the user can start playing.
if ( powerCheck % 2 === 0 ) {
console.log( "Turned Off" );
randColors = [];
$( ".count" ).removeClass( "led-on" );
//Add "disabled" status to normal
//mode (Play) and strict mode buttons again.
$( ".btn" ).addClass( "disabled" );
//$(".btn").prop( "disabled", true );
$( "canvas" ).prop( "disabled", true );
//$("canvas").addClass("disabled");
//Reset counter to "00"
$( "#counter" ).text( "00" );
} else {
//The game has been turned on
console.log( "Turned On" );
randColors = [];
// Generate random color secuence
function randomColorsGenerator() {
while ( randColors.length < 10 ) {
if ( Math.random() * 4 < 1 ) {
randColors.push( "red" );
} else
if ( Math.random() * 4 >= 1 && Math.random() * 4 < 2 ) {
randColors.push( "blue" );
} else
if ( Math.random() * 4 >= 2 && Math.random() * 4 < 3 ) {
randColors.push( "yellow" );
} else {
randColors.push( "green" );
}
}
console.log( "Actual color sequence is (" + randColors + ")" );
}
//Change color of led display numbers
$( ".count" ).addClass( "led-on" );
//Remove "disabled" status from normal
//mode (Play) and strict mode buttons
$( ".btn" ).removeClass( "disabled" );
//document.getElementByClassName(".btn").disabled = false;
//document.getElementsByName("canvas").disabled = false;
//POST (Power On Sound Test)
//This is optional.
function post() {
greenPad.audio.play();
$( "#green" ).addClass( "green-grad" );
setTimeout(function() {
$( "#green" ).removeClass( "green-grad" );
$( "#red" ).addClass( "red-grad" );
redPad.audio.play();
setTimeout( function() {
$( "#red" ).removeClass( "red-grad" );
$( "#blue" ).addClass( "blue-grad" );
bluePad.audio.play();
setTimeout( function() {
$( "#blue" ).removeClass( "blue-grad" );
$( "#yellow" ).addClass( "yellow-grad" );
yellowPad.audio.play();
setTimeout( function() {
$( "#yellow" ).removeClass( "yellow-grad" );
}, 300);
}, 300);
}, 300);
}, 300);
}
// Execute the POST function
post();
//End of test
//Press Play to begin
$( ".btn-success" ).click( function() {
// But begin only if the game is powered on
if ( powerCheck % 2 === 0 ) {
console.log( "The game is powered off" );
alert( "To start your game you have to first turn it on " );
} else {
// If the game is powered on,
// Normal Mode begins
console.log( "Simon has started in Normal Mode" );
// Reset counter to "00"
$( "#counter" ).text(0);
// Generate a new random array of colors
randomColorsGenerator();
// Increment display number by 1
function incrDisplay() {
var x = $( "#counter" ).text();
$("#counter").text( Number(x) + 1 );
}
incrDisplay();
// This function defines Normal Mode gameplay
function normal() {
// Temporary commented
/*
for ( var i=0; i<randColors.length; i++ ) {
illuminate( randColors[i] );
$( "canvas" ).click(function(event) {
console.log(event.target.id + " was clicked.");
if ( event.target.id === randColors[i] ) {
console.log( "You did great" );
incrDisplay();
} else {
console.log( "Ups! Try Again" );
// at this point, the display won't increment by 1
//
}
});
}
*/
}
normal();
// Illuminate 1st element
illuminate(randColors[0]);
// Log 1st click
$( "canvas" ).click( function(event) {
console.log(event.target.id + " was clicked.")
// If the click is the expected color
if (event.target.id === randColors[0]) {
// Output message
console.log("You did great");
// and go to next step
incrDisplay();
illuminate(randColors[0]);
setTimeout (function() {
illuminate(randColors[1]);
}, 300)
// In case of a mistake, repeat last step
} else {
console.log("Ups! Try Again");
}
});
}
});
//Or Play in Strict Mode
$(".btn-danger").click(function() {
console.log("Simon has started in Strict Mode");
});
}
});
});
/*Generic CSS (Aplies to all devices)*/
@import 'https://fonts.googleapis.com/css?family=Alfa+Slab+One|Black+Ops+One';
body {
/*
CSS3 Patterns Gallery. (Carbon)
by Atle Mo (design), Sébastien Grosjean (code)
*/
background: linear-gradient(27deg, #151515 5px, transparent 5px) 0 5px, linear-gradient(207deg, #151515 5px, transparent 5px) 10px 0, linear-gradient(27deg, #222 5px, transparent 5px) 0 10px, linear-gradient(207deg, #222 5px, transparent 5px) 10px 5px, linear-gradient(90deg, #1b1b1b 10px, transparent 10px), linear-gradient(#1d1d1d 36%, #1a1a1a 25%, #1a1a1a 50%, transparent 50%, transparent 75%, #242424 75%, #242424);
background-color: #131313;
background-size: 20px 20px;
}
.inline {
display: inline-block;
}
/*Wrapper*/
#frame {
background-color: #333333;
height:414px;
width: 414px;
margin: -207px 0 0 -207px;
position: absolute;
top: 50%;
left: 50%;
padding: 5px;
border-radius: 50%;
}
/*End*/
#controls {
width: 250px;
height: 250px;
position: absolute;
margin: -125px 0 0 -125px;
top: 50%; left:50%;
border: 4px solid #333333;
border-radius: 50%;
background: white;
text-align: center;
}
/*Simon title inside white circle*/
.brand {
font-family: 'Alfa Slab One', cursive;
color: #222;
font-size: 4rem;
margin-top: 15%;
text-align: center;
}
/*End*/
/* Display/Counter */
.display {
width: 70px;
position: relative;
margin: 7px 15px;
text-align: center;
}
.count {
height: 60px;
font-family: 'Black Ops One', monospace;
color: #DC0D29;
padding-top: 10px;
background-color: #32050C;
position: relative;
border: 4px solid #222;
border-radius: 10px;
margin: 0 auto;
}
.led-off {
font-size:3rem;
color: #430710;
vertical-align: middle;
}
.led-on {
font-size:3rem;
color: #ff0000;
vertical-align: middle;
}
.label {
color: #222;
font-family: 'Oswald', Arial, sans;
font-size: 0.7em;
margin-top: 5px;
text-align: center;
}
.full-red {
background-color: #FC0102;
}
.clickable {
pointer-events: auto;
cursor: pointer;
}
.led {
width: 6px;
height: 6px;
background-color: #32050C;
border-radius: 100%;
position: absolute;
left: 0;
right: 0;
margin: auto;
border: 2px solid #222;
top: -18px;
}
.sw-slot {
height: 20px;
width: 40px;
background-color: #222;
position: relative;
top: 5px;
border-radius: 2px;
cursor: pointer;
}
/*End*/
/*Giving buttons a rounded shape*/
.btn {
border-radius: 40%;
}
/* Power On/Off switch*/
/*Inspiration thanks to: proto.io/freebies/onoff/*/
.onoffswitch {
position: relative;
width: 70px;
user-select:none;
margin: 30px auto;
}
.onoffswitch-checkbox {
display: none;
}
.onoffswitch-label {
display: block;
overflow: hidden;
cursor: pointer;
border: 2px solid #999999;
border-radius: 20px;
}
.onoffswitch-inner {
display: block;
width: 200%;
margin-left: -100%;
transition: margin 0.3s ease-in 0s;
}
.onoffswitch-inner:before, .onoffswitch-inner:after {
display: block;
float: left;
width: 50%;
height: 25px;
padding: 0;
line-height: 25px;
font-size: 12px;
color: white;
font-family: Trebuchet, Arial, sans-serif;
font-weight: bold;
box-sizing: border-box;
}
.onoffswitch-inner:before {
content: "ON";
padding-left: 15px;
background-color: #34A7C1;
color: #FFFFFF;
text-align: left;
}
.onoffswitch-inner:after {
content: "OFF";
padding-right: 10px;
background-color: #EEEEEE;
color: #999999;
text-align: right;
}
.onoffswitch-switch {
display: block;
width: 30px;
margin: -2.5px;
background: #FFFFFF;
position: absolute;
top: 0;
bottom: 0;
right: 41px;
border: 2px solid #999999;
border-radius: 20px;
transition: all 0.3s ease-in 0s;
}
.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-inner {
margin-left: 0;
}
.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-switch {
right: 0px;
}
/*End of Power On/Off Switch*/
/*Canvas color and shape*/
canvas {
width: 200px;
height:200px;
}
#green {
background-color: #27ae60;
border-top-left-radius: 100%
}
.green-grad {
background: radial-gradient(circle, white, #27ae60);
border-top-left-radius: 100%
}
#red {
background-color: #e74c3c;
border-top-right-radius: 100%;
}
.red-grad {
background: radial-gradient(circle, white, #e74c3c);
border-top-right-radius: 100%;
}
#yellow {
background-color: #f1c40f;
border-bottom-left-radius: 100%;
}
.yellow-grad {
background: radial-gradient(circle, white, #f1c40f);
border-bottom-left-radius: 100%;
}
#blue {
background-color: #3498db;
border-bottom-right-radius: 100%;
}
.blue-grad {
background: radial-gradient(circle, white, #3498db);
border-bottom-right-radius: 100%;
}
/* End */
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div id="frame">
<div id="4canvas">
<div id="controls">
<h1 class="brand">Simon<sup>®</sup></h1>
<div>
<!-- Start Button (Bootstrap) -->
<button type="submit" class="btn btn-success btn-lg disabled" data-toggle="button" aria-pressed="false" autocomplete="off">
<span class="glyphicon glyphicon-play"></span>
</button>
<!-- End -->
<!-- LCD Display -->
<div class="display inline">
<h1 id="counter" class="count led-off">00</h1>
</div>
<!-- End -->
<!-- Strict Mode Button (Bootstrap) -->
<button type="submit" class="btn btn-danger btn-lg disabled" data-toggle="button" aria-pressed="false" autocomplete="off">
<span class="glyphicon glyphicon-flash"></span>
</button>
<!--End of Strict Mode Button-->
</div>
<!-- Rounded On/Off switch -->
<div class="onoffswitch" id="onoff">
<input type="checkbox" name="onoffswitch" class="onoffswitch-checkbox" id="myonoffswitch">
<label class="onoffswitch-label" for="myonoffswitch">
<span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span>
</label>
</div>
</div>
<div>
<canvas id="green">
<audio id="audio1" src="https://s3.amazonaws.com/freecodecamp/simonSound1.mp3"></audio>
</canvas>
<canvas id="red">
<audio id="audio2" src="https://s3.amazonaws.com/freecodecamp/simonSound2.mp3"></audio>
</canvas>
</div>
<div>
<canvas id="yellow">
<audio id="audio3" src="https://s3.amazonaws.com/freecodecamp/simonSound3.mp3"></audio>
</canvas>
<canvas id="blue">
<audio id="audio4" src="https://s3.amazonaws.com/freecodecamp/simonSound4.mp3"></audio>
</canvas>
</div>
</div>
</div>