From 09500ff4141db2588ec3ed7da8fb6d9c75d32dbb Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Sat, 21 Apr 2018 14:13:00 +0200 Subject: Avatars. --- src/game/assets.cpp | 1 + src/game/game.hpp | 2 +- src/game/interface.cpp | 96 +++++++++++++++++++++++++++++++++++++++++++++++ src/game/text.cpp | 7 ---- src/game/unit_soldier.cpp | 24 +++++++++++- 5 files changed, 121 insertions(+), 9 deletions(-) (limited to 'src/game') diff --git a/src/game/assets.cpp b/src/game/assets.cpp index 68d94dd..79edd04 100644 --- a/src/game/assets.cpp +++ b/src/game/assets.cpp @@ -42,6 +42,7 @@ void load(void) soldier.dead.load("assets/units/soldier/dead_", 1); soldier.gibbing.load("assets/units/soldier/gibbing_", 3); soldier.rocket.load("assets/units/soldier/rocket_", 4); + soldier.avatar.load("assets/units/soldier/avatar_", 1); soldier.fire.load("assets/units/soldier/fire.ogg"); soldier.fire.volume = 4.0f; diff --git a/src/game/game.hpp b/src/game/game.hpp index 145fc7e..c6d4b53 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -65,6 +65,7 @@ namespace game { render::oriented_sprite_4M2_t legs_idle, legs_walking; render::animated_texture_t dead, gibbing; render::animated_texture_t rocket; + render::animated_texture_t avatar; audio::sound_t fire, step_stone, step_dirt, pain, death, gib_sound; } soldier_assets_t; @@ -132,7 +133,6 @@ namespace game { SAY_FIRING, SAY_NO_ROCKETS, UNIT_NAME_SPIDER, - UNIT_NAME_SOLDIER, UNIT_NAME_NEST, UNIT_NAME_REPL, UNIT_DEATH, diff --git a/src/game/interface.cpp b/src/game/interface.cpp index 26ade2a..34bbcf2 100644 --- a/src/game/interface.cpp +++ b/src/game/interface.cpp @@ -328,11 +328,83 @@ void pie_menu_t::render_to(render::state_t *render) } } +static sf::Color health_to_color(float frac,int alpha) +{ + int t; + + if (frac >= 1.0f) + return sf::Color(0, 255, 0, alpha); + else if (frac > 0.5f) { + t = (int)remap(1.0f, 0.5f, 0.0f, 255.0f, frac); + return sf::Color(t, 255, 0, alpha); + } else if (frac > 0.0f) { + t = (int)remap(0.5f, 0.0f, 255.0f, 0.0f, frac); + return sf::Color(255, t, 0, alpha); + } else + return sf::Color(255, 0, 0, alpha); +} + +static void render_avatar(render::state_t *render, game::unit_t *unit, v2f_t at, + v2f_t avatar_size, float em, bool large) +{ + render::animated_texture_t *image; + rectf_t rect, bar; + v2f_t x; + std::string str; + float frac; + + switch (unit->type) { + case game::unit_t::UNIT_SOLDIER: + image = &assets::soldier.avatar; + break; + + default: + image = &assets::deco.eyething; + break; + } + + rect = rectf_t(at, at + avatar_size * em); + render->render(0, image, rect, sf::Color::White); + + frac = (float)unit->health / unit->max_health; + + if (!large) { + bar = rect; + bar[0][1] = bar[1][1] - em; + render->render_rect(bar, sf::Color(0, 0, 0, 128)); + + bar[1][0] = lerp(bar[0][0], bar[1][0], frac); + render->render_rect(bar, health_to_color(frac, 90)); + + return; + } + + x = v2f_t(rect[0][0], rect[1][1] - em / 2); + bar[0][0] = x[0]; + bar[0][1] = x[1] - 0.5f * em; + bar[1][0] = rect[1][0]; + bar[1][1] = bar[0][1] + 0.9f * em; + render->render_rect(bar, sf::Color(0, 0, 0, 128)); + + bar[1][0] = lerp(bar[0][0], bar[1][0], frac); + render->render_rect(bar, health_to_color(frac, 90)); + + str = std::to_string(unit->health) + "/" + std::to_string(unit->max_health); + render->render_text(x, em, str, render::ALIGN_LEFT_BOTTOM, sf::Color::White); + + x[1] -= em; + render->render_text(x + v2f_t(0.1, 0.1) * em, em, unit->name, render::ALIGN_LEFT_BOTTOM, sf::Color::Black); + render->render_text(x, em, unit->name, render::ALIGN_LEFT_BOTTOM, sf::Color::White); +} + void state_t::render_to(render::state_t *render) { size_t w = window->getSize().x, h = window->getSize().y; v2f_t x; std::stringstream ss; + v2f_t avatar_size; + bool large_avatars = true; + size_t row = 0; if (select.selecting) { sf::Color color; @@ -355,7 +427,31 @@ void state_t::render_to(render::state_t *render) } window->setView(sf::View(sf::FloatRect(0, 0, w, h))); + em = std::max(w, h) * 0.017; + if (em < 15.0f) + em = 15.0f; + + avatar_size = v2f_t(6, 10); + + if (game->selected_units.size() > 8) + large_avatars = false; + + if (game->selected_units.size() > 4) + avatar_size /= (game->selected_units.size() - 5.0f) * 0.1f + 1.0f; + + x = v2f_t(w, h) - avatar_size * em; + for (unit_t *unit : game->selected_units) { + render_avatar(render, unit, x, avatar_size, em, large_avatars); + + row++; + if (row >= 4) { + x[0] = w - avatar_size[0] * em; + x[1] -= avatar_size[1] * em; + row = 0; + } else + x[0] -= avatar_size[0] * em; + } pie_menu.render_to(render); diff --git a/src/game/text.cpp b/src/game/text.cpp index 28addc9..de1e804 100644 --- a/src/game/text.cpp +++ b/src/game/text.cpp @@ -21,10 +21,6 @@ namespace game::text { language_t language = LANG_ENGLISH; -static const char *soldier_names[] = { - "Kowalski", "Jackson", "Carter", "O'Neill", "Hammond", "Mitchell" -}; - static std::string get_english(index_t index) { switch (index) { @@ -61,9 +57,6 @@ static std::string get_english(index_t index) case UNIT_NAME_SPIDER: return "Spider"; - case UNIT_NAME_SOLDIER: - return soldier_names[rand() % COUNT(soldier_names)]; - case UNIT_NAME_NEST: return "Nest"; diff --git a/src/game/unit_soldier.cpp b/src/game/unit_soldier.cpp index 31def92..7985df6 100644 --- a/src/game/unit_soldier.cpp +++ b/src/game/unit_soldier.cpp @@ -19,6 +19,28 @@ along with Minitrem. If not, see . namespace game { +static const char *initials[] = { + "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", + "N", "O", "Ö", "P", "R", "S", "Ś", "T", "U", "Ü", "V", "W", "X", + "Z" +}; + +static std::string soldier_name(procgen::prng_t *prng) +{ + std::stringstream ss; + static const char *names[] = { + "Kowalski", "Jackson", "Carter", "O'Neill", "Hammond", + "Mitchell", "Hitler", "Stalin", "Wyspiański", "Bush", + "Washington" + }; + + ss << initials[prng->next() % (sizeof(initials) / sizeof(initials[0]))]; + ss << ". "; + ss << names[prng->next() % (sizeof(names) / sizeof(names[0]))]; + + return ss.str(); +} + unit_soldier_t::unit_soldier_t(game::state_t *game) : unit_t(game, UNIT_SOLDIER) { size[0] = v2f_t(-0.3f, +0.0f); @@ -28,7 +50,7 @@ unit_soldier_t::unit_soldier_t(game::state_t *game) : unit_t(game, UNIT_SOLDIER) cmodel.cflags = CF_BODY; move.cflags = CF_SOLID | CF_BODY | CF_WATER; - name = text::get(text::UNIT_NAME_SOLDIER); + name = soldier_name(&game->prng); wake(); friendly = true; -- cgit