4

I've created an isometric environment, all in Javascript and HTML5 (2D Canvas), which mostly works fine. The problem I'm facing is to do with having different height tiles and then sorting the indexes of objects on the tiles (in this case, while moving between two tiles side-by-side).

For example, one object may be behind a tile in front of it because the height of the tile it is on is -1. The solution I came up with was to draw each object of a tile directly after drawing the tile, starting at 0,0 and drawing each row and column from there.

This works well until I need to transition an object between two tiles. At this point, either the object must use an intermediate tile (this is what is implemented in the images below) or the tile will overlap the object as the tile is drawn after the object. Using an intermediate tile also gives a problem where the fence object on the same "row" gets draw over because the cube is using much higher z-index from the tile at 1,3 (this is slightly visible in image 1).

https://i.sstatic.net/PQJ0H.png

https://i.sstatic.net/DupM7.png

I think the tried and tested way of drawing isometric environments is just to have 1 layer for tiles and 1 layer for objects and then objects can never be behind tiles, but this is just a limitation that I don't want to adhere to.

So my question is, when drawing the entire environment from top to bottom (or any other way if it makes it possible), drawing each tile and it's objects in turn, is there a clever way to defer drawing of an object or create an array of objects to be drawn in the correct order? Has anyone else encountered similar issues and has anyone else found any solutions for this?

All help much appreciated.

An example of my tiling code:

// each column
for(y=0; y<totalColumns; y++){
    // each row
    for(x=0; x<totalRows; x++){
        tile = tiles[y][x];
        // draw tile
        drawTile(tile);
        objects = objects[y][x];
        // draw objects for that tile
        drawObjects(objects);
    }
}

Edit:

One solution I have thought of (after reading the question back to myself) is to loop through all the tiles, get an array of tile heights, sort that, then do the traditional drawing. Like so:

var layers = [];

for(var y=0; y<cols; y++){
    for(var x=0; x<rows; x++){
        tile = tiles[y][x];
        if(!layers.indexOf(tile.height)) layers.push(tile.height);
    }
}

// sort layers
layers.sort(/*function here to sort layers*/);

for(l=0; l<layers.length; l++){
    // draw tiles for this layer

    // draw objects for this layer

}

Any other solutions possible?

1
  • 2
    You've solved your own problem. The height/Z-value is a common way to determine draw order. Since HTML5's canvas's draw order is the exact order of the code execution, you'll have to sort the draw order yourself.
    – Karis
    Commented Dec 4, 2012 at 6:20

1 Answer 1

1

Your doing the exact right thing in your solution. You want to do this for everything that doesn't have an alpha.

As far as other solutions go I would recommend looking at using an insertion sort rather than rebuilding the list time and time again. In your case there is very little change so just update the ones that need it.

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