Loop update 1/4

master
a327ex 2021-06-23 00:53:37 -03:00
parent 2453a18d9c
commit dbdd585c48
8 changed files with 539 additions and 275 deletions

221
arena.lua
View File

@ -348,229 +348,12 @@ function Arena:update(dt)
end end
if self.shop_text then self.shop_text: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 input.escape.pressed and not self.transitioning and not self.in_credits and not self.choosing_passives then
if not self.paused then if not self.paused then
input:set_mouse_visible(true) open_options(self)
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')
else else
if not state.mouse_control then close_options(self)
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')
end end
end end

View File

@ -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) trigger:tween(1, main_song_instance, {volume = 0.2}, math.linear)
--[[
if self.level == 1 then if self.level == 1 then
self.screen_text = Text2{group = self.ui, x = gw/2, y = gh/2, lines = { 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'}, {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) self.t:tween(0.2, self.screen_text, {sy = 0}, math.linear, function() self.screen_text.sy = 0 end)
end) 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}} 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) 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) 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.main:update(dt*slow_amount)
self.effects:update(dt*slow_amount) self.effects:update(dt*slow_amount)
self.ui: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.ng_text then self.ng_text:update(dt) end
if self.level_text then self.level_text:update(dt) end if self.level_text then self.level_text:update(dt) end
else else
self.ui:update(dt*slow_amount)
self.tutorial:update(dt*slow_amount) self.tutorial:update(dt*slow_amount)
end end
@ -205,6 +208,14 @@ function BuyScreen:update(dt)
self:quit_tutorial() self:quit_tutorial()
end 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 for _, part in ipairs(self.characters) do
part.y = 40 + (part.i-1)*19 part.y = 40 + (part.i-1)*19
end end
@ -230,6 +241,7 @@ function BuyScreen:draw()
self.effects:draw() self.effects:draw()
if self.items_text then self.items_text:draw(32, 145) end 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.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() self.ui:draw()
if self.unit_grabbed then 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) arrow:draw(gw/2 + 93, gh/2 - 10, 0, 0.4, 0.35)
end end
self.tutorial:draw() self.tutorial:draw()
end end

View File

@ -66,10 +66,10 @@ function engine_run(config)
if state.sx and state.sy then if state.sx and state.sy then
sx, sy = state.sx, state.sy 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 else
state.sx, state.sy = sx, sy 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 end
love.window.setTitle(config.game_name) love.window.setTitle(config.game_name)

287
main.lua
View File

@ -1,6 +1,7 @@
require 'engine' require 'engine'
require 'shared' require 'shared'
require 'arena' require 'arena'
require 'mainmenu'
require 'buy_screen' require 'buy_screen'
require 'objects' require 'objects'
require 'player' require 'player'
@ -1474,17 +1475,6 @@ function init()
'magnetism', 'insurance', 'dividends' '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() steam.userStats.requestCurrentStats()
new_game_plus = state.new_game_plus or 0 new_game_plus = state.new_game_plus or 0
if not state.new_game_plus then state.new_game_plus = new_game_plus end 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 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 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_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: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', 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'}) -- main:go_to('buy_screen', 7, run.units or {}, {'unleash'})
--[[ --[[
@ -1552,6 +1545,7 @@ function update(dt)
end end
]]-- ]]--
--[[
if input.n.pressed then if input.n.pressed then
if main.current.sfx_button then if main.current.sfx_button then
main.current.sfx_button:action() main.current.sfx_button:action()
@ -1581,10 +1575,11 @@ function update(dt)
end end
end end
end end
]]--
if input.k.pressed then if input.k.pressed then
if sx > 1 and sy > 1 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) love.window.setMode(480*sx, 270*sy)
state.sx, state.sy = sx, sy state.sx, state.sy = sx, sy
state.fullscreen = false state.fullscreen = false
@ -1592,7 +1587,7 @@ function update(dt)
end end
if input.l.pressed then 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) love.window.setMode(480*sx, 270*sy)
state.sx, state.sy = sx, sy state.sx, state.sy = sx, sy
state.fullscreen = false state.fullscreen = false
@ -1614,10 +1609,268 @@ function draw()
end 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() function love.run()
return engine_run({ return engine_run({
game_name = 'SNKRX', game_name = 'SNKRX',
window_width = 480*4, window_width = 'max',
window_height = 270*4, window_height = 'max',
}) })
end end

