cssAudio - Activefile-genericCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - ActiveLovehtmlicon-new-collectionicon-personicon-teamlog-outoctocatpop-outspinnerstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

            
              <body>
  <div class="bg"></div> <!-- Empty div containing background image -->
  <main class="container">
    <header>
      <!-- Blue box for displaying the current round & play/replay button -->
      <div class="controls">
        <h3>ROUND</h3>
        <div id="rounds" class="option"><i id="round">0</i> <span>/20</span></div>
        <div onclick="restart()" id="replay" class="option playMe">
          <i id="playIcon">&#9658;</i> <span id="playMsg">PLAY?</span>
        </div> 
      </div>
      
      <h1 id="gameTitle">HIT THE <br> DIAMOND</h1> <!-- Game title -->
      
     <!-- Blue box for displaying the game modes (Strict & forgiving) -->
      <div class="controls">
        <h3>MODE</h3>
        <div onclick="setMode('strict')"    id="strict"    class="option">       <i>&diams;</i> <span>STRICT   </span></div>
        <div onclick="setMode('forgiving')" id="forgiving" class="option active"><i>&starf;</i> <span>FORGIVING</span></div>
      </div>
      
    </header>
    
    <div class="wrapper">
      <h1 id="winMessage">YOU<br>WIN</h1>
      
      <div id="diamond_container">
        <div id="diamonds">
          <div id="white-diamond"  class="diamond" onclick="guess(whiteDiamond)" ><div class="cover"></div></div>
          <div id="yellow-diamond" class="diamond" onclick="guess(yellowDiamond)"><div class="cover"></div></div>
          <div id="blue-diamond"   class="diamond" onclick="guess(blueDiamond)"  ><div class="cover"></div></div>
          <div id="pink-diamond"   class="diamond" onclick="guess(pinkDiamond)"  ><div class="cover"></div></div>
        </div>
      </div>
      
    </div>
    <a onclick="toggleFooter()" id="info">
      <h3>More<br>Info</h3>
    </a>
  </main>
      <footer id="footer"> 
      <div><h1>Game &amp; Rules</h1>
        <p>Press play to begin!  Until you do so the game functions like a 4 note instrument. </p> The rules are exactly the same as the classic Simon game. <br> But in case you've never played Simon here are the rules: 
      <ul>
        <li>You are presented with a sequence of button presses (The diamonds light up and make a sound).  The length of the sequence is the same as the current round you're on.</li>
        <li>After the sequence is done playing, you press the diamonds ( or use arrow or WASD keys) in the same pattern that just played.</li>
        <li>If you enter the entire current sequence correctly, the round will increase. The pattern will play again, adding one more button press at the end of the sequence. The game continues like this until round 20.</li>
        <li>If you enter the sequence incorrectly, a sound will play letting you know you made a mistake. If the mode is set to 'forgiving' (the default) the pattern will play again, and you can try again.  If the mode is 'strict' the pattern will reset and you'll have to start all over from round 1.</li>
        <li>If you beat round 20, you'll win the game! You'll be notified of your victory and the game will start over.</li>
      </ul>
      </p>
        </div><div>
      <h1>Credit &amp; Inspiration</h1>
      <p>Made for freeCodeCamp's <a target="_blank" href="https://www.freecodecamp.com/challenges/build-a-simon-game">'Build a Simon Game' Challenge</a>.<p>
      <p>The look and feel of this Simon clone was inspired by Rebecca Sugar's <a href="https://en.wikipedia.org/wiki/Steven_Universe" target="_blank">Steven Universe</a>.<p> <p>This pen uses the Web Audio API for its sounds. The Sound class used is based on code from Greg Hovanesyan's <a target="_blank" href="https://codepen.io/gregh/pen/RKVNgB">pen.</a>  </p>
  <h1>Special Thanks!</h1>
  <p>I want to say thank you to the CodePen team for picking this pen!  I was floored when I saw my pen on the front page! &lt;3 </p>
  </div>
    </footer>
</body>
            
          
!
            
              /*--------------------------------------------------------------
>>> TABLE OF CONTENTS:
----------------------------------------------------------------
# Top Level Containers
  ## Main Container
    ### Header
    ### Wrapper
# Text / Font
  ## 'Hit the Diamond' (Game title h1)
  ## 'You Win'
# Diamonds
  ## White Diamond
  ## Yellow Diamond
  ## Blue Diamond
  ## Pink Diamond
# Controls / Options (Blue boxes)
  ## Icon
  ## Text
    ### Header (Round, Mode)
    ### Undertext
  ## Active (glowing) class
  ## Animated Glowing 'Play' button
# 'You Win' Animation 
  ## Intro
    ### Diamonds
    ### Win Message
  ## Outro
    ### Diamonds
    ### Win Message
# More Info Button
$ Footer
# Media Queries
# Animation Keyframes (Definitions)
--------------------------------------------------------------*/

