Vanilla JS Tutorials

JsIso Tutorials

RSS feed

02 - Creating a simple isometric Tile Engine

This tutorial covers switching from a tile map to an isometric tile map.

In this sample we make use of all the previous tutorial logic however we expand on it for images and isometric shaped tiles. We also tidy up our code by adding scope, getting rid of the onLoad <body> attribute and switch out fillRect for drawImage.

Isometric tiles are just as easy to achieve as a standard tile map. With a bit of shape alteration and minor positioning adjustment, you can change your flat 2D game concept into a user grasping “2D.5″ isometric engine, capable of graphical destruction and full user awe.

But where do you begin in creating such an experience?

To the drawing board!

So you start off with a 52×52 pixel square which represents part of the fields of Felderon, which gives your hero enlightenment and a sanithy increase while walked on, at the risk of a slight game ending seizure. Such a tile may look like this:



However this hero isn’t walking on any standard field of Felderon, he is standing on an isometric field of Felderon. So how do we change our tile to meet these requirements?

Basically we rotate it and half the height so our tile is now 52px wide and 26px tall. For drawing purposes it's best to keep both dimension values as even numbers. Instantly our field tile looks like it has some slight depth to it with the grass blades of pixel beauty growing out. For image format, pngs are used allowing alpha and the image overlap. This tile when placed into our soon to be coded engine would look like this:



So we have our tile and now we need to alter our previous example on creating a tile engine to match the isometric view.
Although our Felderon field tile is of a graphically inspiring status, we will need some other tiles to go along with it. Feel free to use this tile which represents the sea of despair, that when drank, generously reduces charisma with a 30% chance of sporadic teeth implosion.



Like the previous tutorial we have a map with each number representing a tile. We also have an array which will be used to store the loaded tile graphics.


var map = [
  [1,0,0,0],
  [1,0,0,1],
  [0,0,1,1],
  [1,1,1,1]
];

var tileGraphics = [];

Loading the desired images can be achieved with the following loop contained in our loadImg() function.

In this simple function for loading multiple tile images, tileGraphicsToLoad will hold all our tile images to be loaded, and our global variable tileImages array will contain the graphics for accessing.


function loadImg() {
    
  var tileGraphicsToLoad = ["/tutorials/images/water.png","/tutorials/images/land.png"],
      tileGraphicsLoaded = 0;

  for (var i = 0; i < tileGraphicsToLoad.length; i++) {
  
    tileGraphics[i] = new Image();
    tileGraphics[i].src = tileGraphicsToLoad[i];
    
    tileGraphics[i].onload = function() {
      tileGraphicsLoaded++;
      if (tileGraphicsLoaded === tileGraphicsToLoad.length) {
          drawMap();
      }
    }
  
  }

}

Pretty simple code really, it runs through the length of your tileGraphicsToLoad and as each image is successfully loaded it increments tileGraphicsLoaded by 1.

Next we adjust our drawMap to be specific for an isometric view and to make use of our loaded images.


function drawMap() {
    
  var ctx = document.getElementById('main').getContext('2d');

  var tileH = 25;
  var tileW = 52;
  
  var mapX = 76;
  var mapY = 52;

  var drawTile;

  for (var i = 0; i < map.length; i++) {
    for (var j = 0; j < map[i].length; j++) {
      drawTile = map[i][j];
      ctx.drawImage(tileGraphics[drawTile], (i - j) * tileH + mapX, (i + j) * tileH / 2 + mapY);
    }
  }
}

Exactly the same as the first tutorial we loop through the array lengths however the tile positioning code is slightly different.
Taking the changes in size and the fact that we are now positioning for an isometric view into account we calculate the position accordingly.
drawTile is set as the value of the current map array tile, and used for getting the matching tile image from the tileGraphics array.

Next we add an init function that will be called once the page has finished loading. This function removes the Event Listner and calls for the engine tile images to be loaded via loadImg();.


function init() {
    isometric.removeEventListener('load', init);
    loadImg();
};

And behold the fields of Felderon with the sea of despair flowing powerfully through it. That really is all there is to it as seen in the following Canvas element.


