For a software project (a multi-user browser game) I am currentlyevaluating different sorts of grid and coordinate system combinations. Icame across a few great posts about that topic ( Amit’s Thoughts on Grids and Blobs in Games: Distances on a triangular grid). The latter provides a promising coordinate system based on this paper. To review the grid and coordinate system I put together an example.
Example
Move your mouse over the grid.
Crossing an edge changes exactly one coordinate.
The graphics are generated by Raphaël.
- darkred , darkblue and darkgreen u, v and w-lane (the corresponding coordinate does not change on that lane)
- red highlighted triangle
- blue neighbours of the highlighted triangle (triangles with at least one shared vertex)
Code
The conversion code is written in Coffeescript.
# some constants
SR3 = Math.sqrt 3
PI30 = Math.PI / 6
PI60 = Math.PI / 3
SIN30 = Math.sin PI30
COS30 = Math.cos PI30
SIN60 = Math.sin PI60
COS60 = Math.cos PI60
# convert u/v/w coordinates to x/y coordinates based on the
# side length s
to_xy = (s, u, v, w) ->
r = SR3 * s / 6
R = SR3 * s / 3
h = SR3 * s / 2
xu = 0
yu = u * R
xv = -v * COS30 * R
yv = -v * SIN30 * R
xw = w * COS30 * R
yw = -w * SIN30 * R
x = xu + xv + xw
y = yu + yv + yw
[x, y]
# convert x/y coordinates to u/v/w coordinates based on the
# side length s
to_uvw = (s, x, y) ->
return [0, 0, 0] if x is 0 and y is 0
r = SR3 * s / 6
R = SR3 * s / 3
h = SR3 * s / 2
u = (Math.floor (R + y) / h)
if y > 0
factor = -1
offset = r
else
factor = 1
offset = R
v = factor * (Math.floor (Math.cos(PI60 - (Math.atan x/y)) * Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) + offset) / h)
if y > 0
factor = 1
offset = R
else
factor = -1
offset = r
w = factor * (Math.floor (Math.cos(2 * PI60 - (Math.atan x/y)) * Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) + offset) / h)
[u, v, w]