Grids & Coordinate Systems

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]