gameplay score board

This commit is contained in:
2025-12-06 21:07:17 +01:00
parent 1355ce49fe
commit ec9eb45cc3
14 changed files with 123 additions and 45 deletions

View File

@ -7,6 +7,7 @@
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <limits>
#include <random>
#include <vector>
#include "../../core/Settings.h"
@ -147,6 +148,7 @@ void GameRenderer::renderPlayingState(
FontAtlas* pixelFont,
LineEffect* lineEffect,
SDL_Texture* blocksTex,
SDL_Texture* scorePanelTex,
float logicalW,
float logicalH,
float logicalScale,
@ -212,7 +214,6 @@ void GameRenderer::renderPlayingState(
const float statsX = layoutStartX + contentOffsetX;
const float gridX = layoutStartX + PANEL_WIDTH + PANEL_SPACING + contentOffsetX;
const float scoreX = layoutStartX + PANEL_WIDTH + PANEL_SPACING + GRID_W + PANEL_SPACING + contentOffsetX;
const float gridY = contentStartY + NEXT_PIECE_HEIGHT + contentOffsetY;
const float statsY = gridY;
@ -241,9 +242,6 @@ void GameRenderer::renderPlayingState(
SDL_FRect lbg{statsX - 16, gridY - 10, statsW + 32, GRID_H + 20};
SDL_RenderFillRect(renderer, &lbg);
SDL_FRect rbg{scoreX - 16, gridY - 16, statsW + 32, GRID_H + 32};
SDL_RenderFillRect(renderer, &rbg);
// Draw grid lines
SDL_SetRenderDrawColor(renderer, 40, 45, 60, 255);
for (int x = 1; x < Game::COLS; ++x) {
@ -650,22 +648,27 @@ void GameRenderer::renderPlayingState(
const float contentPad = 36.0f;
float scoreContentH = (contentBottomOffset - contentTopOffset) + contentPad;
float baseY = gridY + (GRID_H - scoreContentH) * 0.5f;
pixelFont->draw(renderer, scoreX, baseY + 0, "SCORE", 1.0f, {255, 220, 0, 255});
const float statsPanelGap = 12.0f;
const float statsPanelLeft = gridX + GRID_W + statsPanelGap;
const float statsPanelPadLeft = 40.0f;
const float statsPanelPadRight = 34.0f;
const float statsPanelPadY = 28.0f;
const float statsTextX = statsPanelLeft + statsPanelPadLeft;
const SDL_Color labelColor{255, 220, 0, 255};
const SDL_Color valueColor{255, 255, 255, 255};
const SDL_Color nextColor{80, 255, 120, 255};
char scoreStr[32];
snprintf(scoreStr, sizeof(scoreStr), "%d", game->score());
pixelFont->draw(renderer, scoreX, baseY + 25, scoreStr, 0.9f, {255, 255, 255, 255});
pixelFont->draw(renderer, scoreX, baseY + 70, "LINES", 1.0f, {255, 220, 0, 255});
char linesStr[16];
snprintf(linesStr, sizeof(linesStr), "%03d", game->lines());
pixelFont->draw(renderer, scoreX, baseY + 95, linesStr, 0.9f, {255, 255, 255, 255});
pixelFont->draw(renderer, scoreX, baseY + 140, "LEVEL", 1.0f, {255, 220, 0, 255});
char levelStr[16];
snprintf(levelStr, sizeof(levelStr), "%02d", game->level());
pixelFont->draw(renderer, scoreX, baseY + 165, levelStr, 0.9f, {255, 255, 255, 255});
// Next level progress
int startLv = game->startLevelBase();
int firstThreshold = (startLv + 1) * 10;
@ -678,46 +681,98 @@ void GameRenderer::renderPlayingState(
nextThreshold = firstThreshold + ((blocksPast / 10) + 1) * 10;
}
int linesForNext = std::max(0, nextThreshold - linesDone);
pixelFont->draw(renderer, scoreX, baseY + 200, "NEXT LVL", 1.0f, {255, 220, 0, 255});
char nextStr[32];
snprintf(nextStr, sizeof(nextStr), "%d LINES", linesForNext);
pixelFont->draw(renderer, scoreX, baseY + 225, nextStr, 0.9f, {80, 255, 120, 255});
// Time display
pixelFont->draw(renderer, scoreX, baseY + 265, "TIME", 1.0f, {255, 220, 0, 255});
int totalSecs = static_cast<int>(game->elapsed());
int mins = totalSecs / 60;
int secs = totalSecs % 60;
char timeStr[16];
snprintf(timeStr, sizeof(timeStr), "%02d:%02d", mins, secs);
pixelFont->draw(renderer, scoreX, baseY + 290, timeStr, 0.9f, {255, 255, 255, 255});
// Debug: Gravity timing info
if (Settings::instance().isDebugEnabled()) {
pixelFont->draw(renderer, scoreX, baseY + 330, "GRAVITY", 0.8f, {150, 150, 150, 255});
const bool debugEnabled = Settings::instance().isDebugEnabled();
char gravityStr[32] = "";
char dropStr[32] = "";
char gravityHud[64] = "";
SDL_Color dropColor{100, 255, 100, 255};
if (debugEnabled) {
double gravityMs = game->getGravityMs();
double fallAcc = game->getFallAccumulator();
// Calculate effective gravity (accounting for soft drop)
bool isSoftDrop = game->isSoftDropping();
double effectiveGravityMs = isSoftDrop ? (gravityMs / 2.0) : gravityMs;
double timeUntilDrop = std::max(0.0, effectiveGravityMs - fallAcc);
char gravityStr[32];
snprintf(gravityStr, sizeof(gravityStr), "%.0f ms%s", gravityMs, isSoftDrop ? " (SD)" : "");
pixelFont->draw(renderer, scoreX, baseY + 350, gravityStr, 0.7f, {180, 180, 180, 255});
char dropStr[32];
snprintf(dropStr, sizeof(dropStr), "Drop: %.0f", timeUntilDrop);
SDL_Color dropColor = isSoftDrop ? SDL_Color{255, 200, 100, 255} : SDL_Color{100, 255, 100, 255};
pixelFont->draw(renderer, scoreX, baseY + 370, dropStr, 0.7f, dropColor);
// Gravity HUD (Top)
char gms[64];
double gms_val = game->getGravityMs();
double gfps = gms_val > 0.0 ? (1000.0 / gms_val) : 0.0;
snprintf(gms, sizeof(gms), "GRAV: %.0f ms (%.2f fps)", gms_val, gfps);
pixelFont->draw(renderer, logicalW - 260, 10, gms, 0.9f, {200, 200, 220, 255});
dropColor = isSoftDrop ? SDL_Color{255, 200, 100, 255} : SDL_Color{100, 255, 100, 255};
double gfps = gravityMs > 0.0 ? (1000.0 / gravityMs) : 0.0;
snprintf(gravityHud, sizeof(gravityHud), "GRAV: %.0f ms (%.2f fps)", gravityMs, gfps);
}
struct StatLine {
const char* text;
float offsetY;
float scale;
SDL_Color color;
};
std::vector<StatLine> statLines;
statLines.reserve(debugEnabled ? 13 : 10);
statLines.push_back({"SCORE", 0.0f, 1.0f, labelColor});
statLines.push_back({scoreStr, 25.0f, 0.9f, valueColor});
statLines.push_back({"LINES", 70.0f, 1.0f, labelColor});
statLines.push_back({linesStr, 95.0f, 0.9f, valueColor});
statLines.push_back({"LEVEL", 140.0f, 1.0f, labelColor});
statLines.push_back({levelStr, 165.0f, 0.9f, valueColor});
statLines.push_back({"NEXT LVL", 200.0f, 1.0f, labelColor});
statLines.push_back({nextStr, 225.0f, 0.9f, nextColor});
statLines.push_back({"TIME", 265.0f, 1.0f, labelColor});
statLines.push_back({timeStr, 290.0f, 0.9f, valueColor});
if (debugEnabled) {
SDL_Color debugLabelColor{150, 150, 150, 255};
SDL_Color debugValueColor{180, 180, 180, 255};
statLines.push_back({"GRAVITY", 330.0f, 0.8f, debugLabelColor});
statLines.push_back({gravityStr, 350.0f, 0.7f, debugValueColor});
statLines.push_back({dropStr, 370.0f, 0.7f, dropColor});
}
if (!statLines.empty()) {
float statsContentTop = std::numeric_limits<float>::max();
float statsContentBottom = std::numeric_limits<float>::lowest();
float statsContentMaxWidth = 0.0f;
for (const auto& line : statLines) {
int textW = 0;
int textH = 0;
pixelFont->measure(line.text, line.scale, textW, textH);
float y = baseY + line.offsetY;
statsContentTop = std::min(statsContentTop, y);
statsContentBottom = std::max(statsContentBottom, y + textH);
statsContentMaxWidth = std::max(statsContentMaxWidth, static_cast<float>(textW));
}
float statsPanelWidth = statsPanelPadLeft + statsContentMaxWidth + statsPanelPadRight;
float statsPanelHeight = (statsContentBottom - statsContentTop) + statsPanelPadY * 2.0f;
float statsPanelTop = statsContentTop - statsPanelPadY;
SDL_FRect statsBg{statsPanelLeft, statsPanelTop, statsPanelWidth, statsPanelHeight};
if (scorePanelTex) {
SDL_RenderTexture(renderer, scorePanelTex, nullptr, &statsBg);
} else {
SDL_SetRenderDrawColor(renderer, 12, 18, 32, 205);
SDL_RenderFillRect(renderer, &statsBg);
}
}
for (const auto& line : statLines) {
pixelFont->draw(renderer, statsTextX, baseY + line.offsetY, line.text, line.scale, line.color);
}
if (debugEnabled) {
pixelFont->draw(renderer, logicalW - 260, 10, gravityHud, 0.9f, {200, 200, 220, 255});
}
// Hold piece (if implemented)