From 78c891b80f04b4beb54c4b33da973a551bbdaf54 Mon Sep 17 00:00:00 2001 From: Nicholas Hayashi Date: Mon, 1 Feb 2021 02:29:27 -0500 Subject: [PATCH] pause menu --- .DS_Store | Bin 6148 -> 0 bytes .gitignore | 1 + color.lua | 2 +- main.lua | 141 +++++++++------------------------------ res/.DS_Store | Bin 6148 -> 0 bytes res/tower_lighthouse.png | Bin 643 -> 796 bytes res/tower_moat.png | Bin 1819 -> 1443 bytes res/tower_redeye.png | Bin 640 -> 637 bytes res/tower_wall.png | Bin 2033 -> 1428 bytes src/entity.lua | 38 +++-------- src/grid.lua | 19 ++---- src/gui.lua | 116 +++++++++++++++++++++++++++----- src/mob.lua | 34 +++++----- src/projectile.lua | 26 +++++--- src/tower.lua | 106 ++++++++++++++++++++++++++--- 15 files changed, 278 insertions(+), 205 deletions(-) delete mode 100644 .DS_Store delete mode 100644 res/.DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 1572c514ac9ee1e97d15ded89d38cef5d2771c2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%}T>S5Z-O8ZYyFBLiM&6Z#|^dR(lXa)q^)7q6ZaCXwg7TN|RbNR`MABypZ?; zzK%1y>tAcHDl!AJ-|XznhWQe9GmJ6b?6)e66&Yg!6fu*B;Tyqq)G^5zPY#gd9#Plp zgdWVEyzW>uIsPI8`0ldIV?GPK!RPna@uS$XUU(*(o0^^xq96)$g=6PD95}HX_oJrU zJH*+p8=rf|-V4LdyX|`WetU3IT-XeQ*!6>UPbK@UHiR4<_(3ZiG{b(-iqt-iUJxQL z@+ZYolC0Ira&6TbmSxhYT4lMqQXdZUqO@Gu*g3tpx=wC}w|AOS4qu;=d4q3o4~D7k z(&+`AFgODbMrT=%wORD3=4Y?_yEQK*NyVx{)ztQru846f6`FHM|nFx9Bj88^)bH&5oKL*eS_u)kE{jN2M%BnF6quMA}Mw21fr z_T>KmYZA?f0b<}^F~D -0.5 and tile.elevation <= 0.5 + return tile and tile_is_medium_elevation(tile) end) end diff --git a/src/gui.lua b/src/gui.lua index 99f2b9d..580ead5 100644 --- a/src/gui.lua +++ b/src/gui.lua @@ -12,8 +12,8 @@ function set_hot(id) if not active then hot = { id = id } end end -function register_button_widget(id, rect) - register_widget(id, function() +function register_button_widget(id, rect, onclick) + register_widget(id, function(i) local click = false if active and active.id == id then @@ -27,23 +27,107 @@ function register_button_widget(id, rect) if point_in_rect(WIN:mouse_position(), rect) then set_hot(id) end - return click + if click then onclick() end end) end -function make_button_widget(id, position, dimensions, text) - local rect = am.rect( - -dimensions.x/2, - dimensions.y/2, - dimensions.x/2, - -dimensions.y/2, - vec4(1, 0, 0, 1) - ) +function do_gui_updates() + for i,w in pairs(widgets) do + w.poll(i) + end +end - register_button_widget(id, rect) - return am.group{ - rect, - am.text(text) - }:tag(id) +local function get_tower_tooltip_text(tower_type) + return string.format( + "%s\n%s\n%s\ncost: %d" + , get_tower_name(tower_type) + , get_tower_placement_rules_text(tower_type) + , get_tower_short_description(tower_type) + , get_tower_base_cost(tower_type) + ) end +function toolbelt() + local function button(size, half_size, tower_texture, padding, i, offset, key_name) + local x1 = (size + padding) * i + offset.x + local y1 = offset.y + local x2 = (size + padding) * i + offset.x + size + local y2 = offset.y + size + + register_button_widget("toolbelt_tower_button" .. i, am.rect(x1, y1, x2, y2), function() select_tower_type(i) end) + + return am.translate(vec2(size + padding, 0) * i + offset) + ^ am.group{ + am.translate(0, half_size) + ^ pack_texture_into_sprite(TEXTURES.BUTTON1, size, size), + + am.translate(0, half_size) + ^ pack_texture_into_sprite(tower_texture, size, size), + + am.translate(vec2(half_size)) + ^ am.group{ + pack_texture_into_sprite(TEXTURES.BUTTON1, half_size, half_size), + am.scale(2) + ^ am.text(key_name, COLORS.BLACK) + } + } + end + + -- init the toolbelt + local toolbelt_height = hex_height(HEX_SIZE) * 2 + local toolbelt = am.group{ + am.translate(WIN.left + 10, WIN.bottom + toolbelt_height + 20) + ^ am.text(get_tower_tooltip_text(SELECTED_TOWER_TYPE), "left", "bottom"):tag"tower_tooltip", + am.rect(WIN.left, WIN.bottom, WIN.right, WIN.bottom + toolbelt_height, COLORS.TRANSPARENT) + }:tag"toolbelt" + + local padding = 15 + local size = toolbelt_height - padding + local half_size = size/2 + local offset = vec2(WIN.left + padding*3, WIN.bottom + padding/3) + local tab_button = am.translate(vec2(0, half_size) + offset) ^ am.group{ + pack_texture_into_sprite(TEXTURES.WIDER_BUTTON1, 54, 32), + pack_texture_into_sprite(TEXTURES.TAB_ICON, 25, 25) + } + toolbelt:append(tab_button) + local tower_select_square = ( + am.translate(vec2(size + padding, half_size) + offset) + ^ am.rect(-size/2-3, -size/2-3, size/2+3, size/2+3, COLORS.SUNRAY) + ):tag"tower_select_square" + toolbelt:append(tower_select_square) + + -- fill in the other tower options + local tower_type_values = { + TOWER_TYPE.REDEYE, + TOWER_TYPE.LIGHTHOUSE, + TOWER_TYPE.WALL, + TOWER_TYPE.MOAT + } + local keys = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=' } + for i = 1, #keys do + toolbelt:append( + button( + size, + half_size, + get_tower_texture(tower_type_values[i]), + padding, + i, + offset, + keys[i] + ) + ) + end + + select_tower_type = function(tower_type) + SELECTED_TOWER_TYPE = tower_type + if TOWER_SPECS[SELECTED_TOWER_TYPE] then + WIN.scene"tower_tooltip".text = get_tower_tooltip_text(tower_type) + local new_position = vec2((size + padding) * tower_type, size/2) + offset + WIN.scene"tower_select_square":action(am.tween(0.1, { position2d = new_position })) + + WIN.scene:action(am.play(am.sfxr_synth(SOUNDS.SELECT1), false, 1, SFX_VOLUME)) + end + end + + return toolbelt +end diff --git a/src/mob.lua b/src/mob.lua index 0294e92..013f423 100644 --- a/src/mob.lua +++ b/src/mob.lua @@ -1,14 +1,6 @@ ---[[ -mob(entity) structure: -{ - path - 2d table - map of hexes to other hexes, forms a path - speed - number - multiplier on distance travelled per frame, up to the update function to use correctly - bounty - number - score bonus you get when this mob is killed - hurtbox_radius - number - -} ---]] +MOBS = {} MAX_MOB_SIZE = hex_height(HEX_SIZE, ORIENTATION.FLAT) / 2 MOB_SIZE = MAX_MOB_SIZE @@ -33,7 +25,7 @@ end -- check if a the tile at |hex| is passable by |mob| function mob_can_pass_through(mob, hex) local tile = HEX_MAP.get(hex.x, hex.y) - return tile and tile.elevation <= 0.5 and tile.elevation > -0.5 + return tile and tile_is_medium_elevation(tile) end function mob_die(mob, mob_index) @@ -143,12 +135,6 @@ local function update_mob(mob, mob_index) if mob.frame_target and mob.frame_target == last_frame_hex then --log('backpedaling') - -- backpedaling or failing to find anywhere to go, run Astar and hope it works - --local made_it - --mob.path, made_it = Astar(HEX_MAP, mob.hex, HEX_GRID_CENTER, grid_heuristic, grid_cost) - --if not made_it then - -- log('stuck!') - --end end -- do movement @@ -187,7 +173,7 @@ local function make_and_register_mob(mob_type) register_entity(MOBS, mob) end -local SPAWN_CHANCE = 25 +local SPAWN_CHANCE = 45 function do_mob_spawning() --if WIN:key_pressed"space" then if math.random(SPAWN_CHANCE) == 1 then @@ -196,3 +182,17 @@ function do_mob_spawning() end end +function delete_all_mobs() + for mob_index,mob in pairs(MOBS) do + if mob then delete_entity(MOBS, mob_index) end + end +end + +function do_mob_updates() + for mob_index,mob in pairs(MOBS) do + if mob and mob.update then + mob.update(mob, mob_index) + end + end +end + diff --git a/src/projectile.lua b/src/projectile.lua index 19b8187..2a823e3 100644 --- a/src/projectile.lua +++ b/src/projectile.lua @@ -1,16 +1,8 @@ ---[[ -bullet/projectile(entity) structure -{ - vector - vec2 - normalized vector of the current direction of this projectile - velocity - number - multplier on distance travelled per frame - damage - number - guess - hitbox_radius - number - hitboxes are circles -} ---]] +PROJECTILES = {} -function update_projectile(projectile, projectile_index) +local function update_projectile(projectile, projectile_index) projectile.position = projectile.position + projectile.vector * projectile.velocity projectile.node.position2d = projectile.position projectile.hex = pixel_to_hex(projectile.position) @@ -80,3 +72,17 @@ function make_and_register_projectile(hex, vector, velocity, damage, hitbox_radi register_entity(PROJECTILES, projectile) end +function delete_all_projectiles() + for projectile_index,projectile in pairs(PROJECTILES) do + if projectile then delete_entity(PROJECTILES, projectile_index) end + end +end + +function do_projectile_updates() + for projectile_index,projectile in pairs(PROJECTILES) do + if projectile and projectile.update then + projectile.update(projectile, projectile_index) + end + end +end + diff --git a/src/tower.lua b/src/tower.lua index 26fd029..f1bf01e 100644 --- a/src/tower.lua +++ b/src/tower.lua @@ -1,5 +1,7 @@ +TOWERS = {} + TOWER_TYPE = { REDEYE = 1, LIGHTHOUSE = 2, @@ -72,6 +74,34 @@ local function make_tower_sprite(tower_type) return pack_texture_into_sprite(get_tower_texture(tower_type), HEX_PIXEL_WIDTH, HEX_PIXEL_HEIGHT) end +local function make_tower_node(tower_type) + if tower_type == TOWER_TYPE.REDEYE then + return make_tower_sprite(tower_type) + + elseif tower_type == TOWER_TYPE.LIGHTHOUSE then + return am.group( + make_tower_sprite(tower_type) + ) + elseif tower_type == TOWER_TYPE.WALL then + return am.circle(vec2(0), HEX_SIZE, COLORS.VERY_DARK_GRAY, 6) + + elseif tower_type == TOWER_TYPE.MOAT then + return am.circle(vec2(0), HEX_SIZE, (COLORS.WATER){a=1}, 6) + + end +end + +function towers_on_hex(hex) + local t = {} + for tower_index,tower in pairs(TOWERS) do + if tower and tower.hex == hex then + table.insert(t, tower_index, tower) + end + end + return t +end + + function tower_on_hex(hex) return table.find(TOWERS, function(tower) return tower.hex == hex @@ -81,9 +111,24 @@ end function tower_is_buildable_on(hex, tile, tower_type) if hex == HEX_GRID_CENTER then return false end - local blocked = tower_on_hex(hex) or #mobs_on_hex(hex) ~= 0 + local blocking_towers = towers_on_hex(hex) + local blocking_mobs = mobs_on_hex(hex) + + local towers_blocking = #blocking_towers ~= 0 + local mobs_blocking = #blocking_mobs ~= 0 + + local blocked = mobs_blocking or towers_blocking if tower_type == TOWER_TYPE.REDEYE then + if not mobs_blocking and towers_blocking then + blocked = false + for _,tower in pairs(TOWERS) do + if tower.type ~= TOWER_TYPE.WALL then + blocked = true + break + end + end + end return not blocked and tile.elevation > 0.5 elseif tower_type == TOWER_TYPE.LIGHTHOUSE then @@ -96,13 +141,13 @@ function tower_is_buildable_on(hex, tile, tower_type) break end end - return not blocked and tile.elevation <= 0.5 and tile.elevation > -0.5 and has_water_neighbour + return not blocked and tile_is_medium_elevation(tile) and has_water_neighbour elseif tower_type == TOWER_TYPE.WALL then - return not blocked and tile.elevation <= 0.5 and tile.elevation > -0.5 + return not blocked and tile_is_medium_elevation(tile) elseif tower_type == TOWER_TYPE.MOAT then - return not blocked and tile.elevation <= 0.5 and tile.elevation > -0.5 + return not blocked and tile_is_medium_elevation(tile) end end @@ -158,10 +203,11 @@ end function make_and_register_tower(hex, tower_type) local tower = make_basic_entity( hex, - make_tower_sprite(tower_type), + make_tower_node(tower_type), get_tower_update_function(tower_type) ) + local need_to_regen_flow_field = true tower.type = tower_type if tower_type == TOWER_TYPE.REDEYE then tower.range = 7 @@ -171,18 +217,46 @@ function make_and_register_tower(hex, tower_type) HEX_MAP[hex.x][hex.y].elevation = 2 elseif tower_type == TOWER_TYPE.LIGHTHOUSE then - tower.range = 4 + tower.range = 5 tower.perimeter = ring_map(tower.hex, tower.range) + --[[ + tower.node:append( + am.particles2d{ + source_pos = vec2(0, 12), + source_pos_var = vec2(2), + start_size = 1, + start_size_var = 1, + end_size = 1, + end_size_var = 1, + angle = 0, + angle_var = math.pi, + speed = 1, + speed_var = 2, + life = 10, + life_var = 1, + start_color = COLORS.WHITE, + start_color_var = vec4(0.1, 0.1, 0.1, 1), + end_color = COLORS.SUNRAY, + end_color_var = vec4(0.1), + emission_rate = 4, + start_particles = 4, + max_particles = 200 + } + ) + ]] + -- @HACK + need_to_regen_flow_field = false elseif tower_type == TOWER_TYPE.WALL then HEX_MAP[hex.x][hex.y].elevation = 1 elseif tower_type == TOWER_TYPE.MOAT then - HEX_MAP[hex.x][hex.y].elevation = 0 - + HEX_MAP[hex.x][hex.y].elevation = -1 end - generate_and_apply_flow_field(HEX_MAP, HEX_GRID_CENTER, WORLD) + if need_to_regen_flow_field then + generate_and_apply_flow_field(HEX_MAP, HEX_GRID_CENTER, WORLD) + end register_entity(TOWERS, tower) end @@ -193,3 +267,17 @@ function build_tower(hex, tower_type) vplay_sfx(SOUNDS.EXPLOSION4) end +function delete_all_towers() + for tower_index,tower in pairs(TOWERS) do + if tower then delete_entity(TOWERS, tower_index) end + end +end + +function do_tower_updates() + for tower_index,tower in pairs(TOWERS) do + if tower and tower.update then + tower.update(tower, tower_index) + end + end +end +