Skip to content

Instantly share code, notes, and snippets.

@programus
Last active June 23, 2016 01:34
Show Gist options
  • Save programus/2192639 to your computer and use it in GitHub Desktop.
Save programus/2192639 to your computer and use it in GitHub Desktop.
Javascript Game Memory
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
Remove this if you use the .htaccess -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>memory</title>
<meta name="description" content="A memory game." />
<meta name="author" content="Programus" />
<meta name="viewport" content="width=device-width; initial-scale=1.0" />
<script src="http://code.jquery.com/jquery-latest.js" type="text/javascript"></script>
<script src="http://www.codebase.es/riffwave/riffwave.js" type="text/javascript"></script>
<!-- Replace favicon.ico & apple-touch-icon.png in the root of your domain and delete these references -->
<link rel="shortcut icon" href="images/memory.ico" />
<link rel="stylesheet" href="memory.css" />
<script type="text/javascript" src="memory.js"></script>
</head>
<body>
<div>
<header>
<h1>memory</h1>
</header>
<div id="game-panel" align="center">
<noscript>This page need javascript...</noscript>
<div id="settings">
<span id="matrix-size-span">
<select id="matrix-size" name="matrix-size">
</select>
</span>
</div>
<hr />
<div>
<table id="matrix" class="matrix">
<tbody class="matrix" id="matrix-body"></tbody>
</table>
</div>
<div id="score-panel">
<span id="score-bar">
<label for="score">Score:</label>
<span id="score" class="score-value">0</span>
</span>
</div>
<div>
<input type="button" id="start-action" class="start-button" value="START" />
</div>
</div>
<footer>
</footer>
</div>
</body>
</html>
table.matrix,tbody.matrix {
border-style:double;
border-width:3px;
border-color:#000000;
border-spacing:0;
padding:0;
margin:0;
background-color:#aaffff;
}
table.matrix td {
border-style:solid;
border-width:1px;
border-color:#AAAAAA;
padding:0;
margin:0;
width:1.5em;
height:1.5em;
}
table.matrix td.action {
background:#ffffff;
cursor:pointer;
}
table.matrix td.fading {
background:#ffffff;
}
table.matrix td.action:hover {
background:#ccffcc;
cursor:pointer;
}
table.matrix td.error {
border-color:#ff0000;
}
table.matrix td.error-action {
border-color:#aaff00;
}
table.matrix td.show {
background:#dddddd;
}
#matrix-size-span {
width:3em;
overflow-x:hidden;
display:inline-block;
background-image:url("../select-arrow.png");
background-repeat:no-repeat;
background-position:center right;
border: 1px solid #ccc;
}
#matrix-size-span.disabled {
background-color:#777777;
}
#matrix-size {
color:#777777;
width:5em;
background: transparent;
border: 0px;
cursor:pointer;
}
#matrix-size:disabled {
color:#444444;
text-decoration:none;
text-shadow:1px 1px 0px #aaaaaa;
cursor:default;
}
#score.updating {
color:#00aa00;
background:#dddd88;
}
#score.stable {
background:inherit;
}
#score-panel {
margin-top:0.3em;
margin-bottom:0.2em;
}
#score-bar {
padding:2px;
}
#score-bar.finished {
color:#444444;
background:#edcfaa;
}
#score-bar.normal {
color:#777777;
}
#game-panel {
}
#start-action {
background-color:#ededed;
border:1px solid #dcdcdc;
display:inline-block;
color:#777777;
font-family:arial;
font-size:11px;
font-weight:bold;
padding:2px 5px;
text-decoration:none;
cursor:pointer;
}
#start-action:disabled {
background-color:#777777;
color:#444444;
border:1px solid #444444;
text-decoration:none;
text-shadow:1px 1px 0px #aaaaaa;
cursor:default;
}
#start-action:enabled:hover {
background-color:#dfdfdf;
}
#start-action:enabled:active {
position:relative;
top:1px;
}
h1 {
text-align:center;
color:#444444;
text-decoration:none;
text-shadow:1px 1px 0px #aaaaaa;
}
body {
background-color:#ededed;
}
/**
* @author Programus
*/
var GLOBAL = function( ) {
var LOWEST_LEVEL = 3;
var NODES = [
261.63 ,
277.18 ,
293.66 ,
311.13 ,
329.63 ,
349.23 ,
369.99 ,
392 ,
415.3 ,
440 ,
466.16 ,
493.88 ,
/*
523.26 ,
554.37 ,
587.33 ,
622.25 ,
659.26 ,
698.46 ,
739.99 ,
783.99 ,
830.61 ,
880 ,
932.33 ,
987.77 ,
*/
];
var audio;
try {
audio = new Audio();
} catch(e) {
// If browser is not support Audio. create a fake one.
audio = {
src: null,
play: function(){},
};
}
var wave = new RIFFWAVE();
wave.header.sampleRate = 44100;
wave.header.numChannel = 1;
var that = {
showSeq: [],
actionSeq: [],
currLevel: 0,
score: 0,
state: 'finished',
};
that.playSound = function(index) {
var soundLevel = parseInt(index / NODES.length);
var vol = 96 / (soundLevel / 2 + 1) + 32;
var frequency = NODES[index % NODES.length] * Math.pow(2, soundLevel);
var samples = [];
var samples_length = 44100; // Plays for 1 second (44.1 KHz)
for (var i=0; i < samples_length ; i++) { // fills array with samples
var t = i/samples_length; // time from 0 to 1
samples[i] = Math.sin(frequency*2*Math.PI*t); // wave equation (between -1,+1)
samples[i] *= (1-t); // "fade" effect (from 1 to 0)
samples[i] = 128 + vol * samples[i];
}
wave.Make(samples);
audio.src = wave.dataURI;
audio.play();
};
that.playCell = function(cell) {
var index = that.getCellIndex(cell);
if (index !== null) {
that.playSound(that.getCellIndex(cell));
}
};
that.getCellIndex = function(cell) {
var c;
if (cell.hasOwnProperty('length')) {
if (cell.length > 0) {
c = cell[0];
} else {
c = null;
}
} else {
c = cell;
}
return c === null ? null : parseInt(c.id.slice('td-'.length));
};
that.generateShowSeq = function(arr, level, max) {
return function(level, max) {
arr.splice(0, arr.length);
for (var i = 0; i < level; i++) {
var rand = null;
while (rand === null || (i < max && $.inArray(rand, arr) >= 0)) {
rand = parseInt(Math.random() * max);
}
arr[i] = rand;
}
return arr;
};
}(that.showSeq);
that.clearMatrix = function() {
var tds = $('#matrix td');
if (tds.hasClass('show')) {
tds.attr('class', 'show');
} else {
tds.attr('class', 'action');
}
tds.removeAttr('title');
};
that.enableAction = function(isEnable) {
if (isEnable) {
$('#matrix td').removeClass('show').addClass('action');
} else {
$('#matrix td').removeClass('action').addClass('show');
}
};
that.enableSettings = function(isEnable) {
$('#matrix-size').attr('disabled', !isEnable);
if (isEnable) {
$('#matrix-size-span').removeClass('disabled');
} else {
$('#matrix-size-span').addClass('disabled');
}
};
that.enableStartButton = function(isEnable) {
$('#start-action').attr('disabled', !isEnable);
};
that.finishedScore = function(isFinished) {
$('#score-bar').attr('class', isFinished ? 'finished' : 'normal');
};
that.nextLevel = function() {
that.enableAction(false);
level = that.currLevel + LOWEST_LEVEL;
that.currLevel++;
var max = $('#matrix td').length;
that.showQeustion(that.generateShowSeq(level, max));
};
that.showQeustion = function(seq) {
for (var i = 0; i < seq.length; i++) {
var v = seq[i];
setTimeout((function(num) {
return function() {
that.highlightCell(num);
};
})(v), 1000 * i);
}
setTimeout(function() {
that.startAction();
}, 1000 * seq.length);
};
that.startAction = function() {
that.enableAction(true);
that.actionSeq.splice(0, that.actionSeq.length);
};
that.highlightCell = function(cell) {
if (cell % 1 === 0) {
cell = $('#td-' + cell);
}
that.playCell(cell);
cell.addClass('fading');
cell.fadeOut(500).fadeIn(500);
cell.removeClass('fading');
};
that.errorCell = function(cell, type) {
if (cell % 1 === 0) {
cell = $('#td-' + cell);
}
cell.addClass(type === 'action' ? 'error-action' : 'error');
cell.attr('title', type === 'action' ? 'you clicked' : 'it should be');
};
that.refreshActionSeq = function(cell) {
var index = that.getCellIndex(cell);
if (index !== null) {
that.actionSeq.push(that.getCellIndex(cell));
}
};
that.refreshScore = function() {
that.score += (1 << (that.currLevel + LOWEST_LEVEL)) * $('#matrix td').length;
var plusScore = function() {
var scoreCtrl = $('#score');
var score = parseInt(scoreCtrl.text());
if (score < that.score) {
score += Math.max(parseInt(that.score / 100), 1);
if (score > that.score) {
score = that.score;
}
scoreCtrl.text(score);
scoreCtrl.attr('class', 'updating');
setTimeout(plusScore, 10);
} else {
scoreCtrl.attr('class', 'stable');
setTimeout(that.nextLevel, 100);
}
};
plusScore();
};
that.judge = function() {
for (var i = 0; i < that.actionSeq.length; i++) {
if (that.showSeq[i] !== that.actionSeq[i]) {
that.errorCell(that.showSeq[i], 'show');
that.errorCell(that.actionSeq[i], 'action');
return false;
}
}
return true;
};
that.startGame = function() {
that.currLevel = 0;
that.score = 0;
that.enableSettings(false);
that.enableStartButton(false);
that.clearMatrix();
that.nextLevel();
that.finishedScore(false);
};
that.finishGame = function() {
that.enableAction(false);
that.enableSettings(true);
that.enableStartButton(true);
that.finishedScore(true);
};
return that;
}( );
$().ready(function() {
if ($.browser.msie) {
// sorry, not support IE.
$('#game-panel').text('This game cannot be run on IE. Please use firefox or chrome.');
return;
}
// set up settings.
for (var i = 2; i < 9; i++ ) {
$('#matrix-size')
.append($('<option>')
.attr('value', i)
.text(i + 'x' + i));
}
// setting matrix
$('#matrix-size').change(function() {
var n = this.value;
var html4matrix = $('<tbody>');
html4matrix.addClass('matrix');
for (var r = 0; r < n; r++) {
var row = $('<tr>');
for (var c = 0; c < n; c++) {
var num = r * n + c;
var cell = $('<td>').attr('id', 'td-' + num);
cell.attr('class', 'show');
cell.click(function(theCell) {
return function() {
if (theCell.attr('class') === 'action') {
GLOBAL.highlightCell(theCell);
setTimeout(function(){
GLOBAL.refreshActionSeq(theCell);
if (!GLOBAL.judge()) {
GLOBAL.finishGame();
} else if (GLOBAL.actionSeq.length >= GLOBAL.showSeq.length) {
GLOBAL.refreshScore();
}
}, 1000);
}
};
}(cell));
row.append(cell);
}
html4matrix.append(row);
}
$('#matrix').html(html4matrix);
});
$('#matrix-size').change();
$('#start-action').click(function() {
$('#score').text(0);
GLOBAL.startGame();
});
GLOBAL.finishGame();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment