Minesweeper in Javascript and Canvas

Drawing the game playing, won, or lost

To draw the playing screen, as well as the won or lost screens, we use the drawPlaying method, which begins by creating some temporary variables to improve readability, such as halfW and halfH (half tile width and height), and a reference to the current difficulty information (cDiff):

function drawPlaying()
{
	var halfW = gameState.tileW / 2;
	var halfH = gameState.tileH / 2;
	
	var cDiff = difficulties[gameState.difficulty];

The font is then set and used to draw the current game difficulty level name and the link to return to the menu screen.

	ctx.textAlign = "center";
	ctx.textBaseline = "bottom";
	
	ctx.fillStyle = "#000000";
	ctx.font = "12px sans-serif";
	ctx.fillText(cDiff.name, 150, 20);
	
	ctx.fillText("Return to menu", 150, 390);

If the game has not been lost, we'll show how many mines are on the grid:

	if(gameState.screen!='lost')
	{
		ctx.textAlign = "left";
		ctx.fillText("Mines: " + cDiff.mines, 10, 40);

We then choose either the currently elapsed gameTime, or the gameState.timeTaken, depending on whether the game is still ongoing or has been won, and format the time to show minutes and seconds.

		var whichT = (gameState.screen=='won' ?
			gameState.timeTaken : gameTime);
		var t = '';
		if((gameTime / 1000) > 60)
		{
			t = Math.floor((whichT / 1000) / 60) + ':';
		}
		var s = Math.floor((whichT / 1000) % 60);
		t+= (s > 9 ? s : '0' + s);
	
		ctx.textAlign = "right";
		ctx.fillText("Time: " + t, 290, 40);
	}

If the game is no longer playing (it has been lost or won), we show text stating so slightly above the game grid.

	if(gameState.screen=='lost' || gameState.screen=='won')
	{
		ctx.textAlign = "center";
		ctx.font = "bold 20px sans-serif";
		ctx.fillText(
			(gameState.screen=='lost' ?
				"Game Over" : "Cleared!"), 150, offsetY - 15);
	}

Next, we draw a boundary rect around the outside of the game grid area, and set the font we'll be using to draw each Tile.

	ctx.strokeStyle = "#999999";
	ctx.strokeRect(offsetX, offsetY,
		(cDiff.width * gameState.tileW),
		(cDiff.height * gameState.tileH));
	
	ctx.font = "bold 10px monospace";
	ctx.textAlign = "center";
	ctx.textBaseline = "middle";

We then loop over all the Tile objects in the grid array, and calculate the pixel position of the current Tile (px, py):

	for(var i in grid)
	{
		var px = offsetX + (grid[i].x * gameState.tileW);
		var py = offsetY + (grid[i].y * gameState.tileH);

If the game has been lost and this tile contained a mine, we draw a red square for the Tile and place and x on it.

		if(gameState.screen=='lost' && grid[i].hasMine)
		{
			ctx.fillStyle = "#ff0000";
			ctx.fillRect(px, py,
				gameState.tileW, gameState.tileH);
			ctx.fillStyle = "#000000";
			ctx.fillText("x", px + halfW, py + halfH);
		}

If the Tile does not have a mine but is visible, we draw a light grey square, and show the danger level if it is greater than 0.

		else if(grid[i].currentState=='visible')
		{
			ctx.fillStyle = "#dddddd";
			
			if(grid[i].danger)
			{
				ctx.fillStyle = "#000000";
				ctx.fillText(grid[i].danger, px + halfW, py + halfH);
			}
		}

When the Tile is not revealed, we'll just draw a darker grey square and stroke it to give it a border.

		else
		{
			ctx.fillStyle = "#cccccc";
			ctx.fillRect(px, py,
				gameState.tileW, gameState.tileH);
			ctx.strokeRect(px, py,
				gameState.tileW, gameState.tileH);
			
			if(grid[i].currentState=='flagged')
			{
				ctx.fillStyle = "#0000cc";
				ctx.fillText("P", px + halfW, py + halfH);
			}
		}
	}
}

That was all the logic we needed for drawing our playing, won and lost screens, so we can close the method and our open if blocks.

Page loaded in 0.01 second(s).