HTML5 Canvas [108]
Next, we loop through every column and row, randomly choosing a piece from the board array and moving it into newBoard:
for (var i = 0; i < cols; i++) {
NOTE
We use two nested for:next loops here once again.
Every time we come to an iteration of the outer nested loop, we create a new array that we will fill up in the second nested loop. Then we drop into that nested loop. The found variable will be set to true when we have found a random location to place the piece in the newBoard array. The rndRow and rndCol variables hold the random values we will create to try and find a random location for the puzzle pieces:
newBoard[i] = new Array();
for (var j =0; j < rows; j++) {
var found = false;
var rndCol = 0;
var rndRow = 0;
Now we need to find a location in newBoard in which to put the puzzle piece from the board array. We use a while() loop that continues to iterate as long as the found variable is false. To find a piece to move, we randomly choose a row and column, and then use them to see whether that space (board[rndCol][rndRow]) is set to false. If it is not false, we have found a piece to move to the newBoard array. We then set found equal to true so we can get out of the while() loop and move to the next space in newBoard that we need to fill:
while (!found) {
var rndCol = Math.floor(Math.random() * cols);
var rndRow = Math.floor(Math.random() * rows);
if (board[rndCol][rndRow] != false) {
found = true;
}
}
Finally, we move the piece we found in board to the current location we are filling in newBoard. Then, we set the piece in the board array to false so that when we test for the next piece, we won’t try to use the same piece we just found. When we are done filling up newBoard, we return it as the newly randomized array of puzzle pieces:
newBoard[i][j] = board[rndCol][rndRow];
board[rndCol][rndRow] = false;
}
}
return newBoard;
}
Drawing the screen
The drawScreen() function is the heart of this application. It is called on an interval, and then used to update the video frames and to draw the puzzle pieces on the screen. A good portion of drawScreen() looks like applications we have built many times already in this book. When it begins, we draw the background and a bounding box on the screen:
function drawScreen () {
//Background
context.fillStyle = '#303030';
context.fillRect(0, 0, theCanvas.width, theCanvas.height);
//Box
context.strokeStyle = '#FFFFFF';
context.strokeRect(5, 5, theCanvas.width−10, theCanvas.height−10);
However, the primary work of this function is—you guessed it—another set of two nested for:next loops that draw the puzzle pieces onto the canvas. This set needs to do three things:
Draw a grid of puzzle pieces on the canvas based on their placement in the board two-dimensional array.
Find the correct part of the video to render for each piece based on the finalCol and finalRow properties we set in the dynamic object for each piece.
Draw a yellow box around the piece that has its selected property set to true.
We start our loop by finding the x and y (imageX, imageY) locations to “cut” the puzzle piece from the video object. We do this by taking the finalRow and finalCol properties of the dynamic piece objects we created, and multiplying them by the partWidth and partHeight, respectively. We then have the origin point (top-left x and y locations) for the piece of the video to display:
for (var c = 0; c < cols; c++) {
for (var r = 0; r < rows; r++) {
var tempPiece = board[c][r];
var imageX = tempPiece.finalCol*partWidth;
var imageY = tempPiece.finalRow*partHeight;
Now that we know the origin point of the video we will display for a particular piece of the puzzle, we need to know where it will be placed on the canvas. While the code below might look confusing, it’s really just simple arithmetic. To find the x location (placeX) of a piece, multiply the partWidth times the current iterated column (c), then add the current iterated column multiplied by the xPad (the number of pixels between each piece), and add the startXOffset, which is