Level Up - Choose a Curse!
[b]Devlog #013:[/b]
I've been fighting with the level up screen - all the bits and pieces animating in, with the right timing and everything.
Turned into a whole unreadable heap of spaghetti, which just barely worked. Any additions and I'd be completely lost.
Y'know the type of "when I wrote this code, only god and I knew what it did - now only god knows", but already 5 minutes after the fact.
Just had a little state variable, just a counter, which I would increment somewhere in the whole heap of spaghetti, and then go into another if-else case updating the blood splatters, or the cards animating into the screen.
I think I just expected this to be less complex, but I wanted several things happening after one another, and soon I was left with a 200-ish line monstrosity that was quickly growing out of hand.
A literal shower thought brought me to the simple solution: My data structure (none) was the wrong one for this type of thing.
All I needed to clean it up was a main loop that called an array of functions with the corresponding update and draw functions split into them.
local states = { { --blood splatters and title animation_duration = 0.75, update = wait_update, draw = function () SCREEN_MAIN_GAME.draw() local cw = level_up_canvas:getWidth() local ch = level_up_canvas:getHeight() local spl = SPRITES.ui.splatter_left.image local spr = SPRITES.ui.splatter_right.image local title = SPRITES.ui.choose_your_curse.image local v_unit = SCREEN_H / 25 local shadow_offset = v_unit / 2 local scale_factor = SCREEN_W / NATIVE_SCREEN_W local spl_x = 0 local spl_y = ch / 5 local spr_x = cw - spl:getWidth() * scale_factor local spr_y = 0 local splatter_left_percentage = UTIL.ease_in_quint(animation_percentage) LG.setCanvas(level_up_canvas) LG.clear(0, 0, 0, 0) --draw the splatters if OPTIONS.ui.childsafe_mode then LG.setColor(INK_BLACK) else LG.setColor(BLOOD_RED) end circular_splash_shader:send("visible_dist", splatter_left_percentage * cw) LG.setShader(circular_splash_shader) LG.draw( spl, spl_x, spl_y, 0, scale_factor ) LG.draw( spr, spr_x, spr_y, 0, scale_factor ) LG.setShader() LG.setColor(1, 1, 1, 1) SHARED_SHADERS.reveal_shader:send("mask_canvas", level_up_canvas) LG.setShader(SHARED_SHADERS.reveal_shader) LG.draw( title, cw / 2 - (title:getWidth() / 2 * scale_factor), ch * .55 - (title:getHeight() / 2 * scale_factor), 0, scale_factor ) LG.setShader() LG.setCanvas() draw_title() end }, { --wait animation_duration = 0.25, update = wait_update, draw = function () SCREEN_MAIN_GAME.draw() draw_title() end }, { --animate in cards animation_duration = 1, update = function () animation_percentage = get_animation_percentage() local card_rot_percentage = UTIL.ease_out_circ(animation_percentage) for i = 1, card_amount do cards[i].y = card_bottom_y - card_heights[i] * UTIL.ease_out_circ(animation_percentage) if i == selected_card_index then cards[i].y = cards[i].y - card_selection_height end cards[i].rot_x = card_rot_percentage * card_rotations[i] end if animation_percentage == 1 then state = state + 1 time_start = LT.getTime() end end, draw = function () SCREEN_MAIN_GAME.draw() draw_title() draw_cards() end }, { --wait animation_duration = 0.1, update = wait_update, draw = function () SCREEN_MAIN_GAME.draw() draw_title() draw_cards() end }, { --flip cards animation_duration = 1, update = function () animation_percentage = get_animation_percentage() local card_rot_percentage = UTIL.ease_in_quint(animation_percentage) for i = 1, card_amount do cards[i].rot_z = -math.pi + card_rot_percentage * math.pi * 2 end if animation_percentage == 1 then state = state + 1 time_start = LT.getTime() end end, draw = function () SCREEN_MAIN_GAME.draw() draw_title() draw_cards() end }, { --wait for input animation_duration = 1, update = function () user_input_blocked = false --next state is being set by user input for i = 1, #cards do cards[i].y = card_bottom_y - card_heights[i] * UTIL.ease_out_circ(animation_percentage) if i == selected_card_index then cards[i].y = cards[i].y - card_selection_height end end end, draw = function () SCREEN_MAIN_GAME.draw() draw_title() draw_cards() end }, { --animate out cards animation_duration = 1, update = function () animation_percentage = get_animation_percentage() for i = 1, card_amount do if i ~= selected_card_index then cards[i].y = card_bottom_y - card_heights[i] * (1 - UTIL.ease_out_circ(animation_percentage)) end --cards[i].rot_z = animation_percentage end if animation_percentage == 1 then state = state + 1 time_start = LT.getTime() end end, draw = function () SCREEN_MAIN_GAME.draw() draw_title() draw_cards() end }, { --fade out card highlight animation_duration = .3, update = wait_update, draw = function () SCREEN_MAIN_GAME.draw() draw_title() cards[selected_card_index]:draw(true, 1 - animation_percentage) end }, { --burn up remaining card animation_duration = 2, update = wait_update, draw = function () SCREEN_MAIN_GAME.draw() draw_title() dissolve_shader:send("time", UTIL.ease_in_quint(animation_percentage)) LG.setShader(dissolve_shader) --TODO: optimally, I'd spawn a few embers floating away while the card burns up cards[selected_card_index]:draw(false) LG.setShader() end }, { --wipe away blood stains animation_duration = 1.5, update = function () animation_percentage = get_animation_percentage() if animation_percentage == 1 then state = 1 UTIL.change_screen(SCREEN_MAIN_GAME) end end, draw = function () SCREEN_MAIN_GAME.draw() SHARED_SHADERS.wipeaway_shader:send("animation_percentage", animation_percentage) LG.setShader(SHARED_SHADERS.wipeaway_shader) draw_title() LG.setShader() end }, }
Here it is in action:
Everything I wanted in that screen is there, but yet again, I feel the discrepancy between my vision and what I'm able to achieve. Need to study more shaders, need to study more maths.
I'll get there some day.
Cursed Existence
Status | Released |
Author | Bananicorn |
Genre | Action |
Tags | Action RPG, Roguelite |
More posts
- Pause screen implemented! (exciting, right?)14 days ago
- Mockups, Mockups, Mockups!21 days ago
Leave a comment
Log in with itch.io to leave a comment.