diff --git a/CMakeLists.txt b/CMakeLists.txt index c43accc..10e034b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ set(ASSETS assets-cg/bosonx_logo_empty.png assets-cg/lepheyatis_logo.png assets-cg/font_boson.png + assets-cg/font_energy.png assets-cg/erik_running.gif assets-cg/erik_jumping.gif assets-cg/stages/stage1.png diff --git a/assets-cg/font_energy.png b/assets-cg/font_energy.png new file mode 100644 index 0000000..8fff808 Binary files /dev/null and b/assets-cg/font_energy.png differ diff --git a/assets-cg/fxconv-metadata.txt b/assets-cg/fxconv-metadata.txt index e2062b8..15684c8 100644 --- a/assets-cg/fxconv-metadata.txt +++ b/assets-cg/fxconv-metadata.txt @@ -33,6 +33,11 @@ font_boson.png: proportional: true height: 9 +font_energy.png: + type: bopti-image + name: img_font_energy + profile: p8_rgb565a + *.gif: custom-type: animation name_regex: (.*)\.gif anim_\1 diff --git a/src/game.h b/src/game.h index 884bd36..213e2e6 100644 --- a/src/game.h +++ b/src/game.h @@ -68,7 +68,10 @@ struct player //======= Data =======// - /* TODO: Energy -> speed multiplier, skin, others? */ + /* Energy collected, in percent */ + num energy_percent; + + /* TODO: Skin, others? */ }; /* Dynamic information about one or multiple attempts at a single level. */ diff --git a/src/level.cpp b/src/level.cpp index 48c2e8e..beb2dab 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -1,5 +1,6 @@ #include "level.h" #include "generator.h" +#include "util.h" #include struct level level_create(int level) @@ -7,14 +8,18 @@ struct level level_create(int level) struct level l; switch(level) { + default: + l.gen = std::make_unique(); + l.bgcolor = RGB24(0x49759f); + break; case 2: l.gen = std::make_unique(); + l.bgcolor = RGB24(0xe7c272); break; case 3: l.gen = std::make_unique(); + l.bgcolor = C_WHITE; break; - default: - l.gen = std::make_unique(); } return l; } diff --git a/src/level.h b/src/level.h index 64b2b60..6e8c92f 100644 --- a/src/level.h +++ b/src/level.h @@ -26,6 +26,7 @@ struct Generator; struct level { std::vector platform_buffer; std::unique_ptr gen; + uint16_t bgcolor; }; diff --git a/src/main.cpp b/src/main.cpp index 14fde68..7c23442 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,6 +39,7 @@ int play_level(int level_id) player->height = 1.0; player->vheight = 0.0; player->frame = 0; + player->energy_percent = 0.0; /* FPS regulation setup */ int volatile need_frame = 1; @@ -80,7 +81,7 @@ int play_level(int level_id) //======= Rendering =======// azrp_perf_clear(); - azrp_clear(RGB24(0x49759f)); + azrp_clear(game.level.bgcolor); prof_t perf_comp = prof_make(); prof_enter_norec(perf_comp); @@ -110,7 +111,7 @@ int play_level(int level_id) render_anim_frame((int)player_dot.x, (int)player_dot.y, player_anim, player_frame); - if(standing_on && standing_on->type == PLATFORM_BLUE) { + if(standing_on && standing_on->type == PLATFORM_BLUE) { prof_enter(game.perf.effect_bpp); render_effect_bpp(&effect_bpp, game.t); azrp_image((int)player_dot.x - effect_bpp->width / 2, @@ -119,6 +120,12 @@ int play_level(int level_id) prof_leave(game.perf.effect_bpp); } + /* Render energy score */ + char energy_str[32]; + sprintf(energy_str, "%.2f%%", (float)player->energy_percent); + azrp_rect(DWIDTH-100, 4, 96, 20, AZRP_RECT_DARKEN); + render_energy_str(DWIDTH-8, 8, DTEXT_RIGHT, energy_str); + prof_leave_norec(perf_comp); azrp_update(); @@ -188,7 +195,8 @@ int play_level(int level_id) //======= Simulation =======// - player->z += player->vz * dt; + num vz = player->vz * (num(1) + player->energy_percent / 200); + player->z += vz * dt; player->height += player->vheight * dt; /* Apply gravity */ @@ -246,6 +254,10 @@ int play_level(int level_id) if(death_1 || death_2) break; + if(standing_on && standing_on->type == PLATFORM_BLUE) { + player->energy_percent += dt * vz * 5.5; + } + game_advance(&game); prof_leave_norec(perf_frame); last_frame_us = prof_time(perf_frame); diff --git a/src/render.cpp b/src/render.cpp index afbe9f1..349289b 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -166,6 +166,55 @@ void render_anim_frame(int x, int y, struct anim *anim, int frame) anim->frames[frame]); } +static bool render_energy_str_glyph_params(int c, int *ix, int *w) +{ + if(c >= '0' && c <= '9') { + *ix = 13 * (c - '0') - (c >= '2' ? 3 : 0); + *w = (c == '1') ? 8 : 11; + return true; + } + if(c == '.') { + *ix = 127; + *w = 4; + return true; + } + if(c == '%') { + *ix = 132; + *w = 8; + return true; + } + return false; +} + +void render_energy_str(int x, int y, int halign, char const *str) +{ + extern image_t img_font_energy; + int ix, w; + + /* First compute width of string */ + int total_width = 0; + for(int i = 0; str[i]; i++) { + if(render_energy_str_glyph_params(str[i], &ix, &w)) + total_width += w + 2; + } + total_width -= (total_width ? 2 : 0); + + /* Apply horizontal alignment */ + if(halign == DTEXT_CENTER) + x -= total_width >> 1; + if(halign == DTEXT_RIGHT) + x -= total_width - 1; + + /* Render string */ + for(int i = 0; str[i]; i++) { + if(!render_energy_str_glyph_params(str[i], &ix, &w)) + continue; + azrp_subimage(x, y, &img_font_energy, ix, 0, w, + img_font_energy.height, DIMAGE_NONE); + x += w + 2; + } +} + void render_effect_bpp(image_t **image, num t) { enum { BPP_PARTICLE = 0x81 }; diff --git a/src/render.h b/src/render.h index af4eed4..75eaf5b 100644 --- a/src/render.h +++ b/src/render.h @@ -92,6 +92,9 @@ void render_triangle(vec3 *p1, vec3 *p2, vec3 *p3, int color); used, z is ignored. */ void render_dots(std::initializer_list const &&points); +/* Render an energy string (energy font, characters supported: 0-9.%) */ +void render_energy_str(int x, int y, int halign, char const *str); + /* Render a frame of an animation. */ void render_anim_frame(int x, int y, struct anim *anim, int frame);