If you have done any work with hex grids, the chances are good that you came across the best guide for the mathematics and algorithms for hex grids: Hexagonal Grids by Amit Patel. One user suggested that it may be a good idea to show how Grids can be used for all the operations described in that guide (and where those functions are) since it is so popular. We agree, so here it is!
Angles, Size and Spacing
For the most part, if you use Grids, you don’t have to worry about these low-level details. Conversion to world space is handled by maps. Hex maps need a Vector2 of dimensions – the width and height of your cell, and it will automatically work out the correct spacing and division of space.
It also means that you can work with hexagons scaled differently along each axis. This is useful when working with isometric hexes, for example.
Coordinate Systems
Grids only work with one coordinate system: axial coordinates. In the very early days of Grids (before it was for sale), we used offset coordinates. As we made more examples and implemented more algorithms, we found that the offset coordinate system is very clumsy, so we changed it to use axial coordinates instead. The axial coordinate system works like a (integer) vector space, and many algorithms are much simpler compared their implementations using offset coordinates. In particular, it makes sense to add two points together to get a third (where the second point is interpreted as an offset).
There are two cases where offset coordinates can be useful:
- For display (on certain boards, the coordinates may be more compact and attractive, since they don’t have to have negative values, while still having a corner as the origin)
- For certain algorithms (if your game uses for instance rows and wiggly columns)
In these two cases, you will have to implement a conversion, something which is straightforward to do.
Neighbors
Grids have two methods for accessing the neighbors of a point:
Grid.GetAllNeighbors(point)
gives a list of all neighboring points, regardless of whether they are in the grid or not.
Grid.GetNeighbors(point)
gives a list of neighbors that are also in the grid. This is the method you will most commonly use in your own algorithms.
Hex grids also have constants defined for each direction a neighbour can be in:
PointyHexPoint.NorthWest
etc.
These can be added to a point to get the neighbor:
var northWestNeighbor = point + PointyHexPoint.NorthWest;
Diagonals
Grids does not support diagonals directly, but it is easy to define your own constants for diagonal directions, for example:
readonly PointyHexPoint North = PointyHexPoint.NorthWest + PointyHexPoint.NorthEast;
You can then add them to points to get their “diagonal” neighbors:
var northNeighbor = point + North;
Distances
To get the grid distance between two points, you can use the DistanceFrom method defined on points.
var distance = onePoint.DistanceFrom(otherPoint);
Line Drawing
We provide line drawing methods as extensions for maps.
To get a line between two points, you call
var points = Map.GetLine(p1, p2); //where map is the map you used to position cells, or the Map property of the GridBehaviour, if you use GridBehaviours.
Coordinate Ranges
To get all the points within a certain distance from a give point, you can use a simple LINQ query:
var pointsInRange = grid.Where(p => p.DistanceFrom(center) <= range);
For intersections, you can chain queries
var pointsInRange = grid .Where(p => p.DistanceFrom(center1) <= range1) .Where(p => p.DistanceFrom(center2) <= range2);
There are too complications which you may face in your game: you may wish either of these:
- to use different distance metrics (including weighted costs)
- to take obstacles into account
For this, we provide PointsInRange methods. There is a tutorial for using this feature here: ###
Rotation
Hex points have several rotation functions: Rotate60, Rotate60About, Rotate120, Rotate120About, and so on.
There are also methods defined on Algorithms to transform a list of points: Transform, which you can use as follows:
var newList = Algorithms.Transform(p => p.Rotate60);
Algorithms also define special rotations: rotations around an edge (you give the two neighboring points as input), and rotations around a vertex (you give the three neighboring points as input).
Rings
As with point in range, you can use a LINQ query to get all the points in a ring around another point:
var pointsInRange = grid.Where(p => p.DistanceFrom(center) == range);
Spirals
Hex grids provides methods SpiralIterator to get spirals.
You can either use them in a loop:
for(var point in grid.SpiralIterator(4)) { DoSomethingWith(point); }
Or just get a list straight:
grid.SpiralIterator(4).ToList();
Field of View
We do not have this function. But it’s easy to implement as we show in this example: Field of View Example.
Hex to Pixel and Pixel to Hex
Here, you can use maps for both operations:
var pixel = map[hexPoint];
OR
Var hexPoint = map[pixel];
Rounding to nearest hex
Generally, rounding to nearest hex is not necessary. If for some reason you do need to do it, you can simply use a map, with dimensions 1×1.
Map Storage
The beauty of Grids is that you need not worry about storage at all, everything is taken care of behind the scenes. This is really convenient when making more complicated shapes using the grid builder functionality.
Pingback: Hexagonal Grids (2013) – Veritas Reporters