Creating the Memory Game

Main Game loop

Our drawGame method is called every time the window is ready for us to draw another frame to the Canvas. In this function we begin by checking the ctx (2D drawing context) is not null - if it does we leave the function and processing is finished. This happens if a problem has occured, such as if the sprites could not be loaded.

We also check if the sprites are loaded with spritesLoaded flag. If they are not, we tell the window to check back next time it's ready to do some drawing, and leave the function for now...

function drawGame()
{
	if(ctx==null) { return; }
	if(!spritesLoaded) { requestAnimationFrame(drawGame); return; }

We can now calculate the elapsed game time from the current time, in milliseconds, subtracting the time of the last frame. If the lastFrameTime is 0 (such as the first time this code is executed when a new game has begun), we immediately set it to the current time:

	var currentFrameTime = Date.now();
	if(lastFrameTime==0) { lastFrameTime = currentFrameTime; }
	var timeElapsed = currentFrameTime - lastFrameTime;
	gameTime+= timeElapsed;

Now we can call our updateGame method to process game logic. After, we update our frame counting (framerate) variables to keep track of the number of frames being drawn each second.

	updateGame();

	// Frame counting
	var sec = Math.floor(Date.now()/1000);
	if(sec!=currentSecond)
	{
		currentSecond = sec;
		framesLastSecond = frameCount;
		frameCount = 1;
	}
	else { frameCount++; }

The Canvas is then cleared to plain white, and we call the draw method for the current screen.

	ctx.fillStyle = "#ddddee";
	ctx.fillRect(0, 0, 300, 400);
	
	// Draw the current screen
	if(gameState.screen=='won') { drawWon(); }
	else if(gameState.screen=='playing') { drawPlaying(); }
	else if(gameState.screen=='menu') { drawMenu(); }

We then set our font and draw the framerate.

	ctx.textAlign = "left";
	ctx.font = "10pt sans-serif";
	ctx.fillStyle = "#000000";
	ctx.fillText("Frames: " + framesLastSecond, 5, 15);

Finally, we update the lastFrameTime to the value of currentFrameTime, and let the window know we'll handle the drawing next time it's ready for us to do so, before closing the function.

	lastFrameTime = currentFrameTime;
	
	// Wait for the next frame...
	requestAnimationFrame(drawGame);
}

Click coordinates helper

We'll also make use of a helper function to convert the event listener mouse coordinates (which are relative to the top-left of the document), to the actual position on the Canvas element:

function realPos(x, y)
{
	var p = document.getElementById('game');
	
	do {
		x-= p.offsetLeft;
		y-= p.offsetTop;
		
		p = p.offsetParent;
	} while(p!=null);
	
	return [x, y];
}
Page loaded in 0.01 second(s).