feat(renderer): polish gameplay visuals — transport, starfield, sparkles, smooth piece motion

Add transport/transfer effect for NEXT → grid with cross-fade and preview swap
Integrate in-grid Starfield3D with magnet targeting tied to active piece
Spawn ambient sparkles and impact sparks (hard-drop crackle + burst on expiry)
Smooth horizontal/fall interpolation for active piece (configurable smooth scroll)
Refactor next panel / preview rendering and connector drawing
Tweak stats/score panel layout, progress bars and typography for compact view
Preserve safe alpha handling and restore renderer blend/scale state after overlays
This commit is contained in:
2025-12-08 20:43:51 +01:00
parent 815913b15b
commit 57eac01bcb
8 changed files with 293 additions and 48 deletions

View File

@ -25,20 +25,13 @@ float fitScale(FontAtlas& font, const char* text, float initialScale, float maxW
}
return scale;
}
}
} // anonymous namespace
namespace HelpOverlay {
void Render(
SDL_Renderer* renderer,
FontAtlas& font,
float logicalWidth,
float logicalHeight,
float offsetX,
float offsetY) {
if (!renderer) {
return;
}
void Render(SDL_Renderer* renderer, FontAtlas& font, float logicalWidth, float logicalHeight, float offsetX, float offsetY) {
if (!renderer) return;
const std::array<ShortcutEntry, 5> generalShortcuts{{
{"H", "Toggle this help overlay"},
@ -58,7 +51,7 @@ void Render(
{"DOWN", "Soft drop (faster fall)"},
{"SPACE", "Hard drop / instant lock"},
{"UP", "Rotate clockwise"},
{"X", "Rotate counter-clockwise"},
{"X", "Toggle rotation direction used by UP"},
{"P", "Pause or resume"},
{"ESC", "Open exit confirmation"}
}};
@ -72,7 +65,8 @@ void Render(
drawRect(renderer, boxX - 2.0f, boxY - 2.0f, boxW + 4.0f, boxH + 4.0f, {10, 12, 20, 255});
drawRect(renderer, boxX, boxY, boxW, boxH, {18, 22, 35, 240});
const float titleScale = 1.7f;
// Slightly smaller overall title to fit tighter layouts
const float titleScale = 1.45f;
font.draw(renderer, boxX + 28.0f, boxY + 24.0f, "HELP & SHORTCUTS", titleScale, {255, 220, 0, 255});
const float contentPadding = 32.0f;
@ -83,24 +77,43 @@ void Render(
const float footerHeight = 46.0f;
const float footerPadding = 18.0f;
const float sectionTitleScale = 1.1f;
const float comboScale = 0.92f;
const float descBaseScale = 0.8f;
const float comboSpacing = 22.0f;
const float sectionSpacing = 14.0f;
// Slightly reduced scales for a more compact popup
const float sectionTitleScale = 1.0f;
const float comboScale = 0.82f;
const float descBaseScale = 0.72f;
// Increase vertical spacing between combo label and description for readability
const float comboSpacing = 28.0f;
// Increase spacing between sections and after titles
const float sectionSpacing = 22.0f;
// Helper to draw text with extra letter-spacing (tracking) for section titles
auto drawSpaced = [&](float sx, float sy, const char* text, float scale, SDL_Color color, float extraPx) {
std::string stext(text);
float x = sx;
for (size_t i = 0; i < stext.size(); ++i) {
std::string ch(1, stext[i]);
font.draw(renderer, x, sy, ch.c_str(), scale, color);
int cw = 0, chh = 0;
font.measure(ch.c_str(), scale, cw, chh);
x += static_cast<float>(cw) + extraPx;
}
};
auto drawSection = [&](float startX, float& cursorY, const char* title, const auto& entries) {
font.draw(renderer, startX, cursorY, title, sectionTitleScale, {180, 200, 255, 255});
cursorY += 26.0f;
drawSpaced(startX, cursorY, title, sectionTitleScale, {180, 200, 255, 255}, 4.0f);
// extra gap after section title
cursorY += 34.0f;
for (const auto& entry : entries) {
font.draw(renderer, startX, cursorY, entry.combo, comboScale, {255, 255, 255, 255});
// larger spacing between combo label and description
cursorY += comboSpacing;
float descScale = fitScale(font, entry.description, descBaseScale, columnWidth - 10.0f);
font.draw(renderer, startX, cursorY, entry.description, descScale, {200, 210, 230, 255});
int descW = 0, descH = 0;
font.measure(entry.description, descScale, descW, descH);
cursorY += static_cast<float>(descH) + 10.0f;
// a bit more space after description row
cursorY += static_cast<float>(descH) + 14.0f;
}
cursorY += sectionSpacing;
};
@ -121,7 +134,7 @@ void Render(
SDL_SetRenderDrawColor(renderer, 90, 110, 170, 255);
SDL_RenderRect(renderer, &footerRect);
const char* closeLabel = "PRESS H TO CLOSE";
const char* closeLabel = "PRESS H OR ESC TO CLOSE";
float closeScale = fitScale(font, closeLabel, 1.0f, footerRect.w - footerPadding * 2.0f);
int closeW = 0, closeH = 0;
font.measure(closeLabel, closeScale, closeW, closeH);