/*--------------------------------------------------------------
# Top Level Containers
--------------------------------------------------------------*/
body{
  background: #0b0d26;
  width: 100%;
  height: 100vh;
  margin: 0;
  position: relative;
}

.bg{ /*Background image*/ 
  width: 100%;
  height: 100vh;
  background: #061640;
  background-image: url(https://media.giphy.com/media/3qePHOEQYRPDG/giphy.gif); /*Background image is commented out during development*/
  background-repeat: no-repeat;
  background-position: center top;
  background-size: cover;
  opacity: .4;
  position: fixed;
  left: 0;
  right: 0;
  z-index: -1;
  -webkit-filter: blur(5px); -moz-filter: blur(5px); -o-filter: blur(5px); -ms-filter: blur(5px); filter: blur(5px);
}

/*--------------------------------------------------------------
  ## Main Container
--------------------------------------------------------------*/
.container { /*Main game container*/
  position: relative;
  max-width: 100vh;
  margin: auto;
}

/*--------------------------------------------------------------
  ## Main Container >>    ### Header
--------------------------------------------------------------*/
header{ /*Header containing the blue option boxes and Game title h1*/
  display: flex;
  justify-content: space-around;
  flex-wrap: nowrap;
  align-items: center;
}
/*--------------------------------------------------------------
  ## Main Container >>    ### Wrapper
--------------------------------------------------------------*/
.wrapper { /* Contains the diamonds and 'You Win' message*/
  position: relative;
  height: 50%;
  max-width: 700px;
  min-height: 400px;
  margin: auto;
  display: flex;
}

/*--------------------------------------------------------------
# Text / Font
--------------------------------------------------------------*/

body{
  font-family: 'Dosis', sans-serif;
  color: #fff;
}

/*--------------------------------------------------------------
  ## 'Hit the Diamond' (Game title h1)
--------------------------------------------------------------*/
#gameTitle{
  background-image: url(http://hd.wallpaperswide.com/thumbs/abstract_wallpaper_for_mac-t2.jpg);
  background-size: cover;
  filter: brightness(1.5) drop-shadow(-2px 2px 0px rgba(255,255,255,1));
  color: #b95087;
  -webkit-text-fill-color: transparent; text-fill-color: transparent;
  background: -webkit-linear-gradient(transparent, transparent), url(http://hd.wallpaperswide.com/thumbs/abstract_wallpaper_for_mac-t2.jpg);
  background-size: cover;
  background: -o-linear-gradient(transparent, transparent);
  -webkit-background-clip: text; background-clip: text;
  font-size: 5em;
  text-align: center;
  margin: 0; 
  padding: .5em;
}

/*--------------------------------------------------------------
  ## 'You Win'
--------------------------------------------------------------*/
#winMessage {
  text-transform: uppercase;
  text-align: center;
  text-shadow: 0px 0px 10px #ffffff;
  font-size: 10em;
  vertical-align: middle;
  margin: auto;
  position: relative;
  padding: 0;
  transition: .75s;
  opacity: 0;
  z-index: -1;
  line-height: 1em;
}

/*--------------------------------------------------------------
# Diamonds
--------------------------------------------------------------*/

/*Contains the large diamond shape (#diamonds) which in turn contains the four smaller diamonds*/
#diamond_container { 
  position: absolute;
  width: 50%;
  height: 50%;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  margin: auto;
}

/* Big diamond shaped box which contains all 4 diamonds */
#diamonds {
  position: absolute;
  z-index: 5;
  left: 0; right: 0;
  top: 0; bottom: 0;
  margin: auto;
  width: 100%;
  height: 0;
  padding: 50% 0;
  text-align: center;
  -ms-transform: rotate(45deg);  -moz-transform: rotate(45deg);
  -webkit-transform: rotate(45deg);  transform: rotate(45deg);
}


/* General Diamond styles */
.diamond {
  position: absolute;
  width: 49%;
  height: 49%;
  transition: .5s;
  box-sizing: border-box;
  cursor: pointer;
}

/* We can't animate smoothly to different gradient backgrounds so 
  we have a .cover div element on top that we just fade in and out
  for a glowing effect*/
.diamond .cover {
  border-radius: inherit;
  background-image: linear-gradient(#ccc, #fff);
  content: '';    
  display: block;
  height: 100%;
  position: absolute;
  top: -2px; left: -2px; /* Offset glovwing border */
  opacity: 0;
  width: 100%;
  box-sizing: content-box;
  transition: opacity 0.45s;
}

.diamond:hover .cover {
  opacity: 1;
}

.diamond.glowing .cover {
  -webkit-animation: smoothFade 1s;
     -moz-animation: smoothFade 1s;
          animation: smoothFade 1s;
}

/*--------------------------------------------------------------
  ## White Diamond
--------------------------------------------------------------*/
/*White Diamond Default*/
#white-diamond {
  left: 0;
  top: 0;
  border: 2px solid #fff;
  background: rgba(255, 255, 255, 0.71);
  background: -webkit-radial-gradient(rgba(255, 255, 255, 0.38), rgba(255, 255, 255, 0.91));
  background: radial-gradient(rgba(255, 255, 255, 0.38), rgba(255, 255, 255, 0.91));
  box-sizing: border-box;
  transition: .3s;
}

