Square tilemaps implementation: Static maps - Game development 编辑

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

词条统计

浏览:115 次

字数:6023

最后编辑:7年前

编辑次数:0 次

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文