I programmed a web adaption of the game Simon for to improving my JavaScript skills. A live version of the results are here.
I got two more ideas which I like to incorporate. Moreover, I'd like to improve the look. But before I go on I would like to make some improvements. I guess there are a few necessary.
function SimonSays( timeLapse,
elements,
cssClass,
messageBoard,
display,
breakTime,
board) {
var order = [];
if (!Array.isArray(elements)) {
// Change nodeList into an real array.
elements = Array.prototype.slice.apply(elements);
}
// Every round the count
// of the moves is incremented.
var moves = (function() {
var moves = 1;
return function() {
return moves++;
}
})();
var getRounds = (function() {
var rounds = 1;
return function() {
return rounds++;
}
})();
var incrementDisplay = function() {
var tmp = '000' + getRounds();
display.innerHTML = tmp.slice(-3);
}
var reactToMove = function() {
this.classList.add(cssClass);
var that = this;
setTimeout(function() {
that.classList.remove(cssClass);
}, timeLapse);
var currentFirst = elements[order.shift()].id;
if (currentFirst !== this.id) {
SimonSays.prototype.toggleReact();
messageBoard.style['display'] = 'block';
} else if (!order.length) {
setTimeout(SimonSays.prototype.setUpRound, breakTime);
}
}
SimonSays.prototype.toggleReact = function(direction) {
elements.forEach(function(element) {
direction === true ?
element.addEventListener('click', reactToMove) :
element.removeEventListener('click', reactToMove);
});
}
SimonSays.prototype.setUpRound = function() {
var limit = moves();
order.length = 0;
// Update GUI-counter.
incrementDisplay();
// Put random numbers into an array. =>
// Order of blicking buttons.
for (var i = 0; i < limit; i++) {
order.push(Math.floor(Math.random() * 4));
}
// Prevent click on the game-board.
document.body.style['pointer-events'] = 'none';
var times;
order.forEach(function(number, i) {
var tmp = number;
var step = 2 * +i;
times = i;
setTimeout(function() {
elements[tmp].classList.add(cssClass);
}, timeLapse * step)
setTimeout(function() {
elements[tmp].classList.remove(cssClass);
}, timeLapse * (step + 1) );
});
// Re-enable clicking on the game-board.
setTimeout(function() {
document.body.style['pointer-events'] = 'auto';
}, (timeLapse * times) + timeLapse);
}
}
window.addEventListener('load', function() {
var buttons
= document.querySelectorAll('.play-button');
var start
= document.querySelector('#start-game');
var reset
= document.querySelector('#reset-game');
var display
= document.querySelector('#rounds-display');
var gameOverMessage
= document.querySelector('#game-over');
var board
= document.querySelector('#board');
var game = new SimonSays( 500,
buttons,
'active-button',
gameOverMessage,
display,
2000,
board );
reset.addEventListener('click', function() {
location.reload(true);
});
start.addEventListener('click', function() {
game.setUpRound();
start.setAttribute('disabled', 'disabled');
document.body.style['cursor'] = 'pointer';
game.toggleReact(true);
});
})
html {
color: #222;
font-size: 1em;
line-height: 1.4;
background-color: rgba(230, 230, 230, 1.0);
}
#wrap {
width: 1000px;
margin: 50px auto;
}
.label-element-group {
display: flex;
align-items: center;
width: 160px;
justify-content: space-around;
}
.display {
height: 24px;
width: 75px;
background-color: rgba(150, 150, 150, 1.0);
border-radius: 12px;
border: 1px solid rgba(200, 200, 200, 0.1);
box-shadow: inset 3px 3px 1px rgba(100, 100, 100, 0.9);
font-size: 1.2em;
text-align: center;
color: rgba(240, 240, 240, 1.0);
display: inline-block;
}
nav {
display: flex;
width: 420px;
height: 50px;
justify-content: space-around;
align-items: center;
margin: 0 auto 15px;
}
nav button {
font-size: 1em;
border-radius: 16px;
}
#board {
width: 420px;
height: 420px;
margin: 0 auto;
display: flex;
background-color: rgba(100, 100, 100, 0.6);
flex-direction: row;
flex-wrap: wrap;
align-items: center;
justify-content: space-around;
border-radius: 16px;
border: 2px solid black;
position: relative;
}
.message {
width: 320px;
height: 80px;
background-color: rgba(100, 100, 100, 1.0);
color: rgba(240, 240, 240, 1.0);
text-align: center;
font-size: 3em;
line-height: 80px;
border-radius: 16px;
position: absolute;
top: 140px;
left: 55px;
border: 3px solid rgba(240, 240, 240, 1.0);
transform: rotate(-7deg);
box-shadow: 8px 8px 16px rgba(15, 15, 15, 1.0);
display: none;
}
.play-button {
width: 200px;
height: 200px;
border: 2px solid black;
}
#green {
background-color: rgba(0, 240, 0, 0.5);
border-top-left-radius: 100%;
}
#red {
background-color: rgba(240, 0, 0, 0.5);
border-top-right-radius: 100%;
}
#blue {
background-color: rgba(0, 0, 240, 0.6);
border-bottom-right-radius: 100%;
}
#yellow {
background-color: rgba(240, 240, 0, 0.5);
border-bottom-left-radius: 100%;
}
.active-button {
background-color: rgba(250, 250, 250, 1.0) !important;
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>SimonSays</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div id="wrap">
<nav>
<button id="start-game">Start</button>
<div class="label-element-group">
<label for="rounds-display">Round: </label>
<div class="display" id="rounds-display"></div>
</div>
<button id="reset-game">New game</button>
</nav>
<div id="board">
<div id="green" class="play-button"></div>
<div id="red" class="play-button"></div>
<div id="yellow" class="play-button"></div>
<div id="blue" class="play-button"></div>
<div class="message" id="game-over"
title="Hit <New game> to start a new game!">
GAME OVER
</div>
</div>
</div>
</body>
</html>