gameplay score board
This commit is contained in:
@ -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)
|
||||
|
||||
Reference in New Issue
Block a user