• Skip to main content
  • Select language
  • Skip to search
MDN Web Docs
  • Technologies
    • HTML
    • CSS
    • JavaScript
    • Graphics
    • HTTP
    • APIs / DOM
    • WebExtensions
    • MathML
  • References & Guides
    • Learn web development
    • Tutorials
    • References
    • Developer Guides
    • Accessibility
    • Game development
    • ...more docs
Game development
  1. MDN
  2. Game development
  3. Techniques for game development
  4. Tiles and tilemaps overview
  5. Square tilemaps implementation: Static maps

Square tilemaps implementation: Static maps

In This Article
  1. The tile atlas
  2. The tilemap data structure
  3. Rendering the map
  4. Demo

This article covers how to implement static square tilemaps using the Canvas API.

Note: When writing this article, we assumed previous reader knowledge of canvas basics such as how get a 2D canvas context, load images, etc., which is all explained in the Canvas API tutorial, as well as the basic information included in our Tilemaps introduction article.

The tile atlas

A tilemap might use one or serveral atlases — or spritesheets — that contain all of the tile images. This is the atlas we will be using as an example, which features five different tiles:

Tiles packaged in an atlas

To draw a tile from the atlas into the canvas we make use of the drawImage() method in a canvas 2D context. We need to supply the atlas image, the coordinates and dimensions of the tile inside the atlas, and the target coordinates and size (a different tile size in here would scale the tile.)

So, for instance, to draw the tree tile, which is the third in the atlas, at the screen coordinates (128, 320), we would call drawImage() with these values:

context.drawImage(atlasImage, 192, 0, 64, 64, 128, 320, 64, 64);

In order to support atlases with multiple rows and columns, you would need to know how many rows and columns there are to be able to compute the source x and y.

The tilemap data structure

To store that map data, we can use a plain object or a custom class. For the sake of simplicity, in the example code a plain object has been used. It contains the basic map properties:

  • cols: The width of the map, in columns.
  • rows: The height of the map, in rows.
  • tsize: The tile size, in pixels.
  • tiles: A 1-dimensional array containing the visual grid.
  • getTile(): A helper method that gets the tile index in a certain position.

tiles contains the actual visual map data. We are representing the tiles with indices, assigned to the tiles dependant on their position in the atlas (e.g. 0 for the left-most tile.) However, we must account for empty tiles, since they are crucial for implementing layers — empty tiles are usually assigned a negative index value, 0, or a null value. In these examples, empty tiles will be represented by index 0, so we will shift the indices of the atlases by one (and thus the first tile of the atlas will be assigned index 1, the second index 2, etc.)

The getTile() helper method returns the tile contained at the specified column and row. If tiles were a 2D matrix, then the returned value would just be tiles[column][row]. However, it's usually more common to represent the grid with a 1-dimensional array. In this case, we need to map the column and row to an array index:

var index = row * map.cols + column;

Wrapping up, an example of a tilemap object could look like the following. This features an 8 x 8 map with tiles 64 x 64 pixels in size:

var map = {
  cols: 8,
  rows: 8,
  tsize: 64,
  tiles: [
    1, 3, 3, 3, 1, 1, 3, 1,
    1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 2, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 2, 1, 1, 1, 1,
    1, 1, 1, 1, 2, 1, 1, 1,
    1, 1, 1, 1, 2, 1, 1, 1,
    1, 1, 1, 0, 0, 1, 1, 1
  ],
  getTile: function(col, row) {
    return this.tiles[row * map.cols + col]
  }
};

Rendering the map

We can render the map by iterating over its columns and rows. This snippets assumes the following definitions:

  • context: A 2D canvas context.
  • tileAtlas: An image object containing the tile atlas.
  • map: The tilemap object discussed above.
for (var c = 0; c < map.cols; c++) {
  for (var r = 0; r < map.rows; r++) {
    var tile = map.getTile(c, r);
    if (tile !== 0) { // 0 => empty tile
      context.drawImage(
        tileAtlas, // image
        (tile - 1) * map.tsize, // source x
        0, // source y
        map.tsize, // source width
        map.tsize, // source height
        c * map.tsize, // target x
        r * map.tsize, // target y
        map.tsize, // target width
        map.tsize // target height
      );
    }
  }
}

Demo

Our static tilemap implementation demo pulls the above code together to show what an implementation of this map looks like. You can see a live demo and grab the full source code.

Document Tags and Contributors

Tags: 
  • atlas
  • Canvas
  • Games
  • JavaScript
  • spritesheet
  • Static
  • tilemap
  • tilemaps
  • tiles
 Contributors to this page: chrisdavidmills, ladybenko
 Last updated by: chrisdavidmills, Oct 14, 2015, 11:36:24 AM
  1. Introduction
    1. Introduction to game development for the Web
    2. Anatomy of a video game
    3. Examples
  2. APIs for game development
    1. Canvas
    2. CSS
    3. Full Screen
    4. Gamepad
    5. IndexedDB
    6. JavaScript
    7. Pointer Lock
    8. SVG
    9. Typed Arrays
    10. Web Audio
    11. WebGL
    12. WebRTC
    13. Web Sockets
    14. WebVR
    15. Web Workers
    16. XmlHttpRequest
  3. Techniques
    1. Using async scripts for asm.js
    2. Optimizing startup performance
    3. Using WebRTC peer-to-peer data channels
    4. Efficient animation for web games
    5. 3D games on the Web
      1. 3D games on the Web overview
      2. Explaining basic 3D theory
      3. Building up a basic demo with A-Frame
      4. Building up a basic demo with Babylon.js
      5. Building up a basic demo with PlayCanvas
      6. Building up a basic demo with Three.js
      7. Building up a basic demo with Whitestorm.js
      8. WebVR

    6. Audio for Web Games
    7. 2D collision detection
    8. 3D collision detection
      1. 3D collision detection overview
      2. Bounding volume collision detection with THREE.js
    9. Tiles and tilemaps
      1. Tiles and tilemaps overview
      2. Static maps
      3. Scrolling maps
    10. Implementing game control mechanisms
      1. Game control mechanisms overview
      2. Mobile touch controls
      3. Desktop mouse and keyboard controls
      4. Desktop gamepad controls
      5. Unconventional controls
  4. Tutorials
    1. 2D breakout game using pure JavaScript
    2. 2D breakout game using Phaser
    3. 2D maze game with device orientation
    4. 2D platform game using Phaser
  5. Publishing games
    1. Publishing games overview
    2. Game distribution
    3. Game promotion
    4. Game monetization