Skip to content

Instantly share code, notes, and snippets.

@Jubin369
Created April 1, 2018 07:49
Show Gist options
  • Save Jubin369/4e556e1e7a7792a6a996cfdf75d180b3 to your computer and use it in GitHub Desktop.
Save Jubin369/4e556e1e7a7792a6a996cfdf75d180b3 to your computer and use it in GitHub Desktop.
FCC: Simon Game
<div class="wrap">
<div class="wrap-in">
<div class="rw">
<div class="t-l inline push green unclickable" id='3' ></div><div class="t-r inline push red but unclickable" id='2'></div>
</div>
<div class="rw">
<div class="b-l inline push yellow unclickable" id='1'></div><div class="b-r inline push blue but unclickable" id='0'></div>
</div>
</div>
<div class="center">
<h1 class="brand">Simon<span class="small">®</span></h1>
<div class="rw">
<div class="display inline">
<h1 class="count led-off">--</h1>
<h3 class="label">COUNT</h3>
</div>
<div class="btn-box inline">
<div class="round-btn full-red but clickable" id="start"></div>
<h3 class="label">START</h3>
</div>
<div class="btn-box inline">
<div class="round-btn but clickable" id="mode"></div>
<h3 class="label">STRICT</h3>
<div class="led" id="mode-led"></div>
</div>
</div>
<div class="rw bot">
<h3 class="label inline">OFF</h3>
<div class="sw-slot inline">
<div class="switch" id="pwr-sw"></div>
</div>
<h3 class="label inline">ON</h3>
</div>
</div>
</div>
$(document).ready(function(){
// Checking for Web Audio API on your browser ...
var AudioContext = window.AudioContext // Default
|| window.webkitAudioContext // Safari and old versions of Chrome
|| false;
if(!AudioContext) {
// Sorry, but the game won't work for you
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');
} else {
// You can play the game !!!!
var audioCtx = new AudioContext();
var frequencies = [329.63,261.63,220,164.81];
var errOsc = audioCtx.createOscillator();
errOsc.type = 'triangle';
errOsc.frequency.value = 110;
errOsc.start(0.0); //delay optional parameter is mandatory on Safari
var errNode = audioCtx.createGain();
errOsc.connect(errNode);
errNode.gain.value = 0;
errNode.connect(audioCtx.destination);
var ramp = 0.01;
var vol = 0.5;
var gameStatus = {};
gameStatus.reset = function(){
this.init();
this.strict = false;
}
gameStatus.init = function(){
this.lastPush = $('#0');
this.sequence = [];
this.tStepInd = 0;
this.index = 0;
this.count = 0;
this.lock = false;
};
// create Oscillators
var oscillators = frequencies.map(function(frq){
var osc = audioCtx.createOscillator();
osc.type = 'sine';
osc.frequency.value = frq;
osc.start(0.0); //delay optional parameter is mandatory on Safari
return osc;
});
var gainNodes = oscillators.map(function(osc){
var g = audioCtx.createGain();
osc.connect(g);
g.connect(audioCtx.destination);
g.gain.value = 0;
return g;
});
function playGoodTone(num){
gainNodes[num].gain
.linearRampToValueAtTime(vol, audioCtx.currentTime + ramp);
gameStatus.currPush = $('#'+num);
gameStatus.currPush.addClass('light');
};
function stopGoodTones(){
if(gameStatus.currPush)
gameStatus.currPush.removeClass('light');
gainNodes.forEach(function(g){
g.gain.linearRampToValueAtTime(0, audioCtx.currentTime + ramp);
});
gameStatus.currPush = undefined;
gameStatus.currOsc = undefined;
};
function playErrTone(){
errNode.gain.linearRampToValueAtTime(vol, audioCtx.currentTime + ramp);
};
function stopErrTone(){
errNode.gain.linearRampToValueAtTime(0, audioCtx.currentTime + ramp);
};
function gameStart(){
resetTimers();
stopGoodTones();
stopErrTone();
$('.count').text('--').removeClass('led-off');
flashMessage('--',1);
gameStatus.init();
addStep();
}
function setTimeStep(num){
var tSteps = [1250 , 1000 , 750, 500 ];
if (num < 4)
return tSteps[0];
if (num < 8)
return tSteps[1];
if (num < 12)
return tSteps[2];
return tSteps[3];
}
function notifyError(pushObj){
gameStatus.lock = true;
$('.push').removeClass('clickable').addClass('unclickable');
playErrTone();
if(pushObj)
pushObj.addClass('light');
gameStatus.toHndl = setTimeout(function(){
stopErrTone();
if(pushObj)
pushObj.removeClass('light');
gameStatus.toHndlSt = setTimeout(function(){
if(gameStatus.strict)
gameStart()
else
playSequence();
},1000);
},1000);
flashMessage('!!',2);
};
function notifyWin(){
var cnt = 0;
var last = gameStatus.lastPush.attr('id');
gameStatus.seqHndl = setInterval(function(){
playGoodTone(last);
gameStatus.toHndl = setTimeout(stopGoodTones,80);
cnt++;
if(cnt === 8){
clearInterval(gameStatus.seqHndl);
}
},160);
flashMessage('**',2);
}
function flashMessage(msg,times){
$('.count').text(msg);
var lf = function(){
$('.count').addClass('led-off');
gameStatus.toHndlFl = setTimeout(function(){
$('.count').removeClass('led-off');
},250);
};
var cnt = 0;
lf();
gameStatus.flHndl = setInterval(function(){
lf();
cnt++;
if(cnt === times)
clearInterval(gameStatus.flHndl);
},500)
};
function displayCount(){
var p = (gameStatus.count < 10) ? '0' : '';
$('.count').text(p+(gameStatus.count+''));
}
function playSequence(){
var i = 0;
gameStatus.index = 0;
gameStatus.seqHndl = setInterval(function(){
displayCount();
gameStatus.lock = true;
playGoodTone(gameStatus.sequence[i]);
gameStatus.toHndl = setTimeout(stopGoodTones,gameStatus.timeStep/2 - 10);
i++;
if(i === gameStatus.sequence.length){
clearInterval(gameStatus.seqHndl);
$('.push').removeClass('unclickable').addClass('clickable');
gameStatus.lock = false;
gameStatus.toHndl = setTimeout(notifyError,5*gameStatus.timeStep);
}
},gameStatus.timeStep);
};
function addStep(){
gameStatus.timeStep = setTimeStep(gameStatus.count++);
gameStatus.sequence.push(Math.floor(Math.random()*4));
gameStatus.toHndl=setTimeout(playSequence,500);
};
function resetTimers(){
clearInterval(gameStatus.seqHndl);
clearInterval(gameStatus.flHndl);
clearTimeout(gameStatus.toHndl);
clearTimeout(gameStatus.toHndlFl);
clearTimeout(gameStatus.toHndlSt);
};
function pushColor(pushObj){
if(!gameStatus.lock) {
clearTimeout(gameStatus.toHndl);
var pushNr = pushObj.attr('id');
if( pushNr == gameStatus.sequence[gameStatus.index]
&& gameStatus.index < gameStatus.sequence.length){
playGoodTone(pushNr);
gameStatus.lastPush = pushObj;
gameStatus.index++;
if(gameStatus.index < gameStatus.sequence.length){
gameStatus.toHndl = setTimeout(notifyError,5*gameStatus.timeStep);
}else if (gameStatus.index == 20){
$('.push').removeClass('clickable').addClass('unclickable');
gameStatus.toHndl = setTimeout(notifyWin,gameStatus.timeStep);
}else{
$('.push').removeClass('clickable').addClass('unclickable');
addStep();
}
}else{
$('.push').removeClass('clickable').addClass('unclickable');
notifyError(pushObj);
}
}
}
$('.push').mousedown(function(){
pushColor($(this));
});
$('*').mouseup(function(e){
e.stopPropagation();
if(!gameStatus.lock)
stopGoodTones();
});
function toggleStrict(){
$('#mode-led').toggleClass('led-on');
gameStatus.strict = !gameStatus.strict;
}
$('.sw-slot').click(function(){
$('#pwr-sw').toggleClass('sw-on');
if($('#pwr-sw').hasClass('sw-on')==false){
gameStatus.reset();
$('.count').text('--');
$('.count').addClass('led-off');
$('#mode-led').removeClass('led-on');
$('.push').removeClass('clickable').addClass('unclickable');
$('#start').off('click');
$('#mode').off('click');
$('.btn').removeClass('unclickable').addClass('clickable');
resetTimers();
stopGoodTones();
stopErrTone();
}else{
$('.btn').removeClass('unclickable').addClass('clickable');
$('.count').removeClass('led-off');
$('#start').click(gameStart);
$('#mode').click(toggleStrict);
}
});
gameStatus.reset();
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://raw.githubusercontent.com/shinnn/AudioContext-Polyfill/master/audiocontext-polyfill.js"></script>
@import url('https://fonts.googleapis.com/css?family=Alfa+Slab+One|VT323|Oswald');
/* Basic Reset */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
/* Disable mouse selection */
-webkit-user-select: none; /* Chrome/Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE10+ */
/* Rules below not implemented in browsers yet */
-o-user-select: none;
user-select: none;
}
html{
background-image: url('http://cdn.backgroundhost.com/backgrounds/subtlepatterns/retina_wood.png');
}
.inline{
display: inline-block;
}
.push{
position : relative;
width:200px;
height:200px;
background-color : grey;
border: 12px solid #333;
}
.rw{
margin-bottom:-4px;
}
.b-r{
border-bottom-right-radius : 100%;
}
.b-l{
border-bottom-left-radius : 100%;
}
.t-l{
border-top-left-radius : 100%;
}
.t-r{
border-top-right-radius : 100%;
}
.wrap{
width: 472px;
height:472px;
border-radius:100%;
position: relative;
text-align: center;
margin:auto;
background-color:#333;
top:10vh;
box-shadow: 0px 0px 12px #222;
}
.wrap-in{
position: relative;
top:12px;
}
.center{
width:220px;
height:220px;
position : absolute;
border-radius:100%;
top:50%;
left:50%;
margin: -122px 0 0 -122px;
background-color:#ECE7EE;
border: 12px solid #333;
}
.brand{
font-family: 'Alfa Slab One', cursive;
color : #222;
font-size: 3.2em;
margin-top : 35px;
}
.brand .small{
font-size : 0.3em;
position : relative;
top : -20px;
}
.count{
font-family: 'VT323', monospace;
color : #DC0D29;
padding : 0px;
font-size : 2em;
width : 50px;
background-color: #32050C;
position:relative;
border : 4px solid #222;
border-radius : 10px;
margin:auto;
}
.round-btn{
width : 20px;
height : 20px;
position: relative;
background-color : yellow;
border-radius : 100%;
border : 4px solid #444;
box-shadow : 0px 2px 3px #222;
margin:auto;
top : -5px;
}
.round-btn:active{
box-shadow : 0 1px 1px #292929;
top : -4px;
}
.clickable{
pointer-events : auto;
cursor:pointer;
}
.unclickable{
pointer-events:none;
}
.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;
}
.led-on{
background-color:#DC0D29;
}
.led-off{
color:#430710;
}
.label{
color : #222;
font-family : 'Oswald',Arial,sans;
font-size:0.7em;
margin-top:5px;
text-align:center;
}
.display{
width : 60px;
position:relative;
text-align:center;
}
.btn-box{
width : 50px;
position:relative;
}
.sw-slot{
height:20px;
width:40px;
background-color : #222;
position:relative;
top:5px;
border-radius:2px;
cursor: pointer;
}
.switch{
height:16px;
width: 16px;
border-radius:4px;
background-color : #3193DE;
position:relative;
border : 2px solid #333;
}
.sw-on{
left:20px;
}
.rw.bot{
margin-top: 10px;
}
.full-red{
background-color : #FC0102;
}
.red{
background-color : #9f0f17;
}
.green{
background-color : #00a74a;
}
.yellow{
background-color : #cca707;
}
.blue{
background-color : #094a8f;
}
.yellow.light{
background-color : #fed93f;
}
.blue.light{
background-color : #1c8cff;
}
.red.light{
background-color : #ff4c4c;
}
.green.light{
background-color : #13ff7c;
}
/* Scaling for Mobile */
@media screen and (max-width: 500px){
.wrap {
top: 40px;
-moz-transform: scale(0.6);
-ms-transform: scale(0.6);
-o-transform: scale(0.6);
-webkit-transform: scale(0.6);
transform: scale(0.6);
-o-transform-origin: 0 0;
-ms-transform-origin: 0 0;
-webkit-transform-origin: 0 0;
-moz-transform-origin: 0 0;
transform-origin: 0 0;
left: 50%;
margin-left: -142px;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment