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)

27 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. Plastic Surgeon Dr. Brzowski, serving Salt Lake City & Ogden, Utah Plastic Surgery expert, performs a wide array of cosmetic surgery procedures for residents
    how often should you get a chemical peel
    Loss of GRHL3 leads to TARC/CCL17-mediated keratinocyte proliferation in the epidermis Cell Death &ampe Therapy

    Zukstab Mon, 25 Mar 2019

  5. aller à bientôt tu en

    http://videobrunesexy.hotviber.fr/ Wed, 27 Mar 2019

  6. Get answers to some of the most frequently asked questions about dermabrasion and other skin care procedures offered by Dr. John Kim.
    acne scars before and after chemical peel
    Minimally Invasive Rejuvenation of the Face and Neck, An Issue of Clinics in ... - Kenneth Rothaus - Googleed.com

    Zukstab Mon, 1 Apr 2019

  7. useful and interesting article, found a lot of useful information, glad to join your community!
    192.168.1.254

    192.168.1.1 Wed, 3 Apr 2019

  8. https://www.lechateauguillestre.com/
    MARINE

    MARINE Fri, 12 Apr 2019

  9. El servicio electrГіnico de verificaciГіn de elegibilidad de empleo E-Verify ha reanudado sus operaciones despuГ©s de no haber estado disponible por mГЎs de
    inteligencia artificial
    Un puntaje bajo de iq puede calificarlo para beneficios de seguridad social. judgelondonsteverson obteniendo seguridad social Obtenga una nueva tarjeta de seguridad social, nГєmero de telГ©fono de seguridad social, cambio de nombre de seguridad social, oficina de administraciГіn de seguridad social, oficinas de seguridad social

    Zyccorm Sat, 13 Apr 2019

  10. Really good explanation of the basics - thank you for sharing

    Commercial Cleaning Companies Tue, 16 Apr 2019

  11. Great guide, many thanks for sharing

    removals service

    Rubbish removal Wed, 17 Apr 2019

  12. https://www.explosederire.com/
    MARINE

    MARINE Wed, 17 Apr 2019

  13. Breast Cancer - Causes, Signs, Symptoms & Prevention - Times of India
    [url=http://armpit.info/how-much-should-you-worry-about-painful-lump-under-armpit/]lump under armpit hurts[/url]

    BOLWhova Fri, 19 Apr 2019

  14. https://www.explosederire.com/
    MARINE

    MARINE Sat, 20 Apr 2019

  15. I have read your blog it is very helpful for me. I want to say thanks to you. I have bookmark your site for future updates.ahealthytalk.com

    — jams Mon, 22 Apr 2019

  16. https://www.explosederire.com/
    MARINE

    MARINE Tue, 23 Apr 2019

  17. Thank you for making it understandable. I would appreciate it more if you can share a video on how you tweak it. Thanks!

    concrete repair yuma Thu, 25 Apr 2019

  18. I never thought creating isometric engine tiles could be this easy. Thank you so much for your help! I survived the semester because of this.

    concrete driveway contractors little rock ar Thu, 2 May 2019

  19. “ burned out ” fibrotic This was the first time Kimuras disease was observed as a pigmented area located on the hard palate. The diagnosis of melanoma first had to be ruled out. The
    [url=http://magdalenabus.tk/page/burnt-top-of-mouth/]Burnt top of mouth[/url]

    Bernphida Fri, 3 May 2019

  20. The dental hygienist salary in the US stands at $54,495 per year, while in Canada that is C$57,794 ($44,270) every year. Australia has an even lower pay for
    [url=http://bobijoel.ml/dental-hygienist-jobs-seattle/1/]Dental hygienist jobs seattle[/url]

    Denkap Sun, 5 May 2019

  21. Creating a simple isometric Tile Engine is not an easy one, because this is so tricky and it's hard to understand, but I'm thankful to have this guide because it really helps me to pass the said process. Good Job!

    Cincinnati Channel Letter Signs Thu, 9 May 2019

  22. https://www.explosederire.com/
    MARINE

    MARINE Thu, 9 May 2019

  23. I have encountered this on my college days and I never thought I could apply it on my present job today. Plus this will be a review material for me as well. Thanks for posting this! More power!

    Want to file or renew your social security site? visit our site

    Brielle Fri, 10 May 2019

  24. 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

  25. Great post! Thanks for sharing these tutorials! Keep 'em posting!
    Aryan | Falls Church towing

    AryanMag Mon, 13 May 2019

  26. i will try to make a kinda FFTA clone someday
    domaineverest.org

    domaineverest Mon, 20 May 2019

  27. I'm impressed with the process that you've shared, this is a big help to me for my future research. Thanks for posting!

    Top Mexico Destinations Wed, 22 May 2019

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

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