Simon Game

In this example below you will see how to do a Simon Game with some HTML / CSS and Javascript

FreeCodeCamp Simon Game

Thumbnail
This awesome code was written by afaisalsahar, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright afaisalsahar ©

Technologies

  • HTML
  • CSS
  • JavaScript
<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>Simon Game</title>
  <link href="https://fonts.googleapis.com/css?family=Alegreya+Sans+SC:400,700" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,900" rel="stylesheet">

  
  
      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>

  <div class="container">
    <h1 class="title">simon</h1>
    <div class="simon-app">
        <div class="results">
            <div id="error" class="error"><span class="icon"></span></div>
            <div id="success" class="success"><span class="icon"></span></div>
        </div>
        <div class="io">
            <div id="rounds" class="rounds">Round:00</div>
            <div class="buttons">
                <div id="start" class="button"><span class="label">Start<span></div>
                <div id="reset" class="button"><span class="label">Reset<span></div>
                <div id="strict" class="button"><span class="label">Strict<span></div>
            </div>
        </div>
        <div class="tones">
            <span data-wave="sine" data-color="G"class="light light-1"></span>
            <span data-wave="square" data-color="B"class="light light-2"></span>
            <span data-wave="triangle" data-color="R"class="light light-3"></span>
            <span data-wave="sawtooth" data-color="O"class="light light-4"></span>
        </div>
    </div>
    <div class="footer">
        <span class="icon">
            <svg width="14px" height="16px" viewBox="0 0 14 16" version="1.1" aria-hidden="true">
                <path fill-rule="evenodd" d="M9.5,3 L8,4.5 L11.5,8 L8,11.5 L9.5,13 L14,8 L9.5,3 L9.5,3 Z M4.5,3 L0,8 L4.5,13 L6,11.5 L2.5,8 L6,4.5 L4.5,3 L4.5,3 Z"></path>
            </svg>
        </span>
        with
        <span class="icon heart">
            <svg width="12px" height="16px" viewBox="0 0 12 16" version="1.1">
                <path fill-rule="evenodd" d="M11.2,3 C10.68,2.37 9.95,2.05 9,2 C8.03,2 7.31,2.42 6.8,3 C6.29,3.58 6.02,3.92 6,4 C5.98,3.92 5.72,3.58 5.2,3 C4.68,2.42 4.03,2 3,2 C2.05,2.05 1.31,2.38 0.8,3 C0.28,3.61 0.02,4.28 0,5 C0,5.52 0.09,6.52 0.67,7.67 C1.25,8.82 3.01,10.61 6,13 C8.98,10.61 10.77,8.83 11.34,7.67 C11.91,6.51 12,5.5 12,5 C11.98,4.28 11.72,3.61 11.2,2.98 L11.2,3 Z"></path>
            </svg>
        </span>
        by <a href="https://twitter.com/afaisalsahar" target="_blank">Fay</a>
    </div>
</div>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>

  

    <script  src="js/index.js"></script>




</body>

</html>

/*Downloaded from https://www.codeseek.co/afaisalsahar/simon-game-opBrKX */
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
html, body, .container{
    width: 100%;
    height: 100%;
}
body {
    font: 100%/1.5 'Alegreya Sans SC', sans-serif;
    color: #818486;
}
.container {
    display: flex;
    flex-flow: column nowrap;
    justify-content: center;
    align-items: center;
    /*background: #EEE;*/
    background: #26212f;
}
.simon-app {
    width: 95%;
    max-width: 350px;
    /*height: 350px;*/
    /*box-shadow: 0 0 5px rgba(0,0,0,.2);*/
}
.io {
    box-sizing: content-box;
    padding: 2em 0;
    display: flex;
    flex-flow: column nowrap;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 80%;
    background: #F9F9F9;
    text-align: center;
}
.rounds {
    font-size: 1.7em;
    font-weight: 700;
    margin-bottom: 1em;
}
.buttons {
    flex: 0 0 180px;
    width: 245px;
    position: relative;
}
.button {
    cursor: pointer;
    display: flex;
    flex-flow: row nowrap;
    justify-content: center;
    align-items: center;
    box-sizing: content-box;
    width: 60px;
    height: 60px;
    position: absolute;
    top: 0;
    border: 20px solid #56bbb6;
    transform: rotateZ(-45deg);
    transition: all .3s;
}
.button:hover {
    color: #333;
}
.button.active {
    background: #56bbb6;
    color: #F9F9F9;
}

.button .label {
    transform: rotate(45deg);
}
#start, #strict {
    left: 0;
    border-radius: 50px 50px 0;
}
#reset {
    right: 0;
    border-radius: 0 50px 50px;
}
#strict {
    transform: rotateZ(-134deg);
    top: 75px;
    left: 72px;
}
#strict .label {
    transform: rotateZ(134deg);
}

