fixed level selector
This commit is contained in:
146
src/main.cpp
146
src/main.cpp
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user