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.

269 lines
7.7 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
  1. -- @TODO
  2. -- music
  3. -- -- title theme
  4. -- -- game theme
  5. --
  6. -- settings menu
  7. -- -- music volume
  8. -- -- sfx volume
  9. -- -- resolution settings & fix grid size being based on resolution
  10. --
  11. -- save games
  12. -- -- allow saving by name
  13. -- -- allow loading by name
  14. -- -- encode/decode save game data (low priority)
  15. --
  16. -- map editor
  17. -- -- paint terrain elevation levels
  18. -- -- place tiles of set elevation
  19. -- -- place towers
  20. -- -- move home?
  21. --
  22. -- game
  23. -- -- is 1920x1080 the optimal default resolution?
  24. -- -- HEX_GRID_CENTER =/= HOME
  25. -- -- allow selecting of tiles, if tower is selected then allow sell/upgrade
  26. -- -- button/ui to open pause menu - make it obvious that 'esc' is the button
  27. -- -- play the game and tweak numbers
  28. -- -- new game menu allowing set seed
  29. -- -- gattling gun tower
  30. -- -- spooder mob
  31. -- -- make art, birds-eye-ify the redeye tower and lighthouse maybe?
  32. settings = am.load_state("settings", "json") or {
  33. fullscreen = false,
  34. window_width = 1920,
  35. window_height = 1080,
  36. music_volume = 0.1,
  37. sfx_volume = 0.1,
  38. }
  39. math.randomseed(os.time())
  40. math.random()
  41. math.random()
  42. math.random()
  43. math.random()
  44. do
  45. win = am.window{
  46. width = settings.window_width,
  47. height = settings.window_height,
  48. title = "hexyz",
  49. mode = settings.fullscreen and "fullscreen" or "windowed",
  50. highdpi = true,
  51. letterbox = true,
  52. resizable = true, -- user should probably set their resolution instead of resizing the window, but hey.
  53. }
  54. end
  55. -- asset interfaces and/or trivial code
  56. require "conf"
  57. require "color"
  58. require "sound"
  59. require "texture"
  60. require "src/entity"
  61. require "src/extra"
  62. require "src/geometry"
  63. require "src/hexyz"
  64. require "src/game"
  65. require "src/gui"
  66. require "src/grid"
  67. require "src/mob"
  68. require "src/projectile"
  69. require "src/tower"
  70. -- js style popup in the middle of the screen that dissapates
  71. function alert(message)
  72. win.scene:append(
  73. am.scale(3) ^ am.text(message)
  74. :action(coroutine.create(function(self)
  75. am.wait(am.tween(self, 1, { color = vec4(0) }))
  76. win.scene:remove(self)
  77. end))
  78. )
  79. end
  80. function main_action(self)
  81. if win:key_pressed("escape") then
  82. if win.scene("game") then
  83. win.scene("game").paused = false
  84. win.scene:remove(self)
  85. else
  86. --win:close()
  87. end
  88. end
  89. if self"hex_backdrop" then
  90. self"hex_backdrop""rotate".angle = math.wrapf(self"hex_backdrop""rotate".angle - 0.005 * am.delta_time, math.pi*2)
  91. end
  92. end
  93. function make_main_scene_toolbelt()
  94. local include_save_option = game
  95. local options = {
  96. false,
  97. false,
  98. false,
  99. {
  100. texture = TEXTURES.NEW_GAME_HEX,
  101. action = function()
  102. win.scene:remove"menu"
  103. game_init()
  104. end
  105. },
  106. false,
  107. include_save_option and {
  108. texture = TEXTURES.SAVE_GAME_HEX,
  109. action = function()
  110. game_save()
  111. alert("succesfully saved!")
  112. end
  113. } or false,
  114. false,
  115. {
  116. texture = TEXTURES.LOAD_GAME_HEX,
  117. action = function()
  118. local save = am.load_state("save", "json")
  119. if save then
  120. win.scene:remove"menu"
  121. game_init(save)
  122. else
  123. alert("no saved games")
  124. end
  125. end
  126. },
  127. false,
  128. {
  129. texture = TEXTURES.MAP_EDITOR_HEX,
  130. action = function() alert("not yet :)") end
  131. },
  132. {
  133. texture = TEXTURES.SETTINGS_HEX,
  134. action = function() alert("not yet :)") end
  135. },
  136. {
  137. texture = TEXTURES.ABOUT_HEX,
  138. action = function() alert("not yet :)") end
  139. },
  140. false,
  141. {
  142. texture = TEXTURES.QUIT_HEX,
  143. action = function() win:close() end
  144. }
  145. }
  146. local spacing = 160
  147. -- calculate the dimensions of the whole grid
  148. local grid_width = 8
  149. local grid_height = 2
  150. local hhs = hex_horizontal_spacing(spacing)
  151. local hvs = hex_vertical_spacing(spacing)
  152. local grid_pixel_width = grid_width * hhs
  153. local grid_pixel_height = grid_height * hvs
  154. -- @TODO the vertical offset should be different depending on if this is the main menu or the pause menu
  155. -- perhaps the map that makes the grid of hexes should be different as well
  156. local pixel_offset = vec2(-grid_pixel_width/2, win.bottom + hex_height(spacing)/2 + 20)
  157. local map = hex_rectangular_map(grid_width, grid_height, HEX_ORIENTATION.POINTY)
  158. local group = am.group()
  159. local option_index = 1
  160. for i,_ in pairs(map) do
  161. for j,_ in pairs(map[i]) do
  162. local hex = vec2(i, j)
  163. local position = hex_to_pixel(hex, vec2(spacing), HEX_ORIENTATION.POINTY)
  164. local option = options[option_index]
  165. local texture = option and option.texture or TEXTURES.SHADED_HEX
  166. local color = option and COLORS.TRANSPARENT or vec4(0.3)
  167. local node = am.translate(position)
  168. ^ pack_texture_into_sprite(texture, texture.width, texture.height, color)
  169. hex_map_set(map, i, j, {
  170. node = node,
  171. option = option
  172. })
  173. local tile = hex_map_get(map, i, j)
  174. local selected = false
  175. node:action(function(self)
  176. local mouse = win:mouse_position()
  177. local hex_ = pixel_to_hex(mouse - pixel_offset, vec2(spacing), HEX_ORIENTATION.POINTY)
  178. if tile.option then
  179. if hex == hex_ then
  180. if not selected then
  181. play_sfx(SOUNDS.SELECT1)
  182. end
  183. selected = true
  184. tile.node"sprite".color = vec4(1)
  185. if win:mouse_pressed("left") then
  186. tile.option.action()
  187. end
  188. else
  189. selected = false
  190. tile.node"sprite".color = COLORS.TRANSPARENT
  191. end
  192. end
  193. end)
  194. group:append(node)
  195. option_index = option_index + 1
  196. end
  197. end
  198. return am.translate(pixel_offset) ^ group
  199. end
  200. function main_scene(do_backdrop, do_logo)
  201. local group = am.group()
  202. if do_backdrop then
  203. local map = hex_hexagonal_map(30)
  204. local hex_backdrop = (am.rotate(0) ^ am.group()):tag"hex_backdrop"
  205. for i,_ in pairs(map) do
  206. for j,n in pairs(map[i]) do
  207. local color = map_elevation_color(n)
  208. color = color{a=color.a - 0.1}
  209. local node = am.translate(hex_to_pixel(vec2(i, j), vec2(HEX_SIZE)))
  210. ^ am.circle(vec2(0), HEX_SIZE, vec4(0), 6)
  211. node"circle":action(am.tween(0.6, { color = color }))
  212. hex_backdrop:append(node)
  213. end
  214. end
  215. group:append(hex_backdrop)
  216. else
  217. group:append(am.rect(win.left, win.bottom, win.right, win.top, COLORS.TRANSPARENT))
  218. end
  219. group:append(
  220. am.translate(win.right - 10, win.bottom + 10)
  221. ^ am.text(string.format("v%s, by %s", version, author), COLORS.WHITE, "right", "bottom")
  222. )
  223. if do_logo then
  224. group:append(
  225. am.translate(0, win.top - 20 - TEXTURES.LOGO.height/2)
  226. ^ pack_texture_into_sprite(TEXTURES.LOGO, TEXTURES.LOGO.width, TEXTURES.LOGO.height)
  227. )
  228. end
  229. group:append(make_main_scene_toolbelt())
  230. group:action(main_action)
  231. return group:tag"menu"
  232. end
  233. win.scene = am.group(
  234. main_scene(true, true)
  235. )
  236. noglobals()