This is about the creation of a tile map (64x64 pixel PNGs).
For demonstration purposes I simplified my code and reduced the grid to a 3x3 field.
The issue is essentially that the images are still loading when I draw the grid, so the canvas won't show on first load. On refresh however, the grid loads fine as all image files are now cached.
<body>
<canvas id="canvas" width="200px" height="200px"></canvas>
<script>
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
// 3X3 GRID
var mapArray=[
["tile1","tile3","tile1"],
["tile1","tile1","tile2"],
["tile3","tile1","tile2"]
];
var tile1 = new Image();
var tile2 = new Image();
var tile3 = new Image();
tile1.src='../images/test/tile1.png';
tile2.src='../images/test/tile2.png';
tile3.src='../images/test/tile3.png';
var posX=0;
var posY=0;
for(var i=0; i < mapArray.length; i++) {
for(var j=0; j < mapArray[i].length; j++) {
switch(mapArray[i][j]) {
case "tile1":
context.drawImage(tile1, posX, posY, 64, 64);
break;
case "tile2":
context.drawImage(tile2, posX, posY, 64, 64);
break;
case "tile3":
context.drawImage(tile3, posX, posY, 64, 64);
break;
}
posX+=64;
}
posX=0;
posY+=64;
}
</script>
</body>
Similar issues can be found:
Canvas image not displaying until second attempt
Why do my canvases only load on refresh?
In this case though I am trying to generate not just one image, but a grid of images and my attempt at solving this seems to run into issues as nothing loads at all:
<body>
<canvas id="canvas" width="200px" height="200px"></canvas>
<script>
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
// 3X3 GRID
var mapArray=[
["tile1","tile3","tile1"],
["tile1","tile1","tile2"],
["tile3","tile1","tile2"]
];
var tile1 = new Image();
var tile2 = new Image();
var tile3 = new Image();
var posX=0;
var posY=0;
for(var i=0; i < mapArray.length; i++) {
for(var j=0; j < mapArray[i].length; j++) {
switch(mapArray[i][j]) {
case "tile1":
//use onload so drawing waits until image file is loaded
tile1.onload = function() {
//draw image
context.drawImage(tile1, posX, posY, 64, 64);
};
//load image file
tile1.src='../images/test/tile1.png';
break;
case "tile2":
tile2.onload = function() {
context.drawImage(tile2, posX, posY, 64, 64);
};
tile2.src='../images/test/tile2.png';
break;
case "tile3":
tile3.onload = function() {
context.drawImage(tile3, posX, posY, 64, 64);
tile3.src='../images/test/tile3.png';
break;
}
posX+=64;
}
posX=0;
posY+=64;
}
</script>
</body>
As you can see, my 3 switch options each are now waiting for the image to load before drawing it.
I read somewhere that it might be to do with the FOR loop, and I'd have to use an IIFE which I found more on here: What is the (function() { } )() construct in JavaScript? However, am completely unfamiliar with this term / concept nor do I know if I'm on the right track.
I was also trying to load this via an external js and then onload="drawTileMap()" in the body tag, however that throws up even funkier behaviour, because then it really seems to load random tiles instead of the entire grid.
Any help much appreciated!