/*White Diamond Glowing*/
#white-diamond .cover {
  background: #ffffff;
  -moz-box-shadow: 2px 1px 45px -3px rgba(255,255,255,1);
  box-shadow: 2px 1px 45px -3px rgba(255,255,255,1);
  border: 2px solid #fff;
}
/*--------------------------------------------------------------
  ## Yellow Diamond
--------------------------------------------------------------*/
/*Yellow Diamond Default*/
#yellow-diamond {
  right: 0;
  top: 0;
  background: #ece273;
  background: rgba(236, 226, 115, 71);
  border: 2px solid #fff79f;
  background: -webkit-radial-gradient(rgba(239, 232, 149, 0.4), 
                                      rgba(233, 226, 147, 0.85));
}
/*Yellow Diamond Glowing*/
#yellow-diamond .cover {
  background: #fff79f;
  border: 2px solid #fffde7;
  background: -webkit-radial-gradient(rgb(255, 255, 255), rgb(255, 245, 135));
  box-shadow: 2px 1px 45px -3px #fffcdc;
}

/*--------------------------------------------------------------
  ## Blue Diamond
--------------------------------------------------------------*/
/*Blue Diamond Default*/
#blue-diamond {
  left: 0;
  bottom: 0;
  background: #92edf0;
  background: rgba(146, 237, 240, 71);
  border: 2px solid #92edf0;
  background: -webkit-radial-gradient(rgba(146, 237, 240, 0.33), 
    rgba(146, 237, 240, 0.85));
}
/*Blue Diamond Glowing*/
#blue-diamond .cover {
  background: #92edf0;
  border: 2px solid #5efaff;
  background: -webkit-radial-gradient(rgb(255, 255, 255), rgb(146, 237, 240));
  box-shadow: 2px 1px 45px -3px rgb(198, 245, 247);
}

/*--------------------------------------------------------------
  ## Pink Diamond
--------------------------------------------------------------*/
/*Pink Diamond Default*/
#pink-diamond {
  right: 0;
  bottom: 0;
  border: 2px solid #ef82c5;
  background: #ef82c5; /*Fallback: Solid Pink color*/
  background: rgba(239, 130, 197, 71); /*Fallback: Semi-transparent Pink color*/
  background: -webkit-radial-gradient(rgba(239, 130, 197, 0.33), /*Prefixed for Webkit: Radial gradient with mostly transparent center*/
    rgba(239, 130, 197, 0.85));
  background: radial-gradient(rgba(239, 130, 197, 0.33),  /* Standard Syntax: Radial gradient with mostly transparent center*/
    rgba(239, 130, 197, 0.85));
}
/*Pink Diamond Glowing*/
#pink-diamond .cover {
  background: #f9d4eb;
  border: 2px solid #f9d4eb;
  background: -webkit-radial-gradient(rgb(255, 255, 255), rgb(239, 130, 197));
  box-shadow: 2px 1px 45px -3px rgb(239, 130, 197);
}


/*--------------------------------------------------------------
# Controls / Options (Blue boxes)
--------------------------------------------------------------*/
.controls {
  padding: 1em 0;
  text-align: center;
  background: #6ab2bf;
  background: -webkit-radial-gradient(rgba(0, 247, 255, 0), rgba(0, 247, 255, 0.42));
  border: 1px solid #7bccd5;
  box-sizing: border-box;
  width: 180px;
}

.option { /* Mini Boxes within controls*/
  /* Ex: "★
       FORGIVING" */
  text-align: center;
  flex-wrap: wrap;
  cursor: pointer;
  opacity: .25;
  transition: .3s;
  display: inline-flex;
  margin: 0px; 
  box-sizing: border-box;
  width: 49%;
  min-width: 60px;
}

.option:hover {
  opacity: 1;
}

/*--------------------------------------------------------------
 # Controls / Options >>   ## Icon
--------------------------------------------------------------*/
.option i {
  text-align: center;
  width: 100%;
  display: block;
  font-size: 3em;
  font-style: normal;
}

/*--------------------------------------------------------------
 # Controls / Options >>   ## Text
--------------------------------------------------------------*/
/*--------------------------------------------------------------
    ### Header ("Round", "Mode")
--------------------------------------------------------------*/
.controls h3 {margin: 0 auto;}

/*--------------------------------------------------------------
 # Controls / Options >>    ### Under text
--------------------------------------------------------------*/
.option span {
  text-align: center;
  font-size: .8em;
  display: block;
  width: 100%;
}


