From dbdd585c48790271d6131623293b026639b01953 Mon Sep 17 00:00:00 2001 From: a327ex Date: Wed, 23 Jun 2021 00:53:37 -0300 Subject: [PATCH] Loop update 1/4 --- arena.lua | 221 +------------------------------------ buy_screen.lua | 15 ++- engine/init.lua | 4 +- main.lua | 287 +++++++++++++++++++++++++++++++++++++++++++++--- mainmenu.lua | 202 ++++++++++++++++++++++++++++++++++ player.lua | 35 +++--- shared.lua | 7 +- todo | 43 ++++---- 8 files changed, 539 insertions(+), 275 deletions(-) create mode 100644 mainmenu.lua diff --git a/arena.lua b/arena.lua index 39d4e3b..f1b0890 100644 --- a/arena.lua +++ b/arena.lua @@ -348,229 +348,12 @@ function Arena:update(dt) end if self.shop_text then self.shop_text:update(dt) end - -- print(self.enemy_spawns_prevented) if input.escape.pressed and not self.transitioning and not self.in_credits and not self.choosing_passives then if not self.paused then - input:set_mouse_visible(true) - trigger:tween(0.25, _G, {slow_amount = 0}, math.linear, function() - slow_amount = 0 - self.paused = true - self.paused_t1 = Text2{group = self.ui, x = gw/2, y = gh/2 - 108, sx = 0.6, sy = 0.6, lines = {{text = '[bg10]<-, a or m1 ->, d or m2', font = fat_font, alignment = 'center'}}} - self.paused_t2 = Text2{group = self.ui, x = gw/2, y = gh/2 - 92, lines = {{text = '[bg10]turn left turn right', font = pixul_font, alignment = 'center'}}} - self.ng_t = Text2{group = self.ui, x = gw/2 + 63, y = gh - 50, lines = {{text = '[bg10]current: ' .. current_new_game_plus, font = pixul_font, alignment = 'center'}}} - - self.resume_button = Button{group = self.ui, x = gw/2, y = gh - 225, force_update = true, button_text = 'resume game (esc)', fg_color = 'bg10', bg_color = 'bg', action = function(b) - trigger:tween(0.25, _G, {slow_amount = 1}, math.linear, function() - slow_amount = 1 - self.paused = false - if self.paused_t1 then self.paused_t1.dead = true; self.paused_t1 = nil end - if self.paused_t2 then self.paused_t2.dead = true; self.paused_t2 = nil end - if self.ng_t then self.ng_t.dead = true; self.ng_t = nil end - if self.resume_button then self.resume_button.dead = true; self.resume_button = nil end - if self.restart_button then self.restart_button.dead = true; self.restart_button = nil end - if self.mouse_button then self.mouse_button.dead = true; self.mouse_button = nil end - if self.dark_transition_button then self.dark_transition_button.dead = true; self.dark_transition_button = nil end - if self.sfx_button then self.sfx_button.dead = true; self.sfx_button = nil end - if self.music_button then self.music_button.dead = true; self.music_button = nil end - if self.video_button_1 then self.video_button_1.dead = true; self.video_button_1 = nil end - if self.video_button_2 then self.video_button_2.dead = true; self.video_button_2 = nil end - if self.video_button_3 then self.video_button_3.dead = true; self.video_button_3 = nil end - if self.quit_button then self.quit_button.dead = true; self.quit_button = nil end - if self.screen_shake_button then self.screen_shake_button.dead = true; self.screen_shake_button = nil end - if self.screen_movement_button then self.screen_movement_button.dead = true; self.screen_movement_button = nil end - if self.cooldown_snake_button then self.cooldown_snake_button.dead = true; self.cooldown_snake_button = nil end - if self.arrow_snake_button then self.arrow_snake_button.dead = true; self.arrow_snake_button = nil end - if self.ng_plus_plus_button then self.ng_plus_plus_button.dead = true; self.ng_plus_plus_button = nil end - if self.ng_plus_minus_button then self.ng_plus_minus_button.dead = true; self.ng_plus_minus_button = nil end - system.save_state() - end, 'pause') - end} - - self.restart_button = Button{group = self.ui, x = gw/2, y = gh - 200, force_update = true, button_text = 'restart run (r)', fg_color = 'bg10', bg_color = 'bg', action = function(b) - self.transitioning = true - ui_transition2:play{pitch = random:float(0.95, 1.05), volume = 0.5} - ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5} - ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = state.dark_transitions and bg[-2] or fg[0], transition_action = function() - slow_amount = 1 - gold = 3 - passives = {} - main_song_instance:stop() - run_passive_pool = { - 'centipede', 'ouroboros_technique_r', 'ouroboros_technique_l', 'amplify', 'resonance', 'ballista', 'call_of_the_void', 'crucio', 'speed_3', 'damage_4', 'shoot_5', 'death_6', 'lasting_7', - 'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'hextouch', 'whispers_of_doom', - 'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment', - 'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism', - 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance' - } - max_units = 7 + current_new_game_plus - main:add(BuyScreen'buy_screen') - locked_state = nil - system.save_run() - main:go_to('buy_screen', 1, {}, passives, 1, 0) - end, text = Text({{text = '[wavy, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)} - end} - - self.mouse_button = Button{group = self.ui, x = gw/2 - 57, y = gh - 150, force_update = true, button_text = 'mouse control: ' .. tostring(state.mouse_control and 'yes' or 'no'), fg_color = 'bg10', bg_color = 'bg', - action = function(b) - ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - state.mouse_control = not state.mouse_control - b:set_text('mouse control: ' .. tostring(state.mouse_control and 'yes' or 'no')) - input:set_mouse_visible(state.mouse_control) - end} - - self.dark_transition_button = Button{group = self.ui, x = gw/2 + 64, y = gh - 150, force_update = true, button_text = 'dark transitions: ' .. tostring(state.dark_transitions and 'yes' or 'no'), - fg_color = 'bg10', bg_color = 'bg', action = function(b) - ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - state.dark_transitions = not state.dark_transitions - b:set_text('dark transitions: ' .. tostring(state.dark_transitions and 'yes' or 'no')) - end} - - self.sfx_button = Button{group = self.ui, x = gw/2 - 46, y = gh - 175, force_update = true, button_text = 'sounds (n): ' .. tostring(state.volume_muted and 'no' or 'yes'), fg_color = 'bg10', bg_color = 'bg', - action = function(b) - ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5} - b.spring:pull(0.2, 200, 10) - b.selected = true - ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - if sfx.volume == 0.5 then - sfx.volume = 0 - state.volume_muted = true - elseif sfx.volume == 0 then - sfx.volume = 0.5 - state.volume_muted = false - end - b:set_text('sounds (n): ' .. tostring(state.volume_muted and 'no' or 'yes')) - end} - - self.music_button = Button{group = self.ui, x = gw/2 + 46, y = gh - 175, force_update = true, button_text = 'music (m): ' .. tostring(state.music_muted and 'no' or 'yes'), fg_color = 'bg10', bg_color = 'bg', - action = function(b) - ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5} - b.spring:pull(0.2, 200, 10) - b.selected = true - ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - if music.volume == 0.5 then - music.volume = 0 - state.music_muted = true - elseif music.volume == 0 then - music.volume = 0.5 - state.music_muted = false - end - b:set_text('music (m): ' .. tostring(state.music_muted and 'no' or 'yes')) - end} - - self.video_button_1 = Button{group = self.ui, x = gw/2 - 86, y = gh - 125, force_update = true, button_text = 'window size-', fg_color = 'bg10', bg_color = 'bg', action = function() - if sx > 1 and sy > 1 then - ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - sx, sy = sx - 1, sy - 1 - love.window.setMode(480*sx, 270*sy) - state.sx, state.sy = sx, sy - state.fullscreen = false - end - end} - - self.video_button_2 = Button{group = self.ui, x = gw/2, y = gh - 125, force_update = true, button_text = 'window size+', fg_color = 'bg10', bg_color = 'bg', action = function() - ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - sx, sy = sx + 1, sy + 1 - love.window.setMode(480*sx, 270*sy) - state.sx, state.sy = sx, sy - state.fullscreen = false - end} - - self.video_button_3 = Button{group = self.ui, x = gw/2 + 79, y = gh - 125, force_update = true, button_text = 'fullscreen', fg_color = 'bg10', bg_color = 'bg', action = function() - ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - local _, _, flags = love.window.getMode() - local window_width, window_height = love.window.getDesktopDimensions(flags.display) - sx, sy = window_width/480, window_height/270 - ww, wh = window_width, window_height - love.window.setMode(window_width, window_height, {fullscreen = true}) - state.fullscreen = true - end} - - self.screen_shake_button = Button{group = self.ui, x = gw/2 - 57, y = gh - 100, w = 110, force_update = true, button_text = '[bg10]screen shake: ' .. tostring(state.no_screen_shake and 'no' or 'yes'), - fg_color = 'bg10', bg_color = 'bg', action = function(b) - ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - state.no_screen_shake = not state.no_screen_shake - b:set_text('screen shake: ' .. tostring(state.no_screen_shake and 'no' or 'yes')) - end} - - self.cooldown_snake_button = Button{group = self.ui, x = gw/2 + 75, y = gh - 100, w = 145, force_update = true, button_text = '[bg10]cooldowns on snake: ' .. tostring(state.cooldown_snake and 'yes' or 'no'), - fg_color = 'bg10', bg_color = 'bg', action = function(b) - ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - state.cooldown_snake = not state.cooldown_snake - b:set_text('cooldowns on snake: ' .. tostring(state.cooldown_snake and 'yes' or 'no')) - end} - - self.arrow_snake_button = Button{group = self.ui, x = gw/2 + 65, y = gh - 75, w = 125, force_update = true, button_text = '[bg10]arrow on snake: ' .. tostring(state.arrow_snake and 'yes' or 'no'), - fg_color = 'bg10', bg_color = 'bg', action = function(b) - ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - state.arrow_snake = not state.arrow_snake - b:set_text('arrow on snake: ' .. tostring(state.arrow_snake and 'yes' or 'no')) - end} - - self.screen_movement_button = Button{group = self.ui, x = gw/2 - 69, y = gh - 75, w = 135, force_update = true, button_text = '[bg10]screen movement: ' .. tostring(state.no_screen_movement and 'no' or 'yes'), - fg_color = 'bg10', bg_color = 'bg', action = function(b) - ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - state.no_screen_movement = not state.no_screen_movement - if state.no_screen_movement then - camera.x, camera.y = gw/2, gh/2 - camera.r = 0 - end - b:set_text('screen movement: ' .. tostring(state.no_screen_movement and 'no' or 'yes')) - end} - - self.ng_plus_minus_button = Button{group = self.ui, x = gw/2 - 58, y = gh - 50, force_update = true, button_text = 'NG+ down', fg_color = 'bg10', bg_color = 'bg', action = function(b) - ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - b.spring:pull(0.2, 200, 10) - b.selected = true - current_new_game_plus = math.clamp(current_new_game_plus - 1, 0, 5) - state.current_new_game_plus = current_new_game_plus - self.ng_t.text:set_text({{text = '[bg10]current: ' .. current_new_game_plus, font = pixul_font, alignment = 'center'}}) - end} - - self.ng_plus_plus_button = Button{group = self.ui, x = gw/2 + 5, y = gh - 50, force_update = true, button_text = 'NG+ up', fg_color = 'bg10', bg_color = 'bg', action = function(b) - ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - b.spring:pull(0.2, 200, 10) - b.selected = true - current_new_game_plus = math.clamp(current_new_game_plus + 1, 0, new_game_plus) - state.current_new_game_plus = current_new_game_plus - self.ng_t.text:set_text({{text = '[bg10]current: ' .. current_new_game_plus, font = pixul_font, alignment = 'center'}}) - end} - - self.quit_button = Button{group = self.ui, x = gw/2, y = gh - 25, force_update = true, button_text = 'quit', fg_color = 'bg10', bg_color = 'bg', action = function() - system.save_state() - steam.shutdown() - love.event.quit() - end} - end, 'pause') + open_options(self) else - if not state.mouse_control then - input:set_mouse_visible(false) - end - trigger:tween(0.25, _G, {slow_amount = 1}, math.linear, function() - slow_amount = 1 - self.paused = false - if self.paused_t1 then self.paused_t1.dead = true; self.paused_t1 = nil end - if self.paused_t2 then self.paused_t2.dead = true; self.paused_t2 = nil end - if self.ng_t then self.ng_t.dead = true; self.ng_t = nil end - if self.resume_button then self.resume_button.dead = true; self.resume_button = nil end - if self.restart_button then self.restart_button.dead = true; self.restart_button = nil end - if self.mouse_button then self.mouse_button.dead = true; self.mouse_button = nil end - if self.dark_transition_button then self.dark_transition_button.dead = true; self.dark_transition_button = nil end - if self.sfx_button then self.sfx_button.dead = true; self.sfx_button = nil end - if self.music_button then self.music_button.dead = true; self.music_button = nil end - if self.video_button_1 then self.video_button_1.dead = true; self.video_button_1 = nil end - if self.video_button_2 then self.video_button_2.dead = true; self.video_button_2 = nil end - if self.video_button_3 then self.video_button_3.dead = true; self.video_button_3 = nil end - if self.screen_shake_button then self.screen_shake_button.dead = true; self.screen_shake_button = nil end - if self.screen_movement_button then self.screen_movement_button.dead = true; self.screen_movement_button = nil end - if self.cooldown_snake_button then self.cooldown_snake_button.dead = true; self.cooldown_snake_button = nil end - if self.arrow_snake_button then self.arrow_snake_button.dead = true; self.arrow_snake_button = nil end - if self.quit_button then self.quit_button.dead = true; self.quit_button = nil end - if self.ng_plus_plus_button then self.ng_plus_plus_button.dead = true; self.ng_plus_plus_button = nil end - if self.ng_plus_minus_button then self.ng_plus_minus_button.dead = true; self.ng_plus_minus_button = nil end - system.save_state() - end, 'pause') + close_options(self) end end diff --git a/buy_screen.lua b/buy_screen.lua index bb4b133..7182279 100644 --- a/buy_screen.lua +++ b/buy_screen.lua @@ -165,6 +165,7 @@ function BuyScreen:on_enter(from, level, units, passives, shop_level, shop_xp) trigger:tween(1, main_song_instance, {volume = 0.2}, math.linear) + --[[ if self.level == 1 then self.screen_text = Text2{group = self.ui, x = gw/2, y = gh/2, lines = { {text = '[bg3]press K if screen is too large', font = pixul_font, alignment = 'center'}, @@ -174,6 +175,7 @@ function BuyScreen:on_enter(from, level, units, passives, shop_level, shop_xp) self.t:tween(0.2, self.screen_text, {sy = 0}, math.linear, function() self.screen_text.sy = 0 end) end) end + ]]-- locked_state = {locked = self.locked, cards = {self.cards[1] and self.cards[1].unit, self.cards[2] and self.cards[2].unit, self.cards[3] and self.cards[3].unit}} system.save_run(self.level, gold, self.units, self.passives, self.shop_level, self.shop_xp, run_passive_pool, locked_state) @@ -187,7 +189,7 @@ function BuyScreen:update(dt) self:update_game_object(dt*slow_amount) - if not self.in_tutorial then + if not self.in_tutorial and not self.paused then self.main:update(dt*slow_amount) self.effects:update(dt*slow_amount) self.ui:update(dt*slow_amount) @@ -198,6 +200,7 @@ function BuyScreen:update(dt) if self.ng_text then self.ng_text:update(dt) end if self.level_text then self.level_text:update(dt) end else + self.ui:update(dt*slow_amount) self.tutorial:update(dt*slow_amount) end @@ -205,6 +208,14 @@ function BuyScreen:update(dt) self:quit_tutorial() end + if input.escape.pressed and not self.transitioning and not self.in_tutorial then + if not self.paused then + open_options(self) + else + close_options(self) + end + end + for _, part in ipairs(self.characters) do part.y = 40 + (part.i-1)*19 end @@ -230,6 +241,7 @@ function BuyScreen:draw() self.effects:draw() if self.items_text then self.items_text:draw(32, 145) end if self.level_text then self.level_text:draw(265, gh - 20) end + if self.paused then graphics.rectangle(gw/2, gh/2, 2*gw, 2*gh, nil, nil, modal_transparent) end self.ui:draw() if self.unit_grabbed then @@ -255,6 +267,7 @@ function BuyScreen:draw() arrow:draw(gw/2 + 93, gh/2 - 10, 0, 0.4, 0.35) end self.tutorial:draw() + end diff --git a/engine/init.lua b/engine/init.lua index 27d6457..44189cf 100644 --- a/engine/init.lua +++ b/engine/init.lua @@ -66,10 +66,10 @@ function engine_run(config) if state.sx and state.sy then sx, sy = state.sx, state.sy - love.window.setMode(state.sx*gw, state.sy*gh, {fullscreen = state.fullscreen, vsync = config.vsync, msaa = msaa or 0, display = config.display}) + love.window.setMode(state.sx*gw, state.sy*gh, {vsync = config.vsync, msaa = msaa or 0, display = config.display}) else state.sx, state.sy = sx, sy - love.window.setMode(window_width, window_height, {fullscreen = config.fullscreen, vsync = config.vsync, msaa = msaa or 0, display = config.display}) + love.window.setMode(window_width, window_height, {vsync = config.vsync, msaa = msaa or 0, display = config.display}) end love.window.setTitle(config.game_name) diff --git a/main.lua b/main.lua index f317686..eb2b7d8 100644 --- a/main.lua +++ b/main.lua @@ -1,6 +1,7 @@ require 'engine' require 'shared' require 'arena' +require 'mainmenu' require 'buy_screen' require 'objects' require 'player' @@ -1474,17 +1475,6 @@ function init() 'magnetism', 'insurance', 'dividends' } - local run = system.load_run() - run_passive_pool = run.run_passive_pool or { - 'centipede', 'ouroboros_technique_r', 'ouroboros_technique_l', 'amplify', 'resonance', 'ballista', 'call_of_the_void', 'crucio', 'speed_3', 'damage_4', 'shoot_5', 'death_6', 'lasting_7', - 'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'hextouch', 'whispers_of_doom', - 'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment', - 'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism', - 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance' - } - gold = run.gold or 3 - passives = run.passives or {} - locked_state = run.locked_state steam.userStats.requestCurrentStats() new_game_plus = state.new_game_plus or 0 if not state.new_game_plus then state.new_game_plus = new_game_plus end @@ -1492,12 +1482,15 @@ function init() if not state.current_new_game_plus then state.current_new_game_plus = current_new_game_plus end max_units = 7 + current_new_game_plus - main = Main() - main_song_instance = _G[random:table{'song1', 'song2', 'song3', 'song4', 'song5'}]:play{volume = 0.5} + main = Main() + main:add(MainMenu'mainmenu') + main:go_to('mainmenu') + --[[ main:add(BuyScreen'buy_screen') main:go_to('buy_screen', run.level or 1, run.units or {}, passives, run.shop_level or 1, run.shop_xp or 0) + ]]-- -- main:go_to('buy_screen', 7, run.units or {}, {'unleash'}) --[[ @@ -1552,6 +1545,7 @@ function update(dt) end ]]-- + --[[ if input.n.pressed then if main.current.sfx_button then main.current.sfx_button:action() @@ -1581,10 +1575,11 @@ function update(dt) end end end + ]]-- if input.k.pressed then if sx > 1 and sy > 1 then - sx, sy = sx - 1, sy - 1 + sx, sy = sx - 0.5, sy - 0.5 love.window.setMode(480*sx, 270*sy) state.sx, state.sy = sx, sy state.fullscreen = false @@ -1592,7 +1587,7 @@ function update(dt) end if input.l.pressed then - sx, sy = sx + 1, sy + 1 + sx, sy = sx + 0.5, sy + 0.5 love.window.setMode(480*sx, 270*sy) state.sx, state.sy = sx, sy state.fullscreen = false @@ -1614,10 +1609,268 @@ function draw() end +function open_options(self) + input:set_mouse_visible(true) + trigger:tween(0.25, _G, {slow_amount = 0}, math.linear, function() + slow_amount = 0 + self.paused = true + + if self:is(Arena) then + self.paused_t1 = Text2{group = self.ui, x = gw/2, y = gh/2 - 108, sx = 0.6, sy = 0.6, lines = {{text = '[bg10]<-, a or m1 ->, d or m2', font = fat_font, alignment = 'center'}}} + self.paused_t2 = Text2{group = self.ui, x = gw/2, y = gh/2 - 92, lines = {{text = '[bg10]turn left turn right', font = pixul_font, alignment = 'center'}}} + end + + if self:is(MainMenu) then + self.ng_t = Text2{group = self.ui, x = gw/2 + 63, y = gh - 50, lines = {{text = '[bg10]current: ' .. current_new_game_plus, font = pixul_font, alignment = 'center'}}} + end + + self.resume_button = Button{group = self.ui, x = gw/2, y = gh - 225, force_update = true, button_text = 'resume game (esc)', fg_color = 'bg10', bg_color = 'bg', action = function(b) + trigger:tween(0.25, _G, {slow_amount = 1}, math.linear, function() + slow_amount = 1 + self.paused = false + if self.paused_t1 then self.paused_t1.dead = true; self.paused_t1 = nil end + if self.paused_t2 then self.paused_t2.dead = true; self.paused_t2 = nil end + if self.ng_t then self.ng_t.dead = true; self.ng_t = nil end + if self.resume_button then self.resume_button.dead = true; self.resume_button = nil end + if self.restart_button then self.restart_button.dead = true; self.restart_button = nil end + if self.mouse_button then self.mouse_button.dead = true; self.mouse_button = nil end + if self.dark_transition_button then self.dark_transition_button.dead = true; self.dark_transition_button = nil end + if self.sfx_button then self.sfx_button.dead = true; self.sfx_button = nil end + if self.music_button then self.music_button.dead = true; self.music_button = nil end + if self.video_button_1 then self.video_button_1.dead = true; self.video_button_1 = nil end + if self.video_button_2 then self.video_button_2.dead = true; self.video_button_2 = nil end + if self.video_button_3 then self.video_button_3.dead = true; self.video_button_3 = nil end + if self.video_button_4 then self.video_button_4.dead = true; self.video_button_4 = nil end + if self.quit_button then self.quit_button.dead = true; self.quit_button = nil end + if self.screen_shake_button then self.screen_shake_button.dead = true; self.screen_shake_button = nil end + if self.screen_movement_button then self.screen_movement_button.dead = true; self.screen_movement_button = nil end + if self.cooldown_snake_button then self.cooldown_snake_button.dead = true; self.cooldown_snake_button = nil end + if self.arrow_snake_button then self.arrow_snake_button.dead = true; self.arrow_snake_button = nil end + if self.ng_plus_plus_button then self.ng_plus_plus_button.dead = true; self.ng_plus_plus_button = nil end + if self.ng_plus_minus_button then self.ng_plus_minus_button.dead = true; self.ng_plus_minus_button = nil end + system.save_state() + end, 'pause') + end} + + if not self:is(MainMenu) then + self.restart_button = Button{group = self.ui, x = gw/2, y = gh - 200, force_update = true, button_text = 'restart run (r)', fg_color = 'bg10', bg_color = 'bg', action = function(b) + self.transitioning = true + ui_transition2:play{pitch = random:float(0.95, 1.05), volume = 0.5} + ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5} + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = state.dark_transitions and bg[-2] or fg[0], transition_action = function() + slow_amount = 1 + gold = 3 + passives = {} + main_song_instance:stop() + run_passive_pool = { + 'centipede', 'ouroboros_technique_r', 'ouroboros_technique_l', 'amplify', 'resonance', 'ballista', 'call_of_the_void', 'crucio', 'speed_3', 'damage_4', 'shoot_5', 'death_6', 'lasting_7', + 'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'hextouch', 'whispers_of_doom', + 'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment', + 'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism', + 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance' + } + max_units = 7 + current_new_game_plus + main:add(BuyScreen'buy_screen') + locked_state = nil + system.save_run() + main:go_to('buy_screen', 1, {}, passives, 1, 0) + end, text = Text({{text = '[wavy, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)} + end} + end + + self.mouse_button = Button{group = self.ui, x = gw/2 - 57, y = gh - 150, force_update = true, button_text = 'mouse control: ' .. tostring(state.mouse_control and 'yes' or 'no'), fg_color = 'bg10', bg_color = 'bg', + action = function(b) + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + state.mouse_control = not state.mouse_control + b:set_text('mouse control: ' .. tostring(state.mouse_control and 'yes' or 'no')) + end} + + self.dark_transition_button = Button{group = self.ui, x = gw/2 + 64, y = gh - 150, force_update = true, button_text = 'dark transitions: ' .. tostring(state.dark_transitions and 'yes' or 'no'), + fg_color = 'bg10', bg_color = 'bg', action = function(b) + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + state.dark_transitions = not state.dark_transitions + b:set_text('dark transitions: ' .. tostring(state.dark_transitions and 'yes' or 'no')) + end} + + self.sfx_button = Button{group = self.ui, x = gw/2 - 46, y = gh - 175, force_update = true, button_text = 'sfx volume: ' .. tostring((state.sfx_volume or 0.5)*10), fg_color = 'bg10', bg_color = 'bg', + action = function(b) + ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5} + b.spring:pull(0.2, 200, 10) + b.selected = true + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + sfx.volume = sfx.volume + 0.1 + if sfx.volume > 1 then sfx.volume = 0 end + state.sfx_volume = sfx.volume + b:set_text('sfx volume: ' .. tostring((state.sfx_volume or 0.5)*10)) + end} + + self.music_button = Button{group = self.ui, x = gw/2 + 48, y = gh - 175, force_update = true, button_text = 'music volume: ' .. tostring((state.music_volume or 0.5)*10), fg_color = 'bg10', bg_color = 'bg', + action = function(b) + ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5} + b.spring:pull(0.2, 200, 10) + b.selected = true + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + music.volume = music.volume + 0.1 + if music.volume > 1 then music.volume = 0 end + state.music_volume = music.volume + b:set_text('music volume: ' .. tostring((state.music_volume or 0.5)*10)) + end} + + self.video_button_1 = Button{group = self.ui, x = gw/2 - 136, y = gh - 125, force_update = true, button_text = 'window size-', fg_color = 'bg10', bg_color = 'bg', action = function() + if sx > 1 and sy > 1 then + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + sx, sy = sx - 0.5, sy - 0.5 + love.window.setMode(480*sx, 270*sy) + state.sx, state.sy = sx, sy + state.fullscreen = false + end + end} + + self.video_button_2 = Button{group = self.ui, x = gw/2 - 50, y = gh - 125, force_update = true, button_text = 'window size+', fg_color = 'bg10', bg_color = 'bg', action = function() + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + sx, sy = sx + 0.5, sy + 0.5 + love.window.setMode(480*sx, 270*sy) + state.sx, state.sy = sx, sy + state.fullscreen = false + end} + + self.video_button_3 = Button{group = self.ui, x = gw/2 + 29, y = gh - 125, force_update = true, button_text = 'fullscreen', fg_color = 'bg10', bg_color = 'bg', action = function() + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + local _, _, flags = love.window.getMode() + local window_width, window_height = love.window.getDesktopDimensions(flags.display) + sx, sy = window_width/480, window_height/270 + state.sx, state.sy = sx, sy + ww, wh = window_width, window_height + love.window.setMode(window_width, window_height) + end} + + self.video_button_4 = Button{group = self.ui, x = gw/2 + 129, y = gh - 125, force_update = true, button_text = 'reset video settings', fg_color = 'bg10', bg_color = 'bg', action = function() + local _, _, flags = love.window.getMode() + local window_width, window_height = love.window.getDesktopDimensions(flags.display) + sx, sy = window_width/480, window_height/270 + ww, wh = window_width, window_height + state.sx, state.sy = sx, sy + state.fullscreen = false + ww, wh = window_width, window_height + love.window.setMode(window_width, window_height) + end} + + self.screen_shake_button = Button{group = self.ui, x = gw/2 - 57, y = gh - 100, w = 110, force_update = true, button_text = '[bg10]screen shake: ' .. tostring(state.no_screen_shake and 'no' or 'yes'), + fg_color = 'bg10', bg_color = 'bg', action = function(b) + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + state.no_screen_shake = not state.no_screen_shake + b:set_text('screen shake: ' .. tostring(state.no_screen_shake and 'no' or 'yes')) + end} + + self.cooldown_snake_button = Button{group = self.ui, x = gw/2 + 75, y = gh - 100, w = 145, force_update = true, button_text = '[bg10]cooldowns on snake: ' .. tostring(state.cooldown_snake and 'yes' or 'no'), + fg_color = 'bg10', bg_color = 'bg', action = function(b) + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + state.cooldown_snake = not state.cooldown_snake + b:set_text('cooldowns on snake: ' .. tostring(state.cooldown_snake and 'yes' or 'no')) + end} + + self.arrow_snake_button = Button{group = self.ui, x = gw/2 + 65, y = gh - 75, w = 125, force_update = true, button_text = '[bg10]arrow on snake: ' .. tostring(state.arrow_snake and 'yes' or 'no'), + fg_color = 'bg10', bg_color = 'bg', action = function(b) + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + state.arrow_snake = not state.arrow_snake + b:set_text('arrow on snake: ' .. tostring(state.arrow_snake and 'yes' or 'no')) + end} + + self.screen_movement_button = Button{group = self.ui, x = gw/2 - 69, y = gh - 75, w = 135, force_update = true, button_text = '[bg10]screen movement: ' .. tostring(state.no_screen_movement and 'no' or 'yes'), + fg_color = 'bg10', bg_color = 'bg', action = function(b) + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + state.no_screen_movement = not state.no_screen_movement + if state.no_screen_movement then + camera.x, camera.y = gw/2, gh/2 + camera.r = 0 + end + b:set_text('screen movement: ' .. tostring(state.no_screen_movement and 'no' or 'yes')) + end} + + if self:is(MainMenu) then + self.ng_plus_minus_button = Button{group = self.ui, x = gw/2 - 58, y = gh - 50, force_update = true, button_text = 'NG+ down', fg_color = 'bg10', bg_color = 'bg', action = function(b) + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + b.spring:pull(0.2, 200, 10) + b.selected = true + current_new_game_plus = math.clamp(current_new_game_plus - 1, 0, 5) + state.current_new_game_plus = current_new_game_plus + self.ng_t.text:set_text({{text = '[bg10]current: ' .. current_new_game_plus, font = pixul_font, alignment = 'center'}}) + end} + + self.ng_plus_plus_button = Button{group = self.ui, x = gw/2 + 5, y = gh - 50, force_update = true, button_text = 'NG+ up', fg_color = 'bg10', bg_color = 'bg', action = function(b) + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + b.spring:pull(0.2, 200, 10) + b.selected = true + current_new_game_plus = math.clamp(current_new_game_plus + 1, 0, new_game_plus) + state.current_new_game_plus = current_new_game_plus + self.ng_t.text:set_text({{text = '[bg10]current: ' .. current_new_game_plus, font = pixul_font, alignment = 'center'}}) + end} + end + + if not self:is(MainMenu) then + self.main_menu_button = Button{group = self.ui, x = gw/2, y = gh - 50, force_update = true, button_text = 'main menu', fg_color = 'bg10', bg_color = 'bg', action = function(b) + self.transitioning = true + ui_transition2:play{pitch = random:float(0.95, 1.05), volume = 0.5} + ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5} + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = state.dark_transitions and bg[-2] or fg[0], transition_action = function() + system.save_run() + main:add(MainMenu'main_menu') + main:go_to('main_menu') + end, text = Text({{text = '[wavy, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']..', font = pixul_font, alignment = 'center'}}, global_text_tags)} + end} + end + + self.quit_button = Button{group = self.ui, x = gw/2, y = gh - 25, force_update = true, button_text = 'quit', fg_color = 'bg10', bg_color = 'bg', action = function() + system.save_state() + steam.shutdown() + love.event.quit() + end} + end, 'pause') +end + + +function close_options(self) + if not state.mouse_control then + input:set_mouse_visible(false) + end + if self:is(Arena) then + input:set_mouse_visible(state.mouse_control or false) + end + trigger:tween(0.25, _G, {slow_amount = 1}, math.linear, function() + slow_amount = 1 + self.paused = false + if self.paused_t1 then self.paused_t1.dead = true; self.paused_t1 = nil end + if self.paused_t2 then self.paused_t2.dead = true; self.paused_t2 = nil end + if self.ng_t then self.ng_t.dead = true; self.ng_t = nil end + if self.resume_button then self.resume_button.dead = true; self.resume_button = nil end + if self.restart_button then self.restart_button.dead = true; self.restart_button = nil end + if self.mouse_button then self.mouse_button.dead = true; self.mouse_button = nil end + if self.dark_transition_button then self.dark_transition_button.dead = true; self.dark_transition_button = nil end + if self.sfx_button then self.sfx_button.dead = true; self.sfx_button = nil end + if self.music_button then self.music_button.dead = true; self.music_button = nil end + if self.video_button_1 then self.video_button_1.dead = true; self.video_button_1 = nil end + if self.video_button_2 then self.video_button_2.dead = true; self.video_button_2 = nil end + if self.video_button_3 then self.video_button_3.dead = true; self.video_button_3 = nil end + if self.video_button_4 then self.video_button_4.dead = true; self.video_button_4 = nil end + if self.screen_shake_button then self.screen_shake_button.dead = true; self.screen_shake_button = nil end + if self.screen_movement_button then self.screen_movement_button.dead = true; self.screen_movement_button = nil end + if self.cooldown_snake_button then self.cooldown_snake_button.dead = true; self.cooldown_snake_button = nil end + if self.arrow_snake_button then self.arrow_snake_button.dead = true; self.arrow_snake_button = nil end + if self.quit_button then self.quit_button.dead = true; self.quit_button = nil end + if self.ng_plus_plus_button then self.ng_plus_plus_button.dead = true; self.ng_plus_plus_button = nil end + if self.ng_plus_minus_button then self.ng_plus_minus_button.dead = true; self.ng_plus_minus_button = nil end + if self.main_menu_button then self.main_menu_button.dead = true; self.main_menu_button = nil end + system.save_state() + end, 'pause') +end + + function love.run() return engine_run({ game_name = 'SNKRX', - window_width = 480*4, - window_height = 270*4, + window_width = 'max', + window_height = 'max', }) end diff --git a/mainmenu.lua b/mainmenu.lua new file mode 100644 index 0000000..d068597 --- /dev/null +++ b/mainmenu.lua @@ -0,0 +1,202 @@ +MainMenu = Object:extend() +MainMenu:implement(State) +MainMenu:implement(GameObject) +function MainMenu:init(name) + self:init_state(name) + self:init_game_object() +end + + +function MainMenu:on_enter(from) + slow_amount = 1 + trigger:tween(2, main_song_instance, {volume = 0.5, pitch = 1}, math.linear) + + steam.friends.setRichPresence('steam_display', '#StatusFull') + steam.friends.setRichPresence('text', 'Main Menu') + + self.floor = Group() + self.main = Group():set_as_physics_world(32, 0, 0, {'player', 'enemy', 'projectile', 'enemy_projectile', 'force_field', 'ghost'}) + self.post_main = Group() + self.effects = Group() + self.main_ui = Group():no_camera() + self.ui = Group():no_camera() + self.main:disable_collision_between('player', 'player') + self.main:disable_collision_between('player', 'projectile') + self.main:disable_collision_between('player', 'enemy_projectile') + self.main:disable_collision_between('projectile', 'projectile') + self.main:disable_collision_between('projectile', 'enemy_projectile') + self.main:disable_collision_between('projectile', 'enemy') + self.main:disable_collision_between('enemy_projectile', 'enemy') + self.main:disable_collision_between('enemy_projectile', 'enemy_projectile') + self.main:disable_collision_between('player', 'force_field') + self.main:disable_collision_between('projectile', 'force_field') + self.main:disable_collision_between('ghost', 'player') + self.main:disable_collision_between('ghost', 'projectile') + self.main:disable_collision_between('ghost', 'enemy') + self.main:disable_collision_between('ghost', 'enemy_projectile') + self.main:disable_collision_between('ghost', 'ghost') + self.main:disable_collision_between('ghost', 'force_field') + self.main:enable_trigger_between('projectile', 'enemy') + self.main:enable_trigger_between('enemy_projectile', 'player') + self.main:enable_trigger_between('player', 'enemy_projectile') + self.main:enable_trigger_between('enemy_projectile', 'enemy') + self.main:enable_trigger_between('player', 'ghost') + + self.enemies = {Seeker, EnemyCritter} + + -- Spawn solids and player + self.x1, self.y1 = gw/2 - 0.8*gw/2, gh/2 - 0.8*gh/2 + self.x2, self.y2 = gw/2 + 0.8*gw/2, gh/2 + 0.8*gh/2 + self.w, self.h = self.x2 - self.x1, self.y2 - self.y1 + Wall{group = self.main, vertices = math.to_rectangle_vertices(-40, -40, self.x1, gh + 40), color = bg[-1]} + Wall{group = self.main, vertices = math.to_rectangle_vertices(self.x2, -40, gw + 40, gh + 40), color = bg[-1]} + Wall{group = self.main, vertices = math.to_rectangle_vertices(self.x1, -40, self.x2, self.y1), color = bg[-1]} + Wall{group = self.main, vertices = math.to_rectangle_vertices(self.x1, self.y2, self.x2, gh + 40), color = bg[-1]} + WallCover{group = self.post_main, vertices = math.to_rectangle_vertices(-40, -40, self.x1, gh + 40), color = bg[-1]} + WallCover{group = self.post_main, vertices = math.to_rectangle_vertices(self.x2, -40, gw + 40, gh + 40), color = bg[-1]} + WallCover{group = self.post_main, vertices = math.to_rectangle_vertices(self.x1, -40, self.x2, self.y1), color = bg[-1]} + WallCover{group = self.post_main, vertices = math.to_rectangle_vertices(self.x1, self.y2, self.x2, gh + 40), color = bg[-1]} + + self.t:every(0.375, function() + local p = random:table(star_positions) + Star{group = star_group, x = p.x, y = p.y} + end) + + self.units = { + {character = 'vagrant', level = 1}, + {character = 'magician', level = 1}, + {character = 'bane', level = 1}, + {character = 'scout', level = 1}, + {character = 'cannoneer', level = 1}, + {character = 'swordsman', level = 1}, + {character = 'archer', level = 1}, + } + + for i, unit in ipairs(self.units) do + if i == 1 then + self.player = Player{group = self.main, x = gw/2 + random:float(-48, 48), y = gh/2 + 16 + random:float(-48, 48), leader = true, character = unit.character, level = unit.level, passives = self.passives, ii = i} + else + self.player:add_follower(Player{group = self.main, character = unit.character, level = unit.level, passives = self.passives, ii = i}) + end + end + + self.title_text = Text({{text = '[wavy_mid, fg]SNKRX', font = fat_font, alignment = 'center'}}, global_text_tags) + + self.arena_run_button = Button{group = self.main_ui, x = 55, y = gh/2 - 10, force_update = true, button_text = 'arena run', fg_color = 'bg10', bg_color = 'bg', action = function(b) + self.transitioning = true + ui_transition2:play{pitch = random:float(0.95, 1.05), volume = 0.5} + ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5} + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = state.dark_transitions and bg[-2] or fg[0], transition_action = function() + slow_amount = 1 + local run = system.load_run() + run_passive_pool = run.run_passive_pool or { + 'centipede', 'ouroboros_technique_r', 'ouroboros_technique_l', 'amplify', 'resonance', 'ballista', 'call_of_the_void', 'crucio', 'speed_3', 'damage_4', 'shoot_5', 'death_6', 'lasting_7', + 'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'hextouch', 'whispers_of_doom', + 'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment', + 'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism', + 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance' + } + gold = run.gold or 3 + passives = run.passives or {} + locked_state = run.locked_state + system.save_state() + main:add(BuyScreen'buy_screen') + main:go_to('buy_screen', run.level or 1, run.units or {}, passives, run.shop_level or 1, run.shop_xp or 0) + end, text = Text({{text = '[wavy, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']starting...', font = pixul_font, alignment = 'center'}}, global_text_tags)} + end} + self.options_button = Button{group = self.main_ui, x = 47, y = gh/2 + 12, force_update = true, button_text = 'options', fg_color = 'bg10', bg_color = 'bg', action = function(b) + if not self.paused then + open_options(self) + else + close_options(self) + end + end} + self.quit_button = Button{group = self.main_ui, x = 37, y = gh/2 + 34, force_update = true, button_text = 'quit', fg_color = 'bg10', bg_color = 'bg', action = function(b) + system.save_state() + steam.shutdown() + love.event.quit() + end} + self.t:every(2, function() self.soundtrack_button.spring:pull(0.025, 200, 10) end) + self.soundtrack_button = Button{group = self.main_ui, x = gw - 72, y = gh - 17, force_update = true, button_text = 'buy the soundtrack!', fg_color = 'bg10', bg_color = 'bg', action = function(b) + ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5} + b.spring:pull(0.2, 200, 10) + b.selected = true + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + system.open_url('https://kubbimusic.com/album/ember') + end} +end + + +function MainMenu:on_exit() + self.floor:destroy() + self.main:destroy() + self.post_main:destroy() + self.effects:destroy() + self.ui:destroy() + self.main_ui:destroy() + self.t:destroy() + self.floor = nil + self.main = nil + self.post_main = nil + self.effects = nil + self.ui = nil + self.units = nil + self.player = nil + self.t = nil + self.springs = nil + self.flashes = nil + self.hfx = nil + self.title_text = nil +end + + +function MainMenu:update(dt) + if main_song_instance:isStopped() then + main_song_instance = _G[random:table{'song1', 'song2', 'song3', 'song4', 'song5'}]:play{volume = 0.5} + end + + if input.escape.pressed then + if not self.paused then + open_options(self) + else + close_options(self) + end + end + + self:update_game_object(dt*slow_amount) + + if not self.paused and not self.transitioning then + star_group:update(dt*slow_amount) + self.floor:update(dt*slow_amount) + self.main:update(dt*slow_amount) + self.post_main:update(dt*slow_amount) + self.effects:update(dt*slow_amount) + self.main_ui:update(dt*slow_amount) + if self.title_text then self.title_text:update(dt) end + self.ui:update(dt*slow_amount) + else + self.ui:update(dt*slow_amount) + end +end + + +function MainMenu:draw() + self.floor:draw() + self.main:draw() + self.post_main:draw() + self.effects:draw() + graphics.draw_with_mask(function() + star_canvas:draw(0, 0, 0, 1, 1) + end, function() + camera:attach() + graphics.rectangle(gw/2, gh/2, self.w, self.h, nil, nil, fg[0]) + camera:detach() + end, true) + graphics.rectangle(gw/2, gh/2, 2*gw, 2*gh, nil, nil, modal_transparent) + + self.main_ui:draw() + self.title_text:draw(60, gh/2 - 40) + if self.paused then graphics.rectangle(gw/2, gh/2, 2*gw, 2*gh, nil, nil, modal_transparent) end + self.ui:draw() +end diff --git a/player.lua b/player.lua index 8049e01..13b4ce4 100644 --- a/player.lua +++ b/player.lua @@ -1012,6 +1012,11 @@ function Player:init(args) end self.mouse_control_v_buffer = {} + + if main.current:is(MainMenu) then + self.r = random:table{-math.pi/4, math.pi/4, 3*math.pi/4, -3*math.pi/4} + self:set_angle(self.r) + end end @@ -1216,19 +1221,21 @@ function Player:update(dt) self.t:set_every_multiplier('attack', self.aspd_m) if self.leader then - if input.move_left.pressed and not self.move_right_pressed then self.move_left_pressed = love.timer.getTime() end - if input.move_right.pressed and not self.move_left_pressed then self.move_right_pressed = love.timer.getTime() end - if input.move_left.released then self.move_left_pressed = nil end - if input.move_right.released then self.move_right_pressed = nil end + if not main.current:is(MainMenu) then + if input.move_left.pressed and not self.move_right_pressed then self.move_left_pressed = love.timer.getTime() end + if input.move_right.pressed and not self.move_left_pressed then self.move_right_pressed = love.timer.getTime() end + if input.move_left.released then self.move_left_pressed = nil end + if input.move_right.released then self.move_right_pressed = nil end - if state.mouse_control then - self.mouse_control_v = Vector(math.cos(self.r), math.sin(self.r)):perpendicular():dot(Vector(math.cos(self:angle_to_mouse()), math.sin(self:angle_to_mouse()))) - self.r = self.r + math.sign(self.mouse_control_v)*1.66*math.pi*dt - table.insert(self.mouse_control_v_buffer, 1, self.mouse_control_v) - if #self.mouse_control_v_buffer > 64 then self.mouse_control_v_buffer[65] = nil end - else - if input.move_left.down then self.r = self.r - 1.66*math.pi*dt end - if input.move_right.down then self.r = self.r + 1.66*math.pi*dt end + if state.mouse_control then + self.mouse_control_v = Vector(math.cos(self.r), math.sin(self.r)):perpendicular():dot(Vector(math.cos(self:angle_to_mouse()), math.sin(self:angle_to_mouse()))) + self.r = self.r + math.sign(self.mouse_control_v)*1.66*math.pi*dt + table.insert(self.mouse_control_v_buffer, 1, self.mouse_control_v) + if #self.mouse_control_v_buffer > 64 then self.mouse_control_v_buffer[65] = nil end + else + if input.move_left.down then self.r = self.r - 1.66*math.pi*dt end + if input.move_right.down then self.r = self.r + 1.66*math.pi*dt end + end end local total_v = 0 @@ -2770,7 +2777,7 @@ end function Volcano:update(dt) self:update_game_object(dt) - self.vr = self.vr + self.dvr*dt + if self.dvr then self.vr = self.vr + self.dvr*dt end end @@ -2782,7 +2789,7 @@ function Volcano:draw() graphics.triangle_equilateral(self.x, self.y, 1.5*self.shape.w, self.hfx.hit.f and fg[0] or self.color, 3) graphics.pop() - graphics.push(self.x, self.y, self.r + self.vr, self.spring.x, self.spring.x) + graphics.push(self.x, self.y, self.r + (self.vr or 0), self.spring.x, self.spring.x) -- graphics.circle(self.x, self.y, self.shape.rs + random:float(-1, 1), self.color, 2) graphics.circle(self.x, self.y, 24, self.color_transparent) local lw = 2 diff --git a/shared.lua b/shared.lua index 6ca2ac3..7d90846 100644 --- a/shared.lua +++ b/shared.lua @@ -88,9 +88,10 @@ function shared_draw(draw_action) shadow_shader:unset() end) - background_canvas:draw(0, 0, 0, sx, sy) - shadow_canvas:draw(1.5*sx, 1.5*sy, 0, sx, sy) - main_canvas:draw(0, 0, 0, sx, sy) + local x, y = 0, 0 + background_canvas:draw(x, y, 0, sx, sy) + shadow_canvas:draw(x + 1.5*sx, y + 1.5*sy, 0, sx, sy) + main_canvas:draw(x, y, 0, sx, sy) end diff --git a/todo b/todo index 5165818..a6d3cfb 100644 --- a/todo +++ b/todo @@ -31,6 +31,7 @@ Looping Update Summon Instability - summons explode when disappearing, dealing 100/150/200% damage Changes: Magnetism - also attracts healing orbs + Enchanted - 30/60/90% Healer rework: Enemies have a 8/16% chance to spawn healing orbs on death, orbs prioritize healing low health allies Cleric: creates 1 healing orb, Lv.3: creates 4 healing orbs and grants +20% healing effectiveness @@ -38,7 +39,7 @@ Looping Update Fairy: grants a random unit 100% attack speed for 6 seconds and creates 1 healing orb Psyker rework: Create orbitting, damaging balls at the head of the snake equal to the number of psykers - Flagellant - Lv.3: deals no damage to self and grants +10% damage to all allies per cast + Flagellant - Lv.3: 2X flagellant max HP and grants +10% damage to all allies per cast Psychic - Lv.3: gains up to 300% damage the less HP the psychic has Psykino - Lv.3: gains up to 100% attack speed the less HP the psykino has Psykeeper - creates a healing orb every time the psykeeper takes 30% of its max HP in damage, Lv.3: deal double the damage taken by the psykeeper to all enemies @@ -52,30 +53,30 @@ Looping Update * Decreased reroll cost to 8 * Increased sage's attack speed QoL - Your party + items on end, death and passive screens - https://i.imgur.com/JJUddT3.png - Volume slider - Add visuals divine intervention, fairy buff - Options menu from buy screen - Add option for mouse cursor to always be visible - Add main menu - Soundtrack button - Arena run button - Options button - Quit button + Show cooldown on elite attack + * Options menu from buy screen + * Add main menu + * Title + * Snake DVD + * Arena run button + * Options button + * Quit button + * Soundtrack button https://i.imgur.com/4hOt5uX.png "party 7/9" https://i.imgur.com/dlGbx0k.png lvl 3 effect on shop card + * Volume slider + Your party + items on end, death and passive screens - https://i.imgur.com/JJUddT3.png + Add option for mouse cursor to always be visible + Add visuals divine intervention, fairy buff + Change text for enchanted to "if you have >= 2 enchanters" and change text for reinforce to "if you have >= 1 enchanter" Bug fixes - Fix fullscreen with different resolutions that don't scale properly - https://steamcommunity.com/app/915310/discussions/0/3106901665841020282/ - Fix enemies still spawning after arena clear (this happens with the extra enemy spawns that were blocked earlier) - Kill enemies that go outside play area - https://i.imgur.com/QPgZbve.png - https://i.imgur.com/lCdPFZx.png - dvr crash, already fixed i think + * Fixed fullscreen button and general resolution issues + Fixed a series of crashes that happened rarely right before changing from the arena back to the shop https://i.imgur.com/Rk6qbDD.png - merchant doesnt give reroll if dies + https://i.imgur.com/1soUUdk.png - 5th position stops shooting when 1-4 die + https://i.imgur.com/G9DosVw.png - lasting 7 bug https://i.imgur.com/8he1WDm.png - infinite money https://i.imgur.com/0wZ5wma.png - max unit bugged when changing ng mid run, https://i.imgur.com/qrExpq5.png - https://i.imgur.com/1soUUdk.png - 5th position stops shooting when 1-4 die - https://i.imgur.com/cJMFDfc.png - lasting 7 doesnt work? - "your build" only shows alive units, this is the same problem as merchant not giving interest if dead? - https://i.imgur.com/Ta3lBui.png - Pet bug due to enemies spawning after arena is clear --- @@ -119,6 +120,10 @@ Challenge mode Units die permanently when they die Slower scaling with less individually threatening units Max snake size goes up every 10 levels +Draft mode +Enemy ideas - https://steamcommunity.com/app/915310/discussions/0/3069747783691890511/ +Unit ideas - https://i.imgur.com/VNMS2YV.png +Unit ideas - https://steamcommunity.com/app/915310/discussions/0/3069747783693969554/ --