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.

239 lines
6.2 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
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. ----- [[ GENERALLY USEFUL FUNCTIONS ]] -----------------------------------------
  2. -- rounds numbers. would've been cool to have math.round in lua.
  3. local function round(n)
  4. return n % 1 >= 0.5 and math.ceil(n) or math.floor(n)
  5. end
  6. ----- [[ UI FUNCTIONS ]] -------------------------------------------------------
  7. ----- [[ HEX CONSTANTS & UTILITY FUNCTIONS ]] ----------------------------------
  8. -- all possible vector directions from a given hex by edge
  9. local CUBE_DIRECTIONS = {vec2( 1 , 0),
  10. vec2( 1 , -1),
  11. vec2( 0 , -1),
  12. vec2(-1 , 0),
  13. vec2(-1 , 1),
  14. vec2( 0 , 1)}
  15. -- return hex vector direction via integer index |direction|.
  16. function cube_direction(direction)
  17. return CUBE_DIRECTIONS[(6 + (direction % 6)) % 6 + 1]
  18. end
  19. -- return hexagon adjacent to |hex| in integer index |direction|.
  20. function cube_neighbour(hex, direction)
  21. return hex + HEX_DIRECTIONS[(6 + (direction % 6)) % 6 + 1]
  22. end
  23. -- TODO rotations are different depending on the coordinate system you use.
  24. -- implement this for cube/axial, and doubled.
  25. function cube_rotate_left(hex)
  26. end
  27. function cube_rotate_right(hex)
  28. end
  29. -- rounds a float coordinate trio |x, y, z| to its nearest integer coordinate trio.
  30. -- TODO make work with a table {x, y, z} and vec3(x, y, z)
  31. function cube_round(x, y, z)
  32. local rx = round(x)
  33. local ry = round(y)
  34. local rz = round(z) or round(-x - y)
  35. local xdelta = math.abs(rx - x)
  36. local ydelta = math.abs(ry - y)
  37. local zdelta = math.abs(rz - z)
  38. if xdelta > ydelta and xdelta > zdelta then
  39. rx = -ry - rz
  40. elseif ydelta > zdelta then
  41. ry = -rx - rz
  42. else
  43. rz = -rx - ry
  44. end
  45. return vec3(rx, ry, rz)
  46. end
  47. ----- [[ LAYOUT, ORIENTATION & COORDINATE CONVERSION ]] -----------------------
  48. -- forward & inverse matrices used for the flat orientation.
  49. local FLAT = {M = mat2(3.0/2.0, 0.0, 3.0^0.5/2.0, 3.0^0.5 ),
  50. W = mat2(2.0/3.0, 0.0, -1.0/3.0 , 3.0^0.5/3.0),
  51. start_angle = 0.0}
  52. -- forward & inverse matrices used for the pointy orientation.
  53. local POINTY = {M = mat2(3.0^0.5, 3.0^0.5/2.0, 0.0, 3.0/2.0),
  54. W = mat2(3.0^0.5/3.0, -1.0/3.0, 0.0, 2.0/3.0),
  55. start_angle = 0.5}
  56. -- stores layout: information that does not pertain to map shape
  57. function layout(origin, size, orientation)
  58. return {origin = origin or vec2(0),
  59. size = size or vec2(11),
  60. orientation = orientation or FLAT}
  61. end
  62. -- hex to screen
  63. function cube_to_pixel(cube, layout)
  64. local M = layout.orientation.M
  65. local x = (M[1][1] * cube.x + M[1][2] * cube.y) * layout.size.x
  66. local y = (M[2][1] * cube.x + M[2][2] * cube.y) * layout.size.y
  67. return vec2(x + layout.origin.x, y + layout.origin.y)
  68. end
  69. -- screen to hex
  70. function pixel_to_cube(pix, layout)
  71. local W = layout.orientation.W
  72. local pix = (pix - layout.origin) / layout.size
  73. local s = W[1][1] * pix.x + W[1][2] * pix.y
  74. local t = W[2][1] * pix.x + W[2][2] * pix.y
  75. return cube_round(s, t, -s - t)
  76. end
  77. function hex_corner_offset(corner, layout)
  78. local angle = 2.0 * math.pi * layout.orientation.start_angle + corner / 6
  79. return vec2(layout.size.x * math.cos(angle), layout.size.y * math.sin(angle))
  80. end
  81. function hex_corners(hex, layout)
  82. local corners = {}
  83. end
  84. function cube_to_offset(cube)
  85. return vec2(cube.x, -cube.x - cube.y + (cube.x + (cube.x % 2)) / 2)
  86. end
  87. function offset_to_cube(off)
  88. end
  89. function cube_to_doubled(cube)
  90. return vec2(cube.x, 2 * (-cube.x - cube.y) + cube.x)
  91. end
  92. function doubled_to_cube(dbl)
  93. return vec2(dbl.x, (dbl.y - dbl.x) / 2)
  94. end
  95. ----- [[ MAP STORAGE & RETRIEVAL ]] --------------------------------------------
  96. --[[
  97. TODO make all functions work regardless of layout. as it stands, they kind
  98. of do, just not always nicely.
  99. ]]
  100. -- returns ordered ring-shaped map of |radius| from |center|.
  101. function ring_map(center, radius)
  102. local map = {}
  103. local mt = {__index={center=center, radius=radius}}
  104. setmetatable(map, mt)
  105. local walk = center + HEX_DIRECTIONS[6] * radius
  106. for i = 1, 6 do
  107. for j = 1, radius do
  108. table.insert(map, walk)
  109. walk = hex_neighbour(walk, i)
  110. end
  111. end
  112. return map
  113. end
  114. --[[ returns ordered hexagonal map of |radius| rings from |center|.
  115. the only difference between hex_spiral_map and hex_hexagonal_map is that
  116. hex_spiral_map is ordered, in a spiral path from the |center|.
  117. ]]
  118. function spiral_map(center, radius)
  119. local map = {center}
  120. local mt = {__index={center=center, radius=radius}}
  121. setmetatable(map, mt)
  122. for i = 1, radius do
  123. table.append(map, hex_ring_map(center, i))
  124. end
  125. return map
  126. end
  127. -- returns unordered parallelogram-shaped map of |width| and |height|.
  128. function parallelogram_map(width, height)
  129. local map = {}
  130. local mt = {__index={width=width, height=height}}
  131. setmetatable(map, mt)
  132. for i = 0, width do
  133. for j = 0, height do
  134. map[vec2(i, -j)] = true
  135. end
  136. end
  137. return map
  138. end
  139. -- returns unordered triangular map of |size|.
  140. function triangular_map(size)
  141. local map = {}
  142. local mt = {__index={size=size}}
  143. setmetatable(map, mt)
  144. for i = 0, size do
  145. for j = size - s, size do
  146. map[vec2(i, j)] = true
  147. end
  148. end
  149. return map
  150. end
  151. -- returns unordered hexagonal map of |radius|.
  152. function hexagonal_map(radius)
  153. local map = {}
  154. local mt = {__index={radius=radius}}
  155. setmetatable(map, mt)
  156. for i = -radius, radius do
  157. local j1 = math.max(-radius, -i - radius)
  158. local j2 = math.min(radius, -i + radius)
  159. for j = j1, j2 do
  160. map[vec2(i, j)] = true
  161. end
  162. end
  163. return map
  164. end
  165. -- returns unordered rectangular map of |width| and |height|.
  166. function rectangular_map(width, height)
  167. local map = {}
  168. local mt = {__index={width=width, height=height}}
  169. setmetatable(map, mt)
  170. for i = 0, width do
  171. for j = 0, height do
  172. map[vec2(i, -j - math.floor(i/2))] = true
  173. end
  174. end
  175. return map
  176. end
  177. ----- [[ TESTS ]] --------------------------------------------------------------