/*--------------------------------------------------------------
 # Controls / Options >>  ## Active (glowing) class
--------------------------------------------------------------*/
.option.active, #rounds {
    text-shadow: 0px 0px 10px #ffffff;
    opacity: 1;
}

/*--------------------------------------------------------------
 # Controls / Options >>  ## Animated Glowing 'Play' button
--------------------------------------------------------------*/
#replay.playMe { /*When the user first loads the page, the play button will have a glowing/blinking animation until they start the game */
  opacity: 1;
-webkit-animation: miniGlow .75s ease-in-out infinite alternate;
   -moz-animation: miniGlow .75s ease-in-out infinite alternate;
        animation: miniGlow .75s ease-in-out infinite alternate;
}


/*--------------------------------------------------------------
                 # 'You Win' Animation
--------------------------------------------------------------*/

/*--------------------------------------------------------------
 # 'You Win' Animation >>   ## Intro
--------------------------------------------------------------*/
/*--------------------------------------------------------------
 # 'You Win' Animation >>   ## Intro >>    ### Diamonds
--------------------------------------------------------------*/
/* All of the diamonds fade out */
#diamonds.winner .diamond{
  animation: scaleOut .5s ease-in-out;
  -webkit-animation-fill-mode: forwards;
} 

#info.winner {
  animation: fadeOut .5s ease-in-out;
  -webkit-animation-fill-mode: forwards;
}

/* Animation delays for a one-at-a-time effect */
#diamonds.winner #blue-diamond  {animation-delay: 0.0s; }
#diamonds.winner #white-diamond {animation-delay: 0.5s; }
#diamonds.winner #yellow-diamond{animation-delay: 1.0s; }
#diamonds.winner #pink-diamond  {animation-delay: 1.5s; }

/*--------------------------------------------------------------
 # 'You Win' Animation >>   ## Intro >>     ### Win Message
--------------------------------------------------------------*/
#winMessage.winner {
  animation: fadeIn .5s ease-in-out;
  -webkit-animation-delay: 2s;
  -webkit-animation-fill-mode: forwards;
  z-index: 2;
}

/*--------------------------------------------------------------
 # 'You Win' Animation >>   ## Outro
--------------------------------------------------------------*/
/*--------------------------------------------------------------
 # 'You Win' Animation >>   ## Outro >>    ### Diamonds
--------------------------------------------------------------*/
/* After the "You Win" messages fades out the diamonds scale back into view */
#diamonds.winner.outro .diamond{
  opacity: 0;
  transform: scale(0);
  animation: scaleUp .5s ease-in-out;
  -webkit-animation-fill-mode: forwards;
  animation-fill-mode: forwards;
} 

/* Animation delays for a one-at-a-time effect */
#diamonds.winner.outro #blue-diamond  {animation-delay: 0.5s;}
#diamonds.winner.outro #white-diamond {animation-delay: 1.0s;}
#diamonds.winner.outro #yellow-diamond{animation-delay: 1.5s;}
#diamonds.winner.outro #pink-diamond  {animation-delay: 2.0s;}

/*--------------------------------------------------------------
 # 'You Win' Animation >>   ## Outro >>    ### Win Message
--------------------------------------------------------------*/
#winMessage.winner.outro { 
  animation: fadeOut .5s ease-in-out;
  animation-delay: 0s;
  -webkit-animation-delay: 0s;
  -webkit-animation-fill-mode: initial;
  animation-fill-mode: initial;
}

#info.winner.outro {
  animation: fadeIn .5s ease-in-out;
  -webkit-animation-fill-mode: forwards;
}


/*--------------------------------------------------------------
 # More Info button
--------------------------------------------------------------*/

#info {
  height: 100px;
  width: 100px;
  vertical-align: middle;
  display: block;
  transform: rotate(45deg);
  margin-left: 20%;
  margin-top: -50px;
  margin-bottom: 20px;
  position: relative;
  bottom: 10px;
  background: -webkit-radial-gradient(rgba(0, 247, 255, 0), rgba(0, 247, 255, 0.42));
  border: 1px solid #7bccd5;
  box-sizing: border-box;
  cursor: pointer;
}

#info h3 {
  transform: rotate(-45deg);
  text-align: center;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  vertical-align: middle;
  line-height: 30px;
  color: #fff;
}

/*--------------------------------------------------------------
 # Footer
--------------------------------------------------------------*/

footer {
  background: -webkit-radial-gradient(rgba(0, 247, 255, 0), rgba(239, 130, 197, 0.42));
  border-top: 1px solid #ef82c5;
  /* padding: 0 10vw; */
  box-sizing: border-box;
  max-height: 0px;
  opacity: 0;
  transition: 1s;
  overflow: hidden;
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  text-shadow: 0px 0px 10px #000000;
}
footer.visible {
  max-height: 1500px;
  opacity: 1;
}
footer div {
  flex-basis: 50%;
  min-width: 300px;
  box-sizing: border-box;
  padding: 0 1em;
  max-width: 500px;
}

