SimonGame

/**
*             SIMON GAME
*         for freeCodeCamp.com
*
*           by EmAnt - 2015
*
*     Simple Game using CSS3 & jQuery
*
***********************************************
* !!! It uses the new Web Audio API !!!
* You Need an up-to-date browser.
* Tested on Firefox, Chrome, Safari
***********************************************
*/


$(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();

  }
});

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值