Autotiling

A guide to automatic tile selection for procedural maps & level editors

When building tile-based games, you usually want tiles to connect seamlessly. Grass should blend into dirt; walls should form proper corners and edges. Placing each tile variant by hand is tedious and error-prone. Autotiling automates this: for every cell in the grid, we look at its neighbors and pick the right tile variant automatically.

This article builds up autotiling from first principles, starting with the simplest approach (4 neighbors) and working up to the full 8-neighbor bitmask and the elegant dual-grid technique. Every section has an interactive demo — click on the grids to experiment.

Try it now: Click cells in the grid below to toggle them between two terrain types. The system automatically selects the right tile shape for every cell.

4-bit autotiling — click to paint terrain. Tiles update in real time.

1. The Core Idea: Neighbor Bitmask

Every autotiling system follows the same basic pattern:

  1. Check neighbors — For each cell, look at the cells around it.
  2. Encode as a number — Assign each neighbor direction a bit. If the neighbor matches (same terrain type), that bit is 1; otherwise 0.
  3. Look up the tile — Use that number as an index into a tileset.

The number of neighbors you check determines the number of possible tile variants:

Neighbors checkedBitsPossible valuesUnique tiles needed
4 (cardinal)40 – 1516
8 (cardinal + diagonal)80 – 25547 (with reduction)

Wait — 8 bits should give 256 values, so why only 47 tiles? We'll get to that in Section 3. Let's start simple.

2. Four-Bit Autotiling

We check only the four cardinal (N/E/S/W) neighbors. Each direction gets one bit:

DirectionBitValue
North01
East12
South24
West38

For a cell with matching neighbors to the North and West, the bitmask is 1 + 8 = 9. This gives us exactly 16 possible bitmask values (0 through 15), one for each combination.

The 16 tiles

Each bitmask value maps to a specific tile shape. Here are all 16:

All 16 four-bit tile variants with their bitmask values.

Implementation

function getAutotileIndex4(grid, x, y) {
    const here = grid[y][x];
    let mask = 0;
    if (y > 0            && grid[y-1][x] === here) mask |= 1;  // North
    if (x < width - 1    && grid[y][x+1] === here) mask |= 2;  // East
    if (y < height - 1   && grid[y+1][x] === here) mask |= 4;  // South
    if (x > 0            && grid[y][x-1] === here) mask |= 8;  // West
    return mask;
}

That's it. For each cell, compute the mask, then draw tileset[mask]. The demo at the top uses exactly this code.

3. Eight-Bit Autotiling (The "Blob" Tileset)

Four-bit autotiling handles edges nicely, but notice how corners look awkward — there's no way to distinguish an inner corner from an outer corner. To fix this, we also check diagonal neighbors.

DirectionBitValue
North01
NorthEast12
East24
SouthEast38
South416
SouthWest532
West664
NorthWest7128

The corner rule: 256 → 47

Eight bits naively gives 256 values, but many are impossible or redundant. The key insight: a diagonal neighbor only matters if both adjacent cardinal neighbors are also present.

For example, the NorthEast diagonal only matters if both North and East are filled. If North is empty, there's no visible corner to the NorthEast regardless of what's there. So we mask out irrelevant diagonal bits:

function getAutotileIndex8(grid, x, y) {
    const W = grid[0].length, H = grid.length;
    const here = grid[y][x];
    const match = (dx, dy) =>
        x+dx >= 0 && x+dx < W && y+dy >= 0 && y+dy < H
        && grid[y+dy][x+dx] === here;

    const n  = match( 0,-1), e  = match( 1, 0),
          s  = match( 0, 1), w  = match(-1, 0);
    const ne = match( 1,-1), se = match( 1, 1),
          sw = match(-1, 1), nw = match(-1,-1);

    let mask = 0;
    if (n)          mask |= 1;
    if (n && e && ne) mask |= 2;
    if (e)          mask |= 4;
    if (e && s && se) mask |= 8;
    if (s)          mask |= 16;
    if (s && w && sw) mask |= 32;
    if (w)          mask |= 64;
    if (w && n && nw) mask |= 128;
    return mask;
}

With this reduction, only 47 unique tile shapes are possible. This is called the "blob" tileset or 47-tile set.

Why "blob"? Because the tiles can form any blob-like shape with smooth inner and outer corners. The 47 tiles cover every possible neighborhood configuration.

Interactive 8-bit demo

Click below to paint. Notice how inner corners (concave turns) are now properly handled — something the 4-bit version couldn't do.

8-bit (47-tile) autotiling — notice the smooth inner corners.

4. The Bitmask-to-Tile Lookup

