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.

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