3

Here is my script, I can't seem to figure out what's wrong, I want to draw a tile map 12*12 and the tiles are 32px - 32px. The tiles dont draw when I run the page, Ive tried using parse int as shown below but still, it didn't work.

if(parseInt(mapArray[x][y]) == 0){
    ctx.drawImage(rockTile, posX, posY, tileSize, tileSize);
}

Here is the script I have created.

var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = (32 * 12);
canvas.height = (32 * 12);
document.body.appendChild(canvas);

var rockTile = new Image();
rockTile.src = "../Images/dc-dngn/floor/rect_gray0.png";
var tileSize = 32;
var posX = 0;
var posY = 0;

var mapArray = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
];

$(document).ready(function(){
    drawMap();
});

function drawMap(){
    for(var x = 0; x < mapArray.length; x++){
        for(var y = 0; y < mapArray[x].length; y++){
            if(mapArray[x][y] == 0){
                ctx.drawImage(rockTile, posX, posY, tileSize, tileSize);
            }
            posX += 32;
        }
        posX = 0;
        posY += 32;
    }
}

If anyone can help me to get my tiles to draw that would greatly appreciated, Thank you!

3
  • Are you sure this should be jquery tagged? I don't see any jquery here?
    – Kolban
    Commented Nov 1, 2014 at 20:55
  • 2
    @Kolban $(document).ready( is jQuery
    – Entity
    Commented Nov 1, 2014 at 21:05
  • @TheAdamGaskins Thank you sir, I missed that. I usually expect to see more jQuery in there than just an onload handler.
    – Kolban
    Commented Nov 1, 2014 at 21:06

2 Answers 2

2

You must wait for the image to load. That image is not part of the DOM and therefore waiting for the loading of the document won't help.

You need to place an handler for the image.onload slot and trigger a redraw when that code is called.

The normal procedure is

  1. create the image object
  2. register the onload event for it
  3. set up the image src value

only when the registered event is called you can use the image object.

The tricky part is that, depending on the browser, the image may become instantly valid after setting src if it's already in the cache, so when you don't follow the correct procedure things may apparently work anyway (but they will not work in real cases when loading requires internet access).

2
  • +1 -- @MitchWardle, I forked my original Fiddle to use this approach (and deleted my original approach, since it was missing the key step explained in this answer). Now the rock grid shows up on the initial load. It also works in a separate HTML file on my workstation, even without jQuery. Here's the new, correctly working Fiddle: jsfiddle.net/troygizzi/ura8kkw2
    – Troy Gizzi
    Commented Nov 1, 2014 at 21:07
  • @TroyGizzi Your code is being executed onLoad. OP's code was being executed onDomReady.
    – Entity
    Commented Nov 1, 2014 at 22:50
0

You have two main problems that I can see:

  1. You are accessing document.body before it is defined.
  2. You are using the image possibly before it is loaded.

Here is code that solves both these problems:

// variables are defined as global variables
var posX = 0;
var posY = 0;
var tileSize = 32;
var mapArray;
var canvas;
var ctx;
var rockTile;

$(function() {
    // document should be defined now
    canvas = document.createElement("canvas");
    ctx = canvas.getContext("2d");
    canvas.width = (32 * 12);
    canvas.height = (32 * 12);
    document.body.appendChild(canvas);

    mapArray = [
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    ];

    // wait until the image is loaded to draw
    rockTile = new Image();
    rockTile.onload = drawMap;
    rockTile.src = "../Images/dc-dngn/floor/rect_gray0.png";        
});

function drawMap(){
    posX = 0;
    posY = 0;
    for(var x = 0; x < mapArray.length; x++){
        for(var y = 0; y < mapArray[x].length; y++){
            if(mapArray[x][y] == 0){
                ctx.drawImage(rockTile, posX, posY, tileSize, tileSize);
            }
            posX += 32;
        }
        posX = 0;
        posY += 32;
    }
}

Also be sure to double check your image path.

2
  • The document object is available from the moment JavaScript begins executing. Commented Nov 2, 2014 at 0:54
  • @GregBurghardt You are correct. I should have put document.body.
    – Entity
    Commented Nov 2, 2014 at 1:11

Not the answer you're looking for? Browse other questions tagged or ask your own question.