In practice, you don't draw 47 (or 256) separate sprites. There are two common strategies:

Strategy A: Lookup table

Pre-compute a mapping from each valid bitmask to a tile index (0–46). Many engines (Godot, Tiled, RPG Maker) use this approach. You create the 47 tiles in your art tool, assign them indices, and build a lookup array.

Strategy B: Composite from sub-tiles

Split each tile into four quarter-tiles (mini-tiles). Each quarter only needs to know about three neighbors (two cardinal + one diagonal). This means each quarter has only 2³ = 8 possible states — so you need just 8 mini-tile variants per quarter. In total: 5 unique mini-tile shapes (due to symmetry), composited into 4 quadrants.

A tile split into four quadrants. Each quadrant picks from 5 mini-tile shapes.

RPG Maker uses a variant of this mini-tile approach, which is why its tilesets look compact yet produce smooth results.

5. Dual-Grid Autotiling

There's an elegant alternative to bitmasks that simplifies art production: the dual-grid (sometimes called "dual tilemap") technique.

The idea: maintain two grids offset by half a tile. The data grid stores your terrain values. The display grid is offset so that each display tile sits at the intersection of four data cells:

  Data grid:           Display grid (offset by half):

  A . B . C              ╔═══╦═══╗
  . . . . .              ║ ab║ bc║
  D . E . F              ╠═══╬═══╣
  . . . . .              ║ de║ ef║
  G . H . I              ╚═══╩═══╝

Each display tile looks at the four data-grid corners surrounding it. With two terrain types, that's 2⁴ = 16 possible combinations — the same as 4-bit autotiling, but now the tiles represent transitions between four corners rather than edges from a center.

Why is this great?

Dual-grid autotiling — click to toggle data cells (small squares). Display tiles update automatically.

6. Wang Tiles

Wang tiles come from mathematics (Hao Wang, 1961) but map beautifully onto game tiling. The concept: each tile edge is assigned a color (or label). Tiles can only be placed next to each other if their shared edges have the same color.

In autotiling terms, the bitmask encodes which edges should "match" with neighbors. Wang tiles formalize this — and they also enable aperiodic tiling, where you can fill an infinite plane without repeating patterns. This is useful for procedural generation to avoid the visual monotony of repeating tiles.

A common game-dev application: create a small set of Wang tiles with two edge colors (2-edge-color Wang tile set = 16 tiles, same count as our 4-bit autotile set). The tile placement algorithm ensures matching edges, producing organic-looking variety.

7. Marching Squares Connection

If you've used Marching Squares for contour rendering, you may recognize the dual-grid idea. Marching Squares assigns values to grid corners and draws contour lines through cells. Dual-grid autotiling is essentially the same concept, but instead of drawing vector contour lines, you select pre-drawn tile sprites.

Marching SquaresDual-Grid Autotiling
InputScalar field at cornersTerrain type at corners
Cases16 (4 corners × 2 states)16 (4 corners × 2 states)
OutputLine segments / polygonsTile sprites

8. Practical Tips

Multiple terrain types

With more than two terrain types, assign a priority to each. A cell "matches" its neighbor if the neighbor has the same or higher priority. Each terrain gets its own tileset overlay, drawn from lowest to highest priority.

Animated tiles

Autotile indices are stable — a cell's bitmask only changes when a neighbor changes. So you can safely animate tiles (e.g., water ripples) by cycling frames within the same bitmask index.

Performance

Recompute bitmasks only when the grid changes, and only for the cells whose neighbors were modified. Cache the resulting tile indices. This makes autotiling essentially free at runtime.

Common tileset layouts

Many engines expect specific tileset arrangements:

9. Comparison Chart

TechniqueTiles neededCorners?Art complexityBest for
4-bit bitmask16NoLowPrototyping, simple styles
8-bit blob47YesMediumPolished 2D games
Dual grid16YesLowSmooth terrain transitions
Mini-tile (2×2)5 shapesYesLowRPG Maker style

10. Summary

  1. Encode neighbors as bits — that's the bitmask.
  2. Use the bitmask to select tiles — from a lookup table or by compositing sub-tiles.
  3. For corners, either use 8-bit bitmasks (47 tiles) or the dual-grid trick (16 tiles).
  4. Only recompute when the grid changes — cache everything.

Autotiling turns a tedious art/design problem into a simple algorithmic one. Once you set up the tileset and the bitmask logic, your maps just work — every edge lines up, every corner is smooth, and your level designers (or your procedural generator) can focus on the big picture instead of fiddling with individual tiles.

Written 2026. Inspired by Red Blob Games. Interactive demos use HTML5 Canvas with no external dependencies.