footer a {
    color: #00deb7;
}

ul {
  list-style: none;
  margin-left: 0;
  padding-left: 0;
}

li {
  padding-left: 1em;
  text-indent: -1em;
}

li:before {
  content: "\2605";
  padding-right: 5px;
}

/*--------------------------------------------------------------
 # Media Queries
--------------------------------------------------------------*/
@media(max-width: 750px) {
  header {align-items: stretch; flex-wrap: wrap;}
  footer div {flex-basis: 100%;}
  #gameTitle {
    flex-basis: 100%;
    order: -1;
    font-size: 4em;
  }
  .option   { flex-basis: 48%; width: 48%;}
  .controls { padding: .5em 0; width: 150px;}
  .option i { display: block; font-size: 2em;}
}

@media(min-aspect-ratio: 2/1) and (max-width: 750px){
  #gameTitle {order: 0; padding: 0;}
  container { max-width: 100vw;}
}

@media(max-width: 500px) {
  #gameTitle {
    padding: 0;
    margin: 0 auto;
    font-size: 3em;
  }
 
  .wrapper {
    min-height: 300px;
  }
}

@media(max-height: 500px) and (min-aspect-ratio: 5/4) {
  .container {max-width: 100vw;}
  header {    justify-content: space-between;    margin: 0 20px;}
  .wrapper { max-width: 400px; min-height: 0; }

}

@media(min-aspect-ratio: 2/1) {
  header{flex-wrap: nowrap; justify-content: space-around;}
  .container {max-width: 75vw;}
}

@media(min-width: 1000px) and (min-aspect-ratio: 5/4) {
  header{flex-wrap: nowrap; justify-content: center;}
  .container {max-width: 75vw;}
}


/*--------------------------------------------------------------
 # Animation Keyframes (Definitions)
--------------------------------------------------------------*/

/*--------------------------------------------------------------
   ## smoothFade (used for glowing diamonds)
--------------------------------------------------------------*/
@-webkit-keyframes smoothFade {
    0% {opacity: 0; }
   50% {opacity: 1; }
  100% {opacity: 0; }
}

@keyframes smoothFade {
    0% {opacity: 0; }
   50% {opacity: 1; }
  100% {opacity: 0; }
}

/*--------------------------------------------------------------
   ## fadeIn
--------------------------------------------------------------*/
@-webkit-keyframes fadeIn {
     0% {opacity: 0;}
   100% {opacity: 1;}
}

@keyframes fadeIn {
     0% {opacity: 0;}
   100% {opacity: 1;}
}

/*--------------------------------------------------------------
   ## fadeOut
--------------------------------------------------------------*/
@-webkit-keyframes fadeOut {
    0% {opacity: 1; }
  100% {opacity: 0; }
}

/*--------------------------------------------------------------
   ## scaleOut
--------------------------------------------------------------*/
@-webkit-keyframes scaleOut {
    0% {opacity: 1; transform: scale(1); }
  100% {opacity: 0; transform: scale(0); }
}


/*--------------------------------------------------------------
   ## scaleUp
--------------------------------------------------------------*/
@-webkit-keyframes scaleUp {
    0% { opacity: 0; transform: scale(0); }
  100% { opacity: 1; transform: scale(1); }
}

/*--------------------------------------------------------------
   ## miniGlow (Used for the play button on first run)
--------------------------------------------------------------*/
@keyframes miniGlow {
  from {text-shadow: 0px 0px 1px rgba(255,255,255,0);  }
  to   {text-shadow: 0px 0px 15px #ffffff;}
}
            
          
!
            
              /*--------------------------------------------------------------
>>> TABLE OF CONTENTS:
----------------------------------------------------------------
# Sound Class
  ## playSound()
# Simon Game
  ## Defaults
  ## Diamond Class
    ### Diamond Methods 
    ### Diamond Instances (Blue, Pink, Yellow & White)
  ## Game Elements (HTML)
  ## Sequence Object
  ## Functions
    ### updateRound() 
    ### setMode() 
    ### restart()
    ### checkWin() 
    ### guess()
    ### allGlow()
    ### errorChime() 
    ### showWin()
    ### hideWin()
    ### winOutro()
# toggleFooter()
# keyPress (Play with arrow or WASD keys!)
--------------------------------------------------------------*/


/* Sound class inspired by Greg Hovanesyan's pen:  https://codepen.io/gregh/pen/RKVNgB */
/* Uses the Web Audio API which let's you play a sound from its frequency | Modified to specify time.*/

'use strict';

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }


