hexyz is tower defense game, and a lua library for dealing with hexagonal grids
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
4.6 KiB

6 years ago
  1. --[[ AXIAL/CUBE COORDINATE SYSTEM FOR AMULET/LUA]]
  2. --[[
  3. all hexes in functions are assumed to be amulet vectors.
  4. in amulet, vector arithmetic works already with [ + - * / ]
  5. things like equality and distance are implemented here.
  6. some algorithms use axial coordinates for hexes: vec2(s, t)
  7. others use cube coordinates: vec3(s, t, z) where s + t + z = 0
  8. this is for simplicity - many algorithms don't care about the
  9. third coordinate, and if they do, the missing coordinate can
  10. be calculated from the other two.
  11. -- note on orientation:
  12. because of the way amulet draws hexagons, it's much easier to assume
  13. the user wants to use the flat map. rotation after the fact to
  14. achieve other orienations is probably possible, but might have some
  15. aliasing issues. TODO work on this.
  16. consequently, I have not implemented stretching. all hexagons are
  17. assumed to be regular. you could implement this yourself by making
  18. layout.size a vec2(sizex, sizey), but you would have to play with
  19. transforms in the amulet library if you wanted to use amulet.
  20. some of the primary resources used to develop this library:
  21. - https://redblobgames.com/grid/hexagons - simply amazing.
  22. - http://amulet.xyz/doc - amulet documentation
  23. - TODO that place that had the inner circle/outer circle ratio??
  24. ]]
  25. -- GENERALLY USEFUL CONSTANTS -------------------------------------------------
  26. -- GENERALLY USEFUL FUNCTIONS --------------------------------------------------
  27. function round(n)
  28. return n % 1 >= 0.5 and math.ceil(n) or math.floor(n)
  29. end
  30. function draw_axes(window, node)
  31. xaxis = am.line(vec2(-window.width / 2, 0) , vec2(window.width / 2, 0))
  32. yaxis = am.line(vec2(0, -window.height / 2), vec2(0, window.height / 2))
  33. node:append(xaxis)
  34. node:append(yaxis)
  35. end
  36. -- HEX CONSTANTS ---------------------------------------------------------------
  37. -- all possible vector directions from a given hex by edge
  38. HEX_DIRECTIONS = {vec2( 1 , 0),
  39. vec2( 1 , -1),
  40. vec2( 0 , -1),
  41. vec2(-1 , 0),
  42. vec2(-1 , 1),
  43. vec2( 0 , 1)}
  44. -- HEX UTILITY FUNCTIONS -------------------------------------------------------
  45. function hex_equals(a, b)
  46. return a.s == a.t and b.s == b.t
  47. end
  48. function hex_nequals(a, b)
  49. return not hex_equals(a, b)
  50. end
  51. function hex_length(hex)
  52. return ((math.abs(hex.s) + math.abs(hex.t) + math.abs(-hex.s - hex.t)) / 2)
  53. end
  54. function hex_distance(a, b)
  55. return hex_length(a - b)
  56. end
  57. function hex_direction(direction)
  58. return HEX_DIRECTIONS[direction]
  59. end
  60. function hex_neighbour(hex, direction)
  61. return hex + HEX_DIRECTIONS[direction]
  62. end
  63. function hex_round(hex)
  64. rs = round(hex.s)
  65. rt = round(hex.t)
  66. rz = round(-hex.s + -hex.t)
  67. sdelta = math.abs(rs - hex.s)
  68. tdelta = math.abs(rt - hex.t)
  69. zdelta = math.abs(rz + hex.s + hex.t)
  70. if sdelta > tdelta and sdelta > zdelta then
  71. rs = -rt - rz
  72. elseif tdelta > zdelta then
  73. rt = -rs - rz
  74. else
  75. rz = -rs - rt
  76. end
  77. return vec2(rs, rt)
  78. end
  79. -- COORDINATE CONVERSION FUNCTIONS ---------------------------------------------
  80. -- forward & inverse matrices used for coordinate conversion
  81. local M = mat2(3.0/2.0, 0.0, 3.0^0.5/2.0, 3.0^0.5 )
  82. local W = mat2(2.0/3.0, 0.0, -1.0/3.0 , 3.0^0.5/3.0)
  83. -- hex to screen
  84. function hex_to_pixel(hex, origin)
  85. x = (M[1][1] * hex.s + M[1][2] * hex.t) * SIZE
  86. y = (M[2][1] * hex.s + M[2][2] * hex.t) * SIZE
  87. return vec2(x + origin.x, y + origin.y)
  88. end
  89. -- screen to hex
  90. function pixel_to_hex(pix, origin)
  91. pix = vec2(pix.x - origin.x) / SIZE,
  92. (pix.y - origin.y) / SIZE
  93. s = W[1][1] * pix.x + W[1][2] * pix.y
  94. t = W[2][1] * pix.x + W[2][2] * pix.y
  95. return hex_round(vec2(s, t))
  96. end
  97. -- MAP FUNCTIONS ---------------------------------------------------------------
  98. function hexagonal_map(radius, origin)
  99. for s = -radius, radius do
  100. t1 = math.max(-radius, -s - radius)
  101. t2 = math.min(radius, -s + radius)
  102. for t = t1, t2 do
  103. color = vec4(math.random(20, 80) / 100,
  104. math.random(20, 80) / 100,
  105. math.random(20, 80) / 100,
  106. 1)
  107. map:append(am.circle(hex_to_pixel(vec2(s, t)), 24, color, 6))
  108. end
  109. end
  110. end
  111. function rectangular_map(width, height, origin)
  112. for s = 0, height do
  113. soffset = math.floor(s / 2)
  114. for t = -soffset, width - soffset do
  115. center = hex_to_pixel(vec2(s, t))
  116. end
  117. end
  118. end
  119. --]]