Reputation: 53
I'm in the process of building a simple level placement script in HTML5 canvas, and I'm having trouble actually placing each element down. I've written a for loop that creates a grid, then I'm trying to create a new loop that iterates through each statement in my 'level' array to set positions for each image. I haven't done a lot with Canvas before; as such, I'm not sure what I'm doing wrong in regards to placing these images; I've written something very similar to this in jQuery that works just fine - in fact, I copied and pasted the code to start with, but it doesn't seem to work in Canvas. Any help would be appreciated!
Here's a snippet of the code; forgive the over-commenting, this is just a thing I do when I'm having trouble understanding why something doesn't work. It's like an inline Rubber Duck.
var $levelArray = [
[0, 0, 0, "blue", "blue"],
[0, "gray", 0, 0, 0],
["blue", "blue", "green", 0, "blue"],
["blue", 0, "yellow", 0, 0],
[0, 0, 0, "gray", 0],
["red", 0, 0, 0, 0]];
var border = 5, // set grid details
spaceWidth = 80,
spaceAmount = 5;
// create a tiled image
function makeTile(imageUrl, horizontalPosition, verticalPosition) {
var tile = new Image();
tile.onload = function() {
context.drawImage(tile, horizontalPosition, verticalPosition);
}
tile.src = imageUrl;
}
// place the image tiles on the board
for (var i=0; i < ($levelArray.length - 1); i++) {
var row = $levelArray[i]; // set each row's iterative position
var rowHeight = 5;
for (var j=0; j < row[j].length; j++) {
var rowPosition = 5; // set the left margin of each element
if (row[j] == 0) {
rowPosition += (spaceWidth + 5); // if an element does not exist, jump forwards to the next space
} else {
//if one DOES exist, place an image in this space
makeTile("http://lorempixel.com/80/80", rowPosition, rowHeight);
rowPosition += (spaceWidth + 5); // then move to the next space
};
};
rowHeight += (spaceWidth + 5); // once a row is complete, drop to the next row's positions
};
I have this in a codepen here: http://codepen.io/sarsparillo/pen/vNrWQG
I'm not sure why it's only loading one image at a time and putting it in the 0,0 space on my grid; using very similar code in jQuery (current code, which is pretty all over the place and sort of unclean, is here - http://codepen.io/sarsparillo/pen/GpdjYY) puts elements in the right place just fine.
More, when I added a console.log statement to those for loops, I honestly can't work out where the hell it's getting data from. Like, one iteration gave me 'green green yellow' as the items in row[j], another 'blue gray blue' - does Canvas do something absolutely bizarre with iterating through an array? I can't see how it could, seeing as this is just Javascript, but...?
Does anyone have any idea why this is happening, or any tips as to how I can resolve this? In theory, it should just be adding the space width + the margin width to the start point of each 'square', so I'm not sure why it just... isn't.
Upvotes: 0
Views: 1330
Reputation: 5897
jsFiddle : https://jsfiddle.net/CanvasCode/4gr9apqm/
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var border = 5, // set grid details
spaceWidth = 80,
spaceAmount = 5;
var $levelArray = [
["blue", 0, 0, "blue", "blue"],
[0, "gray", 0, 0, 0],
["blue", "blue", "green", 0, "blue"],
["blue", 0, "yellow", 0, 0],
[0, 0, 0, "gray", 0],
["red", 0, 0, 0, 0]
];
canvas.width = (spaceWidth * spaceAmount) + (5 * spaceAmount) + 5; // and here's the canvas size
canvas.height = (spaceWidth * spaceAmount) + (5 * spaceAmount) + 5;
// make a rounded corner square; using a sizing hack to make sure that strokes don't effect the full size of the item
function square(originX, originY, size, corner, fill) {
var startFromX = originX + (corner / 2);
var startFromY = originY + (corner / 2);
var extentsX = startFromX + (size - corner);
var extentsY = startFromY + (size - corner);
context.lineJoin = "round";
context.lineWidth = corner;
context.fillStyle = "#513574";
context.strokeStyle = fill;
context.beginPath();
context.moveTo(startFromX, startFromY);
context.lineTo(startFromX, extentsY);
context.lineTo(extentsX, extentsY);
context.lineTo(extentsX, startFromY);
context.closePath();
context.stroke();
context.fill();
}
// build a grid of said squares
function squareGrid(spacing, size, corner, color, amount) {
for (var x = 0; x < amount; x++) {
// build rows
for (var y = 0; y < amount; y++) {
// build column spacing in each row
square(5 + (size * x) + (spacing * x), 5 + (size * y) + (spacing * y), size, corner, color);
// build each square
}
};
};
// actually parse the arguments for said square
squareGrid(border, spaceWidth, (border * 2), "#f13574", spaceAmount);
// create a tiled image
function makeTile(tile, horizontalPosition, verticalPosition) {
switch (tile) {
case "blue":
context.fillStyle = "#00F";
context.fillRect(horizontalPosition, verticalPosition, 80, 80);
break;
case "green":
context.fillStyle = "#0F0";
context.fillRect(horizontalPosition, verticalPosition, 80, 80);
break;
case "red":
context.fillStyle = "#F00";
context.fillRect(horizontalPosition, verticalPosition, 80, 80);
break;
case "gray":
context.fillStyle = "#999";
context.fillRect(horizontalPosition, verticalPosition, 80, 80);
break;
case "yellow":
context.fillStyle = "#FF0";
context.fillRect(horizontalPosition, verticalPosition, 80, 80);
break;
}
};
var gapHeight = 5;
var gapWidth = 5;
for (var y = 0; y < $levelArray.length - 1; y++) {
var row = $levelArray[y];
for (var x = 0; x < row.length; x++) {
var newXPos = (gapWidth * (x + 1)) + (80 * x);
var newYPos = (gapHeight * (y + 1)) + (80 * y)
makeTile($levelArray[y][x], newXPos, newYPos);
}
}
All I have changed is basically how you access your 2D array and the position calculation. Basically the first thing you access is your Y position, then from your Y position you look at all the blocks on that row. So we first find "in my case" blue, 0, 0, blue, blue
. so all of these will have y position 0, and then it will go from 0, 80, 160 and etc. However because you wanted a gap in between the blocks you also have to multiple the gap by the x and y value at that time :)
Upvotes: 2