From e016f4769dc226ff1d997fb4a268eef87ca3c298 Mon Sep 17 00:00:00 2001 From: Nicholas Hayashi Date: Wed, 4 Aug 2021 18:55:44 -0400 Subject: [PATCH] more map editor stuff, end game stats --- main.lua | 150 ++++++++++++++++++-------------------- res/mainmenuhex.png | Bin 0 -> 60458 bytes src/extra.lua | 14 ++++ src/game.lua | 173 ++++++++++++++++++++++++++++---------------- src/grid.lua | 51 ++++++++++--- src/gui.lua | 11 +++ src/hexyz.lua | 2 +- src/map-editor.lua | 73 +++++++++++++++---- src/tower.lua | 2 +- texture.lua | 1 + 10 files changed, 309 insertions(+), 168 deletions(-) create mode 100644 res/mainmenuhex.png diff --git a/main.lua b/main.lua index 0a0e1f6..1f60f0b 100644 --- a/main.lua +++ b/main.lua @@ -69,6 +69,25 @@ win = am.window{ show_cursor = true, } +-- top right display types +-- different scenes overlay different content in the top right of the screen +-- f1 toggles what is displayed in the top right of the screen in some scenes +TRDTS = { + NOTHING = 0, + CENTERED_EVENQ = 1, + EVENQ = 2, + HEX = 3, + PLATFORM = 4, + PERF = 5, + SEED = 6, + TILE = 7, +} + +function make_top_right_display_node() + return am.translate(win.right - 10, win.top - 15) + ^ am.text("", "right", "top"):tag"top_right_display" +end + -- asset interfaces and/or trivial code require "conf" require "color" @@ -89,7 +108,7 @@ require "src/tower" require "src/map-editor" -local sound_toggle_node_tag = "sound-on-off-icon" +local sound_toggle_node_tag = "sound_on_off_icon" local function make_sound_toggle_node(on) local sprite if on then @@ -101,7 +120,7 @@ local function make_sound_toggle_node(on) return (am.translate(win.right - 30, win.top - 60) ^ sprite) :tag(sound_toggle_node_tag) :action(function() - + -- @TODO click me! end) end @@ -126,22 +145,6 @@ local function toggle_mute() win.scene:replace(sound_toggle_node_tag, make_sound_toggle_node(settings.sound_on)) end --- text popup in the middle of the screen that dissapates, call from anywhere -function alert(message, color) - win.scene:append( - am.scale(3) ^ am.text(message, color or COLORS.WHITE) - :action(coroutine.create(function(self) - am.wait(am.tween(self, 1, { color = vec4(0) }, am.ease_out)) - win.scene:remove(self) - end)) - ) -end - -function unpause(root_node) - win.scene("game").paused = false - win.scene:remove(root_node) -end - function main_action(self) if win:key_pressed("escape") then if game then @@ -161,61 +164,7 @@ function main_action(self) end end -function make_main_scene_toolbelt() - local include_save_option = game - local include_unpause_option = game - local options = { - false, - { - texture = TEXTURES.NEW_GAME_HEX, - action = function() - win.scene:remove"menu" - game_init() - end - }, - false, - include_save_option and { - texture = TEXTURES.SAVE_GAME_HEX, - action = function() - game_save() - alert("succesfully saved!") - end - } or false, - false, - { - texture = TEXTURES.LOAD_GAME_HEX, - action = function() - local save = am.load_state("save", "json") - - if save then - win.scene:remove("menu") - game_init(save) - else - alert("no saved games") - end - end - }, - { - texture = TEXTURES.MAP_EDITOR_HEX, - action = function() - win.scene:remove("menu") - map_editor_init() - end - }, - include_unpause_option and { - texture = TEXTURES.UNPAUSE_HEX, - action = function() unpause(win.scene("menu")) end - } or false, - false and { - texture = TEXTURES.SETTINGS_HEX, - action = function() alert("not yet :)") end - }, - { - texture = TEXTURES.QUIT_HEX, - action = function() win:close() end - }, - false - } +function make_scene_menu(scene_options) -- calculate the dimensions of the whole grid local spacing = 150 @@ -227,6 +176,7 @@ function make_main_scene_toolbelt() local grid_pixel_height = grid_height * hvs local pixel_offset = vec2(-grid_pixel_width/2, win.bottom + hex_height(spacing)/2 + 20) + -- generate a map of hexagons (the menu is made up of two rows of hexes) and populate their locations with buttons from the provided options local map = hex_rectangular_map(grid_width, grid_height, HEX_ORIENTATION.POINTY) local group = am.group() local option_index = 1 @@ -234,7 +184,7 @@ function make_main_scene_toolbelt() for j,_ in pairs(map[i]) do local hex = vec2(i, j) local position = hex_to_pixel(hex, vec2(spacing), HEX_ORIENTATION.POINTY) - local option = options[option_index] + local option = scene_options[option_index] local texture = option and option.texture or TEXTURES.SHADED_HEX local color = option and COLORS.TRANSPARENT or vec4(0.3) local node = am.translate(position) @@ -277,7 +227,6 @@ function make_main_scene_toolbelt() return am.translate(pixel_offset) ^ group end - function main_scene(do_backdrop, do_logo) local group = am.group() @@ -338,17 +287,58 @@ function main_scene(do_backdrop, do_logo) group:append(logo) end - group:append(make_main_scene_toolbelt()) + local main_scene_options = { + false, + { + texture = TEXTURES.NEW_GAME_HEX, + action = function() + win.scene:remove"map_editor" + win.scene:remove"menu" + game_init() + end + }, + false, + false, + false, + { + texture = TEXTURES.LOAD_GAME_HEX, + action = function() + local save = am.load_state("save", "json") + + if save then + win.scene:remove("menu") + game_init(save) + else + gui_alert("no saved games") + end + end + }, + { + texture = TEXTURES.MAP_EDITOR_HEX, + action = function() + win.scene:remove("menu") + map_editor_init() + end + }, + false, + { + texture = TEXTURES.SETTINGS_HEX, + action = function() gui_alert("not yet :)") end + }, + { + texture = TEXTURES.QUIT_HEX, + action = function() win:close() end + }, + false + } + + group:append(make_scene_menu(main_scene_options)) group:action(main_action) return group:tag"menu" end -function switch_scene(scene) - win.scene = am.group(scene) -end - win.scene = am.group( main_scene(true, true) ) diff --git a/res/mainmenuhex.png b/res/mainmenuhex.png new file mode 100644 index 0000000000000000000000000000000000000000..383e30e3ea0387c9fd2a3c245b03d382764fa803 GIT binary patch literal 60458 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 Hu0mjf@+aw# literal 0 HcmV?d00001 diff --git a/src/extra.lua b/src/extra.lua index 0277579..ab79e92 100644 --- a/src/extra.lua +++ b/src/extra.lua @@ -29,6 +29,20 @@ function table.count(t) return count end +function table.highest_index(t) + local highest = nil + for i,v in pairs(t) do + if i and not highest then + highest = i + end + + if i > highest then + highest = i + end + end + return highest +end + function table.find(t, predicate) for i,v in pairs(t) do if predicate(v) then diff --git a/src/game.lua b/src/game.lua index eacd862..e2d7b66 100644 --- a/src/game.lua +++ b/src/game.lua @@ -2,24 +2,11 @@ game = false -- flag to tell if there is a game running game_state = {} --- top right display types --- f1 toggles what is displayed in the top right of the screen -local TRDTS = { - NOTHING = 0, - CENTERED_EVENQ = 1, - EVENQ = 2, - HEX = 3, - PLATFORM = 4, - PERF = 5, - SEED = 6, - TILE = 7, -} - local function get_initial_game_state(seed) local STARTING_MONEY = 75 local map = random_map(seed) - local world = make_hex_grid_scene(map) + local world = make_hex_grid_scene(map, true) return { map = map, -- map of hex coords map[x][y] to a 'tile' @@ -47,14 +34,6 @@ local function get_initial_game_state(seed) } end -local function get_wave_timer_text() - if game_state.spawning then - return string.format("WAVE (%d) OVER: %.2f", game_state.current_wave, game_state.time_until_next_break) - else - return string.format("NEXT WAVE (%d): %.2f", game_state.current_wave, game_state.time_until_next_wave) - end -end - local function get_top_right_display_text(hex, evenq, centered_evenq, display_type) local str = "" if display_type == TRDTS.CENTERED_EVENQ then @@ -81,6 +60,14 @@ local function get_top_right_display_text(hex, evenq, centered_evenq, display_ty return str end +local function get_wave_timer_text() + if game_state.spawning then + return string.format("WAVE (%d) OVER: %.2f", game_state.current_wave, game_state.time_until_next_break) + else + return string.format("NEXT WAVE (%d): %.2f", game_state.current_wave, game_state.time_until_next_wave) + end +end + -- initialized later, as part of the init of the toolbelt local function select_tower_type(tower_type) end local function select_toolbelt_button(i) end @@ -104,7 +91,64 @@ end local function game_pause() win.scene("game").paused = true - win.scene:append(main_scene(false, false)) + local game_scene_options = { + false, + { + texture = TEXTURES.NEW_GAME_HEX, + action = function() + game_init() + end + }, + false, + { + texture = TEXTURES.SAVE_GAME_HEX, + action = function() + game_save() + gui_alert("succesfully saved!") + end + }, + false, + { + texture = TEXTURES.LOAD_GAME_HEX, + action = function() + local save = am.load_state("save", "json") + + if save then + game_init(save) + else + gui_alert("no saved games") + end + end + }, + { + texture = TEXTURES.MAP_EDITOR_HEX, + action = function() + win.scene:remove("game") + map_editor_init(game_state.map.seed) + end + }, + { + texture = TEXTURES.UNPAUSE_HEX, + action = function() + + end + }, + { + texture = TEXTURES.SETTINGS_HEX, + action = function() + gui_alert("not yet :)") + end + }, + { + texture = TEXTURES.QUIT_HEX, + action = function() + win:close() + end + }, + false + } + + win.scene:append(make_scene_menu(game_scene_options)) end local function game_deserialize(json_string) @@ -116,7 +160,7 @@ local function game_deserialize(json_string) end new_game_state.map = random_map(new_game_state.seed) - new_game_state.world = make_hex_grid_scene(new_game_state.map) + new_game_state.world = make_hex_grid_scene(new_game_state.map, true) new_game_state.seed = nil for i,t in pairs(new_game_state.towers) do @@ -159,7 +203,7 @@ local function game_deserialize(json_string) end local function game_serialize() - local serialized = table.shallow_copy(state) + local serialized = table.shallow_copy(game_state) serialized.version = version serialized.seed = game_state.map.seed @@ -172,6 +216,7 @@ local function game_serialize() -- and the scene graph needs to be re-constituted at load time -- -- this is dumb and if i forsaw this i would have probably used float arrays instead of vectors + -- (the scene graph bit makes sense though) serialized.towers = {} for i,t in pairs(game_state.towers) do @@ -201,10 +246,16 @@ local function deselect_tile() win.scene:remove("tile_select_box") end +local function game_pause_menu() + +end + local function game_action(scene) - if game_state.score < 0 then game_end() return true end + if game_state.score < 0 then + game_end() + return true + end - local perf = am.perf_stats() game_state.time = game_state.time + am.delta_time game_state.score = game_state.score + am.delta_time @@ -258,14 +309,14 @@ local function game_action(scene) node.color = COLORS.CLARET node:action(am.tween(0.1, { color = COLORS.TRANSPARENT })) play_sfx(SOUNDS.BIRD2) - alert("closes the circle") + gui_alert("closes the circle") elseif cost > game_state.money then local node = win.scene("cursor"):child(2) node.color = COLORS.CLARET node:action(am.tween(0.1, { color = COLORS.TRANSPARENT })) play_sfx(SOUNDS.BIRD2) - alert("not enough money") + gui_alert("not enough money") else update_money(-cost) @@ -532,7 +583,7 @@ local function make_game_toolbelt() -- de-selecting currently selected tower if any toolbelt("toolbelt_select_square").hidden = true - win.scene:replace("cursor", make_hex_cursor(0, COLORS.TRANSPARENT):tag"cursor") + win.scene:replace("cursor", make_hex_cursor_node(0, COLORS.TRANSPARENT):tag"cursor") end end @@ -604,14 +655,6 @@ local function game_scene() end end) - local top_right_display = - am.translate(win.right - 10, win.top - 15) - ^ am.text("", "right", "top"):tag"top_right_display" - - local bottom_right_display = - am.translate(win.right - 10, win.bottom + win.height * 0.07 + 20) - ^ am.text("", "right", "bottom"):tag"bottom_right_display" - local curtain = am.rect(win.left, win.bottom, win.right, win.top, COLORS.TRUE_BLACK) curtain:action(coroutine.create(function() am.wait(am.tween(curtain, 3, { color = vec4(0) }, am.ease.out(am.ease.hyperbola))) @@ -621,12 +664,12 @@ local function game_scene() local scene = am.group( am.scale(1):tag"world_scale" ^ game_state.world, - am.translate(HEX_GRID_CENTER):tag"cursor_translate" ^ make_hex_cursor(0, COLORS.TRANSPARENT):tag"cursor", + am.translate(HEX_GRID_CENTER):tag"cursor_translate" ^ make_hex_cursor_node(0, COLORS.TRANSPARENT):tag"cursor", score, money, wave_timer, send_now_button, - top_right_display, + make_top_right_display_node(), make_game_toolbelt(), curtain ) @@ -638,17 +681,45 @@ local function game_scene() return scene end +-- this is a stupid name, it just returns a scene node group of hexagons in a hexagonal shape centered at 0,0, of size |radius| +-- |color_f| can be a function that takes a hex and returns a color, or just a color +-- optionally, |action_f| is a function that operates on the group node every frame +function make_hex_cursor_node(radius, color_f, action_f) + local color = type(color_f) == "userdata" and color_f or nil + local map = hex_spiral_map(vec2(0), radius) + local group = am.group() + + for _,h in pairs(map) do + local hexagon = am.circle(hex_to_pixel(h, vec2(HEX_SIZE)), HEX_SIZE, color or color_f(h), 6) + group:append(hexagon) + end + + if action_f then + group:action(action_f) + end + + return group +end + function update_score(diff) game_state.score = game_state.score + diff end function update_money(diff) game_state.money = game_state.money + diff end function game_end() + local hmob = table.highest_index(game_state.mobs) + local htower = table.highest_index(game_state.towers) + local hprojectile = table.highest_index(game_state.projectiles) + gui_alert(string.format( + "\nmobs spawned: %d\ntowers built: %d\nprojectiles spawned: %d\n", + hmob, htower, hprojectile + ), COLORS.WHITE, 1000) + game_state = {} game = false end function game_save() am.save_state("save", game_serialize(), "json") - alert("succesfully saved!") + gui_alert("succesfully saved!") end function game_init(saved_state) @@ -673,23 +744,3 @@ function game_init(saved_state) win.scene:append(game_scene()) end --- this is a stupid name, it just returns a scene node group of hexagons in a hexagonal shape centered at 0,0, of size |radius| --- |color_f| can be a function that takes a hex and returns a color, or just a color --- optionally, |action_f| is a function that operates on the group node every frame -function make_hex_cursor(radius, color_f, action_f) - local color = type(color_f) == "userdata" and color_f or nil - local map = hex_spiral_map(vec2(0), radius) - local group = am.group() - - for _,h in pairs(map) do - local hexagon = am.circle(hex_to_pixel(h, vec2(HEX_SIZE)), HEX_SIZE, color or color_f(h), 6) - group:append(hexagon) - end - - if action_f then - group:action(action_f) - end - - return group -end - diff --git a/src/grid.lua b/src/grid.lua index ce140af..0737d16 100644 --- a/src/grid.lua +++ b/src/grid.lua @@ -53,6 +53,25 @@ function evenq_is_in_interactable_region(evenq) }) end +function map_elevation_to_tile_type(elevation) + if elevation < -0.5 then -- lowest elevation + return "Water" + + elseif elevation < 0 then -- med-low elevation + return "Ground - Grass" + + elseif elevation < 0.5 then -- med-high elevation + return "Ground - Dirt" + + elseif elevation < 1 then -- high elevation + return "Mountain" + + else + -- not a normal elevation? not sure when this happens + return "n/a" + end +end + function is_water_elevation(elevation) return elevation < -0.5 end function is_mountain_elevation(elevation) return elevation >= 0.5 end @@ -174,7 +193,22 @@ function map_elevation_color(elevation) end end -function make_hex_grid_scene(map) +function make_hex_node(hex, tile, color) + if not color then + local evenq = hex_to_evenq(vec2(hex.x, hex.y)) + + -- light shading on edge cells + local mask = vec4(0, 0, 0, math.max(((evenq.x - HEX_GRID_WIDTH/2) / HEX_GRID_WIDTH) ^ 2 + , ((-evenq.y - HEX_GRID_HEIGHT/2) / HEX_GRID_HEIGHT) ^ 2)) + + color = map_elevation_color(tile.elevation) - mask + end + + return am.translate(hex_to_pixel(vec2(hex.x, hex.y), vec2(HEX_SIZE))) + ^ am.circle(vec2(0), HEX_SIZE, color, 6) +end + +function make_hex_grid_scene(map, do_generate_flow_field) -- the world's appearance relies largely on a backdrop which can be scaled in -- tone to give the appearance of light or darkness -- @NOTE replace this with a shader program @@ -191,16 +225,7 @@ function make_hex_grid_scene(map) local world = am.group(neg_mask):tag"world" for i,_ in pairs(map) do for j,tile in pairs(map[i]) do - local evenq = hex_to_evenq(vec2(i, j)) - - -- light shading on edge cells - local mask = vec4(0, 0, 0, math.max(((evenq.x - HEX_GRID_WIDTH/2) / HEX_GRID_WIDTH) ^ 2 - , ((-evenq.y - HEX_GRID_HEIGHT/2) / HEX_GRID_HEIGHT) ^ 2)) - - local color = map_elevation_color(tile.elevation) - mask - - local node = am.translate(hex_to_pixel(vec2(i, j), vec2(HEX_SIZE))) - ^ am.circle(vec2(0), HEX_SIZE, color, 6) + local node = make_hex_node(vec2(i, j), tile) hex_map_set(map, i, j, { elevation = tile.elevation, @@ -217,7 +242,9 @@ function make_hex_grid_scene(map) ^ pack_texture_into_sprite(TEXTURES.GEM1, HEX_SIZE, HEX_SIZE*1.1) ) - apply_flow_field(map, generate_flow_field(map, HEX_GRID_CENTER), world) + if do_generate_flow_field then + apply_flow_field(map, generate_flow_field(map, HEX_GRID_CENTER), world) + end return am.translate(WORLDSPACE_COORDINATE_OFFSET) ^ world end diff --git a/src/gui.lua b/src/gui.lua index f1a219c..81f8a0f 100644 --- a/src/gui.lua +++ b/src/gui.lua @@ -1,4 +1,15 @@ +-- text popup in the middle of the screen that dissapates +function gui_alert(message, color, decay_time) + win.scene:append( + am.scale(3) ^ am.text(message, color or COLORS.WHITE) + :action(coroutine.create(function(self) + am.wait(am.tween(self, decay_time or 1, { color = vec4(0) }, am.ease_in_out)) + win.scene:remove(self) + end)) + ) +end + function gui_numberfield(dimensions, opts) end diff --git a/src/hexyz.lua b/src/hexyz.lua index 02a1790..f3fed50 100644 --- a/src/hexyz.lua +++ b/src/hexyz.lua @@ -1,5 +1,5 @@ --- this is a single file with no dependencies which is meant to perform a bunch of mathy stuff +-- this is a single file which is meant to perform a bunch of mathy stuff -- related to hexagons, grids of them, and pathfinding on them -- -- it basically owes its entire existence to this resource: https://www.redblobgames.com/grids/hexagons/ diff --git a/src/map-editor.lua b/src/map-editor.lua index d6e8214..bc2b8be 100644 --- a/src/map-editor.lua +++ b/src/map-editor.lua @@ -1,25 +1,33 @@ local map_editor_state = { map = {}, - world = {} + world = {}, + + selected_tile = false } local function deselect_tile() + map_editor_state.selected_tile = false win.scene:remove("tile_select_box") end function map_editor_action() - local mouse = win:mouse_position() - local hex = pixel_to_hex(mouse - WORLDSPACE_COORDINATE_OFFSET, vec2(HEX_SIZE)) - local rounded_mouse = hex_to_pixel(hex, vec2(HEX_SIZE)) + WORLDSPACE_COORDINATE_OFFSET - local evenq = hex_to_evenq(hex) - local tile = hex_map_get(map_editor_state.map, hex) - local interactable = evenq_is_in_interactable_region(evenq{ y = -evenq.y }) - - if win:mouse_pressed"left" then + local mouse = win:mouse_position() + local hex = pixel_to_hex(mouse - WORLDSPACE_COORDINATE_OFFSET, vec2(HEX_SIZE)) + local rounded_mouse = hex_to_pixel(hex, vec2(HEX_SIZE)) + WORLDSPACE_COORDINATE_OFFSET + local evenq = hex_to_evenq(hex) + local tile = hex_map_get(map_editor_state.map, hex) + local interactable = evenq_is_in_interactable_region(evenq{ y = -evenq.y }) + + if win:key_pressed"escape" then + win.scene("map_editor").paused = true + win.scene:append(make_scene_menu(map_editor_scene_options)) + end + + if win:mouse_down"left" then deselect_tile() - win.scene:remove("tile_select_box") + map_editor_state.selected_tile = tile win.scene:append(( am.translate(rounded_mouse) ^ pack_texture_into_sprite(TEXTURES.SELECT_BOX, HEX_SIZE*2, HEX_SIZE*2, COLORS.SUNRAY) @@ -28,6 +36,36 @@ function map_editor_action() ) end + if map_editor_state.selected_tile then + if win:key_pressed"a" then + -- make the selected tile 'mountain' + map_editor_state.selected_tile.elevation = 0.75 + map_editor_state.selected_tile.node("circle").color = map_elevation_color(map_editor_state.selected_tile.elevation) + + elseif win:key_pressed"w" then + -- make the selected tile 'water' + map_editor_state.selected_tile.elevation = -0.75 + map_editor_state.selected_tile.node("circle").color = map_elevation_color(map_editor_state.selected_tile.elevation) + + elseif win:key_pressed"d" then + -- make the selected tile 'dirt' + map_editor_state.selected_tile.elevation = 0.25 + map_editor_state.selected_tile.node("circle").color = map_elevation_color(map_editor_state.selected_tile.elevation) + + elseif win:key_pressed"g" then + -- make the selected tile 'grass' + map_editor_state.selected_tile.elevation = -0.25 + map_editor_state.selected_tile.node("circle").color = map_elevation_color(map_editor_state.selected_tile.elevation) + end + + -- fine tune tile's elevation with mouse wheel + local mouse_wheel_delta = win:mouse_wheel_delta().y / 100 + if map_editor_state.selected_tile and mouse_wheel_delta ~= 0 then + map_editor_state.selected_tile.elevation = math.clamp(map_editor_state.selected_tile.elevation + mouse_wheel_delta, -1, 1) + map_editor_state.selected_tile.node("circle").color = map_elevation_color(map_editor_state.selected_tile.elevation) + end + end + -- update the cursor if not interactable then win.scene("cursor").hidden = true @@ -36,13 +74,20 @@ function map_editor_action() win.scene("cursor").hidden = false win.scene("cursor_translate").position2d = rounded_mouse end + + if tile then + win.scene("top_right_display").text = string.format( + "raw elevation value: %.2f\ntile type: %s", + tile.elevation, map_elevation_to_tile_type(tile.elevation) + ) + end end function map_editor_init() local map_editor_scene = am.group():tag"map_editor" - map_editor_state.map = default_map_editor_map() - map_editor_state.world = make_hex_grid_scene(map_editor_state.map) + map_editor_state.map = default_map_editor_map(1) + map_editor_state.world = make_hex_grid_scene(map_editor_state.map, false) map_editor_scene:append(map_editor_state.world) @@ -50,9 +95,11 @@ function map_editor_init() win.scene:append(map_editor_scene) win.scene:append( am.translate(HEX_GRID_CENTER):tag"cursor_translate" - ^ make_hex_cursor(0, COLORS.TRANSPARENT):tag"cursor" + ^ make_hex_cursor_node(0, COLORS.TRANSPARENT):tag"cursor" ) + win.scene:append(make_top_right_display_node()) + win.scene:late_action(map_editor_action) end diff --git a/src/tower.lua b/src/tower.lua index 6b7048c..5bb6923 100644 --- a/src/tower.lua +++ b/src/tower.lua @@ -211,7 +211,7 @@ do end) tower_cursors[i] = am.group{ - make_hex_cursor(get_tower_range(i), vec4(0), coroutine_), + make_hex_cursor_node(get_tower_range(i), vec4(0), coroutine_), tower_sprite } end diff --git a/texture.lua b/texture.lua index 0d64996..3bb5df8 100644 --- a/texture.lua +++ b/texture.lua @@ -26,6 +26,7 @@ TEXTURES = { ABOUT_HEX = load_texture("res/abouthex.png"), QUIT_HEX = load_texture("res/quithex.png"), UNPAUSE_HEX = load_texture("res/unpausehex.png"), + MAIN_MENU_HEX = load_texture("res/mainmenuhex.png"), CURTAIN = load_texture("res/curtain1.png"),