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.

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