Skip to content

Instantly share code, notes, and snippets.

@RemLampa
Last active January 13, 2017 08:55
Show Gist options
  • Save RemLampa/27e2995dab01415d43b1c4e28107704d to your computer and use it in GitHub Desktop.
Save RemLampa/27e2995dab01415d43b1c4e28107704d to your computer and use it in GitHub Desktop.
Simon Game
<div class="container" ng-app="simonApp" ng-controller="MainController">
<div class="row">
<simon-button position="upper-left"></simon-button>
<simon-button position="upper-right"></simon-button>
</div>
<div class="row">
<simon-button position="lower-left"></simon-button>
<simon-button position="lower-right"></simon-button>
</div>
<div id="controls" class="text-center">
<button class="btn btn-success" ng-hide="gameOngoing" ng-click="startGame()">start</button>
<button class="btn btn-danger" ng-show="gameOngoing" ng-click="stopGame()" ng-disabled="stopDisabled">stop</button>
<h1 class="title text-center">SIMON GAME</h1>
<h3 class="text-danger">Steps: {{step}}</h2>
<button class="btn btn-sm btn-default" ng-hide="strict" ng-click="strict=true">strict off</button>
<button class="btn btn-sm btn-warning" ng-show="strict" ng-click="strict=false">strict on</button>
<div id="message" ng-show="message !== ''"><h1 class="text-danger">{{message}}</h1></div>
</div>
</div>
var simonApp = angular.module('simonApp', []);
simonApp.directive('simonButton', ['$timeout', 'simonService', function($timeout, simonService) {
var template = '';
template += '<div id="' + '{{position}}' + '" class="col-xs-6">';
template += '<div class="button" ng-class="{\'unselected\':getSelectedButton() !== \'{{position}}\',';
template += '\'clickable\': isEnabled() }" ng-click="isEnabled() ? setSelectedButton() : null"></div>';
template += '</div>';
return {
restrict: 'E',
replace: true,
scope: {
position: '@position'
},
link: function(scope, element, attrs) {
scope.getSelectedButton = function() {
return simonService.getSelectedButton();
};
scope.setSelectedButton = function() {
selectedButton = scope.position;
simonService.addUserStep(scope.position);
};
scope.isEnabled = function() {
return simonService.isEnabled();
}
},
template: template
};
}]);
simonApp.service('simonService', ['$rootScope', '$timeout', 'soundService', function($rootScope, $timeout, soundService) {
var _pattern = [],
_userPattern = [],
_currentRound = 0,
_buttonsEnabled = false,
_selectedButton = '',
_speed = 1000;
var self = this;
this.startRound = function() {
$timeout(function() {
_currentRound++;
self.addStep();
self.disableButtons();
self.clearUserPattern();
self.showPattern();
}, 250);
};
this.startGame = function() {
self.resetGame();
self.startRound();
};
this.resetGame = function() {
_pattern = [];
_userPattern = [];
_currentRound = 0;
_buttonsEnabled = false;
_selectedButton = '';
_speed = 1000;
};
this.getRound = function() {
return _currentRound;
};
this.speedUp = function(speed) {
_speed = _speed / 2;
};
this.addUserStep = function(position) {
_userPattern.push(position);
soundService.play(position);
self.disableButtons();
self.setSelectedButton(position);
$timeout(function() {
self.clearSelectedButton();
self.enableButtons();
soundService.stop();
$rootScope.$broadcast('userPatternChange');
}, 250);
};
this.isUserPatternComplete = function() {
return _userPattern.length === _currentRound;
};
this.clearUserPattern = function() {
_userPattern = [];
};
this.addStep = function() {
var element = Math.floor(Math.random() * 4 + 1);
switch (element) {
case 1:
element = 'upper-left';
break;
case 2:
element = 'upper-right';
break;
case 3:
element = 'lower-left';
break;
case 4:
element = 'lower-right';
break;
}
_pattern.push(element);
};
this.showPattern = function(index) {
var index = index || 0;
self.clearSelectedButton();
soundService.stop();
$timeout(function() {
if (index < _pattern.length) {
self.setSelectedButton(_pattern[index]);
soundService.play(_pattern[index]);
index = index + 1;
$timeout(function() {
self.showPattern(index);
}, _speed);
} else {
$rootScope.$broadcast('patternGenerated');
}
}, 250);
};
this.checkPattern = function() {
return _pattern[_userPattern.length - 1] === _userPattern[_userPattern.length - 1];
};
this.isEnabled = function() {
return _buttonsEnabled;
};
this.enableButtons = function() {
_buttonsEnabled = true;
};
this.disableButtons = function() {
_buttonsEnabled = false;
};
this.getSelectedButton = function() {
return _selectedButton;
};
this.setSelectedButton = function(btn) {
_selectedButton = btn;
};
this.clearSelectedButton = function() {
self.setSelectedButton('');
};
}]);
simonApp.factory('soundService', function() {
var sound = {
'upperLeft': new buzz.sound('https://s3.amazonaws.com/freecodecamp/simonSound1.mp3', {
loop: false,
preload: true
}),
'upperRight': new buzz.sound('https://s3.amazonaws.com/freecodecamp/simonSound2.mp3', {
loop: false,
preload: true
}),
'lowerLeft': new buzz.sound('https://s3.amazonaws.com/freecodecamp/simonSound3.mp3', {
loop: false,
preload: true
}),
'lowerRight': new buzz.sound('https://s3.amazonaws.com/freecodecamp/simonSound4.mp3', {
loop: false,
preload: true
}),
'play': function(position) {
switch (position) {
case 'upper-left':
this.upperLeft.togglePlay();
break;
case 'upper-right':
this.upperRight.togglePlay();
break;
case 'lower-left':
this.upperLeft.togglePlay();
break;
case 'lower-right':
this.lowerRight.togglePlay();
break;
}
},
'playAll': function() {
buzz.all().play();
},
'stop': function() {
buzz.all().stop();
}
};
return sound;
});
simonApp.controller('MainController', ['$scope', '$timeout', 'simonService', 'soundService', function($scope, $timeout, simonService, soundService) {
$scope.step = 0;
$scope.message = '';
$scope.strict = false;
$scope.stopDisabled = true;
$scope.startGame = function() {
$scope.message = 'Starting Game!';
$scope.gameOngoing = true;
$scope.stopDisabled = true;
simonService.disableButtons();
$timeout(function() {
$scope.message = '';
simonService.startRound();
}, 1500);
};
$scope.stopGame = function() {
$scope.gameOngoing = false;
$scope.stopDisabled = true;
simonService.resetGame();
simonService.disableButtons();
};
$scope.$on('patternGenerated', function() {
simonService.enableButtons();
$scope.stopDisabled = false;
$scope.step = simonService.getRound();
});
$scope.$on('userPatternChange', function() {
if (simonService.checkPattern()) {
if (simonService.isUserPatternComplete()) {
$scope.message = 'Correct!';
if (simonService.getRound() === 5 || simonService.getRound() === 9 || simonService.getRound() === 13) {
simonService.speedUp();
}
if (simonService.getRound() === 20) {
$scope.message = 'Congratulations! You won!';
simonService.resetGame();
}
$timeout(function() {
$scope.message = '';
$scope.stopDisabled = true;
simonService.startRound();
}, 1500);
}
} else {
$scope.message = 'Wrong!';
simonService.clearUserPattern();
simonService.disableButtons();
$scope.stopDisabled = true;
$timeout(function() {
$scope.message = '';
if ($scope.strict) {
simonService.resetGame();
simonService.startRound();
} else {
simonService.showPattern()
}
}, 1500);
}
});
}]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/buzz/1.1.10/buzz.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular.min.js"></script>

Simon Game

Emulates the original Simon Game using pure AngularJS and Bootstrap.

Sounds courtesy of Buzz! JS audio library (http://buzz.jaysalvat.com/).

Objective of the Simon Game is for the user to successfully copy the AI's patterns.

When strict mode is activated, game restarts if user fails to copy AI.

A Pen by Rem Lampa on CodePen.

License.

body {
vertical-align: middle;
}
#upper-left {
border-right-style: solid;
border-bottom-style: solid;
}
#upper-left div {
background-color: green;
border-top-left-radius: 100%;
}
#upper-right {
border-left-style: solid;
border-bottom-style: solid;
}
#upper-right div {
background-color: red;
border-top-right-radius: 100%;
}
#lower-left {
border-top-style: solid;
border-right-style: solid;
}
#lower-left div {
background-color: yellow;
border-bottom-left-radius: 100%;
}
#lower-right {
border-top-style: solid;
border-left-style: solid;
}
#lower-right div {
background-color: blue;
border-bottom-right-radius: 100%;
}
#controls {
height: 300px;
width: 300px;
background-color: gray;
border: 20px solid black;
border-radius: 100%;
position: relative;
top: -380px;
margin: 0 auto;
padding-top: 40px;
color: black;
}
h3 {
margin-bottom: 20px;
}
#message {
height: 275px;
width: 275px;
background-color: black;
border-radius: 100%;
position: relative;
top: -230px;
left: -5px;
padding-top: 75px;
margin: 0;
}
.col-xs-6 {
height: 230px;
padding: 0;
border-color: black;
border-width: 10px;
}
.container {
width: 500px;
height: 500px;
margin: auto;
border-radius: 100%;
border: 20px solid black;
background-color: black;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
.button {
height: 100%;
margin: 0;
}
.unselected {
opacity: 0.4;
}
.clickable {
cursor: pointer;
}
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment