Created
January 27, 2017 02:34
-
-
Save shade/68b86d9767cafd0a25c259c3185315bc to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Closure for namespacing, and to prevent name collisions. | |
;(function() { | |
// Initialize constants | |
var NEW_GAME_DELAY = 1200 | |
var NOTE_DURATION = 800 | |
var ACCELERATION_CONSTANT = 0.8 | |
var POINT_CONSTANT = 10 | |
// Initilize the Simon game as a giant singleton, as only one instance is necessary. | |
var Simon = new function () { | |
// Initialize some arrays | |
// Stores the last game state, also used to calculate randomness. | |
this.game = [] | |
// This is mutable and is unreliable for storage. | |
this.state = [] | |
// Initialize the notes object collection. | |
this.notes = {} | |
// This is the simon notebox wheel DOM Element. | |
this.wheel = document.getElementById('notebox') | |
// This is the current score | |
this.score = 0 | |
// This is the highscore | |
this.highscore = 0 | |
// Execute the first Simon. | |
this.click = (key) => { | |
// Pop out the first key in the real sequence. | |
var realKey = this.state.shift() | |
// Check if the user's key matches the real key. | |
if (key == realKey) { | |
// Check if the current sequence is over. | |
if (this.state.length == 0) { | |
// Add points to the score. | |
this.displayScore(POINT_CONSTANT * this.game.length) | |
// Disable all inputs | |
this.disableAll() | |
// Create a new sequence, start the game over again. | |
this.newState() | |
} | |
} else { | |
// Make the current score the high score if possible | |
this.displayHighscore() | |
// Disable all inputs. | |
this.disableAll() | |
// Set the score to zero. | |
this.displayScore(-this.score) | |
// Since the keys didn't match, end the game. | |
this.end() | |
} | |
} | |
this.generate = () => { | |
return KEYS[~~(Math.random() * KEYS.length)] | |
} | |
this.newState = () => { | |
// Create a new letter to add to the sequence and push it into the game. | |
this.game.push(this.generate()) | |
// Deep clone the Simon game into the state, to allow mutability in only the state. | |
this.state = this.game.slice(0) | |
// Give the user some rest, before the next game. | |
setTimeout(() => { | |
// Play the entire new sequence back to the user. | |
this.playAll() | |
}, NEW_GAME_DELAY) | |
} | |
this.disableAll = () => { | |
for (note in this.notes) { | |
this.notes[note].disable() | |
} | |
} | |
this.enableAll = () => { | |
for (note in this.notes) { | |
this.notes[note].enable() | |
} | |
} | |
this.playAll = () => { | |
// Iterate through the game notes and play the sequence. | |
this.game.forEach((note, i) => { | |
setTimeout(() => { | |
this.notes[note].play() | |
if ((i+1) == this.game.length) { | |
this.enableAll() | |
} | |
},i * NOTE_DURATION) | |
}) | |
} | |
this.displayScore = (points) => { | |
let scoreCard = document.getElementById('score') | |
// Split the score value to extract the current score. | |
let scoreArr = scoreCard.innerHTML.split(' ') | |
// Update the score in the object | |
this.score += points | |
// Update the scor on the DOM. | |
scoreArr[1] = this.score | |
// Update the DOM with the new score. | |
scoreCard.innerHTML = scoreArr.join(' ') | |
} | |
this.displayHighscore = () => { | |
// Grab the high score label | |
let highScoreCard = document.getElementById('high-score') | |
// if the current score is greater, update it. | |
if (this.score > this.highscore) { | |
let scoreArr = highScoreCard.innerHTML.split(' ') | |
highScoreCard.style.display = 'block' | |
this.highscore = this.score | |
scoreArr[1] = this.highscore | |
highScoreCard.innerHTML = scoreArr.join(' ') | |
} | |
} | |
this.end = () => { | |
// Initialize number of degrees to turn by | |
var degrees = 0 | |
// This is the change in degrees | |
var ddegrees = -8 | |
// Turn the simon wheel. | |
var turnInterval = setInterval(() => { | |
// Stop everything, on a complete rotation and start a new game. | |
if (Math.abs(degrees) >= 360) { | |
this.newState() | |
clearInterval(turnInterval) | |
this.wheel.style.transform = '' | |
return | |
} | |
// Update the transformation | |
this.wheel.style.transform = 'rotate(' + degrees +'deg)' | |
// Increase the rotation of the wheel | |
degrees += 8-Math.abs(ddegrees) | |
// Add some acceleration to the mix. | |
ddegrees += ACCELERATION_CONSTANT | |
}, 10) | |
// Destroy the game sequence | |
this.state = [] | |
this.game = [] | |
// Play everything at once to give the user negative reinforcement. | |
for (note in this.notes) { | |
this.notes[note].play() | |
} | |
} | |
} | |
// Iterate through the keys and create noteboxes for them, while binding the . | |
KEYS.forEach((key) => { | |
Simon.notes[key] = new NoteBox(key, Simon.click.bind(Simon)); | |
}); | |
// Start the simon. | |
Simon.newState() | |
// Add this is the window as a globally accessible object. | |
window.Simon = Simon | |
})(window) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is the actual simon code, that was compiled/minified and converted to pixels.