202
mainmenu.lua 100644
View File

@ -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

View File

@ -1012,6 +1012,11 @@ function Player:init(args)
end end
self.mouse_control_v_buffer = {} 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 end
@ -1216,19 +1221,21 @@ function Player:update(dt)
self.t:set_every_multiplier('attack', self.aspd_m) self.t:set_every_multiplier('attack', self.aspd_m)
if self.leader then 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 not main.current:is(MainMenu) then
if input.move_right.pressed and not self.move_left_pressed then self.move_right_pressed = love.timer.getTime() end if input.move_left.pressed and not self.move_right_pressed then self.move_left_pressed = love.timer.getTime() end
if input.move_left.released then self.move_left_pressed = nil end if input.move_right.pressed and not self.move_left_pressed then self.move_right_pressed = love.timer.getTime() end
if input.move_right.released then self.move_right_pressed = nil 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 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.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 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) 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 if #self.mouse_control_v_buffer > 64 then self.mouse_control_v_buffer[65] = nil end
else else
if input.move_left.down then self.r = self.r - 1.66*math.pi*dt end 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 input.move_right.down then self.r = self.r + 1.66*math.pi*dt end
end
end end
local total_v = 0 local total_v = 0
@ -2770,7 +2777,7 @@ end
function Volcano:update(dt) function Volcano:update(dt)
self:update_game_object(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 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.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.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, self.shape.rs + random:float(-1, 1), self.color, 2)
graphics.circle(self.x, self.y, 24, self.color_transparent) graphics.circle(self.x, self.y, 24, self.color_transparent)
local lw = 2 local lw = 2

View File

@ -88,9 +88,10 @@ function shared_draw(draw_action)
shadow_shader:unset() shadow_shader:unset()
end) end)
background_canvas:draw(0, 0, 0, sx, sy) local x, y = 0, 0
shadow_canvas:draw(1.5*sx, 1.5*sy, 0, sx, sy) background_canvas:draw(x, y, 0, sx, sy)
main_canvas:draw(0, 0, 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 end

43
todo
View File

@ -31,6 +31,7 @@ Looping Update
Summon Instability - summons explode when disappearing, dealing 100/150/200% damage Summon Instability - summons explode when disappearing, dealing 100/150/200% damage
Changes: Changes:
Magnetism - also attracts healing orbs Magnetism - also attracts healing orbs
Enchanted - 30/60/90%
Healer rework: Healer rework:
Enemies have a 8/16% chance to spawn healing orbs on death, orbs prioritize healing low health allies 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 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 Fairy: grants a random unit 100% attack speed for 6 seconds and creates 1 healing orb
Psyker rework: Psyker rework:
Create orbitting, damaging balls at the head of the snake equal to the number of psykers 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 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 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 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 * Decreased reroll cost to 8
* Increased sage's attack speed * Increased sage's attack speed
QoL QoL
Your party + items on end, death and passive screens - https://i.imgur.com/JJUddT3.png Show cooldown on elite attack
Volume slider * Options menu from buy screen
Add visuals divine intervention, fairy buff * Add main menu
Options menu from buy screen * Title
Add option for mouse cursor to always be visible * Snake DVD
Add main menu * Arena run button
Soundtrack button * Options button
Arena run button * Quit button
Options button * Soundtrack button
Quit button
https://i.imgur.com/4hOt5uX.png "party 7/9" https://i.imgur.com/4hOt5uX.png "party 7/9"
https://i.imgur.com/dlGbx0k.png lvl 3 effect on shop card 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 Bug fixes
Fix fullscreen with different resolutions that don't scale properly - https://steamcommunity.com/app/915310/discussions/0/3106901665841020282/ * Fixed fullscreen button and general resolution issues
Fix enemies still spawning after arena clear (this happens with the extra enemy spawns that were blocked earlier) Fixed a series of crashes that happened rarely right before changing from the arena back to the shop
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
https://i.imgur.com/Rk6qbDD.png - merchant doesnt give reroll if dies 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/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/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 Units die permanently when they die
Slower scaling with less individually threatening units Slower scaling with less individually threatening units
Max snake size goes up every 10 levels 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/
-- --