diff options
-rw-r--r-- | assets/units/soldier/avatar_0.png | bin | 0 -> 12533 bytes | |||
-rw-r--r-- | src/common.hpp | 1 | ||||
-rw-r--r-- | src/game/assets.cpp | 1 | ||||
-rw-r--r-- | src/game/game.hpp | 2 | ||||
-rw-r--r-- | src/game/interface.cpp | 96 | ||||
-rw-r--r-- | src/game/text.cpp | 7 | ||||
-rw-r--r-- | src/game/unit_soldier.cpp | 24 | ||||
-rw-r--r-- | src/render.cpp | 5 |
8 files changed, 127 insertions, 9 deletions
diff --git a/assets/units/soldier/avatar_0.png b/assets/units/soldier/avatar_0.png Binary files differnew file mode 100644 index 0000000..bcb11cf --- /dev/null +++ b/assets/units/soldier/avatar_0.png diff --git a/src/common.hpp b/src/common.hpp index 4ce22bb..a3ba6db 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -438,6 +438,7 @@ namespace render { typedef enum { ALIGN_LEFT_TOP, + ALIGN_LEFT_BOTTOM, ALIGN_CENTER_BOTTOM, ALIGN_RIGHT_BOTTOM } text_align_t; 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 <http://www.gnu.org/licenses/>. 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; diff --git a/src/render.cpp b/src/render.cpp index 69e2d6c..5a03e94 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -382,6 +382,11 @@ void state_t::render_text(v2f_t x, float height, std::string str, offset = v2f_t(0, 0); break; + case ALIGN_LEFT_BOTTOM: + offset[0] = 0.0f; + offset[1] = -rect.height; + break; + case ALIGN_CENTER_BOTTOM: offset[0] = -rect.width / 2; offset[1] = -rect.height; |