summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/units/soldier/avatar_0.pngbin0 -> 12533 bytes
-rw-r--r--src/common.hpp1
-rw-r--r--src/game/assets.cpp1
-rw-r--r--src/game/game.hpp2
-rw-r--r--src/game/interface.cpp96
-rw-r--r--src/game/text.cpp7
-rw-r--r--src/game/unit_soldier.cpp24
-rw-r--r--src/render.cpp5
8 files changed, 127 insertions, 9 deletions
diff --git a/assets/units/soldier/avatar_0.png b/assets/units/soldier/avatar_0.png
new file mode 100644
index 0000000..bcb11cf
--- /dev/null
+++ b/assets/units/soldier/avatar_0.png
Binary files differ
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;