/*--------------------------------------------------------------
 # Sound Class
--------------------------------------------------------------*/
var Sound = function() {
  function Sound(context) {
    _classCallCheck(this, Sound);

    this.context = context;
  }

  Sound.prototype.setup = function setup() {
    this.oscillator = this.context.createOscillator();
    this.gainNode = this.context.createGain();

    this.oscillator.connect(this.gainNode);
    this.gainNode.connect(this.context.destination);
    this.oscillator.type = 'sine';
  };

  Sound.prototype.play = function play(value) {
    this.setup();

    this.oscillator.frequency.value = value;
    this.gainNode.gain.setValueAtTime(0, this.context.currentTime);
    this.gainNode.gain.linearRampToValueAtTime(1, this.context.currentTime + 0.01);

    this.oscillator.start(this.context.currentTime);
    this.stop(this.context.currentTime);
  };

  Sound.prototype.stop = function stop(time = 1) {
    this.gainNode.gain.exponentialRampToValueAtTime(0.001, this.context.currentTime + time);
    this.oscillator.stop(this.context.currentTime + time);
  };

  return Sound;
}();

var context = new (window.AudioContext || window.webkitAudioContext || false)();

if(!context) { //  Sound Test 
  alert('Sorry, but the Web Audio API is not supported by your browser.'
        + ' Please, consider downloading the latest version of '
        + 'Google Chrome or Mozilla Firefox');

}

/*--------------------------------------------------------------
   ## playSound()
--------------------------------------------------------------*/
function playSound(note, time = 1000) {
  var sound = new Sound(context);
  sound.play(note);
  sound.stop(time/1000);
}

/*--------------------------------------------------------------
      # Simon Game
--------------------------------------------------------------*/

/*--------------------------------------------------------------
# Simon Game >>    ## Defaults
--------------------------------------------------------------*/

var defaults = {
  "speed"      : 1000, // Time in milliseconds (ms) between each sequence play
  "round"      : 1,    // Current Round is 1;
  "userInputs" : 0     // User hasn't input / guessed anything 
};

var currentGame =  Object.assign({}, defaults); // ES6 Syntax: cloning defaults while keeping them immutable

var strict      = false; // Mode is `forgiving`     
var started     = false;



/*--------------------------------------------------------------
## Diamond Class
--------------------------------------------------------------*/

//  Diamond Constructor function
function Diamond(sound, element){
  this.element = document.getElementById(element); // Element in the HTML with an ID of element
  this.chime   = function(){playSound(sound, currentGame.speed)}; // Add a chime() for the sound (frequency) provided
  this.cover   = this.element.childNodes[0];
}

/*--------------------------------------------------------------
## Diamond Class >>    ### Diamond Methods
--------------------------------------------------------------*/
// Adding methods to the Diamond prototype that all diamond instances will inherit

Diamond.prototype.hideGlow = function(){ // Removes the 'glowing' class from a particular diamond
  this.element.classList.remove("glowing");
}

Diamond.prototype.glow = function(){ // Adds a 'glowing' class to a particular diamond
  var glowDuration = currentGame.speed - 100;
  this.hideGlow(); // Sanity check: make sure it's not glowing first
  this.element.classList.add("glowing");
  this.cover.style.animationDuration = currentGame.speed;
  var glowing = this; // We can't access the current glowing Diamond in the timer sub function as `this`
  //So we're assigning `this` to a variable called `glowing`
  setTimeout(function() {glowing.hideGlow()}, glowDuration); // After some time, remove the glowing class
}

/*--------------------------------------------------------------
## Diamond Class >>    ### Diamond Instances (Blue, Pink, Yellow & White)
--------------------------------------------------------------*/
// Let's make diamonds with our Diamond constructor function!
// For our first diamond, the note is D5, element refers to the #blue-diamond element on the page
var blueDiamond   = new Diamond(587.33, "blue-diamond"  ); // Note is D5
var pinkDiamond   = new Diamond(659.25, "pink-diamond"  ); // Note is E5
var yellowDiamond = new Diamond(739.99, "yellow-diamond"); // Note is F#5
var whiteDiamond  = new Diamond(880.00, "white-diamond" ); // Note is A5

/* Array of all diamond instances */
var diamonds = [pinkDiamond, yellowDiamond, whiteDiamond, blueDiamond];


/*--------------------------------------------------------------
## Game Elements (HTML)
--------------------------------------------------------------*/

var gameElements = { // A object containing commonly accessed HTML elements
  "round"     : document.getElementById("round"),     // Current Round number text
  "diamonds"  : document.getElementById("diamonds"),  // Big diamond shaped box which contains all 4 diamonds
  "winMsg"    : document.getElementById("winMessage"),// The (normally) hidden 'You Win' message
  "forgiving" : document.getElementById("forgiving"), // The `forgiving` mode button
  "strict"    : document.getElementById("strict")     // The `strict` mode button
}

