I have been using @amitp's excellent guide (and javascript library) to create a hexagonal grid system https://www.redblobgames.com/grids/hexagons/. I'm using flat-top, inverse-y cubic/axial system. However, I have elements that are located on the vertices, rather than "within" a tile. How would I refer to their position? I have considered using the index of the corner, but then the question is which tile do I use as my base? I would also like to extend the concept so that I could precisely position an element anywhere within a tile. I am thinking of something relating to the Ordnance Survey's method of sub-division within the British National Grid (OSGB 1936) but I cannot get my head around how this relates to a cubic/axial coordinate system.
-
1\$\begingroup\$ Maybe not the most elegant way, but if you refer the coordinate as a tripled of the 3 tiles, you dont have the problem of deciding which one is the base tile and you always can refer to the corner. For the side you just need to refer two tiles, for within a single tile with the offset \$\endgroup\$– ZibelasCommented Feb 13, 2020 at 9:28
-
1\$\begingroup\$ An interesting idea but effectively that results in a fairly complex and inconsistent data storage: [q,r,s] for centre of tile; [[q,r,s],[q,r,s]] for edge; [[q,r,s],[q,r,s],[q,r,s]] for vertex. And I'm still none the wise how to do the offset within a tile. And as for calculating distances between these... \$\endgroup\$– George of all tradesCommented Feb 13, 2020 at 9:54
-
\$\begingroup\$ Possible duplicate: gamedev.stackexchange.com/questions/167628/… \$\endgroup\$– MaxCommented Feb 13, 2020 at 21:15
4 Answers
I have considered using the index of the corner, but then the question is which tile do I use as my base?
In an (infinite) hexagonal grid, every hex got 6 adjacent vertices and every vertex is shared by 3 adjacent hexes. That means that if you want each vertex to "belong" to one and only one hex, then each hex would have to "own" two vertices. That way every vertex would have an "owner". Which two vertices? That's up to you. If you choose the same two vertices of each hex (the upper pair, the lower pair, left&right, or any other), then you will notice that every vertex now clearly belongs to a hex.
Unless, of course, if you have a finite grid. Then you would have vertices at the border which would need to be owned by a "virtual" hex that's outside of the grid. But that's a problem you have with rectangular tiles as well.
That means you can address every vertex by the address of its owning tile, plus an additional bit for "left vertex" or "right vertex".
I would also like to extend the concept so that I could precisely position an element anywhere within a tile.
In that case I would use a sub-coordinate system for position within the tile. For consistency, I would recommend to use the same axis conventions as you are using for the tiles themselves. But that might depend on your requirements and personal preference.
Only regarding your first question
but then the question is which tile do I use as my base?
ANY as long as you use a consistent scheme. For example ALWAYS find the leftmost tile (you need phantom extra ones for the edge of your map), and then (if applicable) the topmost of the two possible ones.
And then you only have one line (with a bent) on which to place any objects
An answer depends on a couple of facts: Can your elements only rest on vertices? If not can they move from a vertex of a hex to the center of that hex?
My first thought on this question was to set each vertex's coordinates to the average of the coordinates of the 3 hex' surrounding it, for instance, if a unit was on the vertex between the three tiles [0, 0], [0, -1] and [+1, -1] it would have the coordinate [0.5, -1].
But this results in two issues: one the vertex coordinates aren't unique when compared to the hex coordinates (There is a [-2, +1] tile and its rightmost vertex is also [-2, +1]) and two, referring back to my questions, if the elements can move from vertices to hex center's then when working out the distance becomes weird. Basically the distance from a vertex to an adjacent vertex is 1, from a vertex to one of the connected hexes' centers is also 1 and from a vertex to another vertex that is 2 vertices away (i.e. with flat top hexes from the left most vertex to the top right vertex) is a distance of 1.5 .
In other words the distance from hex to hex becomes equal to that from vertex to vertex with a couple twists.
Hopefully this helps, if you need images to show what I'm describing I can create them but I would rather wait for you to ask for them first.
-
2
-
\$\begingroup\$ Isn't the average in your first example (⅓, -⅔), not (0.5, -1)? If you calculate it this way, the coordinates are indeed unique at the vertices, and the distances are actually uniform. I think the technique shown at the link you shared would be worth summarizing in an answer. \$\endgroup\$– DMGregory ♦Commented Jul 13, 2020 at 10:49
Maybe I'm late, but I'm having similar problems, so here's my 6 cents
If you think about it, you can refer to the corners as neigbors of the center of the hexagon, and the actual neighboring hexagons then become diagonal neighbors. That is, you get a pointy top subdivided coordinate system. And you can easily make it by taking a (hex)vector, rotating it in some direction, and adding the rotated one to the original. You can simplify it to a very cheap calculation, and here's my implementation of it (c#):
GetSubdividedVector(HexVector v) => new(v.q - v.r, v.r - v.s, v.s - v.q);
This will work great. Take note, that the new vector will have a smaller Size, (Size * (sqrt(3)/3)) to be exact.
I'm using this system to consistently label corner verticies and check overlapping positions as floating point errors would make it impossible after converting to world space.
Now tho, good luck reversing the process, that's what I'm struggling with rn 😅