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.

171 lines
4.9 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. ----- [[ AXIAL/CUBE COORDINATE HEXAGON LIBRARY FOR AMULET/LUA]] ----------------
  2. --[[ author@churchianity.ca
  3. -- INTRODUCTION
  4. this is a hexagonal grid library for amulet/lua.
  5. it uses axial coordinates or cube/hex coordinates when necessary.
  6. by amulet convention, hexes are either vec2(s, t) or vec3(s, t, z)
  7. but nearly always the former.
  8. -- RESOURCES USED TO DEVELOP THIS LIBRARY, AND FOR WHICH I AM GRATEFUL
  9. https://redblobgames.com/grid/hexagons - simply amazing.
  10. http://amulet.xyz/doc - amulet documentation
  11. ]]
  12. ----- [[ GENERALLY USEFUL FUNCTIONS ]] -----------------------------------------
  13. -- rounds numbers. would've been cool to have math.round in lua.
  14. local function round(n)
  15. return n % 1 >= 0.5 and math.ceil(n) or math.floor(n)
  16. end
  17. ----- [[ HEX CONSTANTS & UTILITY FUNCTIONS ]] ----------------------------------
  18. -- all possible vector directions from a given hex by edge
  19. local HEX_DIRECTIONS = {vec2( 1 , 0),
  20. vec2( 1 , -1),
  21. vec2( 0 , -1),
  22. vec2(-1 , 0),
  23. vec2(-1 , 1),
  24. vec2( 0 , 1)}
  25. -- return hex vector direction via index |direction|.
  26. function hex_direction(direction)
  27. return HEX_DIRECTIONS[direction]
  28. end
  29. -- return hexagon adjacent to |hex| in |direction|
  30. function hex_neighbour(hex, direction)
  31. return hex + HEX_DIRECTION[direction]
  32. end
  33. -- rounds hexes. without this, pixel_to_hex returns fractional coordinates.
  34. -- using single coordinates instead of a vector, because this should only
  35. -- ever be called internally.
  36. function hex_round(s, t)
  37. local rs = round(s)
  38. local rt = round(t)
  39. local rz = round(-s - t)
  40. local sdelta = math.abs(rs - s)
  41. local tdelta = math.abs(rt - t)
  42. local zdelta = math.abs(rz - (-s - t))
  43. if sdelta > tdelta and sdelta > zdelta then
  44. rs = -rt - rz
  45. elseif tdelta > zdelta then
  46. rt = -rs - rz
  47. else
  48. rz = -rs - rt
  49. end
  50. return vec2(rs, rt)
  51. end
  52. ----- [[ LAYOUT, ORIENTATION & COORDINATE CONVERSION ]] -----------------------
  53. -- forward & inverse matrices used for the flat orientation.
  54. local FLAT = {M = mat2(3.0/2.0, 0.0, 3.0^0.5/2.0, 3.0^0.5 ),
  55. W = mat2(2.0/3.0, 0.0, -1.0/3.0 , 3.0^0.5/3.0)}
  56. -- forward & inverse matrices used for the pointy orientation.
  57. local POINTY = {M = mat2(3.0^0.5, 3.0^0.5/2.0, 0.0, 3.0/2.0),
  58. W = mat2(3.0^0.5/3.0, -1.0/3.0, 0.0, 2.0/3.0)}
  59. -- TODO encapsulate hex_to_pixel and pixel_to_hex in layout table.
  60. -- stores layout information that does not pertain to map shape
  61. function hex_layout(origin, size, orientation)
  62. return {origin = origin or vec2(0),
  63. size = size or vec2(11),
  64. orientation = orientation or FLAT}
  65. end
  66. -- hex to screen
  67. function hex_to_pixel(hex, layout)
  68. local M = layout.orientation.M
  69. local x = (M[1][1] * hex.s + M[1][2] * hex.t) * layout.size.x
  70. local y = (M[2][1] * hex.s + M[2][2] * hex.t) * layout.size.y
  71. return vec2(x + layout.origin.x, y + layout.origin.y)
  72. end
  73. -- screen to hex
  74. function pixel_to_hex(pix, layout)
  75. local W = layout.orientation.W
  76. local pix = (pix - layout.origin) / layout.size
  77. local s = W[1][1] * pix.x + W[1][2] * pix.y
  78. local t = W[2][1] * pix.x + W[2][2] * pix.y
  79. return hex_round(s, t)
  80. end
  81. ----- [[ MAP STORAGE & RETRIEVAL ]] --------------------------------------------
  82. --[[
  83. ]]
  84. -- TODO make all functions work regardless of layout.
  85. -- returns unordered parallelogram-shaped map of |width| and |height|.
  86. function hex_parallelogram_map(width, height)
  87. local map = {}
  88. local mt = {__index={width=width, height=height}}
  89. setmetatable(map, mt)
  90. for s = 0, width do
  91. for t = 0, height do
  92. map[vec2(s, t)] = true
  93. end
  94. end
  95. return map
  96. end
  97. -- returns unordered triangular map of |size|.
  98. function hex_triangular_map(size)
  99. local map = {}
  100. local mt = {__index={size=size}}
  101. setmetatable(map, mt)
  102. for s = 0, size do
  103. for t = size - s, size do
  104. map[vec2(s, t)] = true
  105. end
  106. end
  107. return map
  108. end
  109. -- returns unordered hexagonal map of |radius|.
  110. function hex_hexagonal_map(radius)
  111. local map = {}
  112. local mt = {__index={radius=radius}}
  113. setmetatable(map, mt)
  114. for s = -radius, radius do
  115. local t1 = math.max(-radius, -s - radius)
  116. local t2 = math.min(radius, -s + radius)
  117. for t = t1, t2 do
  118. map[vec2(s, t)] = true
  119. end
  120. end
  121. return map
  122. end
  123. -- returns unordered rectangular map of |width| and |height|.
  124. function hex_rectangular_map(width, height)
  125. local map = {}
  126. local mt = {__index={width=width, height=height}}
  127. setmetatable(map, mt)
  128. for s = 0, width do
  129. for t = 0, height do
  130. map[vec2(s, t)] = true
  131. end
  132. end
  133. return map
  134. end