Merge remote-tracking branch 'origin/master' into gh-pages
This commit is contained in:
commit
bbebf9a7ec
10
README.md
10
README.md
|
@ -6,10 +6,6 @@ Rows with exploded mines cannot be cleared. See how far you can get!
|
||||||
Left-click to clear a tile. Right-click to flag a mine. Middle-click a number to clear any non-flagged adjacent tiles.
|
Left-click to clear a tile. Right-click to flag a mine. Middle-click a number to clear any non-flagged adjacent tiles.
|
||||||
|
|
||||||
## stuff to add
|
## stuff to add
|
||||||
move middle-click functionality to left-click instead
|
|
||||||
|
|
||||||
add support for mobile devices/1-button mice (probably hold down to flag a mine)
|
|
||||||
|
|
||||||
save game using html5 local storage so player can come back later
|
save game using html5 local storage so player can come back later
|
||||||
|
|
||||||
make cleared columns slide left?
|
make cleared columns slide left?
|
||||||
|
@ -21,8 +17,6 @@ Need to test on mobile devices etc.
|
||||||
## bugs
|
## bugs
|
||||||
the player can cheat under certain conditions; if there is only one tile left on a row, the player can flag it and if it is a mine, the row will clear. if not, the player can unflag it and click it. not sure how big a deal this is really.
|
the player can cheat under certain conditions; if there is only one tile left on a row, the player can flag it and if it is a mine, the row will clear. if not, the player can unflag it and click it. not sure how big a deal this is really.
|
||||||
|
|
||||||
the game adds too many rows and then deletes the extra rows, instead of just adding the correct number of rows in the first place. this is due to the row clearing method nesting and adding the new rows several times as a result
|
need a fallback for browsers that don't support CSS3 viewport sizing
|
||||||
|
|
||||||
the scoring system is wrong due to the above problem; if any tiles cascade during removal of rows, the score is added again for each step of the cascade leading to vastly inflated scores
|
colours used are not safe for red-green colourblindness
|
||||||
|
|
||||||
game is apparently broken in Safari (not sure which version)
|
|
||||||
|
|
246
index.html
246
index.html
|
@ -16,6 +16,7 @@
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-family: Helsinki;
|
font-family: Helsinki;
|
||||||
|
-webkit-user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
@ -65,8 +66,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#setup h1 {
|
#setup h1 {
|
||||||
margin-top: 8vmin;
|
margin-top: 6vmin;
|
||||||
margin-bottom: 8vmin;
|
margin-bottom: 6vmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
#setup h2 {
|
#setup h2 {
|
||||||
|
@ -108,7 +109,7 @@
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 38vmin;
|
left: 38vmin;
|
||||||
top: 59vmin;
|
top: 75vmin;
|
||||||
|
|
||||||
background: #768087;
|
background: #768087;
|
||||||
background: -moz-linear-gradient(top, #768087 0%, #53595e 100%);
|
background: -moz-linear-gradient(top, #768087 0%, #53595e 100%);
|
||||||
|
@ -206,17 +207,28 @@
|
||||||
li.mines8 {
|
li.mines8 {
|
||||||
color: #8c4600;
|
color: #8c4600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 4.3vmin;
|
||||||
|
padding: 0 10vmin;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
color: #fe7ac6;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<script src="jquery-2.1.3.min.js"></script>
|
<script src="jquery-2.1.3.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
var gameBoardWidth = 10;
|
var gameBoardWidth = 10;
|
||||||
var gameBoardHeight = 9;
|
var gameBoardHeight = 9;
|
||||||
var score = 0;
|
var score = 0;
|
||||||
var bombs = 1;
|
|
||||||
var firstClick = true;
|
var firstClick = true;
|
||||||
var currentlyIterating = false;
|
var currentlyIterating = false;
|
||||||
var mineChance = 0.2;
|
var mineChance = 0.2;
|
||||||
var inputEnabled = true;
|
var clickholdMs = 200;
|
||||||
|
var timeout; //hold timer
|
||||||
|
var mouseHeld = false;
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
function drawGameBoard() {
|
function drawGameBoard() {
|
||||||
|
@ -228,15 +240,20 @@
|
||||||
|
|
||||||
$('#game ul').each(function() {
|
$('#game ul').each(function() {
|
||||||
for (var i = 0; i < gameBoardWidth; i++) {
|
for (var i = 0; i < gameBoardWidth; i++) {
|
||||||
if (Math.random() < mineChance) {
|
$(this).append(newTile());
|
||||||
$(this).append('<li class="mine"></li>');
|
|
||||||
} else {
|
|
||||||
$(this).append("<li></li>");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function newTile() {
|
||||||
|
if (Math.random() < mineChance) {
|
||||||
|
return '<li class="mine"></li>';
|
||||||
|
} else {
|
||||||
|
return '<li></li>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$.fn.checkRow = function() {
|
$.fn.checkRow = function() {
|
||||||
//unclicked tiles
|
//unclicked tiles
|
||||||
if ($(this).children('li:not(.revealed):not(.flagged)').length > 0) {
|
if ($(this).children('li:not(.revealed):not(.flagged)').length > 0) {
|
||||||
|
@ -256,72 +273,105 @@
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$.fn.checkColumn = function() {
|
||||||
|
//unclicked tiles
|
||||||
|
if ($(this).column().filter(':not(.revealed):not(.flagged)').length > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//incorrectly flagged tiles
|
||||||
|
if ($(this).column().filter('.flagged:not(.mine)').length > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//clicked mines
|
||||||
|
if ($(this).column().filter('.revealed.mine').length > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
window.removeClearedRows = function() {
|
window.removeClearedRows = function() {
|
||||||
var rowsToRemove = $('#game ul').filter(function() {
|
var rowsToRemove = $('#game ul:not(.removing)').filter(function() {
|
||||||
return $(this).checkRow();
|
return $(this).checkRow();
|
||||||
});
|
});
|
||||||
|
|
||||||
var numRowsToRemove = rowsToRemove.length;
|
var numRowsToRemove = rowsToRemove.length;
|
||||||
|
|
||||||
if (rowsToRemove.length == 0) return;
|
if (numRowsToRemove == 0) return;
|
||||||
|
|
||||||
|
rowsToRemove.addClass("removing");
|
||||||
|
|
||||||
rowsToRemove.each(function() {
|
rowsToRemove.each(function() {
|
||||||
score += $(this).children('.mine').length;
|
score += $(this).children('.mine').length;
|
||||||
|
});
|
||||||
|
|
||||||
|
rowsToRemove.slideUp("slow", function() {
|
||||||
|
$(this).remove();
|
||||||
//add new row on bottom
|
//add new row on bottom
|
||||||
|
|
||||||
$('#game').append('<ul></ul>');
|
$('#game').append('<ul></ul>');
|
||||||
|
|
||||||
for (var i = 0; i < gameBoardWidth; i++) {
|
for (var i = 0; i < gameBoardWidth; i++) {
|
||||||
if (Math.random() < mineChance) {
|
$('#game ul').last().append(newTile());
|
||||||
$('#game ul').last().append('<li class="mine"></li>');
|
|
||||||
} else {
|
|
||||||
$('#game ul').last().append('<li></li>');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
inputEnabled = false;
|
refreshMineCounts();
|
||||||
|
|
||||||
rowsToRemove.slideUp("slow", function() {
|
|
||||||
$(this).remove();
|
|
||||||
|
|
||||||
$('li.revealed:not(.mine)').each(function() {
|
|
||||||
$(this).text(
|
|
||||||
$(this).countMinesText()
|
|
||||||
);
|
|
||||||
|
|
||||||
//remove "mines1" etc
|
|
||||||
|
|
||||||
var mine = $(this).hasClass("mine");
|
|
||||||
|
|
||||||
$(this).removeAttr("class");
|
|
||||||
|
|
||||||
if (mine) {
|
|
||||||
$(this).addClass("mine");
|
|
||||||
} else {
|
|
||||||
$(this).addClass(
|
|
||||||
"mines" + $(this).countMinesText()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$(this).addClass("revealed");
|
|
||||||
});
|
|
||||||
|
|
||||||
//refresh last row to reflect new rows beneath
|
|
||||||
$('li.revealed').last().parent().children('li.revealed').mousedown();
|
|
||||||
|
|
||||||
//click blank tiles
|
//click blank tiles
|
||||||
$('li.revealed:not(.mine):empty').mousedown();
|
$('li.revealed:not(.mine):empty').mouseup();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//this is a bit of a hack :( oh well
|
window.removeClearedColumns = function() {
|
||||||
$('ul:gt(' + gameBoardHeight + ')').remove();
|
var columnsToRemove = $('ul:not(.removing):eq(0) li:not(.removing)').filter(function() {
|
||||||
|
return $(this).checkColumn();
|
||||||
});
|
});
|
||||||
|
|
||||||
//this is a bit of a hack :( oh well
|
if (columnsToRemove.length == 0) return;
|
||||||
$('ul:gt(' + gameBoardHeight + ')').remove();
|
|
||||||
|
columnsToRemove.addClass("removing");
|
||||||
inputEnabled = true;
|
|
||||||
|
columnsToRemove.each(function() {
|
||||||
|
score += $(this).column().filter('.mine').length;
|
||||||
|
});
|
||||||
|
|
||||||
|
columnsToRemove.each(function() {
|
||||||
|
$(this).column().animate({width: 0, borderRadius: 0, padding: 0}, "slow", function() {
|
||||||
|
$(this).parent().append(newTile());
|
||||||
|
$(this).remove();
|
||||||
|
|
||||||
|
refreshMineCounts();
|
||||||
|
|
||||||
|
//click blank tiles
|
||||||
|
$('li.revealed:not(.mine):empty').mouseup();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshMineCounts() {
|
||||||
|
$('li.revealed:not(.mine)').each(function() {
|
||||||
|
$(this).text(
|
||||||
|
$(this).countMinesText()
|
||||||
|
);
|
||||||
|
|
||||||
|
//remove "mines1" etc
|
||||||
|
|
||||||
|
var mine = $(this).hasClass("mine");
|
||||||
|
|
||||||
|
$(this).removeAttr("class");
|
||||||
|
|
||||||
|
if (mine) {
|
||||||
|
$(this).addClass("mine");
|
||||||
|
} else {
|
||||||
|
$(this).addClass(
|
||||||
|
"mines" + $(this).countMinesText()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$(this).addClass("revealed");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateScore() {
|
function updateScore() {
|
||||||
|
@ -360,6 +410,18 @@
|
||||||
return $(this).parent('ul').next();
|
return $(this).parent('ul').next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$.fn.column = function() {
|
||||||
|
var x = $(this).getX();
|
||||||
|
|
||||||
|
var column = $('');
|
||||||
|
|
||||||
|
$('ul').each(function() {
|
||||||
|
column = column.add($(this).children().eq(x));
|
||||||
|
});
|
||||||
|
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
$.fn.getX = function() {
|
$.fn.getX = function() {
|
||||||
return $(this).index();
|
return $(this).index();
|
||||||
}
|
}
|
||||||
|
@ -368,10 +430,6 @@
|
||||||
return $(this).parent('ul').index();
|
return $(this).parent('ul').index();
|
||||||
}
|
}
|
||||||
|
|
||||||
$.fn.getGameboardPos = function() {
|
|
||||||
return gameBoard[$(this).getY()][$(this).getX()];
|
|
||||||
}
|
|
||||||
|
|
||||||
$.fn.isMine = function() {
|
$.fn.isMine = function() {
|
||||||
return $(this).hasClass("mine");
|
return $(this).hasClass("mine");
|
||||||
}
|
}
|
||||||
|
@ -468,7 +526,9 @@
|
||||||
$('#setup').hide();
|
$('#setup').hide();
|
||||||
});
|
});
|
||||||
|
|
||||||
$.fn.leftClick = function() {
|
$.fn.leftClick = function(automated) {
|
||||||
|
if (!automated) automated = false;
|
||||||
|
|
||||||
//don't want first click to be a mine
|
//don't want first click to be a mine
|
||||||
if (firstClick) {
|
if (firstClick) {
|
||||||
var x = $(this).getX();
|
var x = $(this).getX();
|
||||||
|
@ -495,13 +555,12 @@
|
||||||
|
|
||||||
//game over, or lose a life, or whatever
|
//game over, or lose a life, or whatever
|
||||||
//...
|
//...
|
||||||
} else if (parseInt($(this).text()) === $(this).getAdjacentTiles().filter('.flagged').length) {
|
} else if (!automated && parseInt($(this).text()) === $(this).getAdjacentTiles().filter('.flagged, .revealed.mine').length) {
|
||||||
//already clicked; use middle click reveal functionality
|
//already clicked; use middle click reveal functionality
|
||||||
//$(this).middleClick();
|
|
||||||
|
|
||||||
//number of flags matches number of adjacent mines
|
//number of flags matches number of adjacent mines
|
||||||
$(this).getAdjacentTiles().filter(':not(.flagged)').each(function() {
|
$(this).getAdjacentTiles().filter(':not(.flagged, .revealed)').each(function() {
|
||||||
//$(this).mousedown();
|
$(this).mouseup();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
$(this).addClass("revealed");
|
$(this).addClass("revealed");
|
||||||
|
@ -514,7 +573,7 @@
|
||||||
|
|
||||||
//if no mines adjacent, cascade!
|
//if no mines adjacent, cascade!
|
||||||
if ($(this).countMinesAdjacent() == 0) {
|
if ($(this).countMinesAdjacent() == 0) {
|
||||||
$(this).getAdjacentTiles().filter(':not(.revealed)').mousedown();
|
$(this).getAdjacentTiles().filter(':not(.revealed)').mouseup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,33 +581,51 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
$.fn.middleClick = function() {
|
$.fn.middleClick = function() {
|
||||||
//move this functionality to left click
|
|
||||||
|
|
||||||
//number of flags matches number of adjacent mines
|
//number of flags matches number of adjacent mines
|
||||||
if (parseInt($(this).text()) === $(this).getAdjacentTiles().filter('.flagged, .revealed.mine').length) {
|
if (parseInt($(this).text()) === $(this).getAdjacentTiles().filter('.flagged, .revealed.mine').length) {
|
||||||
$(this).getAdjacentTiles().filter(':not(.flagged)').each(function() {
|
$(this).getAdjacentTiles().filter(':not(.flagged)').each(function() {
|
||||||
$(this).mousedown();
|
$(this).mouseup();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$.fn.rightClick = function() {
|
$.fn.rightClick = function() {
|
||||||
if ($(this).hasClass("revealed")) {
|
if (!$(this).hasClass("revealed")) {
|
||||||
//deploy a bomb!
|
|
||||||
//...
|
|
||||||
} else {
|
|
||||||
$(this).toggleClass("flagged");
|
$(this).toggleClass("flagged");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearTimeout(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).on("contextmenu", "li", function(event) {
|
$(document).on("contextmenu", "li", function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).on("mousedown", "li", function(event) {
|
|
||||||
|
$(document).on("mousedown touchstart", "li", function(event) {
|
||||||
|
var x = $(this).getX();
|
||||||
|
var y = $(this).getY();
|
||||||
|
|
||||||
|
timeout = setTimeout(function() {
|
||||||
|
$('ul:eq(' + y + ') li:eq(' + x + ')').rightClick();
|
||||||
|
|
||||||
|
mouseHeld = true;
|
||||||
|
}, clickholdMs);
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on("mouseleave", "li", function(event) {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on("mouseup touchend", "li", function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
if (!inputEnabled) return;
|
clearTimeout(timeout);
|
||||||
|
|
||||||
|
if (mouseHeld) {
|
||||||
|
mouseHeld = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (event.which) {
|
switch (event.which) {
|
||||||
case 3:
|
case 3:
|
||||||
|
@ -558,12 +635,15 @@
|
||||||
$(this).middleClick();
|
$(this).middleClick();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
default:
|
|
||||||
$(this).leftClick();
|
$(this).leftClick();
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
$(this).leftClick(true); //automated
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
removeClearedRows();
|
removeClearedRows();
|
||||||
|
//removeClearedColumns();
|
||||||
checkGameOver();
|
checkGameOver();
|
||||||
|
|
||||||
updateScore();
|
updateScore();
|
||||||
|
@ -576,12 +656,20 @@
|
||||||
$('#gameOver').hide();
|
$('#gameOver').hide();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
<script>
|
||||||
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||||
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date(); a=s.createElement(o),
|
||||||
|
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||||
|
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||||
|
|
||||||
|
ga('create', 'UA-60523398-1', 'auto');
|
||||||
|
ga('send', 'pageview');
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="game"></div>
|
<div id="game"></div>
|
||||||
<div id="stats">
|
<div id="stats">
|
||||||
<div id="score">Score: 0</div>
|
<div id="score">Score: 0</div>
|
||||||
<div id="bombs" style="display: none;">Bombs: 0</div>
|
|
||||||
<div id="mines">Mines left: 0</div>
|
<div id="mines">Mines left: 0</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="gameOver">
|
<div id="gameOver">
|
||||||
|
@ -591,6 +679,12 @@
|
||||||
<div id="setup">
|
<div id="setup">
|
||||||
<h1>endless mines</h1>
|
<h1>endless mines</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong>left click</strong> or <strong>tap</strong> to clear a tile. <br>
|
||||||
|
<strong>right click</strong> or <strong>hold</strong> to flag a mine. <br>
|
||||||
|
rows with <strong>exploded mines</strong> cannot be cleared.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2>Difficulty</h2>
|
<h2>Difficulty</h2>
|
||||||
|
|
||||||
<div class="centre">
|
<div class="centre">
|
||||||
|
|
Loading…
Reference in New Issue