A simple game inspired by Ink Spill (in turn by Flood It) in which cells are populated with colour spreading to adjacent cells from the top left of a grid.
Created
March 30, 2019 00:33
-
-
Save olliebennett/26028e6a584670522b124c63e74143d8 to your computer and use it in GitHub Desktop.
Colour Spill Game in JavaScript
This file contains 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
<html> | |
<head> | |
<meta content="text/html;charset=utf-8" http-equiv="Content-Type"> | |
<meta content="utf-8" http-equiv="encoding"> | |
<title>Colour Spill</title> | |
<style> | |
canvas { | |
width: 750px; | |
height: 500px; | |
border: 1px solid black; | |
} | |
.control-button { | |
height: 50px; | |
width: 200px; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>Colour Spill</h1> | |
<canvas id="world"> | |
</canvas> | |
<div id="control-panel"> | |
</div> | |
<script> | |
// CONFIGURATION | |
const gridX = 5; | |
const gridY = 5; | |
const cellWidth = 15; | |
const cellHeight = 10; | |
// List of possible colours | |
var colours = ['red', 'orange', 'green']; | |
// CODE | |
// Build empty matrix (2D Array) with cells containing `value` | |
// Note: seemingly redundant .fill(0) required to bypass shallow copy constructor | |
var buildMatrix = function(x, y, value) { | |
return new Array(x).fill(0).map(row => new Array(y).fill(value)); | |
} | |
// 2D Grid of colours | |
var matrix = buildMatrix(gridX, gridY, 'blue'); | |
// 2D Grid of 'infested' cells | |
var mask; | |
// Colour currently being applied | |
var colour = colours[0]; | |
const canvas = document.getElementById('world'); | |
const ctx = canvas.getContext('2d'); | |
var setRandom = function() { | |
for (var i=0; i < gridX; i++) { | |
for (var j=0; j < gridY; j++) { | |
matrix[i][j] = colours[Math.floor(Math.random()*colours.length)]; | |
} | |
} | |
} | |
var markAdjacent = function() { | |
var changed = false; | |
for (var i=0; i < gridX; i++) { | |
for (var j=0; j < gridY; j++) { | |
// mark this cell if ... | |
if ( | |
// cell not already tagged | |
!mask[i][j] && | |
// ... and the matrix cell is a matching colour | |
matrix[i][j] === colour && | |
// ... and any adjacent cell in the mask is infected | |
( | |
(i > 0 && mask[i-1][j]) || | |
(j > 0 && mask[i][j-1]) || | |
(i < (gridX - 1) && mask[i+1][j]) || | |
(j < (gridY - 1) && mask[i][j+1]) | |
) | |
) { | |
mask[i][j] = true; | |
changed = true; | |
} | |
} | |
} | |
// Iterate repeatedly until no changes are required | |
if (changed) { | |
applyMask() | |
drawMatrix(); | |
// Repeat recursively | |
window.setTimeout(function() { markAdjacent(); }, 10); | |
} | |
} | |
var buildMask = function() { | |
mask = buildMatrix(gridX, gridY, false); | |
// Initially, top left cell is 'infected' | |
mask[0][0] = true; | |
markAdjacent(); | |
} | |
var applyMask = function() { | |
for (var i=0; i < gridX; i++) { | |
for (var j=0; j < gridY; j++) { | |
if (mask[i][j]) { | |
matrix[i][j] = colour; | |
} | |
} | |
} | |
} | |
var setSpill = function(col) { | |
// Update current colour we're tracking | |
colour = col; | |
// Update all matching cells (according to 'mask') with the new colour | |
applyMask(); | |
// Re-build the 'mask' to flag all adjacent cells of same colour | |
buildMask(); | |
// Render the matrix on the canvas | |
drawMatrix(); | |
}; | |
var logMatrix = function() { | |
logArray(matrix); | |
}; | |
var logMask = function() { | |
logArray(mask); | |
}; | |
var logArray = function(arr) { | |
for (var i=0; i<gridX; i++) { | |
console.log(`row#${i}: ${arr[i].join(',')}`) | |
} | |
} | |
var drawMatrix = function() { | |
for (var i=0; i < gridX; i++) { | |
for (var j=0; j < gridY; j++) { | |
ctx.fillStyle = matrix[i][j]; | |
ctx.fillRect(i * cellWidth, j * cellHeight, cellWidth-1, cellHeight-1); | |
} | |
} | |
}; | |
var buildControlPanel = function() { | |
colours.forEach(function(col) { | |
var spillBtn = document.createElement("button"); | |
spillBtn.className = 'control-button'; | |
spillBtn.style.backgroundColor = col; | |
var spillBtnLabel = document.createTextNode(col.toUpperCase()); | |
spillBtn.appendChild(spillBtnLabel); | |
var controlPanel = document.getElementById("control-panel"); | |
document.body.insertBefore(spillBtn, controlPanel); | |
spillBtn.addEventListener('click', function() { | |
setSpill(col); | |
}); | |
}); | |
}; | |
var setupGame = function() { | |
// Initial randomisation and render | |
setRandom(); | |
drawMatrix(); | |
// Prepare blank mask | |
buildMask(); | |
// Initial 'guess' of top-left corner | |
setSpill(colours[0]); | |
buildControlPanel(); | |
}; | |
setupGame(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment