tweak(hud): marcador en tres blocs ancorats (P1 esquerra, P2 dreta, nivell centrat) amb color per jugador
This commit is contained in:
@@ -78,53 +78,85 @@ namespace Systems::InitHud {
|
||||
}
|
||||
}
|
||||
|
||||
void drawScoreboardSegmentsAt(const Graphics::VectorText& text,
|
||||
const ScoreboardSegments& segments,
|
||||
const Vec2& center,
|
||||
namespace {
|
||||
|
||||
// Vides com a text (2 dígits) — provisional fins a migrar-les a icones.
|
||||
auto livesText(int lives) -> std::string {
|
||||
const std::string S = std::to_string(lives);
|
||||
return (lives < 10) ? "0" + S : S;
|
||||
}
|
||||
|
||||
// Pinta el bloc d'un jugador "punts vides" amb el seu color. Si
|
||||
// right_align, el bloc acaba a anchor_x (ancorat a la dreta); si no,
|
||||
// comença a anchor_x (ancorat a l'esquerra).
|
||||
void drawPlayerBlock(const Graphics::VectorText& text,
|
||||
const std::string& score,
|
||||
int lives,
|
||||
SDL_Color color,
|
||||
float anchor_x,
|
||||
float top_y,
|
||||
float scale,
|
||||
float spacing,
|
||||
bool right_align) {
|
||||
const std::string LIVES_STR = livesText(lives);
|
||||
const float W_SCORE = Graphics::VectorText::getTextWidth(score, scale, spacing);
|
||||
const float W_LIVES = Graphics::VectorText::getTextWidth(LIVES_STR, scale, spacing);
|
||||
const float BLOCK_W = W_SCORE + Defaults::Hud::Layout::BLOCK_INNER_GAP + W_LIVES;
|
||||
|
||||
float x = right_align ? (anchor_x - BLOCK_W) : anchor_x;
|
||||
text.render(score, {.x = x, .y = top_y}, scale, spacing, 1.0F, color);
|
||||
x += W_SCORE + Defaults::Hud::Layout::BLOCK_INNER_GAP;
|
||||
text.render(LIVES_STR, {.x = x, .y = top_y}, scale, spacing, 1.0F, color);
|
||||
}
|
||||
|
||||
// Pinta el nivell ("NIVELL" + número) centrat a la pantalla.
|
||||
void drawLevel(const Graphics::VectorText& text,
|
||||
const std::string& label,
|
||||
const std::string& value,
|
||||
float top_y,
|
||||
float scale,
|
||||
float spacing) {
|
||||
const float W_LABEL = Graphics::VectorText::getTextWidth(label, scale, spacing);
|
||||
const float W_VALUE = Graphics::VectorText::getTextWidth(value, scale, spacing);
|
||||
const float CX = Defaults::Game::WIDTH / 2.0F;
|
||||
float x = CX - ((W_LABEL + W_VALUE) / 2.0F);
|
||||
text.render(label, {.x = x, .y = top_y}, scale, spacing, 1.0F, Defaults::Hud::Colors::LEVEL_BRIGHT);
|
||||
x += W_LABEL;
|
||||
text.render(value, {.x = x, .y = top_y}, scale, spacing, 1.0F, Defaults::Hud::Colors::LEVEL_BRIGHT);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void drawScoreboardAt(const Graphics::VectorText& text,
|
||||
const ScoreboardData& data,
|
||||
float center_y,
|
||||
float scale,
|
||||
float spacing) {
|
||||
// Separadors entre segments (preservant el layout legacy: " ", " ", " ", " ").
|
||||
const float W_SEP1 = Graphics::VectorText::getTextWidth(" ", scale, spacing);
|
||||
const float W_SEP2 = Graphics::VectorText::getTextWidth(" ", scale, spacing);
|
||||
// Els blocs s'ancoren a les verticals del PLAYAREA (sota el marc).
|
||||
const SDL_FRect& play = Defaults::Zones::PLAYAREA;
|
||||
const float LEFT = play.x;
|
||||
const float RIGHT = play.x + play.w;
|
||||
const float TOP_Y = center_y - (Graphics::VectorText::getTextHeight(scale) / 2.0F);
|
||||
|
||||
const float W_SP1 = Graphics::VectorText::getTextWidth(segments.score_p1, scale, spacing);
|
||||
const float W_LP1 = Graphics::VectorText::getTextWidth(segments.lives_p1, scale, spacing);
|
||||
const float W_LV = Graphics::VectorText::getTextWidth(segments.level, scale, spacing);
|
||||
const float W_SP2 = Graphics::VectorText::getTextWidth(segments.score_p2, scale, spacing);
|
||||
const float W_LP2 = Graphics::VectorText::getTextWidth(segments.lives_p2, scale, spacing);
|
||||
|
||||
const float TOTAL = W_SP1 + W_SEP1 + W_LP1 + W_SEP2 + W_LV + W_SEP2 + W_SP2 + W_SEP1 + W_LP2;
|
||||
|
||||
const float HEIGHT = Graphics::VectorText::getTextHeight(scale);
|
||||
const float TOP_Y = center.y - (HEIGHT / 2.0F);
|
||||
float x = center.x - (TOTAL / 2.0F);
|
||||
|
||||
text.render(segments.score_p1, {.x = x, .y = TOP_Y}, scale, spacing, 1.0F, Defaults::Hud::Colors::SCORE_P1);
|
||||
x += W_SP1 + W_SEP1;
|
||||
text.render(segments.lives_p1, {.x = x, .y = TOP_Y}, scale, spacing, 1.0F, Defaults::Hud::Colors::LIVES);
|
||||
x += W_LP1 + W_SEP2;
|
||||
text.render(segments.level, {.x = x, .y = TOP_Y}, scale, spacing, 1.0F, Defaults::Hud::Colors::LEVEL);
|
||||
x += W_LV + W_SEP2;
|
||||
text.render(segments.score_p2, {.x = x, .y = TOP_Y}, scale, spacing, 1.0F, Defaults::Hud::Colors::SCORE_P2);
|
||||
x += W_SP2 + W_SEP1;
|
||||
text.render(segments.lives_p2, {.x = x, .y = TOP_Y}, scale, spacing, 1.0F, Defaults::Hud::Colors::LIVES);
|
||||
drawPlayerBlock(text, data.score_p1, data.lives_p1, Defaults::Hud::Colors::P1_BRIGHT, LEFT, TOP_Y, scale, spacing, false);
|
||||
drawPlayerBlock(text, data.score_p2, data.lives_p2, Defaults::Hud::Colors::P2_BRIGHT, RIGHT, TOP_Y, scale, spacing, true);
|
||||
drawLevel(text, data.level_label, data.level_value, TOP_Y, scale, spacing);
|
||||
}
|
||||
|
||||
void drawScoreboardAnimated(const Graphics::VectorText& text,
|
||||
const ScoreboardSegments& segments,
|
||||
const ScoreboardData& data,
|
||||
float progress) {
|
||||
const float EASED = Easing::easeOutQuad(progress);
|
||||
|
||||
constexpr float SCALE = Defaults::Hud::SCOREBOARD_TEXT_SCALE;
|
||||
constexpr float SPACING = Defaults::Hud::SCOREBOARD_TEXT_SPACING;
|
||||
const SDL_FRect& scoreboard_zone = Defaults::Zones::SCOREBOARD;
|
||||
const float CENTRE_X = scoreboard_zone.w / 2.0F;
|
||||
const float Y_FINAL = scoreboard_zone.y + (scoreboard_zone.h / 2.0F);
|
||||
// Posición inicial: fuera de la pantalla por debajo.
|
||||
const auto Y_INI = static_cast<float>(Defaults::Game::HEIGHT);
|
||||
const float Y_ANIM = Y_INI + ((Y_FINAL - Y_INI) * EASED);
|
||||
|
||||
drawScoreboardSegmentsAt(text, segments, {.x = CENTRE_X, .y = Y_ANIM}, SCALE, SPACING);
|
||||
drawScoreboardAt(text, data, Y_ANIM, SCALE, SPACING);
|
||||
}
|
||||
|
||||
} // namespace Systems::InitHud
|
||||
|
||||
Reference in New Issue
Block a user