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.

238 lines
6.8 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
6 years ago
6 years ago
  1. ----- [[ AXIAL/CUBE COORDINATE SYSTEM 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. in some rare cases, coordinates will be passed individually, usually
  9. because they are only passed internally and should never be adjusted
  10. directly.
  11. in amulet, vector arithmetic already works via: + - * /
  12. additional things such as equality, and distance are implemented here.
  13. +support for parallelogram, triangular, hexagonal and rectangular maps.
  14. +support for arbitrary maps with gaps via hashmaps-like storage
  15. +support for simple irregular hexagons (horizontal and vertical stretching).
  16. classes are used sparsely. maps implement a few constructors, for storing
  17. your maps elsewhere.
  18. -- RESOURCES USED TO DEVELOP THIS LIBRARY
  19. https://redblobgames.com/grid/hexagons - simply amazing.
  20. http://amulet.xyz/doc - amulet documentation
  21. TODO that place that had the inner circle/outer circle ratio??
  22. ]]
  23. ----- [[ GENERALLY USEFUL FUNCTIONS ]] -----------------------------------------
  24. -- just incase you don't already have a rounding function.
  25. local function round(n)
  26. return n % 1 >= 0.5 and math.ceil(n) or math.floor(n)
  27. end
  28. ---- [[ HEX CONSTANTS ]] -------------------------------------------------------
  29. -- all possible vector directions from a given hex by edge
  30. local HEX_DIRECTIONS = {vec2( 1 , 0),
  31. vec2( 1 , -1),
  32. vec2( 0 , -1),
  33. vec2(-1 , 0),
  34. vec2(-1 , 1),
  35. vec2( 0 , 1)}
  36. -- HEX UTILITY FUNCTIONS -------------------------------------------------------
  37. function hex_equals(a, b)
  38. return a.s == b.s and a.t == b.t
  39. end
  40. function hex_length(hex)
  41. return round(math.abs(hex.s) + math.abs(hex.r) + math.abs(-hex.s - hex.t)/2)
  42. end
  43. function hex_distance(a, b)
  44. return hex_length(a - b)
  45. end
  46. function hex_round(s, t)
  47. rs = round(s)
  48. rt = round(t)
  49. rz = round(-s - t)
  50. sdelta = math.abs(rs - s)
  51. tdelta = math.abs(rt - t)
  52. zdelta = math.abs(rz - (-s - t))
  53. if sdelta > tdelta and sdelta > zdelta then
  54. rs = -rt - rz
  55. elseif tdelta > zdelta then
  56. rt = -rs - rz
  57. else
  58. rz = -rs - rt
  59. end
  60. return vec2(rs, rt)
  61. end
  62. ----- [[ LAYOUT, ORIENTATION & COORDINATE CONVERSION ]] -----------------------
  63. -- forward & inverse matrices used for the flat orientation.
  64. local FLAT = {3.0/2.0, 0.0, 3.0^0.5/2.0, 3.0^0.5,
  65. 2.0/3.0, 0.0, -1.0/3.0 , 3.0^0.5/3.0}
  66. -- forward & inverse matrices used for the pointy orientation.
  67. local POINTY = {3.0^0.5, 3.0^0.5/2.0, 0.0, 3.0/2.0,
  68. 3.0^0.5/3.0, -1.0/3.0, 0.0, 2.0/3.0}
  69. -- layout.
  70. function layout_init(origin, size, orientation)
  71. return {origin = origin or vec2(0),
  72. size = size or vec2(11),
  73. orientation = orientation or FLAT}
  74. end
  75. -- hex to screen
  76. function hex_to_pixel(hex, layout)
  77. M = layout.orientation
  78. x = (M[1] * hex.s + M[2] * hex.t) * layout.size.x
  79. y = (M[3] * hex.s + M[4] * hex.t) * layout.size.y
  80. return vec2(x + layout.origin.x, y + layout.origin.y)
  81. end
  82. -- screen to hex
  83. function pixel_to_hex(pix, layout)
  84. M = layout.orientation
  85. pix = (pix - layout.origin) / layout.size
  86. s = M[5] * pix.x + M[6] * pix.y
  87. t = M[7] * pix.x + M[8] * pix.y
  88. return hex_round(s, t)
  89. end
  90. ----- [[ MAP STORAGE & RETRIEVAL ]] --------------------------------------------
  91. --[[ _init functions return a table of tables;
  92. a map of points in a chosen shape and specified layout.
  93. grammap_init - parallelogram map
  94. trimap_init - triangular map
  95. hexmap_init - hexagonal map
  96. rectmap_init - rectangular map
  97. calling .retrieve(pix) on your map will get the hexagon at that pixel.
  98. calling .store(hex) on your map will store the hex as pixel coords.
  99. ]]
  100. -- returns parallelogram-shaped map.
  101. function grammap_init(layout, width, height)
  102. map = {}
  103. mt = {__index={layout=layout,
  104. -- get hex in map from pixel coordinate
  105. retrieve=function(pix)
  106. return pixel_to_hex(pix, layout)
  107. end,
  108. -- store pixel in map from hex coordinate
  109. store=function(hex)
  110. map[hex]=hex_to_pixel(hex, layout)
  111. end
  112. }}
  113. setmetatable(map, mt)
  114. for s = 0, width do
  115. for t = 0, height do
  116. table.insert(map, hex_to_pixel(vec2(s, t), layout))
  117. end
  118. end
  119. return map
  120. end
  121. -- returns triangular map.
  122. function trimap_init(layout, size)
  123. map = {}
  124. mt = {__index={layout=layout,
  125. -- get hex in map from pixel coordinate
  126. retrieve=function(pix)
  127. return pixel_to_hex(pix, layout)
  128. end,
  129. -- store pixel in map from hex coordinate
  130. store=function(hex)
  131. map[hex]=hex_to_pixel(hex, layout)
  132. end
  133. }}
  134. for s = 0, size do
  135. for t = size - s, size do
  136. map.store(vec2(s, t))
  137. end
  138. end
  139. return map
  140. end
  141. -- returns hexagonal map. length of map is radius * 2 + 1
  142. function hexmap_init(layout, radius)
  143. map = {}
  144. mt = {__index={layout=layout,
  145. -- get hex in map from pixel coordinate
  146. retrieve=function(pix)
  147. return pixel_to_hex(pix, layout)
  148. end,
  149. -- store pixel in map from hex coordinate
  150. store=function(hex)
  151. map[hex]=hex_to_pixel(hex, layout)
  152. end
  153. }}
  154. setmetatable(map, mt)
  155. for s = -radius, radius do
  156. t1 = math.max(-radius, -s - radius)
  157. t2 = math.min(radius, -s + radius)
  158. for t = t1, t2 do
  159. table.insert(map, hex_to_pixel(vec2(s, t), layout))
  160. end
  161. end
  162. return map
  163. end
  164. -- returns rectangular map.
  165. function rectmap_init(layout, width, height)
  166. map = {}
  167. mt = {__index={layout=layout,
  168. -- get hex in map from pixel coordinate
  169. retrieve=function(pix)
  170. return pixel_to_hex(pix, layout)
  171. end,
  172. -- store pixel in map from hex coordinate
  173. store=function(hex)
  174. map[hex]=hex_to_pixel(hex - vec2(0, math.floor(hex.s/2)), layout)
  175. end
  176. }}
  177. setmetatable(map, mt)
  178. for s = 0, width do
  179. for t = 0, height do
  180. map.store(vec2(s, t))
  181. end
  182. end
  183. return map
  184. end