// Create the isometric scope.
// Tutorial Note: Wrapping all our code within a function this way means all 
// our variables and functions don't become globals. This prevents conflicts if you're using other scripts.
(function(isometric) {

  // Two Dimensional Array storing our isometric map layout. Each number represents a tile.
  var map = [
    [1,0,0,0],
    [1,0,0,1],
    [0,0,1,1],
    [1,1,1,1]
  ];

  var tileGraphics = [];

  function loadImg() {
      
    // Images to be loaded and used.
    // Tutorial Note: As water is loaded first it will be represented by a 0 on the map and land will be a 1.
    var tileGraphicsToLoad = ["/tutorials/images/water.png","/tutorials/images/land.png"],
    tileGraphicsLoaded = 0;

    for (var i = 0; i < tileGraphicsToLoad.length; i++) {
      tileGraphics[i] = new Image();
      tileGraphics[i].src = tileGraphicsToLoad[i];
      tileGraphics[i].onload = function() {
        // Once the image is loaded increment the loaded graphics count and check if all images are ready.
        tileGraphicsLoaded++;
        if (tileGraphicsLoaded === tileGraphicsToLoad.length) {
            drawMap();
        }
      }
    }

  }


  function drawMap() {
      
    // create the canvas context
    var ctx = document.getElementById('main').getContext('2d');

    // Set as your tile pixel sizes, alter if you are using larger tiles.
    var tileH = 25;
    var tileW = 52;
    
    // mapX and mapY are offsets to make sure we can position the map as we want.
    var mapX = 76;
    var mapY = 52;

    var drawTile;

    // loop through our map and draw out the image represented by the number.
    for (var i = 0; i < map.length; i++) {
      for (var j = 0; j < map[i].length; j++) {
        drawTile = map[i][j];
        // Draw the represented image number, at the desired X & Y coordinates followed by the graphic width and height.
        ctx.drawImage(tileGraphics[drawTile], (i - j) * tileH + mapX, (i + j) * tileH / 2 + mapY);
      }
    }
  }

  function init() {
    // Remove Event Listener and load images.
    isometric.removeEventListener('load', init);
    loadImg();
  };

  // Add Event Listener to dectect when page has fully loaded.
  isometric.addEventListener('load', init, false);

})(this);


Tutorial Outcome (View & Run Source)

7 comments

  1. Thank you so much for these tutorials. I am currently working on a isometric html 5 game and these tutorials are really helping me to understand the basics of how the isometric view is done. Thanks again!

    — Kenny Fri, 30 Jan 2015

  2. You are more than welcome Kenny, I'm glad to hear they help a little! Thanks :).

    — Iain Sun, 1 Mar 2015

  3. Thank you for these well made tutorials. Thanks to them I can actually understand how this stuff works.

    — Alan Fri, 11 Dec 2015

  4. To determine internal swelling is difficult enough, therefore, consequently, they influence the body for a long time, which threatens the normal fetus. Fluids are dangerous because they break blood circulation. Such picture leads to the strengthening of negative tendencies feeding and the breath baby, formed hypoxia.
    Fighting such a pathology should be done with the help of correction feeding and special procedures so that water does not stay tissues. If the woman is resting, then under the feet better put a cushion or pillow to improve the blood circulation of tired legs. Prohibited long time to sit or stand, as this leads to stagnation in the body. It is recommended that the knee-elbow position several times a day in order to increase blood flow.
    how to relieve breast pain during pregnancy

    KIRAsene Sun, 1 Jul 2018

  5. Peels help to escape from most age changes of the skin cover. operations effective at any time, adapted for skin of any type. After light exposure disappear small wrinkles, skin area turns out smooth, smooth. Adaptation – three days. an Average peeling well struggles wrinkles (expression, age, affects small scars, removes freckles.
    Adaptation – seven days. Deep peeling conducting in the beauty clinics. This is most effective procedure, but requires long term rehabilitation – about thirty days.
    what does a chemical peel do

    MirkaKall Fri, 27 Jul 2018

  6. Lump armpit delivers discomfort, aches. to Carry trip doctor is not appropriate. Lump under the muscle cavity may become cancer disease. But often it is consequences frequent use antiperspirants, non-compliance rules personal hygiene, strong sweating. Redness causes a close clothing, contaminated razor, the infection.
    i have a lump under my armpit
    Discomfort under the arm, redness, lump getting warm? This is the boil that should cut, next drink medications. In the first stage cost ointments, anti-inflammatory medicines. When the ailment switched to second stage, the required surgical procedure.

    Kulreiz Mon, 13 Aug 2018

  7. i did an randomly generated 2d isometric map generator thank to you !
    i will try to make a kinda FFTA clone someday
    maybe an MMOFFTA eventually if i make enough progress ( but that's an ultimate goal you know , i'd be glad to make a functionning FFTA clone in the first place )

    — sivmatt Tue, 9 Jan 2018

Please insert the result of the arithmetical operation from the following image:

Please insert the result of the arithmetical operation from this image. =