GUI transition when entering level
This commit is contained in:
parent
0546696ac9
commit
e87fa3b6ec
|
@ -5,10 +5,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "util.h"
|
||||
|
||||
typedef int32_t fixed_t;
|
||||
|
||||
#include "util.h"
|
||||
|
||||
/* Type of map coordinates */
|
||||
typedef fixed_t map_coord_t;
|
||||
|
||||
|
|
38
src/menu.c
38
src/menu.c
|
@ -66,6 +66,9 @@ int menu_level_select(int start)
|
|||
|
||||
int selection = (start >= 0 && start < OPTION_COUNT) ? start : 0;
|
||||
int target_x=0, x=0;
|
||||
/* Time spent in the transition animation that moves the GUI items away
|
||||
before starting the level. */
|
||||
fixed_t transition_time = fix(0.0);
|
||||
|
||||
int volatile frame_tick = 1;
|
||||
int t = timer_configure(TIMER_ANY, 1000000 / FRAME_RATE,
|
||||
|
@ -86,6 +89,14 @@ int menu_level_select(int start)
|
|||
x += dx;
|
||||
}
|
||||
|
||||
/* GUI positioning variables, accounting for the final transition */
|
||||
fixed_t TRANSITION_LEN = fix(0.75);
|
||||
int LOGO_Y = cubic(9, 9-85, transition_time, TRANSITION_LEN);
|
||||
int ARROW1_X = cubic(16, 16-50, transition_time, TRANSITION_LEN);
|
||||
int ARROW2_X = cubic(345, 345+50, transition_time, TRANSITION_LEN);
|
||||
int NAME_Y = cubic(DHEIGHT-24, DHEIGHT+10, transition_time,
|
||||
TRANSITION_LEN);
|
||||
|
||||
dclear(C_BLACK);
|
||||
|
||||
for(int i = 0; i < OPTION_COUNT; i++) {
|
||||
|
@ -99,15 +110,17 @@ int menu_level_select(int start)
|
|||
options[i]->camera.x = map_center - fix(local_offset) / TILE_WIDTH;
|
||||
menu_render_game(options[i]);
|
||||
|
||||
dprint_opt(DWIDTH/2 + local_offset, DHEIGHT - 24, C_WHITE, C_NONE,
|
||||
dprint_opt(DWIDTH/2 + local_offset, NAME_Y, C_WHITE, C_NONE,
|
||||
DTEXT_CENTER, DTEXT_MIDDLE, "%s", options[i]->level->name);
|
||||
}
|
||||
|
||||
dimage(148, 9, &img_menu_title);
|
||||
dimage(148, LOGO_Y, &img_menu_title);
|
||||
if(selection > 0)
|
||||
dsubimage(16, 93, &img_menu_arrows, 0, 0, 35, 42, DIMAGE_NOCLIP);
|
||||
dsubimage(ARROW1_X, 93, &img_menu_arrows, 0, 0, 35, 42,
|
||||
DIMAGE_NONE);
|
||||
if(selection < OPTION_COUNT - 1)
|
||||
dsubimage(345, 93, &img_menu_arrows, 35, 0, 35, 42, DIMAGE_NOCLIP);
|
||||
dsubimage(ARROW2_X, 93, &img_menu_arrows, 35, 0, 35, 42,
|
||||
DIMAGE_NONE);
|
||||
|
||||
dupdate();
|
||||
|
||||
|
@ -115,16 +128,25 @@ int menu_level_select(int start)
|
|||
menu_update_animations(options[i], dt);
|
||||
|
||||
int key = getkey_opt(GETKEY_MENU, &frame_tick).key;
|
||||
if(key == KEY_LEFT && selection > 0) {
|
||||
if(transition_time <= fix(0.0)
|
||||
&& key == KEY_LEFT && selection > 0) {
|
||||
selection--;
|
||||
target_x += DWIDTH;
|
||||
}
|
||||
if(key == KEY_RIGHT && selection < OPTION_COUNT - 1) {
|
||||
if(transition_time <= fix(0.0)
|
||||
&& key == KEY_RIGHT && selection < OPTION_COUNT - 1) {
|
||||
selection++;
|
||||
target_x -= DWIDTH;
|
||||
}
|
||||
if(key == KEY_EXE || key == KEY_SHIFT)
|
||||
break;
|
||||
|
||||
if(key == KEY_EXE || key == KEY_SHIFT) {
|
||||
transition_time = dt;
|
||||
}
|
||||
else if(transition_time > fix(0.0)) {
|
||||
transition_time += dt;
|
||||
if(transition_time >= TRANSITION_LEN)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
timer_stop(t);
|
||||
|
|
32
src/render.c
32
src/render.c
|
@ -297,7 +297,7 @@ static void render_entities(game_t const *g, camera_t const *camera,
|
|||
free(rendering_order);
|
||||
}
|
||||
|
||||
static void render_wave_info(game_t const *g)
|
||||
static void render_wave_info(game_t const *g, int y0)
|
||||
{
|
||||
level_t const *level = g->level;
|
||||
level_wave_t const *wave = game_current_wave(g);
|
||||
|
@ -305,7 +305,7 @@ static void render_wave_info(game_t const *g)
|
|||
for(int i = 0; i < wave->entry_count; i++)
|
||||
wave_enemies += wave->entries[i].amount;
|
||||
|
||||
dprint(2, 2, C_WHITE, "Wave %d (%d left)",
|
||||
dprint(2, y0+2, C_WHITE, "Wave %d (%d left)",
|
||||
g->wave, wave_enemies - g->wave_spawned);
|
||||
|
||||
if(g->wave + 1 > level->wave_count)
|
||||
|
@ -314,7 +314,7 @@ static void render_wave_info(game_t const *g)
|
|||
level_wave_t const *next_wave = &level->waves[g->wave+1 - 1];
|
||||
|
||||
int x = DWIDTH - 2;
|
||||
int y = 10;
|
||||
int y = y0 + 10;
|
||||
|
||||
for(int i = next_wave->entry_count - 1; i >= 0; i--) {
|
||||
enemy_t const *enemy = enemy_data(next_wave->entries[i].identity);
|
||||
|
@ -419,18 +419,26 @@ void render_game(game_t const *g, bool show_hitboxes)
|
|||
ctx = prof_make();
|
||||
prof_enter(ctx);
|
||||
|
||||
/* GUI positioning variables used during level entry */
|
||||
fixed_t MAX_GUI_TIME = fix(0.75);
|
||||
fixed_t gui_time = MAX_GUI_TIME;
|
||||
if(g->time_total < MAX_GUI_TIME)
|
||||
gui_time = g->time_total;
|
||||
int HUD_Y = cubic(DHEIGHT+30, DHEIGHT, gui_time, MAX_GUI_TIME);
|
||||
int HEADER_Y = cubic(-15, 0, gui_time, MAX_GUI_TIME);
|
||||
|
||||
/* Render wave information */
|
||||
render_wave_info(g);
|
||||
render_wave_info(g, HEADER_Y);
|
||||
|
||||
/* Render HUD */
|
||||
extern bopti_image_t img_hud;
|
||||
dimage(0, DHEIGHT - img_hud.height, &img_hud);
|
||||
dimage(0, HUD_Y - img_hud.height, &img_hud);
|
||||
|
||||
extern font_t font_hud;
|
||||
dfont(&font_hud);
|
||||
dprint_opt(349, DHEIGHT - 5, RGB24(0x15171a), C_NONE, DTEXT_CENTER,
|
||||
dprint_opt(349, HUD_Y - 5, RGB24(0x15171a), C_NONE, DTEXT_CENTER,
|
||||
DTEXT_TOP, "%d", g->player_data->xp_level);
|
||||
dprint_opt(349, DHEIGHT - 6, RGB24(0xabb1ba), C_NONE, DTEXT_CENTER,
|
||||
dprint_opt(349, HUD_Y - 6, RGB24(0xabb1ba), C_NONE, DTEXT_CENTER,
|
||||
DTEXT_TOP, "%d", g->player_data->xp_level);
|
||||
dfont(&font_rogue);
|
||||
|
||||
|
@ -439,21 +447,21 @@ void render_game(game_t const *g, bool show_hitboxes)
|
|||
/* Render life bar */
|
||||
extern bopti_image_t img_hud_life;
|
||||
int fill_height = (img_hud_life.height * player_f->HP) / player_f->HP_max;
|
||||
dsubimage(184, DHEIGHT - 5 - fill_height, &img_hud_life,
|
||||
dsubimage(184, HUD_Y - 5 - fill_height, &img_hud_life,
|
||||
0, img_hud_life.height - fill_height, img_hud_life.width, fill_height,
|
||||
DIMAGE_NONE);
|
||||
|
||||
/* Render XP bar. The following values indicate the geometry of the XP bar
|
||||
so that we can show a partially-filled version of it */
|
||||
if(anim_in(g->hud_xp_anim.frame, &anims_hud_xp_Explode, 0)) {
|
||||
anim_frame_render(343, DHEIGHT-32, g->hud_xp_anim.frame);
|
||||
anim_frame_render(343, HUD_Y-32, g->hud_xp_anim.frame);
|
||||
}
|
||||
else {
|
||||
static int const XP_FULL=22;
|
||||
int xp_current = g->player_data->xp_current;
|
||||
int xp_total = max(g->player_data->xp_to_next_level, 1);
|
||||
int fill_height = XP_FULL * xp_current / xp_total;
|
||||
anim_frame_subrender(343, DHEIGHT-32, g->hud_xp_anim.frame,
|
||||
anim_frame_subrender(343, HUD_Y-32, g->hud_xp_anim.frame,
|
||||
0, XP_FULL - fill_height, -1, fill_height);
|
||||
}
|
||||
|
||||
|
@ -468,7 +476,7 @@ void render_game(game_t const *g, bool show_hitboxes)
|
|||
fixed_t cooldown_remaining = player_f->actions_cooldown[i+1];
|
||||
|
||||
int x = 31 + 48*i + 64*(i>=3);
|
||||
int y = DHEIGHT - 33;
|
||||
int y = HUD_Y - 33;
|
||||
int bg = (cooldown_remaining != 0);
|
||||
dsubimage(x+2, y+2, &img_skillicons, skill_size * bg, 0, skill_size,
|
||||
skill_size, DIMAGE_NONE);
|
||||
|
@ -480,6 +488,8 @@ void render_game(game_t const *g, bool show_hitboxes)
|
|||
int height = (cooldown_remaining*skill_box_size) / cooldown_total;
|
||||
int ymin = y + skill_box_size - height;
|
||||
int ymax = y + skill_box_size;
|
||||
if(ymin >= DHEIGHT) ymin = DHEIGHT;
|
||||
if(ymax >= DHEIGHT) ymax = DHEIGHT;
|
||||
for(int y1 = ymin; y1 < ymax; y1++) {
|
||||
for(int x1 = x; x1 < x + skill_box_size; x1++) {
|
||||
int i = DWIDTH * y1 + x1;
|
||||
|
|
|
@ -209,3 +209,11 @@ void font_damage_print(int x, int y, int color, int align_x, int align_y,
|
|||
x += char_w;
|
||||
}
|
||||
}
|
||||
|
||||
int cubic(int start, int end, fixed_t t, fixed_t tmax)
|
||||
{
|
||||
t = fdiv(t, tmax);
|
||||
fixed_t x = fix(1.0) - fmul(fmul(fix(1.0)-t, fix(1.0)-t), fix(1.0)-t);
|
||||
x = fix(start) + fmul(fix(end - start), x);
|
||||
return fround(x);
|
||||
}
|
||||
|
|
11
src/util.h
11
src/util.h
|
@ -8,6 +8,11 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Integer square root (recursive, logarithmic complexity). */
|
||||
int64_t sqrtll(int64_t n);
|
||||
|
||||
#include "fixed.h"
|
||||
|
||||
// Heaps
|
||||
|
||||
/* Queue objects are passed by value in this API. */
|
||||
|
@ -47,9 +52,6 @@ void heap_sort(void *base, size_t n, size_t elsize,
|
|||
|
||||
// Other utils
|
||||
|
||||
/* Integer square root (recursive, logarithmic complexity). */
|
||||
int64_t sqrtll(int64_t n);
|
||||
|
||||
/* Round F-key. */
|
||||
void fkey_button(int position, char const *text, int color);
|
||||
|
||||
|
@ -64,3 +66,6 @@ void font_damage_print(int x, int y, int color, int align_x, int align_y,
|
|||
(((hex & 0xf80000) >> 8) | \
|
||||
((hex & 0x00fc00) >> 5) | \
|
||||
((hex & 0x0000f8) >> 3))
|
||||
|
||||
/* Cubic transition from [start] to [end] in total time [tmax] */
|
||||
int cubic(int start, int end, fixed_t t, fixed_t tmax);
|
||||
|
|
Loading…
Reference in New Issue