Grid edges

from Red Blob Games
15 Jan 2019

Games with grids usually use the tiles but there are also cool things to do with edges and vertices. For construction games the edges can be useful for blocking connections between tiles (walls, chasms, windows) and allowing connections between tiles (doors, pipes, wires).

Let's start with an example: building walls. A common approach to implementing walls is to place thick walls on the tiles. An alternative is to place thin walls on the edges. Click on the tiles or edges to toggle the walls:

Thick walls on tiles
Thin walls on edges


Sometimes we want both tiles and edges. I try to make one of the two primary and then calculate the other one. In this example showing grid lighting, the tiles are primary. We can light edges when either tile is lit. Click on tiles:

Tiles are primary; edges are secondary (OR)

Consider the example of pipes/wires between adjacent tiles. We want to know which tiles are connected to the pipe network, but we also want to know which edges connect tiles to each other. If we make the tiles primary, we can place edges when both tiles are marked. Click on tiles:

Tiles are primary; edges are secondary (AND)

Alternatively, we can make the edges primary, and place pipes on tiles when any edge is marked. Click on edges:

Edges are primary; tiles are secondary (OR)

Here's an example of adding thin walls when exactly one neighboring tile has a thick wall. Click on tiles:

Tiles are primary; edges are secondary (XOR)

Whenever possible, I make either tiles or edges primary, and calculate the other using a function. I find this less error prone than putting constraints on what combinations of tiles and edges are allowed. The "pipe" style connectors and the "wall" style dividers use the same logic underneath. A pipe is drawn between the tile centers; a wall is drawn between the corners.

#Coordinate systems

Coordinates for square tiles have two different conventions. In math and in 3D graphics, Y increases upwards; in many 2D graphics systems, Y increases downwards. On this page I'm going to show Y increasing downwards.

{{tile.q}}, {{tile.r}}

How about edges? We could label the four sides of each square:


In many situations we want to treat 0,0,S and 0,1,N as the same edge, and similarly 0,0,E and 1,0,W. In these situations we can keep the N and W sides and discard S and E. We could've kept S instead of N, or E instead of W, but I'll work out the details for N and W.


Given a tile q,r its four bordering edges are q,r,N ; q,r,W ; q,r+1,N ; q+1,r,W.


The rules for edges depend on whether it's an N or W edge. Given an edge q,r,N its two joining tiles are q,r-1 ; q,r. Given an edge q,r,W its two joining tiles are q-1,r ; q,r.


For more details, including coordinates for corners and more tile+edge+corner relationships, see my guide to grids[1] (2006).

#Pixel lookup

In some games we want to be able to determine which tile/edge is closest to the mouse position. When working with tiles, we find the closest tile by looking at squares. These squares are exactly the same as the tiles. It's so simple we don't even think about it! Mouse over the map to see the area of pixels that would activate a tile.

When working with tile edges, we find the closest tile by looking squares at a 45° angle. Mouse over the map to see the area of pixels that would activate an edge.

If we want the mouse to work with both tiles and edges, we can build polygons that work with both. The tiles are detected with small squares, and edges are detected with hexagons. Move the slider to control the sizes, and mouse over the map to see what is activated.

Favor tiles ← → favor edges

Alternatively, calculate both the mouseover tile and mouseover edge, and pick the one that's closer to the mouse pointer.


Some games, such as Oxygen Not Included and Factory Idle, seem to have a hybrid that keeps track of both tile and edge connections. Some games, such as Factorio and Production Line, have directions along the edges; see my page about conveyor belts[5].

Email me at , or tweet to @redblobgames, or post a public comment: