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.

222 lines
6.7 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
  1. ----- [[ AXIAL/CUBE COORDINATE SYSTEM FOR AMULET/LUA]] -------------------------
  2. --[[ author@churchianity.ca
  3. -- INTRODUCTION
  4. this is a library for making grids of hexagons using lua.
  5. it has made exclusive (though not thorough) use of standard lua
  6. 5.2 functionality, making it as portable as possible. it
  7. doesn't even use a point class, simply returning tables
  8. of integers, which can later be unpacked into your amulet
  9. vectors, or whatever else you want to use. in honor of amulet,
  10. when necessary to name cube/hex coordinates, (s, t, z) is the
  11. convention.
  12. only returning tables can result in some nasty looking lines
  13. with lots of table unpacks, but if your graphics library likes
  14. traditional lua types, you will be better off.
  15. it supports triangular, hexagonal, rectangular, and
  16. parallelogram map shapes.
  17. it supports non-regular hexagons, though it's trickier to get
  18. working in amulet. TODO work on this.
  19. -- NOTE ON ORIENTATION + AMULET
  20. because of the way amulet draws hexagons (amulet essentially
  21. draws a 6-sided circle from a centerpoint, instead of of a
  22. series of lines connecting points), the flat orientation is
  23. default and recommended. other orientations are possible
  24. with am.rotate, but can cause aliasing issues. TODO work on this.
  25. -- TODO NOTE -
  26. amulet has another draw function I neglected, simply am.draw.
  27. i don't understand how it works, but it seems to be able to
  28. draw arbitrary polygons via a list of vertices. so.
  29. -- RESOURCES USED TO DEVELOP THIS LIBRARY
  30. https://redblobgames.com/grid/hexagons - simply amazing. amit is a god.
  31. http://amulet.xyz/doc - amulet documentation
  32. TODO that place that had the inner circle/outer circle ratio??
  33. ]]
  34. ----- [[ GENERALLY USEFUL FUNCTIONS ]] -----------------------------------------
  35. -- just incase you don't already have a rounding function.
  36. function round(n)
  37. return n % 1 >= 0.5 and math.ceil(n) or math.floor(n)
  38. end
  39. ---- [[ HEX CONSTANTS ]] -------------------------------------------------------
  40. -- all possible vector directions from a given hex by edge
  41. HEX_DIRECTIONS = {{ 1 , 0},
  42. { 1 , -1},
  43. { 0 , -1},
  44. {-1 , 0},
  45. {-1 , 1},
  46. { 0 , 1}}
  47. -- HEX UTILITY FUNCTIONS -------------------------------------------------------
  48. function hex_round(s, t)
  49. rs = round(s)
  50. rt = round(t)
  51. rz = round(-s - t)
  52. sdelta = math.abs(rs - s)
  53. tdelta = math.abs(rt - t)
  54. zdelta = math.abs(rz - (-s - t))
  55. if sdelta > tdelta and sdelta > zdelta then
  56. rs = -rt - rz
  57. elseif tdelta > zdelta then
  58. rt = -rs - rz
  59. else
  60. rz = -rs - rt
  61. end
  62. return {rs, rt}
  63. end
  64. ----- [[ LAYOUT, ORIENTATION & COORDINATE CONVERSION ]] -----------------------
  65. -- forward & inverse matrices used for the flat orientation.
  66. local FLAT = {3.0/2.0, 0.0, 3.0^0.5/2.0, 3.0^0.5,
  67. 2.0/3.0, 0.0, -1.0/3.0 , 3.0^0.5/3.0}
  68. -- forward & inverse matrices used for the pointy orientation.
  69. local POINTY = {3.0^0.5, 3.0^0.5/2.0, 0.0, 3.0/2.0,
  70. 3.0^0.5/3.0, -1.0/3.0, 0.0, 2.0/3.0}
  71. -- layout.
  72. function layout_init(origin, size, orientation)
  73. return {origin = origin or {0, 0},
  74. size = size or {11, 11},
  75. orientation = orientation or FLAT}
  76. end
  77. -- hex to screen
  78. function hex_to_pixel(s, t, layout)
  79. M = layout.orientation
  80. x = (M[1] * s + M[2] * t) * layout.size[1]
  81. y = (M[3] * s + M[4] * t) * layout.size[2]
  82. return {x + layout.origin[1], y + layout.origin[2]}
  83. end
  84. -- screen to hex
  85. function pixel_to_hex(x, y, layout)
  86. M = layout.orientation
  87. px = {(x - layout.origin[1]) / layout.size[1],
  88. (y - layout.origin[2]) / layout.size[2]}
  89. s = M[5] * px[1] + M[6] * px[2]
  90. t = M[7] * px[1] + M[8] * px[2]
  91. return hex_round(s, t)
  92. end
  93. ----- [[ MAP STORAGE & RETRIEVAL ]] --------------------------------------------
  94. --[[ _init functions return a table of tables;
  95. a map of points in a chosen shape and specified layout.
  96. the shape, as well as the layout used is stored in a metatable
  97. for reuse.
  98. ]]
  99. -- returns parallelogram-shaped map.
  100. function map_parallelogram_init(layout, width, height)
  101. map = {}
  102. setmetatable(map, {__index={layout=layout,
  103. shape="parallelogram",
  104. width=width,
  105. height=height}})
  106. for s = 0, width do
  107. for t = 0, height do
  108. table.insert(map, hex_to_pixel(s, t, layout))
  109. end
  110. end
  111. return map
  112. end
  113. -- returns triangular map.
  114. function map_triangular_init(layout, size)
  115. map = {}
  116. setmetatable(map, {__index={layout=layout,
  117. shape="triangular",
  118. size=size}})
  119. for s = 0, size do
  120. for t = size - s, size do
  121. table.insert(map, hex_to_pixel(s, t, layout))
  122. end
  123. end
  124. return map
  125. end
  126. -- returns hexagonal map. length of map is radius * 2 + 1
  127. function map_hexagonal_init(layout, radius)
  128. map = {}
  129. setmetatable(map, {__index={layout=layout,
  130. shape="hexagonal",
  131. radius=radius}})
  132. for s = -radius, radius do
  133. t1 = math.max(-radius, -s - radius)
  134. t2 = math.min(radius, -s + radius)
  135. for t = t1, t2 do
  136. table.insert(map, hex_to_pixel(s, t, layout))
  137. end
  138. end
  139. return map
  140. end
  141. -- returns rectangular map.
  142. function map_rectangular_init(layout, width, height)
  143. map = {}
  144. setmetatable(map, {__index={layout=layout,
  145. shape="rectangular",
  146. width=width,
  147. height=height}})
  148. for s = 0, width do
  149. soffset = math.floor(s/2)
  150. for t = -soffset, height - soffset do
  151. table.insert(map, hex_to_pixel(s, t, layout))
  152. end
  153. end
  154. return map
  155. end
  156. -- places single hex into map table, if it is not already present.
  157. function map_store(map)
  158. end
  159. -- retrieves single hex from map table. explodes if can't find it.
  160. function map_retrieve(map, hex)
  161. if map.shape == "rectangular" then
  162. if map.layout.orientation == FLAT then
  163. return {hex[1] + math.floor(hex[2]/2), hex[2]}
  164. else
  165. return {hex[1], hex[2] + math.floor(hex[1]/2)}
  166. end
  167. elseif map.shape == "hexagonal" then
  168. if map.layout.orientation == FLAT then
  169. else
  170. end
  171. elseif map.shape == "parallelogram" then
  172. if map.layout.orientation == FLAT then
  173. else
  174. end
  175. else
  176. end
  177. end