/*--------------------------------------------------------------
 ## Sequence Object
--------------------------------------------------------------*/
var sequence  = { // An object containing all the properties and methods to play & generate a sequence
  "current" : [], // The current sequence (Start off as nothing)
  "playing" : false,         // Is the sequence currently playing? (Start off as false)
  "index"   : 0,             // Current step for playing the sequence (Start at the beginning)
  "play"    : function(){  // Play the current sequence
                this.playing = true;        // The sequence currently playing
                currentGame.userInputs = 0; // Reset the user's input to the start of the sequence
                var _this =  this; // 'this' will be undefined in the timer function so we're storing it in "_this" 
    
                setTimeout(function() {// Wait a second then loop again, going through the sequence
                  var currentDiamond = _this.current[_this.index];
                  currentDiamond.glow();
                  currentDiamond.chime();
                  _this.index++;             //  increment the counter
                  if (_this.index < currentGame.round) { //  if the counter < the current round, call the loop function
                    _this.play();           //  again which will trigger another sequence play
                  } else {
                    _this.playing = false; // Otherwise the sequence isn't playing the the user can guess
                  }                   
                }, currentGame.speed) // The speed of the timer is the same as the currentGame.speed (default 1s)
              },
  
  "generate": function(){ // Generate a random sequence
                this.index = 0;   // Reset the sequence to play from the beginning
                this.current = [];// Empty the old sequence
                var currentSequence = this.current; // Temp var because of undefined 'this' in sub function
                var easyCheatin = []; // Not necessary, making it easy to cheat.
                  for(var j=0; j <20; j++){ // Loop over 20 times
                    var randomDiamond = diamonds[Math.floor(Math.random()*diamonds.length)]; // randomly select a diamond
                    currentSequence.push(randomDiamond); // And add it to the current sequence
                    easyCheatin.push(randomDiamond.element.id);
                  }
                console.log(easyCheatin); // Log the sequence to the console cuz we're cheaters
              }
};


/*--------------------------------------------------------------
# Simon Game >>   ## Functions
--------------------------------------------------------------*/    

/*--------------------------------------------------------------
# Simon Game >>   ## Functions >>     ### updateRound() 
--------------------------------------------------------------*/   
function updateRound() { // Update the round counter text on the page
    gameElements.round.innerHTML = currentGame.round; 
}

/*--------------------------------------------------------------
# Simon Game >>   ## Functions >>     ### setMode() 
--------------------------------------------------------------*/  
function setMode(mode){ // Sets the game mode to the mode passed (Either strict or forgiving)
  var other  = (mode === "strict") ? 'forgiving' : 'strict'; // Ternary: Other = not the current mode
      strict = (mode === "strict") ? true        : false;
  gameElements[other].classList.remove("active"); // remove active (glowing) from the other element
  gameElements[mode].classList.add("active"); // Add active class to current mode
}

/*--------------------------------------------------------------
# Simon Game >>   ## Functions >>     ### restart() 
--------------------------------------------------------------*/  
function restart(){ // Starts a new game
  if(started === false){ // If this is the first game played
    started = true; // then it's been started
    document.getElementById("playMsg").innerHTML = "RESTART?"; // Change text from 'PLAY?' to 'RESTART?'
    document.getElementById("playIcon").innerHTML = "&#8635;"; // Change the icon from '►' to '↻'
    document.getElementById("replay").classList.remove("playMe"); // Get rid of playMe (glowing) class
  } // Do the rest of this stuff always
  currentGame =  Object.assign({}, defaults); // Reset to game defaults
  updateRound();       // Update the round counter to 1
  sequence.generate(); // Generate a new sequence
  sequence.play();     // Play the new sequence
}

/*--------------------------------------------------------------
# Simon Game >>   ## Functions >>     ### checkWin() 
--------------------------------------------------------------*/  
function checkWin(){ // Check to see if the user won
  if(currentGame.userInputs >= sequence.current.length){ 
    // If the user's correct guesses are the same as the length of the whole sequence
    showWin(); // They've won.  Show the winning animation
    setTimeout(function() {restart()}, 7000); // Wait 7 seconds and restart the game
  } else if(currentGame.userInputs >= currentGame.round){ // Else if the has cleared the current round (but not won the whole game)
      currentGame.round++; // Increase the round
      updateRound();       // Update the round text on screen
      currentGame.speed -= 25; // Shave off 25ms from time (Slowly gets faster each round)
      sequence.index = 0;  // Reset the sequence index to the beginning
      sequence.play();     // And play the sequence again
  }
}

