diff --git a/CMakeLists.txt b/CMakeLists.txt index 850673e..f819758 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,8 @@ set(ASSETS # HUD assets-cg/hud_wave.png assets-cg/hud_wave2.png + assets-cg/hud_life.png + assets-cg/hud_life2.png assets-cg/skillicons.png # Player animations assets-cg/player/player_up.aseprite diff --git a/assets-cg/hud_life.png b/assets-cg/hud_life.png new file mode 100644 index 0000000..cb5ffe9 Binary files /dev/null and b/assets-cg/hud_life.png differ diff --git a/assets-cg/hud_life2.png b/assets-cg/hud_life2.png new file mode 100644 index 0000000..271cbdb Binary files /dev/null and b/assets-cg/hud_life2.png differ diff --git a/assets-cg/hud_wave.png b/assets-cg/hud_wave.png index 1203649..f1c9840 100644 Binary files a/assets-cg/hud_wave.png and b/assets-cg/hud_wave.png differ diff --git a/assets-cg/hud_wave2.png b/assets-cg/hud_wave2.png index e8996a7..b3666e5 100644 Binary files a/assets-cg/hud_wave2.png and b/assets-cg/hud_wave2.png differ diff --git a/src/enemies.c b/src/enemies.c index 2c92d87..f29b988 100644 --- a/src/enemies.c +++ b/src/enemies.c @@ -105,9 +105,11 @@ entity_t *enemy_spawn(int enemy_id, int level) e->identity = enemy_id; - e->HP = instantiate_stat(&data->HP, level); - e->ATK = instantiate_stat(&data->ATK, level); - e->DEF = instantiate_stat(&data->DEF, level); + e->HP_max = instantiate_stat(&data->HP, level); + e->ATK = instantiate_stat(&data->ATK, level); + e->DEF = instantiate_stat(&data->DEF, level); + + e->HP = e->HP_max; return e; } diff --git a/src/entities.h b/src/entities.h index 7baed60..9a1bef4 100644 --- a/src/entities.h +++ b/src/entities.h @@ -75,7 +75,7 @@ typedef struct { /* Enemy ID (0 for player) */ uint8_t identity; /* Combat statistics */ - uint16_t HP, ATK, DEF; + uint16_t HP, ATK, DEF, HP_max; /* Time left until nexth pathfinding run (ms) */ // uint8_t pathfind_delay; diff --git a/src/main.c b/src/main.c index 2cef8cf..9412d81 100644 --- a/src/main.c +++ b/src/main.c @@ -96,6 +96,7 @@ int main(void) game_add_entity(&game, player); game.player = player; + player->HP_max += 100; player->HP += 100; player->movement_params = &emp_player; player->identity = 0; diff --git a/src/render.c b/src/render.c index c4c0512..f32631f 100644 --- a/src/render.c +++ b/src/render.c @@ -30,7 +30,7 @@ void camera_init(camera_t *c, map_t const *m) c->y = (c->limits.y_min + c->limits.y_max) / 2; /* Slightly off-center to add space for the HUD */ - c->y -= fix(0.5); + c->y -= fix(0.375); } ipoint_t camera_map2screen(camera_t const *c, fpoint_t p) @@ -117,7 +117,7 @@ void render_map(map_t const *m, camera_t const *c) extern bopti_image_t img_tileset_decor; /* Render floor and walls */ - for(int row = -2; row < m->height + 1; row++) + for(int row = -2; row < m->height + 2; row++) for(int col = -1; col < m->width + 1; col++) { struct tile *t = map_tile(m, col, row); fpoint_t tile_pos = { fix(col), fix(row) }; @@ -131,11 +131,11 @@ void render_map(map_t const *m, camera_t const *c) /* Floor/wall layer */ dsubimage(p.x, p.y, &img_tileset_base, TILE_WIDTH * (t->base % 16), TILE_HEIGHT * (t->base / 16), - TILE_WIDTH, TILE_HEIGHT, DIMAGE_NONE); + TILE_WIDTH, TILE_HEIGHT, DIMAGE_NOCLIP); /* Decoration layer */ if(t->decor) dsubimage(p.x, p.y, &img_tileset_decor, TILE_WIDTH * (t->decor % 16), TILE_HEIGHT * (t->decor / 16), - TILE_WIDTH, TILE_HEIGHT, DIMAGE_NONE); + TILE_WIDTH, TILE_HEIGHT, DIMAGE_NOCLIP); } } @@ -230,27 +230,32 @@ void render_game(game_t const *g, bool show_hitboxes) enemies_left += (g->entities[i]->identity != 0); extern bopti_image_t img_hud_wave, img_hud_wave2; - dimage((DWIDTH-img_hud_wave.width) / 2, 17, &img_hud_wave); - dsubimage((DWIDTH-img_hud_wave2.width) / 2, 17, &img_hud_wave2, - 0, 0, (img_hud_wave2.width*enemies_left) / - g->level->waves[g->wave-1].enemy_count, img_hud_wave2.height, - DIMAGE_NONE); + dimage(DWIDTH - img_hud_wave.width, 17, &img_hud_wave); + int fill_length = (img_hud_wave2.width * enemies_left) / + g->level->waves[g->wave-1].enemy_count; + dsubimage(DWIDTH - fill_length, 17, &img_hud_wave2, + img_hud_wave2.width - fill_length, 0, fill_length, + img_hud_wave2.height, DIMAGE_NONE); if(g->wave_spawned < game_current_wave(g)->enemy_count) - dprint_opt(DWIDTH / 2, 2, C_WHITE, C_NONE, DTEXT_CENTER, DTEXT_TOP, - "Wave %d: %d enemies spawning", g->wave, + dprint_opt(DWIDTH - 4, 2, C_WHITE, C_NONE, DTEXT_RIGHT, DTEXT_TOP, + "Wave %d is preppin' up...", g->wave, game_current_wave(g)->enemy_count - g->wave_spawned); else if(enemies_left > 0) - dprint_opt(DWIDTH / 2, 2, C_WHITE, C_NONE, DTEXT_CENTER, DTEXT_TOP, - "Wave %d: %d enemies left", g->wave, enemies_left); + dprint_opt(DWIDTH - 4, 2, C_WHITE, C_NONE, DTEXT_RIGHT, DTEXT_TOP, + "Wave %d is here for you!", g->wave, enemies_left); else - dprint_opt(DWIDTH / 2, 2, C_WHITE, C_NONE, DTEXT_CENTER, DTEXT_TOP, - "Wave %d: Victory!", g->wave); + dprint_opt(DWIDTH - 4, 2, C_WHITE, C_NONE, DTEXT_RIGHT, DTEXT_TOP, + "Victory! For now...", g->wave); entity_t const *player = g->player; - dprint(2, 2, C_WHITE, "HP: %d", player->HP); - dprint_opt(DWIDTH - 2, 2, C_WHITE, C_NONE, DTEXT_RIGHT, DTEXT_TOP, - "ATK:%d DEF:%d", player->ATK, player->DEF); + dprint(2, 2, C_WHITE, "HP: %d/%d", player->HP, player->HP_max); + + extern bopti_image_t img_hud_life, img_hud_life2; + dimage(0, 17, &img_hud_life); + fill_length = (img_hud_life2.width * player->HP) / player->HP_max; + dsubimage(0, 17, &img_hud_life2, 0, 0, fill_length, img_hud_life2.height, + DIMAGE_NONE); /* Render skill icons */ extern bopti_image_t img_skillicons; @@ -265,7 +270,7 @@ void render_game(game_t const *g, bool show_hitboxes) cooldown_remaining=fix(1); } - int x=15+68*i, y=DHEIGHT-28, bg=(cooldown_remaining!=0); + int x=15+68*i, y=DHEIGHT-27, bg=(cooldown_remaining!=0); dsubimage(x, y, &img_skillicons, 23*bg, 0, 23, 23, DIMAGE_NONE); dsubimage(x, y, &img_skillicons, 23*(i+2), 0, 23, 23, DIMAGE_NONE);