new next block

This commit is contained in:
2025-12-07 19:02:03 +01:00
parent a74d7135e6
commit 9d989ab395
9 changed files with 68 additions and 29 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

View File

@ -1133,6 +1133,7 @@ void ApplicationManager::setupStateHandlers() {
m_stateContext.blocksTex, m_stateContext.blocksTex,
m_stateContext.statisticsPanelTex, m_stateContext.statisticsPanelTex,
m_stateContext.scorePanelTex, m_stateContext.scorePanelTex,
m_stateContext.nextPanelTex,
LOGICAL_W, LOGICAL_W,
LOGICAL_H, LOGICAL_H,
logicalScale, logicalScale,

View File

@ -122,6 +122,9 @@ void GameRenderer::renderPlayingState(
FontAtlas* pixelFont, FontAtlas* pixelFont,
LineEffect* lineEffect, LineEffect* lineEffect,
SDL_Texture* blocksTex, SDL_Texture* blocksTex,
SDL_Texture* statisticsPanelTex,
SDL_Texture* scorePanelTex,
SDL_Texture* nextPanelTex,
float logicalW, float logicalW,
float logicalH, float logicalH,
float logicalScale, float logicalScale,
@ -242,8 +245,16 @@ void GameRenderer::renderPlayingState(
drawRectWithOffset(statsX - contentOffsetX, statsY - contentOffsetY, statsW, statsH, {30, 35, 50, 255}); drawRectWithOffset(statsX - contentOffsetX, statsY - contentOffsetY, statsW, statsH, {30, 35, 50, 255});
// Draw next piece preview panel border // Draw next piece preview panel border
drawRectWithOffset(nextX - 3 - contentOffsetX, nextY - 3 - contentOffsetY, nextW + 6, nextH + 6, {100, 120, 200, 255}); // If a NEXT panel texture was provided, draw it instead of the custom
drawRectWithOffset(nextX - contentOffsetX, nextY - contentOffsetY, nextW, nextH, {30, 35, 50, 255}); // background/outline. The texture will be scaled to fit the panel area.
if (nextPanelTex) {
SDL_FRect dst{ nextX - contentOffsetX, nextY - contentOffsetY, nextW, nextH };
SDL_SetTextureBlendMode(nextPanelTex, SDL_BLENDMODE_BLEND);
SDL_RenderTexture(renderer, nextPanelTex, nullptr, &dst);
} else {
drawRectWithOffset(nextX - 3 - contentOffsetX, nextY - 3 - contentOffsetY, nextW + 6, nextH + 6, {100, 120, 200, 255});
drawRectWithOffset(nextX - contentOffsetX, nextY - contentOffsetY, nextW, nextH, {30, 35, 50, 255});
}
// Draw the game board // Draw the game board
const auto &board = game->boardRef(); const auto &board = game->boardRef();
@ -306,7 +317,8 @@ void GameRenderer::renderPlayingState(
// Draw next piece preview // Draw next piece preview
pixelFont->draw(renderer, nextX + 10, nextY - 20, "NEXT", 1.0f, {255, 220, 0, 255}); pixelFont->draw(renderer, nextX + 10, nextY - 20, "NEXT", 1.0f, {255, 220, 0, 255});
if (game->next().type < PIECE_COUNT) { if (game->next().type < PIECE_COUNT) {
drawSmallPiece(renderer, blocksTex, static_cast<PieceType>(game->next().type), nextX + 10, nextY + 10, finalBlockSize * 0.6f); // Nudge preview slightly upward to remove thin bottom artifact
drawSmallPiece(renderer, blocksTex, static_cast<PieceType>(game->next().type), nextX + 10, nextY + 5, finalBlockSize * 0.6f);
} }
// Draw block statistics (left panel) // Draw block statistics (left panel)

View File

@ -20,8 +20,11 @@ public:
Game* game, Game* game,
FontAtlas* pixelFont, FontAtlas* pixelFont,
LineEffect* lineEffect, LineEffect* lineEffect,
SDL_Texture* blocksTex, SDL_Texture* blocksTex,
float logicalW, SDL_Texture* statisticsPanelTex,
SDL_Texture* scorePanelTex,
SDL_Texture* nextPanelTex,
float logicalW,
float logicalH, float logicalH,
float logicalScale, float logicalScale,
float winW, float winW,

View File

@ -152,7 +152,8 @@ void GameRenderer::startTransportEffectForGame(Game* game, SDL_Texture* blocksTe
float rel = startX - gridOriginX; float rel = startX - gridOriginX;
float nearestTile = std::round(rel / finalBlockSize); float nearestTile = std::round(rel / finalBlockSize);
startX = gridOriginX + nearestTile * finalBlockSize; startX = gridOriginX + nearestTile * finalBlockSize;
startY = std::round(startY); // Raise preview slightly to remove a thin line artifact under the panel
startY = std::round(startY) - 5.0f;
// Target is the current piece's grid position // Target is the current piece's grid position
float targetX = gridX + piece.x * finalBlockSize; float targetX = gridX + piece.x * finalBlockSize;
@ -180,7 +181,7 @@ void GameRenderer::startTransportEffectForGame(Game* game, SDL_Texture* blocksTe
float rel2 = nextPreviewX - gridOriginX2; float rel2 = nextPreviewX - gridOriginX2;
float nearestTile2 = std::round(rel2 / finalBlockSize); float nearestTile2 = std::round(rel2 / finalBlockSize);
nextPreviewX = gridOriginX2 + nearestTile2 * finalBlockSize; nextPreviewX = gridOriginX2 + nearestTile2 * finalBlockSize;
nextPreviewY = std::round(nextPreviewY); nextPreviewY = std::round(nextPreviewY) - 5.0f;
// Initialize transport state to perform fades: preview fade-out -> grid fade-in -> next preview fade-in // Initialize transport state to perform fades: preview fade-out -> grid fade-in -> next preview fade-in
s_transport.active = true; s_transport.active = true;
@ -396,6 +397,7 @@ void GameRenderer::renderNextPanel(
SDL_Renderer* renderer, SDL_Renderer* renderer,
FontAtlas* pixelFont, FontAtlas* pixelFont,
SDL_Texture* blocksTex, SDL_Texture* blocksTex,
SDL_Texture* nextPanelTex,
const Game::Piece& nextPiece, const Game::Piece& nextPiece,
float panelX, float panelX,
float panelY, float panelY,
@ -412,27 +414,37 @@ void GameRenderer::renderNextPanel(
const SDL_Color bayOutline{25, 62, 86, 220}; const SDL_Color bayOutline{25, 62, 86, 220};
const SDL_Color labelColor{255, 220, 0, 255}; const SDL_Color labelColor{255, 220, 0, 255};
SDL_FRect bayRect{panelX, panelY, panelW, panelH}; // If an external NEXT panel texture is provided, draw it scaled into
SDL_SetRenderDrawColor(renderer, bayColor.r, bayColor.g, bayColor.b, bayColor.a); // the panel rectangle and skip the custom background/frame drawing.
SDL_RenderFillRect(renderer, &bayRect); if (nextPanelTex) {
SDL_FRect dst{panelX, panelY, panelW, panelH};
SDL_RenderTexture(renderer, nextPanelTex, nullptr, &dst);
// Draw the panel label over the texture — user requested visible label
const float labelPad = tileSize * 0.25f;
pixelFont->draw(renderer, panelX + labelPad, panelY + labelPad * 0.5f, "NEXT", 0.9f, labelColor);
} else {
SDL_FRect bayRect{panelX, panelY, panelW, panelH};
SDL_SetRenderDrawColor(renderer, bayColor.r, bayColor.g, bayColor.b, bayColor.a);
SDL_RenderFillRect(renderer, &bayRect);
SDL_FRect thinOutline{panelX - 1.0f, panelY - 1.0f, panelW + 2.0f, panelH + 2.0f}; SDL_FRect thinOutline{panelX - 1.0f, panelY - 1.0f, panelW + 2.0f, panelH + 2.0f};
auto drawOutlineNoBottom = [&](const SDL_FRect& rect, SDL_Color color) { auto drawOutlineNoBottom = [&](const SDL_FRect& rect, SDL_Color color) {
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a); SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
const float left = rect.x; const float left = rect.x;
const float top = rect.y; const float top = rect.y;
const float right = rect.x + rect.w; const float right = rect.x + rect.w;
const float bottom = rect.y + rect.h; const float bottom = rect.y + rect.h;
SDL_RenderLine(renderer, left, top, right, top); // top edge SDL_RenderLine(renderer, left, top, right, top); // top edge
SDL_RenderLine(renderer, left, top, left, bottom); // left edge SDL_RenderLine(renderer, left, top, left, bottom); // left edge
SDL_RenderLine(renderer, right, top, right, bottom); // right edge SDL_RenderLine(renderer, right, top, right, bottom); // right edge
}; };
drawOutlineNoBottom(thinOutline, gridBorderColor); //drawOutlineNoBottom(thinOutline, gridBorderColor);
drawOutlineNoBottom(bayRect, bayOutline); //drawOutlineNoBottom(bayRect, bayOutline);
const float labelPad = tileSize * 0.25f; const float labelPad = tileSize * 0.25f;
pixelFont->draw(renderer, panelX + labelPad, panelY + labelPad * 0.5f, "NEXT", 0.9f, labelColor); pixelFont->draw(renderer, panelX + labelPad, panelY + labelPad * 0.5f, "NEXT", 0.9f, labelColor);
}
if (nextPiece.type >= PIECE_COUNT) { if (nextPiece.type >= PIECE_COUNT) {
return; return;
@ -478,8 +490,8 @@ void GameRenderer::renderNextPanel(
float rel = startX - gridOriginX; float rel = startX - gridOriginX;
float nearestTile = std::round(rel / tileSize); float nearestTile = std::round(rel / tileSize);
startX = gridOriginX + nearestTile * tileSize; startX = gridOriginX + nearestTile * tileSize;
// Round Y to pixel to avoid subpixel artifacts // Round Y to pixel to avoid subpixel artifacts and nudge upward slightly
startY = std::round(startY); startY = std::round(startY) - 5.0f;
// If a transfer fade is active, the preview cells will be drawn by the // If a transfer fade is active, the preview cells will be drawn by the
// transport effect (with fade). Skip drawing the normal preview in that case. // transport effect (with fade). Skip drawing the normal preview in that case.
@ -505,6 +517,7 @@ void GameRenderer::renderPlayingState(
SDL_Texture* blocksTex, SDL_Texture* blocksTex,
SDL_Texture* statisticsPanelTex, SDL_Texture* statisticsPanelTex,
SDL_Texture* scorePanelTex, SDL_Texture* scorePanelTex,
SDL_Texture* nextPanelTex,
float logicalW, float logicalW,
float logicalH, float logicalH,
float logicalScale, float logicalScale,
@ -821,7 +834,7 @@ void GameRenderer::renderPlayingState(
SDL_SetRenderDrawBlendMode(renderer, oldBlend); SDL_SetRenderDrawBlendMode(renderer, oldBlend);
renderNextPanel(renderer, pixelFont, blocksTex, game->next(), NEXT_PANEL_X, NEXT_PANEL_Y, NEXT_PANEL_WIDTH, NEXT_PANEL_HEIGHT, finalBlockSize); renderNextPanel(renderer, pixelFont, blocksTex, nextPanelTex, game->next(), NEXT_PANEL_X, NEXT_PANEL_Y, NEXT_PANEL_WIDTH, NEXT_PANEL_HEIGHT, finalBlockSize);
// Draw a small filled connector to visually merge NEXT panel and grid border // Draw a small filled connector to visually merge NEXT panel and grid border
SDL_SetRenderDrawColor(renderer, 60, 80, 160, 255); // same as grid border SDL_SetRenderDrawColor(renderer, 60, 80, 160, 255); // same as grid border

View File

@ -23,6 +23,7 @@ public:
SDL_Texture* blocksTex, SDL_Texture* blocksTex,
SDL_Texture* statisticsPanelTex, SDL_Texture* statisticsPanelTex,
SDL_Texture* scorePanelTex, SDL_Texture* scorePanelTex,
SDL_Texture* nextPanelTex,
float logicalW, float logicalW,
float logicalH, float logicalH,
float logicalScale, float logicalScale,
@ -69,7 +70,7 @@ private:
static void drawBlockTexture(SDL_Renderer* renderer, SDL_Texture* blocksTex, float x, float y, float size, int blockType); static void drawBlockTexture(SDL_Renderer* renderer, SDL_Texture* blocksTex, float x, float y, float size, int blockType);
static void drawPiece(SDL_Renderer* renderer, SDL_Texture* blocksTex, const Game::Piece& piece, float ox, float oy, float tileSize, bool isGhost = false, float pixelOffsetX = 0.0f, float pixelOffsetY = 0.0f); static void drawPiece(SDL_Renderer* renderer, SDL_Texture* blocksTex, const Game::Piece& piece, float ox, float oy, float tileSize, bool isGhost = false, float pixelOffsetX = 0.0f, float pixelOffsetY = 0.0f);
static void drawSmallPiece(SDL_Renderer* renderer, SDL_Texture* blocksTex, PieceType pieceType, float x, float y, float tileSize); static void drawSmallPiece(SDL_Renderer* renderer, SDL_Texture* blocksTex, PieceType pieceType, float x, float y, float tileSize);
static void renderNextPanel(SDL_Renderer* renderer, FontAtlas* pixelFont, SDL_Texture* blocksTex, const Game::Piece& nextPiece, float panelX, float panelY, float panelW, float panelH, float tileSize); static void renderNextPanel(SDL_Renderer* renderer, FontAtlas* pixelFont, SDL_Texture* blocksTex, SDL_Texture* nextPanelTex, const Game::Piece& nextPiece, float panelX, float panelY, float panelW, float panelH, float tileSize);
// Helper function for drawing rectangles // Helper function for drawing rectangles
static void drawRect(SDL_Renderer* renderer, float x, float y, float w, float h, SDL_Color c); static void drawRect(SDL_Renderer* renderer, float x, float y, float w, float h, SDL_Color c);

View File

@ -710,6 +710,10 @@ int main(int, char **)
if (statisticsPanelTex) { if (statisticsPanelTex) {
SDL_SetTextureBlendMode(statisticsPanelTex, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(statisticsPanelTex, SDL_BLENDMODE_BLEND);
} }
SDL_Texture* nextPanelTex = loadTextureFromImage(renderer, "assets/images/next_panel.png");
if (nextPanelTex) {
SDL_SetTextureBlendMode(nextPanelTex, SDL_BLENDMODE_BLEND);
}
Game game(startLevelSelection); Game game(startLevelSelection);
// Apply global gravity speed multiplier from config // Apply global gravity speed multiplier from config
@ -859,6 +863,7 @@ int main(int, char **)
ctx.blocksTex = blocksTex; ctx.blocksTex = blocksTex;
ctx.scorePanelTex = scorePanelTex; ctx.scorePanelTex = scorePanelTex;
ctx.statisticsPanelTex = statisticsPanelTex; ctx.statisticsPanelTex = statisticsPanelTex;
ctx.nextPanelTex = nextPanelTex;
ctx.mainScreenTex = mainScreenTex; ctx.mainScreenTex = mainScreenTex;
ctx.mainScreenW = mainScreenW; ctx.mainScreenW = mainScreenW;
ctx.mainScreenH = mainScreenH; ctx.mainScreenH = mainScreenH;
@ -1760,6 +1765,7 @@ int main(int, char **)
blocksTex, blocksTex,
ctx.statisticsPanelTex, ctx.statisticsPanelTex,
scorePanelTex, scorePanelTex,
nextPanelTex,
(float)LOGICAL_W, (float)LOGICAL_W,
(float)LOGICAL_H, (float)LOGICAL_H,
logicalScale, logicalScale,

View File

@ -223,6 +223,7 @@ void PlayingState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect l
ctx.blocksTex, ctx.blocksTex,
ctx.statisticsPanelTex, ctx.statisticsPanelTex,
ctx.scorePanelTex, ctx.scorePanelTex,
ctx.nextPanelTex,
1200.0f, // LOGICAL_W 1200.0f, // LOGICAL_W
1000.0f, // LOGICAL_H 1000.0f, // LOGICAL_H
logicalScale, logicalScale,
@ -309,6 +310,7 @@ void PlayingState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect l
ctx.blocksTex, ctx.blocksTex,
ctx.statisticsPanelTex, ctx.statisticsPanelTex,
ctx.scorePanelTex, ctx.scorePanelTex,
ctx.nextPanelTex,
1200.0f, 1200.0f,
1000.0f, 1000.0f,
logicalScale, logicalScale,

View File

@ -42,6 +42,7 @@ struct StateContext {
SDL_Texture* blocksTex = nullptr; SDL_Texture* blocksTex = nullptr;
SDL_Texture* scorePanelTex = nullptr; SDL_Texture* scorePanelTex = nullptr;
SDL_Texture* statisticsPanelTex = nullptr; SDL_Texture* statisticsPanelTex = nullptr;
SDL_Texture* nextPanelTex = nullptr;
SDL_Texture* mainScreenTex = nullptr; SDL_Texture* mainScreenTex = nullptr;
int mainScreenW = 0; int mainScreenW = 0;
int mainScreenH = 0; int mainScreenH = 0;