/*--------------------------------------------------------------
# Simon Game >>   ## Functions >>     ### guess() 
--------------------------------------------------------------*/  
function guess(diamond){ // Checks a users guess (diamond clicked on)
  if(sequence.current.length === 0){ 
    diamond.chime(); // If the game hasn't started it acts like a music instrument!
  }
  if(sequence.playing || !started){ return;} // If the sequence is playing, return (do nothing)
  if(sequence.current[currentGame.userInputs] === diamond){ // If the user guessed correctly
    currentGame.userInputs++; // Increase the user's input (steps)
    diamond.chime(); // Chime!
    checkWin(); // And check to see if they won
    
  } else { // Otherwise they guessed incorrectly
    errorChime(); // Play the error music
      if(strict === true){ // If the game mode is strict
        setTimeout(function(){ restart(); }, 1100); // Wait for the error chime to finish (1100ms) then restart the game
      } else { // Otherwise the mode is forgiving
        currentGame.userInputs = 0; // Reset the user's guess
        sequence.index = 0;         // Start from the beginning of the sequence
        
        // Wait for the error chime to finish (1100ms) then replay the sequence
        setTimeout(function(){ sequence.playing = false; sequence.play(); }, 1100);
      }
  }
}

/*--------------------------------------------------------------
# Simon Game >>   ## Functions >>     ### allGlow() 
--------------------------------------------------------------*/  
function allGlow(){ // Make all the diamonds glow!
    pinkDiamond.glow();
    blueDiamond.glow();
  yellowDiamond.glow();
   whiteDiamond.glow();
}

/*--------------------------------------------------------------
# Simon Game >>   ## Functions >>     ### errorChime() 
--------------------------------------------------------------*/  
function errorChime(){ // Let the user know they guessed incorrectly
  sequence.playing = true; // We don't want the user to guess while the error music is playing
  allGlow(); // Light all the diamonds up
  playSound(261.63); // Play a C4
  setTimeout(function(){ playSound(246.94);}, 500); // Wait half a sec, then play a B3
  setTimeout(function(){ playSound(220.00);}, 1000);// Wait a sec, then play an A3
}

/*--------------------------------------------------------------
# Simon Game >>   ## Functions >>     ### showWin() 
--------------------------------------------------------------*/  
function showWin(){ // Show the user they won!
  hideWin(); // Sanity check: Make sure the winning class isn't already active
  allGlow(); // Make all the diamonds glow!
  gameElements.diamonds.classList.add("winner");// Add "winning" class to diamonds (They shrink out of view)
  document.getElementById("info").classList.add("winner");
  gameElements.winMsg.classList.add("winner");  // Add "winning" class to winMsg ("You Win" fades in)
  setTimeout(function() {winOutro()}, 3000);    // Wait three seconds then play the outro
}

/*--------------------------------------------------------------
# Simon Game >>   ## Functions >>     ### hideWin() 
--------------------------------------------------------------*/  
function hideWin(){ // Remove all classes pertaining to showing the 'You Win' message
  gameElements.diamonds.classList.remove("winner");
  gameElements.winMsg.classList.remove("winner");
  gameElements.winMsg.classList.remove("outro");
  gameElements.diamonds.classList.remove("outro");
  document.getElementById("info").classList.remove("winner");
  document.getElementById("info").classList.remove("outro");
}
/*--------------------------------------------------------------
# Simon Game >>   ## Functions >>     ### winOutro() 
--------------------------------------------------------------*/  
function winOutro(){  // Return to the game's default appearance
  gameElements.winMsg.classList.add("outro");  // Add "outro" class to winMsg ("You Win" fades back out)
  document.getElementById("info").classList.add("outro");
  gameElements.diamonds.classList.add("outro");// Add "outro" class to diamonds (They scale back into view)
  setTimeout(function() {allGlow()}, 500); // Wait half a second, then have all the diamonds glow
  setTimeout(function() {hideWin()}, 3000);// When the animation is complete (3s) we can remove all the classes
}

/*--------------------------------------------------------------
 # toggleFooter()
--------------------------------------------------------------*/
var footerHidden = true;
function toggleFooter(){
  footerHidden = !footerHidden;
  var message = (footerHidden) ? 'More' : 'Hide';
  document.getElementById("footer").classList.toggle("visible");
  document.getElementById("info").childNodes[1].innerHTML = message +" <br> Info";
}

/*--------------------------------------------------------------
 # keyPress (Play with arrow or WASD keys!)
--------------------------------------------------------------*/

document.onkeydown = function (e) {
    e = e || window.event;
     if(sequence.playing){return;}
    if (e.keyCode == 38 || e.keyCode == 87) { // Up keycode || W keycode
        guess(whiteDiamond);
        whiteDiamond.glow();
    } else if (e.keyCode == 37 || e.keyCode == 65) { // left keycode || A
        guess(blueDiamond);
        blueDiamond.glow();
    } else if (e.keyCode == 39 || e.keyCode == 68) { // right keycode || D
        guess(yellowDiamond);
        yellowDiamond.glow();
    } else if (e.keyCode == 40 || e.keyCode == 83) { // down keycode || S
        guess(pinkDiamond);
        pinkDiamond.glow();
    }
};
            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.
Loading ..................

Console