tweak(hud): vides com a slots fixos (NUM_SLOTS = MAX_VIDES-1) que s'encenen/atenuen
This commit is contained in:
@@ -81,49 +81,57 @@ namespace Systems::InitHud {
|
||||
|
||||
namespace {
|
||||
|
||||
// Alçada de la icona de vida (px lògics) derivada de l'alçada del marcador.
|
||||
auto lifeIconHeight() -> float {
|
||||
return Defaults::Hud::Lives::ICON_HEIGHT_RATIO * Defaults::Zones::SCOREBOARD_BOTTOM_H;
|
||||
// Nombre de slots de vides: una nau menys que el màxim (la nau en joc
|
||||
// no es dibuixa; els slots són repuestos). Deriva de MAX_VIDES.
|
||||
constexpr int NUM_SLOTS = Defaults::Game::MAX_VIDES - 1;
|
||||
|
||||
// Pas d'un dígit (amplada + tracking, escalat): és la diferència entre
|
||||
// l'ample de dos caràcters i el d'un. Marca el ritme de tot el bloc.
|
||||
auto digitPitch(float scale, float spacing) -> float {
|
||||
return Graphics::VectorText::getTextWidth("00", scale, spacing) -
|
||||
Graphics::VectorText::getTextWidth("0", scale, spacing);
|
||||
}
|
||||
|
||||
// Nombre d'icones de vida a dibuixar (acotat a MAX_ICONS, mai negatiu).
|
||||
auto lifeIconCount(int lives) -> int {
|
||||
return std::clamp(lives, 0, Defaults::Hud::Lives::MAX_ICONS);
|
||||
// Mida d'un slot = alçada de la majúscula del dígit (mètrica del glif).
|
||||
auto slotSize(float scale) -> float {
|
||||
return Graphics::VectorText::getTextHeight(scale);
|
||||
}
|
||||
|
||||
// Ample del bloc de vides (0 si no hi ha vides). N icones = (N-1) passos
|
||||
// de separació + l'amplada d'una icona.
|
||||
auto livesBlockWidth(int lives) -> float {
|
||||
const int N = lifeIconCount(lives);
|
||||
if (N <= 0) {
|
||||
// Ample del bloc de slots: constant, independent de les vides. NUM_SLOTS
|
||||
// slots al pas del dígit (l'últim slot ocupa la seva pròpia mida).
|
||||
auto slotsBlockWidth(float scale, float spacing) -> float {
|
||||
if (NUM_SLOTS <= 0) {
|
||||
return 0.0F;
|
||||
}
|
||||
const float ICON_H = lifeIconHeight();
|
||||
const float STEP = ICON_H * Defaults::Hud::Lives::ICON_SPACING_FACTOR;
|
||||
return (static_cast<float>(N - 1) * STEP) + ICON_H;
|
||||
return (static_cast<float>(NUM_SLOTS - 1) * digitPitch(scale, spacing)) + slotSize(scale);
|
||||
}
|
||||
|
||||
// Dibuixa les vides com a icones de la nau (apuntant amunt, color del
|
||||
// jugador). El glow el posa el shader. x_left = vora esquerra del bloc.
|
||||
void drawLives(Rendering::Renderer* renderer,
|
||||
// Dibuixa els slots de vides com a naus en miniatura en posicions FIXES.
|
||||
// Slot amb vida disponible (repuesto) → color encès; slot buit → atenuat.
|
||||
// Repuestos = vides − 1 (la nau en joc no compta com a slot).
|
||||
void drawSlots(Rendering::Renderer* renderer,
|
||||
const std::shared_ptr<Graphics::Shape>& shape,
|
||||
int lives,
|
||||
SDL_Color color,
|
||||
SDL_Color bright,
|
||||
SDL_Color dim,
|
||||
float x_left,
|
||||
float center_y) {
|
||||
const int N = lifeIconCount(lives);
|
||||
if (N <= 0 || !shape) {
|
||||
float center_y,
|
||||
float scale,
|
||||
float spacing) {
|
||||
if (NUM_SLOTS <= 0 || !shape) {
|
||||
return;
|
||||
}
|
||||
const float ICON_H = lifeIconHeight();
|
||||
const float STEP = ICON_H * Defaults::Hud::Lives::ICON_SPACING_FACTOR;
|
||||
// Escala que ajusta el cercle circumscrit de la shape a l'alçada
|
||||
// objectiu (mida predictible independent del .shp).
|
||||
const float SIZE = slotSize(scale);
|
||||
const float PITCH = digitPitch(scale, spacing);
|
||||
// Escala que ajusta el cercle circumscrit de la shape a la mida del
|
||||
// slot (mida predictible independent del .shp).
|
||||
const float RADIUS = shape->getBoundingRadius();
|
||||
const float SCALE = (RADIUS > 0.001F) ? (ICON_H / (2.0F * RADIUS)) : 1.0F;
|
||||
for (int i = 0; i < N; i++) {
|
||||
const Vec2 POS = {.x = x_left + (ICON_H / 2.0F) + (static_cast<float>(i) * STEP), .y = center_y};
|
||||
Rendering::renderShape(renderer, shape, POS, 0.0F, SCALE, 1.0F, 1.0F, color);
|
||||
const float ICON_SCALE = (RADIUS > 0.001F) ? (SIZE / (2.0F * RADIUS)) : 1.0F;
|
||||
const int FILLED = std::clamp(lives - 1, 0, NUM_SLOTS);
|
||||
for (int i = 0; i < NUM_SLOTS; i++) {
|
||||
const SDL_Color COLOR = (i < FILLED) ? bright : dim;
|
||||
const Vec2 POS = {.x = x_left + (SIZE / 2.0F) + (static_cast<float>(i) * PITCH), .y = center_y};
|
||||
Rendering::renderShape(renderer, shape, POS, 0.0F, ICON_SCALE, 1.0F, 1.0F, COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,13 +184,14 @@ namespace Systems::InitHud {
|
||||
bool right_align) {
|
||||
const float TOP_Y = center_y - (Graphics::VectorText::getTextHeight(scale) / 2.0F);
|
||||
const float W_SCORE = Graphics::VectorText::getTextWidth(score, scale, spacing);
|
||||
const float W_LIVES = livesBlockWidth(lives);
|
||||
const float BLOCK_W = W_SCORE + Defaults::Hud::Layout::BLOCK_INNER_GAP + W_LIVES;
|
||||
const float GAP = digitPitch(scale, spacing); // separació punts↔slots = un pas de dígit
|
||||
const float W_LIVES = slotsBlockWidth(scale, spacing);
|
||||
const float BLOCK_W = W_SCORE + GAP + W_LIVES;
|
||||
|
||||
float x = right_align ? (anchor_x - BLOCK_W) : anchor_x;
|
||||
drawScore(text, score, bright, dim, x, TOP_Y, scale, spacing);
|
||||
x += W_SCORE + Defaults::Hud::Layout::BLOCK_INNER_GAP;
|
||||
drawLives(renderer, shape, lives, bright, x, center_y);
|
||||
x += W_SCORE + GAP;
|
||||
drawSlots(renderer, shape, lives, bright, dim, x, center_y, scale, spacing);
|
||||
}
|
||||
|
||||
// Pinta el nivell centrat: etiqueta "NIVELL" en verd atenuat i el número
|
||||
|
||||
Reference in New Issue
Block a user