diff --git a/main.lua b/main.lua index b97c553..9620b62 100644 --- a/main.lua +++ b/main.lua @@ -29,7 +29,7 @@ -- -- make art, birds-eye-ify the redeye tower and lighthouse maybe? --- resolutions and aspect ratios seem like a huge mess +-- aspect ratios seem like a huge mess -- for now, i think we should enforce 4:3 local RESOLUTION_OPTIONS = { -- 16:9 @@ -47,6 +47,7 @@ local RESOLUTION_OPTIONS = { { width = 832, height = 624 }, { width = 800, height = 600 }, } + settings = am.load_state("settings", "json") or { fullscreen = false, window_width = 1400, @@ -69,8 +70,8 @@ do mode = settings.fullscreen and "fullscreen" or "windowed", resizable = true, highdpi = true, - letterbox = true, resizable = true, -- user should probably set their resolution instead of resizing the window, but hey. + letterbox = true, show_cursor = true, } end diff --git a/res/mob2_1.png b/res/mob2_1.png deleted file mode 100644 index 53a7e49..0000000 Binary files a/res/mob2_1.png and /dev/null differ diff --git a/res/shaded_hex1.png b/res/shaded_hex1.png deleted file mode 100644 index 0a5fe4e..0000000 Binary files a/res/shaded_hex1.png and /dev/null differ diff --git a/src/game.lua b/src/game.lua index ce34b59..f57c36d 100644 --- a/src/game.lua +++ b/src/game.lua @@ -36,7 +36,7 @@ local function get_initial_game_state(seed) projectiles = {}, -- list of projectile entities current_wave = 1, - time_until_next_wave = 0, + time_until_next_wave = 15, time_until_next_break = 0, spawning = false, spawn_chance = 0, @@ -334,12 +334,40 @@ local function game_action(scene) end win.scene("score").text = string.format("SCORE: %.2f", state.score) - win.scene("money").text = string.format("MONEY: %d", state.money) + win.scene("money").text = string.format("MONEY: $%d", state.money) win.scene("wave_timer").text = get_wave_timer_text() + win.scene("send_now_button").hidden = state.spawning win.scene("top_right_display").text = get_top_right_display_text(hex, evenq, centered_evenq, state.selected_top_right_display_type) end local function make_game_toolbelt() + local toolbelt_height = win.height * 0.07 + local function get_tower_tooltip_text_node(tower_type) + local name = get_tower_name(tower_type) + local placement_rules = get_tower_placement_rules_text(tower_type) + local short_desc = get_tower_short_description(tower_type) + local cost = get_tower_cost(tower_type) + + if not (name or placement_rules or short_desc or cost) then + return am.group():tag"tower_tooltip_text" + end + + local color = COLORS.WHITE + return (am.translate(win.left + 10, win.bottom + toolbelt_height + 20) + ^ am.scale(1) + ^ am.group( + am.translate(0, 40) + ^ am.text(string.format("%s - %s", name, short_desc), color, "left"):tag"tower_name", + + am.translate(0, 20) + ^ am.text(placement_rules, color, "left"):tag"tower_placement_rules", + + am.translate(0, 0) + ^ am.text(string.format("$%d", cost), color, "left"):tag"tower_cost" + ) + ) + :tag"tower_tooltip_text" + end local function toolbelt_button(size, half_size, tower_texture, padding, i, offset, key_name) local button = am.translate(vec2(size + padding, 0) * i + offset) @@ -366,47 +394,24 @@ local function make_game_toolbelt() button:action(function(self) if point_in_rect(win:mouse_position(), rect) then - win.scene:replace("tower_tooltip_text", get_tower_tooltip_text_node(tower_type)) + -- @TODO make hover on tower show you the tooltip + win.scene:replace("tower_tooltip_text", get_tower_tooltip_text_node(i)) if win:mouse_pressed"left" then select_toolbelt_button(i) end + else + if state.selected_tower_type then + win.scene:replace("tower_tooltip_text", get_tower_tooltip_text_node(state.selected_tower_type)) + else + --win.scene:replace("tower_tooltip_text", am.group():tag"tower_tooltip_text") + end end end) return button end - local toolbelt_height = win.height * 0.07 - local function get_tower_tooltip_text_node(tower_type) - local name = get_tower_name(tower_type) - local placement_rules = get_tower_placement_rules_text(tower_type) - local short_desc = get_tower_short_description(tower_type) - local cost = get_tower_cost(tower_type) - - if not (name or placement_rules or short_desc or cost) then - return am.group():tag"tower_tooltip_text" - end - - local color = COLORS.WHITE - return (am.translate(win.left + 10, win.bottom + toolbelt_height + 20) - ^ am.scale(1) - ^ am.group( - am.translate(0, 60) - ^ am.text(name, color, "left"):tag"tower_name", - - am.translate(0, 40) - ^ am.text(placement_rules, color, "left"):tag"tower_placement_rules", - - am.translate(0, 20) - ^ am.text(short_desc, color, "left"):tag"tower_short_description", - - am.translate(0, 0) - ^ am.text(string.format("cost: %d", cost), color, "left"):tag"tower_cost" - ) - ) - :tag"tower_tooltip_text" - end local toolbelt = am.group( am.group():tag"tower_tooltip_text", am.rect(win.left, win.bottom, win.right, win.bottom + toolbelt_height, COLORS.TRANSPARENT) @@ -456,8 +461,7 @@ local function make_game_toolbelt() ) end - local a = win.left + #toolbelt_options * (size + padding) - log(a) + --local a = win.left + #toolbelt_options * (size + padding) local settings_button_position = vec2(win.right - half_size - 20, win.bottom + half_size + padding/3) local settings_button_rect = { @@ -472,7 +476,7 @@ local function make_game_toolbelt() am.translate(settings_button_position) ^ am.group( pack_texture_into_sprite(TEXTURES.BUTTON1, size, size), - pack_texture_into_sprite(TEXTURES.GEAR, size-padding, size-padding) + pack_texture_into_sprite(TEXTURES.GEAR, size - padding, size - padding) ) :action(function(self) if point_in_rect(win:mouse_position(), settings_button_rect) then @@ -524,19 +528,50 @@ end local function game_scene() local score = - am.translate(win.left + 10, win.top - 20) - ^ am.text("", "left"):tag"score" + am.translate(win.left + 10, win.top - 15) + ^ am.text("", "left", "top"):tag"score" local money = - am.translate(win.left + 10, win.top - 40) - ^ am.text("", "left"):tag"money" + am.translate(win.left + 10, win.top - 35) + ^ am.text("", "left", "top"):tag"money" local wave_timer = am.translate(0, win.top - 20) ^ am.text(get_wave_timer_text()):tag"wave_timer" + local send_now_button_position = vec2(0, win.top - 40) + local send_now_button_dimensions = vec2(200, 20) + local send_now_button_rect = { + x1 = -send_now_button_dimensions.x/2 + send_now_button_position.x, + y1 = -send_now_button_dimensions.y/2 + send_now_button_position.y, + x2 = send_now_button_dimensions.x/2 + send_now_button_position.x, + y2 = send_now_button_dimensions.y/2 + send_now_button_position.y + } + local send_now_button = + am.translate(send_now_button_position) + ^ am.text("> SEND NOW <") + :tag"send_now_button" + :action(function(self) + local mouse = win:mouse_position() + + if point_in_rect(mouse, send_now_button_rect) then + self.color = COLORS.SUNRAY + + if win:mouse_pressed("left") then + if state.spawning then + + else + play_sfx(SOUNDS.PUSH1) + state.time_until_next_wave = 0 + end + end + else + self.color = vec4(1) + end + end) + local top_right_display = - am.translate(win.right - 10, win.top - 20) + am.translate(win.right - 10, win.top - 15) ^ am.text("", "right", "top"):tag"top_right_display" local bottom_right_display = @@ -556,6 +591,7 @@ local function game_scene() score, money, wave_timer, + send_now_button, top_right_display, make_game_toolbelt(), curtain diff --git a/src/grid.lua b/src/grid.lua index 2b53b8c..9e06995 100644 --- a/src/grid.lua +++ b/src/grid.lua @@ -43,13 +43,13 @@ WORLDSPACE_COORDINATE_OFFSET = -HEX_GRID_PIXEL_DIMENSIONS/2 -- the outer edges of the map are not interactable -- the interactable region is defined with this function and constant -HEX_GRID_INTERACTABLE_REGION_MARGIN = 3 +HEX_GRID_INTERACTABLE_REGION_MARGIN = vec2(3, 4) function evenq_is_in_interactable_region(evenq) return point_in_rect(evenq, { - x1 = HEX_GRID_INTERACTABLE_REGION_MARGIN, - x2 = HEX_GRID_WIDTH - HEX_GRID_INTERACTABLE_REGION_MARGIN, - y1 = HEX_GRID_INTERACTABLE_REGION_MARGIN, - y2 = HEX_GRID_HEIGHT - HEX_GRID_INTERACTABLE_REGION_MARGIN + x1 = HEX_GRID_INTERACTABLE_REGION_MARGIN.x, + x2 = HEX_GRID_WIDTH - HEX_GRID_INTERACTABLE_REGION_MARGIN.x, + y1 = HEX_GRID_INTERACTABLE_REGION_MARGIN.y, + y2 = HEX_GRID_HEIGHT - HEX_GRID_INTERACTABLE_REGION_MARGIN.y }) end diff --git a/src/mob.lua b/src/mob.lua index 0303872..6221a72 100644 --- a/src/mob.lua +++ b/src/mob.lua @@ -33,7 +33,7 @@ function get_mob_spec(mob_type) end local function grow_mob_health(mob_type, spec_health, time) - return spec_health + (state.current_wave - 1) * 3 + return spec_health + math.pow(state.current_wave - 1, 2) end local function grow_mob_speed(mob_type, spec_speed, time) -- @TODO maybe speed shouldn't grow with time at all. @@ -41,7 +41,7 @@ local function grow_mob_speed(mob_type, spec_speed, time) return spec_speed end local function grow_mob_bounty(mob_type, spec_bounty, time) - return spec_bounty + (state.current_wave - 1) * 3 + return spec_bounty + math.pow(state.current_wave - 1, 2) end function mobs_on_hex(hex) @@ -219,9 +219,9 @@ local function update_mob_spooder(mob, mob_index) -- or between when we last calculated this target and now -- check for that now if mob_can_pass_through(mob, mob.frame_target) then - local from = state.map.get(mob.hex.x, mob.hex.y) - local to = state.map.get(mob.frame_target.x, mob.frame_target.y) - local rate = (math.abs(from.elevation - to.elevation) * 100) * mob.speed * am.delta_time + local from = hex_map_get(state.map, mob.hex) + local to = hex_map_get(state.map, mob.frame_target) + local rate = (math.abs(from.elevation - to.elevation) * mob.speed) + 0.0001 * am.delta_time mob.position = mob.position + math.normalize(hex_to_pixel(mob.frame_target, vec2(HEX_SIZE)) - mob.position) * rate mob.node.position2d = mob.position @@ -329,7 +329,11 @@ end function do_mob_spawning() if can_spawn_mob() then - make_and_register_mob(MOB_TYPE.BEEPER) + if state.current_wave % 2 == 0 then + make_and_register_mob(MOB_TYPE.SPOODER) + else + make_and_register_mob(MOB_TYPE.BEEPER) + end end end diff --git a/src/tower.lua b/src/tower.lua index d46102d..853e3c1 100644 --- a/src/tower.lua +++ b/src/tower.lua @@ -30,8 +30,8 @@ TOWER_SPECS = { }, [TOWER_TYPE.HOWITZER] = { name = "Howitzer", - placement_rules_text = "Place on non-Water, non-Mountain or on Walls", - short_description = "Fires artillery. Range increases with elevation of terrain underneath.", + placement_rules_text = "Place on non-Water, non-Mountain", + short_description = "Fires area of effect artillery.", texture = TEXTURES.TOWER_HOWITZER, icon_texture = TEXTURES.TOWER_HOWITZER_ICON, cost = 20, @@ -42,12 +42,12 @@ TOWER_SPECS = { }, [TOWER_TYPE.REDEYE] = { name = "Redeye", - placement_rules_text = "Place on Mountains or on Walls", + placement_rules_text = "Place on Mountains", short_description = "Long-range, single-target laser tower", texture = TEXTURES.TOWER_REDEYE, icon_texture = TEXTURES.TOWER_REDEYE_ICON, cost = 20, - range = 8, + range = 9, fire_rate = 1, size = 0, height = 1,