fixed level selector

This commit is contained in:
2025-08-16 21:58:19 +02:00
parent 5ca03fb689
commit eddd1a24b2
5 changed files with 163 additions and 74 deletions

View File

@ -71,6 +71,9 @@ static void drawRect(SDL_Renderer *r, float x, float y, float w, float h, SDL_Co
SDL_RenderFillRect(r, &fr);
}
// Hover state for level popup ( -1 = none, 0..19 = hovered level )
static int hoveredLevel = -1;
// ...existing code...
// -----------------------------------------------------------------------------
@ -229,10 +232,9 @@ static void drawSmallPiece(SDL_Renderer* renderer, SDL_Texture* blocksTex, Piece
// -----------------------------------------------------------------------------
static void drawLevelSelectionPopup(SDL_Renderer* renderer, FontAtlas& font, SDL_Texture* bgTex, int selectedLevel) {
// Popup dims scale with logical size for responsiveness
float popupW = std::min(760.0f, LOGICAL_W * 0.75f);
float popupH = std::min(520.0f, LOGICAL_H * 0.7f);
float popupX = (LOGICAL_W - popupW) / 2.0f;
float popupY = (LOGICAL_H - popupH) / 2.0f;
float popupW = 400, popupH = 300;
float popupX = (LOGICAL_W - popupW) / 2;
float popupY = (LOGICAL_H - popupH) / 2;
// Draw the background picture stretched to full logical viewport if available
if (bgTex) {
@ -258,12 +260,12 @@ static void drawLevelSelectionPopup(SDL_Renderer* renderer, FontAtlas& font, SDL
font.draw(renderer, popupX + 28, popupY + 18, "SELECT STARTING LEVEL", 2.4f, {255, 220, 0, 255});
// Grid layout for levels: 4 columns x 5 rows
int cols = 4, rows = 5;
float padding = 24.0f;
float gridW = popupW - padding * 2;
float gridH = popupH - 120.0f; // leave space for title and instructions
float cellW = gridW / cols;
float cellH = std::min(80.0f, gridH / rows - 12.0f);
int cols = 4, rows = 5;
float padding = 24.0f;
float gridW = popupW - padding * 2;
float gridH = popupH - 120.0f; // leave space for title and instructions
float cellW = gridW / cols;
float cellH = std::min(80.0f, gridH / rows - 12.0f);
float gridStartX = popupX + padding;
float gridStartY = popupY + 70;
@ -279,6 +281,13 @@ static void drawLevelSelectionPopup(SDL_Renderer* renderer, FontAtlas& font, SDL
SDL_Color fg = isSelected ? SDL_Color{0, 0, 0, 255} : SDL_Color{240, 240, 245, 255};
// Button background
// Hover highlight
bool isHovered = (level == hoveredLevel);
if (isHovered && !isSelected) {
// slightly brighter hover background
SDL_Color hoverBg = SDL_Color{95, 120, 170, 255};
drawRect(renderer, cx + 8 - 2, cy - 2, cellW - 12, cellH + 4, hoverBg);
}
drawRect(renderer, cx + 8, cy, cellW - 16, cellH, bg);
// Level label centered
@ -560,6 +569,9 @@ int main(int, char **)
float levelFadeAlpha = 0.0f; // 0..1 blend factor where 1 means next fully visible
const float LEVEL_FADE_DURATION = 3500.0f; // ms for fade transition (3.5s)
float levelFadeElapsed = 0.0f;
// Default start level selection: 0 (declare here so it's in scope for all handlers)
int startLevelSelection = 0;
// Load blocks texture using native SDL BMP loading
SDL_Texture *blocksTex = nullptr;
@ -574,46 +586,24 @@ int main(int, char **)
// No global exposure of blocksTex; states receive textures via StateContext.
if (!blocksTex) {
(void)0;
// Create a 630x90 texture (7 blocks * 90px each)
blocksTex = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 630, 90);
if (blocksTex) {
// Set texture as render target and draw colored blocks
SDL_SetRenderTarget(renderer, blocksTex);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
// Draw each block type with its color
for (int i = 0; i < PIECE_COUNT; ++i) {
SDL_Color color = COLORS[i + 1];
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 255);
SDL_FRect rect = {float(i * 90 + 4), 4, 82, 82}; // 4px padding, 82x82 block
SDL_RenderFillRect(renderer, &rect);
// Add a highlight effect
SDL_SetRenderDrawColor(renderer,
(Uint8)std::min(255, color.r + 30),
(Uint8)std::min(255, color.g + 30),
(Uint8)std::min(255, color.b + 30), 255);
SDL_FRect highlight = {float(i * 90 + 4), 4, 82, 20};
SDL_RenderFillRect(renderer, &highlight);
}
// Reset render target
SDL_SetRenderTarget(renderer, nullptr);
(void)0;
} else {
std::fprintf(stderr, "Failed to create programmatic texture: %s\n", SDL_GetError());
// Generate blocks by drawing colored rectangles to texture
SDL_SetRenderTarget(renderer, blocksTex);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
for (int i = 0; i < PIECE_COUNT; ++i) {
SDL_Color c = COLORS[i + 1];
SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, c.a);
SDL_FRect rect{(float)(i * 90), 0, 90, 90};
SDL_RenderFillRect(renderer, &rect);
}
} else {
(void)0;
SDL_SetRenderTarget(renderer, nullptr);
}
// Provide the blocks sheet to the fireworks system through StateContext (no globals).
// Default start level selection: 0
int startLevelSelection = 0;
Game game(startLevelSelection);
// Initialize sound effects system
@ -843,31 +833,38 @@ int main(int, char **)
float contentOffsetY = (winH - contentH) * 0.5f / logicalScale;
if (showLevelPopup) {
// Handle level selection popup clicks
// Handle level selection popup clicks (use same math as drawLevelSelectionPopup)
float popupW = 400, popupH = 300;
float popupX = (LOGICAL_W - popupW) / 2;
float popupY = (LOGICAL_H - popupH) / 2;
int cols = 4, rows = 5;
float padding = 24.0f;
float gridW = popupW - padding * 2;
float gridH = popupH - 120.0f;
float cellW = gridW / cols;
float cellH = std::min(80.0f, gridH / rows - 12.0f);
float gridStartX = popupX + padding;
float gridStartY = popupY + 70;
if (lx >= popupX && lx <= popupX + popupW && ly >= popupY && ly <= popupY + popupH) {
// Click inside popup - check level grid
float gridStartX = popupX + 50;
float gridStartY = popupY + 70;
float cellW = 70, cellH = 35;
if (lx >= gridStartX && ly >= gridStartY) {
int col = int((lx - gridStartX) / cellW);
int row = int((ly - gridStartY) / cellH);
if (col >= 0 && col < 4 && row >= 0 && row < 5) {
int selectedLevel = row * 4 + col;
int row = int((ly - gridStartY) / (cellH + 12.0f));
if (col >= 0 && col < cols && row >= 0 && row < rows) {
int selectedLevel = row * cols + col;
if (selectedLevel < 20) {
startLevelSelection = selectedLevel;
showLevelPopup = false;
hoveredLevel = -1;
}
}
}
} else {
// Click outside popup - close it
showLevelPopup = false;
hoveredLevel = -1;
}
} else if (showSettingsPopup) {
// Click anywhere closes settings popup
@ -960,7 +957,7 @@ int main(int, char **)
if (mx >= logicalVP.x && my >= logicalVP.y && mx <= logicalVP.x + logicalVP.w && my <= logicalVP.y + logicalVP.h)
{
float lx = (mx - logicalVP.x) / logicalScale, ly = (my - logicalVP.y) / logicalScale;
if (state == AppState::Menu && !showLevelPopup && !showSettingsPopup)
if (state == AppState::Menu && !showSettingsPopup)
{
// Compute content offsets and responsive buttons (match MenuState)
float contentW = LOGICAL_W * logicalScale;
@ -976,11 +973,40 @@ int main(int, char **)
SDL_FRect playBtn{btnCX - btnW * 0.6f - btnW/2.0f, btnCY - btnH/2.0f, btnW, btnH};
SDL_FRect levelBtn{btnCX + btnW * 0.6f - btnW/2.0f, btnCY - btnH/2.0f, btnW, btnH};
// If level popup is not shown, clear hoveredLevel; otherwise compute it
hoveredButton = -1;
if (lx >= playBtn.x && lx <= playBtn.x + playBtn.w && ly >= playBtn.y && ly <= playBtn.y + playBtn.h)
hoveredButton = 0;
else if (lx >= levelBtn.x && lx <= levelBtn.x + levelBtn.w && ly >= levelBtn.y && ly <= levelBtn.y + levelBtn.h)
hoveredButton = 1;
if (!showLevelPopup) {
if (lx >= playBtn.x && lx <= playBtn.x + playBtn.w && ly >= playBtn.y && ly <= playBtn.y + playBtn.h)
hoveredButton = 0;
else if (lx >= levelBtn.x && lx <= levelBtn.x + levelBtn.w && ly >= levelBtn.y && ly <= levelBtn.y + levelBtn.h)
hoveredButton = 1;
hoveredLevel = -1;
} else {
// compute hover over popup grid using same math as drawLevelSelectionPopup
float popupW = 400, popupH = 300;
float popupX = (LOGICAL_W - popupW) / 2;
float popupY = (LOGICAL_H - popupH) / 2;
int cols = 4, rows = 5;
float padding = 24.0f;
float gridW = popupW - padding * 2;
float gridH = popupH - 120.0f;
float cellW = gridW / cols;
float cellH = std::min(80.0f, gridH / rows - 12.0f);
float gridStartX = popupX + padding;
float gridStartY = popupY + 70;
hoveredLevel = -1;
if (lx >= popupX && lx <= popupX + popupW && ly >= popupY && ly <= popupY + popupH) {
if (lx >= gridStartX && ly >= gridStartY) {
int col = int((lx - gridStartX) / cellW);
int row = int((ly - gridStartY) / (cellH + 12.0f));
if (col >= 0 && col < cols && row >= 0 && row < rows) {
int sel = row * cols + col;
if (sel < 20) hoveredLevel = sel;
}
}
}
}
}
}
}