.tones {
    display: flex;
    height: 20%;
}
.light {
    cursor: pointer;
    flex: 0 0 25%;
    height: 100%;
    min-height: 70px;
    transition: background .3s;
}
.light-1 {
    background: rgba(26, 187, 156, .5);
}
.light-1.active {
    background: rgba(26, 187, 156, 1);
}

.light-2 {
    background: rgba(1, 151, 218, .5);
}
.light-2.active {
    background: rgba(1, 151, 218, 1);
}

.light-3 {
    background: rgba(236, 85, 85, .5);
}
.light-3.active {
    background: rgba(236, 85, 85, 1);
}

.light-4 {
    background: rgba(249, 182, 73, .5);
}
.light-4.active {
    background: rgba(249, 182, 73, 1);
}

.simon-app {
    position: relative;
}
.results {
    display: flex;
    justify-content: center;
    align-items: center;
    position: absolute;
    height: 100%;
    width: 100%;
    z-index: 2;
    background: #818486;
}
.results.error {background: #ec5657;}
.results.success {background: #1abc9c;}

.results, .error, .success {display: none;}

.error .icon {
    display: block;
    -webkit-box-sizing: content-box;
    -moz-box-sizing: content-box;
    box-sizing: content-box;
    float: none;
    z-index: auto;
    width: 0.75em;
    height: 0.75em;
    position: relative;
    cursor: default;
    opacity: 1;
    margin: 0;
    padding: 0;
    overflow: visible;
    border: 0.15em solid #F9F9F9;
    -webkit-border-radius: 1em;
    border-radius: 1em;
    font: normal 8em/normal Arial, Helvetica, sans-serif;
    color: rgba(0,0,0,1);
    -o-text-overflow: clip;
    text-overflow: clip;
    background: none;
    -webkit-box-shadow: none;
    box-shadow: none;
    text-shadow: none;
    -webkit-transition: none;
    -moz-transition: none;
    -o-transition: none;
    transition: none;
    -webkit-transform: none;
    transform: none;
    -webkit-transform-origin: 50% 50% 0;
    transform-origin: 50% 50% 0;
}
.error .icon:after{
    display: inline-block;
    -webkit-box-sizing: content-box;
    -moz-box-sizing: content-box;
    box-sizing: content-box;
    float: none;
    z-index: auto;
    width: 0.85em;
    height: 0.15em;
    position: absolute;
    content: "";
    cursor: default;
    opacity: 1;
    top: 0.3em;
    left: -0.05em;
    margin: 0;
    padding: 0;
    overflow: visible;
    border: none;
    -webkit-border-radius: 0;
    border-radius: 0;
    font: normal 100%/normal Arial, Helvetica, sans-serif;
    color: rgba(0,0,0,1);
    -o-text-overflow: clip;
    text-overflow: clip;
    background: #F9F9F9;
    -webkit-box-shadow: none;
    box-shadow: none;
    text-shadow: none;
    -webkit-transition: none;
    -moz-transition: none;
    -o-transition: none;
    transition: none;
    -webkit-transform: rotateZ(-45deg)   ;
    transform: rotateZ(-45deg)   ;
    -webkit-transform-origin: 50% 50% 0;
    transform-origin: 50% 50% 0;
}

.success .icon {
    display: block;
    -webkit-box-sizing: content-box;
    -moz-box-sizing: content-box;
    box-sizing: content-box;
    float: none;
    z-index: auto;
    width: 135px;
    height: 135px;
    position: relative;
    cursor: default;
    opacity: 1;
    margin: 0;
    padding: 0;
    overflow: visible;
    border: none;
    -webkit-border-radius: 0;
    border-radius: 0;
    font: normal 100%/normal Arial, Helvetica, sans-serif;
    color: rgba(0,0,0,1);
    -o-text-overflow: clip;
    text-overflow: clip;
    background: none;
    -webkit-box-shadow: none;
    box-shadow: none;
    text-shadow: none;
    -webkit-transition: none;
    -moz-transition: none;
    -o-transition: none;
    transition: none;
    -webkit-transform: none;
    transform: none;
    -webkit-transform-origin: 50% 50% 0;
    transform-origin: 50% 50% 0;
}
.success .icon:before {
    display: block;
    -webkit-box-sizing: content-box;
    -moz-box-sizing: content-box;
    box-sizing: content-box;
    float: none;
    z-index: auto;
    width: 70px;
    height: 125px;
    position: absolute;
    content: "";
    cursor: default;
    opacity: 1;
    top: 0;
    left: 70px;
    margin: 0;
    padding: 0;
    overflow: visible;
    border: none;
    -webkit-border-radius: 50px 50px 0 0;
    border-radius: 50px 50px 0 0;
    font: normal 100%/normal Arial, Helvetica, sans-serif;
    color: rgba(0,0,0,1);
    -o-text-overflow: clip;
    text-overflow: clip;
    background: #F9F9F9;
    -webkit-box-shadow: none;
    box-shadow: none;
    text-shadow: none;
    -webkit-transition: none;
    -moz-transition: none;
    -o-transition: none;
    transition: none;
    -webkit-transform: rotateZ(-45deg)   ;
    transform: rotateZ(-45deg)   ;
    -webkit-transform-origin: 0 100% 0;
    transform-origin: 0 100% 0;
}
.success .icon:after {
    display: block;
    -webkit-box-sizing: content-box;
    -moz-box-sizing: content-box;
    box-sizing: content-box;
    float: none;
    z-index: auto;
    width: 70px;
    height: 125px;
    position: absolute;
    content: "";
    cursor: default;
    opacity: 1;
    top: 0;
    left: 0;
    margin: 0;
    padding: 0;
    overflow: visible;
    border: none;
    -webkit-border-radius: 50px 50px 0 0;
    border-radius: 50px 50px 0 0;
    font: normal 100%/normal Arial, Helvetica, sans-serif;
    color: rgba(0,0,0,1);
    -o-text-overflow: clip;
    text-overflow: clip;
    background: #F9F9F9;
    -webkit-box-shadow: none;
    box-shadow: none;
    text-shadow: none;
    -webkit-transition: none;
    -moz-transition: none;
    -o-transition: none;
    transition: none;
    -webkit-transform: rotateZ(45deg)   ;
    transform: rotateZ(45deg)   ;
    -webkit-transform-origin: 100% 100% 0;
    transform-origin: 100% 100% 0;
}


.title {
    color: #F9F9F9;
    font-family: 'Montserrat', sans-serif;
    text-transform: uppercase;
    font-size: 4em;
    font-weight: 900;
    background-image: -webkit-linear-gradient(45deg,#1abc9c,#0197da);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    -webkit-animation: hue 20s infinite linear;
}
@-webkit-keyframes hue {
  from {
    -webkit-filter: hue-rotate(0deg);
  }

  to {
    -webkit-filter: hue-rotate(-360deg);
  }
}

.footer {
    font-family: 'Montserrat', sans-serif;
    color: #F9F9F9;
    margin-top: 3em;
    text-align: center;
}
a {
    text-decoration: none;
}
.footer a {
    color: #56bbb6;
}
.footer span {
    display: inline-block;
    margin-top: 5px;
    vertical-align: middle;
    fill: #56bbb6;
}
.footer span.heart {
    fill: #ec5657;
}

/*Downloaded from https://www.codeseek.co/afaisalsahar/simon-game-opBrKX */
var colors = ["G", "B", "R", "O"], simonSounds = [], playerSounds = [];
var rounds = 0, strictMode = false, gameStart = false, playersTurn = false, nextRound = false, patternError = false, playerclick = false;

var audioC = new (window.AudioContext || window.webkitAutioContext)(), audioO, audioG, audioTada = "";

function randomColor() { return colors[Math.floor(Math.random() * 4)]; }

function check(color) {
    if(color == simonSounds[playerSounds.length]) {
        playerSounds.push(color);
        if(playerSounds.length == simonSounds.length && color == simonSounds[simonSounds.length-1]) {
            if(rounds == 20) return {status: true, lastmatch: true, win: true};
            else return {status: true, lastmatch: true, win: false};
        } else {
            return {status: true, lastmatch: false, win: false};
        }
    }
    return false;
}

function error() {
    patternError = true; playersTurn = false;
    loadSound("square", 2500);
    audioG.gain.setValueAtTime(0.5, audioC.currentTime);
    audioO.start();
    results(1, "error");

    if(strictMode) {
        setTimeout(function() {
            results(0, "error");
        }, 800);
        setTimeout(stopSound, 810);
        setTimeout(resetGame, 820);
    } else {
        setTimeout(function() {
            results(0, "error");
        }, 800);
        setTimeout(stopSound, 810);
        setTimeout(function() {
            simonSpeaks(false);
        }, 820);
    }
}

function success() {
    stopSound();
    audioTada[0].play();
    results(1, "success");
    setTimeout(function() {
        results(0, "success");
    }, 2000);
    setTimeout(function() {
        resetGame(true);
    }, 2200);
}

function results(mode, status) {
    if(mode) {
        $(".results").addClass(status).fadeIn(200, function() {
        	$("#"+status).fadeIn(200);
        }).css("display", "flex");

        return;
    }

    $("#"+status).fadeOut(200, function() {
        $(".results").removeClass(status).fadeOut(200);
    });
}

function lights(mode, light) {
    // mode = 0 (turn off), 1 (turn on);
    var lights = $(".light");
    for (var i = 0; i < lights.length; i++) {$(lights[i]).removeClass("active");}

    if(mode == 1) $(lights[light]).addClass("active");
}

function showRounds(increment) {$("#rounds").html((++rounds < 10) ? "Round: 0"+rounds : "Round: "+rounds);}

function loadSound(oType, freq) {
    audioO = audioC.createOscillator();
    audioO.type = oType;
    audioO.frequency.value = freq;
    audioG = audioC.createGain();

    audioO.connect(audioG);
    audioG.connect(audioC.destination);
}

function playSound(index, wave, freq) {
    loadSound(wave, freq);
    lights(1, index);
    audioG.gain.setValueAtTime(0.5, audioC.currentTime);
    audioO.start();
}

function stopSound(value) {
    lights(0, false);
    audioG.gain.exponentialRampToValueAtTime(0.001, audioC.currentTime + 1)
    audioO.stop(audioC.currentTime + 1);
}

function simonSpeaks(generateSound) {
    if(generateSound) simonSounds.push(randomColor());

    (function theLoop(i) {
        setTimeout(function() {
            var lights = $(".light");
            for (var j = 0; j < lights.length; j++) {
                if(lights[j].dataset.color == simonSounds[i]) {
                    playSound(j, lights[j].dataset.wave, 400);
                }
            }
            setTimeout(function() {
                stopSound();
                if(++i < simonSounds.length) {
                    theLoop(i);
                } else {
                    playersTurn = true;
                }
            }, 800);
        }, 800);
    })(0);
}

function startGame() {
    showRounds(true);
    simonSpeaks(true);
    gameStart = true;
}

function resetGame(stop) {
    simonSounds.length = 0; playerSounds.length = 0;
    rounds = 0, gameStart = false, playersTurn = false, nextRound = false, patternError = false;

    if(stop) {
        strictMode = false;
        $("#strict").removeClass("active");
        $("#rounds").html("Round:00");
    } else {
        startGame();
    }
};

function gradientColors(color) {
    switch (color) {
        case "G": return "#1abc9c";
        case "B": return "#0197da";
        case "R": return "#ec5657";
        case "O": return "#f9b649";
        default: return "#818486";
    }
}

function clickedBtn(event) {
    if(("button" in event && (event.button == 2 || event.button == 3)) ||
    ("which" in event && (event.which == 2 || event.button == 3))) return false;

    return true;
}

function init() {
    audioTada = $("<audio>");
    $(audioTada).attr("src", "http://soundbible.com/mp3/Ta%20Da-SoundBible.com-1884170640.mp3");

    $(".title").css("background-image", "linear-gradient(45deg,"+gradientColors(randomColor())+","+gradientColors(randomColor())+")");

    $(".button").on("click", function(e) {
        if((this.id == "reset" && !gameStart) || (this.id == "start" && gameStart) || !clickedBtn(e)) return false;

        if(this.id == "strict" && !strictMode) {
            $(this).addClass("active");
            strictMode = true;
            return;
        } else {
            $(this).addClass("active");
        }

        (function(button) {
            setTimeout(function() {
                $(button).removeClass("active");
                if(button.id == "start" && !gameStart) return startGame();
                if(button.id == "strict" && strictMode) strictMode = false;
                if(button.id == "reset" && gameStart) return resetGame(true);
            }, 400);
        })(this);
    });


    $(".light").on("mousedown", function(e) {
        if((!playersTurn) || (!clickedBtn(e))) return false;

        $(this).addClass("active");
        playerclick = true;

        var checkLight = check(this.dataset.color);
        if(checkLight.status) {
            if(patternError) patternError = false;

            playSound(colors.indexOf(this.dataset.color), this.dataset.wave, 400);

            if(checkLight.win) {return success();}
            if(checkLight.lastmatch) {nextRound = true; playerSounds.length = 0;}
        } else {
            playerSounds.length = 0;
            error();
        }
    });

    $(".light").on("mouseup", function(e) {
        if((!playersTurn) || patternError) return false;
        $(this).removeClass("active");
        if(playerclick) {
            playerclick = false;
            stopSound();
            if(nextRound) {
                showRounds(true);
                simonSpeaks(true);
                nextRound = false;
                playersTurn = false;
            }
        }
    });

    $(".light").on("mouseenter", function(e) {
        if(!playersTurn) return false;
        $(this).addClass("active");
    }).on("mouseleave", function(e) {
        if(!playersTurn) return false;
        $(this).removeClass("active");
        if(playerclick) {
            playerclick = false;
            stopSound();
            if(nextRound) {
                showRounds(true);
                simonSpeaks(true);
                nextRound = false;
                playersTurn = false;
            }
        }
    });
}

init();

Comments