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.

261 lines
7.6 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
  1. --[[============================================================================
  2. ----- GENERALLY USEFUL FUNCTIONS -----
  3. ============================================================================]]--
  4. -- rounds numbers. would've been cool to have math.round in lua.
  5. local function round(n)
  6. return n % 1 >= 0.5 and math.ceil(n) or math.floor(n)
  7. end
  8. --[[============================================================================
  9. ----- HEX CONSTANTS AND UTILITY FUNCTIONS -----
  10. ============================================================================]]--
  11. -- all possible vector directions from a given hex by edge
  12. local CUBE_DIRECTIONS = {vec2( 1 , 0),
  13. vec2( 1 , -1),
  14. vec2( 0 , -1),
  15. vec2(-1 , 0),
  16. vec2(-1 , 1),
  17. vec2( 0 , 1)}
  18. -- return hex vector direction via integer index |direction|.
  19. function cube_direction(direction)
  20. return CUBE_DIRECTIONS[(6 + (direction % 6)) % 6 + 1]
  21. end
  22. -- return hexagon adjacent to |hex| in integer index |direction|.
  23. function cube_neighbour(hex, direction)
  24. return hex + CUBE_DIRECTIONS[(6 + (direction % 6)) % 6 + 1]
  25. end
  26. -- return cube coords at location 60deg away to the left; counter-clockwise
  27. function cube_rotate_left(hex)
  28. return vec2(hex.x + hex.y, -hex.x)
  29. end
  30. -- return cube coords at location 60deg away to the right; clockwise
  31. function cube_rotate_right(hex)
  32. return vec2(-hex.y, hex.x + hex.y)
  33. end
  34. -- rounds a float coordinate trio |x, y, z| to nearest integer coordinate trio
  35. local function cube_round(x, y, z)
  36. local rx = round(x)
  37. local ry = round(y)
  38. local rz = round(z) or round(-x - y)
  39. local xdelta = math.abs(rx - x)
  40. local ydelta = math.abs(ry - y)
  41. local zdelta = math.abs(rz - z or round(-x - y))
  42. if xdelta > ydelta and xdelta > zdelta then
  43. rx = -ry - rz
  44. elseif ydelta > zdelta then
  45. ry = -rx - rz
  46. else
  47. rz = -rx - ry
  48. end
  49. return vec2(rx, ry)
  50. end
  51. --[[============================================================================
  52. ----- ORIENTATION & LAYOUT -----
  53. ============================================================================]]--
  54. -- forward & inverse matrices used for the flat orientation
  55. local FLAT = {M = mat2(3.0/2.0, 0.0, 3.0^0.5/2.0, 3.0^0.5 ),
  56. W = mat2(2.0/3.0, 0.0, -1.0/3.0 , 3.0^0.5/3.0),
  57. start_angle = 0.0}
  58. -- forward & inverse matrices used for the pointy orientation
  59. local POINTY = {M = mat2(3.0^0.5, 3.0^0.5/2.0, 0.0, 3.0/2.0),
  60. W = mat2(3.0^0.5/3.0, -1.0/3.0, 0.0, 2.0/3.0),
  61. start_angle = 0.5}
  62. -- stores layout: information that does not pertain to map shape
  63. function layout(origin, size, orientation)
  64. return {origin = origin or vec2(0),
  65. size = size or vec2(11),
  66. orientation = orientation or FLAT}
  67. end
  68. -- hex to screen
  69. function cube_to_pixel(cube, layout)
  70. local M = layout.orientation.M
  71. local x = (M[1][1] * cube[1] + M[1][2] * cube[2]) * layout.size[1]
  72. local y = (M[2][1] * cube[1] + M[2][2] * cube[2]) * layout.size[2]
  73. return vec2(x + layout.origin[1], y + layout.origin[2])
  74. end
  75. -- screen to hex
  76. function pixel_to_cube(pix, layout)
  77. local W = layout.orientation.W
  78. local pix = (pix - layout.origin) / layout.size
  79. local s = W[1][1] * pix[1] + W[1][2] * pix[2]
  80. local t = W[2][1] * pix[1] + W[2][2] * pix[2]
  81. return cube_round(s, t, -s - t)
  82. end
  83. -- TODO test, learn am.draw
  84. function hex_corner_offset(corner, layout)
  85. local angle = 2.0 * math.pi * layout.orientation.start_angle + corner / 6
  86. return vec2(layout.size[1] * math.cos(angle),
  87. layout.size[2] * math.sin(angle))
  88. end
  89. -- TODO this thing
  90. function hex_corners(hex, layout)
  91. local corners = {}
  92. end
  93. -- offset coordinates are prettier to look at
  94. function cube_to_offset(cube)
  95. return vec2(cube[1], -cube[1] - cube[2] + (cube[1] + (cube[1] % 2)) / 2)
  96. end
  97. -- back to cube coordinates
  98. function offset_to_cube(off)
  99. return vec2(off[1], off[2] - off[1] * (off[1] % 2) / 2)
  100. end
  101. --[[============================================================================
  102. ----- MAPS & STORAGE -----
  103. MAPS STORE CUBE COORDINATES. MAPS STORE CUBE COORDINATES. MAPS STORE CUBE COOR
  104. This means, you are not to draw using the coordinates stored in your map.
  105. You are to draw using the cube_to_pixel of those coordinates.
  106. If you wish to draw a hexagon to the screen, you must first use cube_to_pixel
  107. to retrieve the center of the hexagon on each set of cube coordinates stored
  108. in your map.
  109. Information about the maps' dimensions are stored in a metatable, so you can
  110. retrieve details about arbitrary maps after they are created.
  111. TODO make all functions work regardless of layout. as it stands, they kind
  112. of do, just not always nicely.
  113. ============================================================================]]--
  114. -- returns ordered ring-shaped map of |radius| from |center|.
  115. function ring_map(center, radius)
  116. local map = {}
  117. local mt = {__index={center=center, radius=radius}}
  118. setmetatable(map, mt)
  119. local walk = center + CUBE_DIRECTIONS[6] * radius
  120. for i = 1, 6 do
  121. for j = 1, radius do
  122. table.insert(map, walk)
  123. walk = cube_neighbour(walk, i)
  124. end
  125. end
  126. return map
  127. end
  128. -- returns ordered hexagonal map of |radius| rings from |center|.
  129. -- the only difference between hex_spiral_map and hex_hexagonal_map is that
  130. -- hex_spiral_map is ordered, in a spiral path from the |center|.
  131. function spiral_map(center, radius)
  132. local map = {center}
  133. local mt = {__index={center=center, radius=radius}}
  134. setmetatable(map, mt)
  135. for i = 1, radius do
  136. table.append(map, ring_map(center, i))
  137. end
  138. return map
  139. end
  140. -- returns unordered parallelogram-shaped map of |width| and |height|.
  141. function parallelogram_map(width, height)
  142. local map = {}
  143. local mt = {__index={width=width, height=height}}
  144. setmetatable(map, mt)
  145. for i = 0, width do
  146. for j = 0, height do
  147. map[vec2(i, -j)] = true
  148. end
  149. end
  150. return map
  151. end
  152. -- returns unordered triangular map of |size|.
  153. function triangular_map(size)
  154. local map = {}
  155. local mt = {__index={size=size}}
  156. setmetatable(map, mt)
  157. for i = 0, size do
  158. for j = size - s, size do
  159. map[vec2(i, j)] = true
  160. end
  161. end
  162. return map
  163. end
  164. -- returns unordered hexagonal map of |radius|.
  165. function hexagonal_map(radius)
  166. local map = {}
  167. local mt = {__index={radius=radius}}
  168. setmetatable(map, mt)
  169. for i = -radius, radius do
  170. local j1 = math.max(-radius, -i - radius)
  171. local j2 = math.min(radius, -i + radius)
  172. for j = j1, j2 do
  173. map[vec2(i, j)] = true
  174. end
  175. end
  176. return map
  177. end
  178. -- returns unordered rectangular map of |width| and |height|.
  179. function rectangular_map(width, height)
  180. local map = {}
  181. local mt = {__index={width=width, height=height}}
  182. setmetatable(map, mt)
  183. for i = 0, width do
  184. for j = 0, height do
  185. map[vec2(i, -j - math.floor(i/2))] = true
  186. end
  187. end
  188. return map
  189. end
  190. --[[============================================================================
  191. ----- PATHFINDING -----
  192. ============================================================================]]--
  193. --[[============================================================================
  194. ----- TESTS -----
  195. ============================================================================]]--
  196. function test_all()
  197. print("it works trust me")
  198. end