|
|
|
|
@ -9,6 +9,8 @@
|
|
|
|
|
#include "../audio/Audio.h"
|
|
|
|
|
#include "../audio/SoundEffect.h"
|
|
|
|
|
#include <SDL3/SDL.h>
|
|
|
|
|
#include <SDL3/SDL_render.h>
|
|
|
|
|
#include <SDL3/SDL_surface.h>
|
|
|
|
|
#include <cstdio>
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include <array>
|
|
|
|
|
@ -256,7 +258,7 @@ void MenuState::renderMainButtonTop(SDL_Renderer* renderer, float logicalScale,
|
|
|
|
|
ui::BottomMenu menu = ui::buildBottomMenu(params, startLevel, coopVsAI);
|
|
|
|
|
|
|
|
|
|
const int hovered = (ctx.hoveredButton ? *ctx.hoveredButton : -1);
|
|
|
|
|
const double baseAlpha = 1.0;
|
|
|
|
|
const double baseAlpha = 1.0; // Base alpha for button rendering
|
|
|
|
|
// Pulse is encoded as a signed delta so PLAY can dim/brighten while focused.
|
|
|
|
|
const double pulseDelta = (buttonPulseAlpha - 1.0);
|
|
|
|
|
const double flashDelta = buttonFlash * buttonFlashAmount;
|
|
|
|
|
@ -274,6 +276,7 @@ void MenuState::onExit() {
|
|
|
|
|
if (optionsIcon) { SDL_DestroyTexture(optionsIcon); optionsIcon = nullptr; }
|
|
|
|
|
if (exitIcon) { SDL_DestroyTexture(exitIcon); exitIcon = nullptr; }
|
|
|
|
|
if (helpIcon) { SDL_DestroyTexture(helpIcon); helpIcon = nullptr; }
|
|
|
|
|
if (coopInfoTexture) { SDL_DestroyTexture(coopInfoTexture); coopInfoTexture = nullptr; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MenuState::handleEvent(const SDL_Event& e) {
|
|
|
|
|
@ -969,8 +972,8 @@ void MenuState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect logi
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Small TOP PLAYER label under the logo
|
|
|
|
|
const std::string smallTitle = "TOP PLAYER";
|
|
|
|
|
// Small label under the logo — show "COOPERATE" when coop setup is active
|
|
|
|
|
const std::string smallTitle = (coopSetupAnimating || coopSetupVisible) ? "COOPERATE" : "TOP PLAYER";
|
|
|
|
|
float titleScale = 0.9f;
|
|
|
|
|
int tW = 0, tH = 0;
|
|
|
|
|
useFont->measure(smallTitle, titleScale, tW, tH);
|
|
|
|
|
@ -1279,12 +1282,15 @@ void MenuState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect logi
|
|
|
|
|
// highscores area (not sliding offscreen with the scores).
|
|
|
|
|
const float panelBaseY = scoresStartY - 20.0f;
|
|
|
|
|
|
|
|
|
|
// Make the choice buttons larger and center them vertically in the highscores area
|
|
|
|
|
const float btnW2 = std::min(420.0f, panelW * 0.44f);
|
|
|
|
|
const float btnH2 = 84.0f;
|
|
|
|
|
const float gap = 28.0f;
|
|
|
|
|
const float bx = panelBaseX + (panelW - (btnW2 * 2.0f + gap)) * 0.5f;
|
|
|
|
|
const float by = panelBaseY + (panelH - btnH2) * 0.5f;
|
|
|
|
|
// Make the choice buttons smaller, add more spacing, and raise them higher
|
|
|
|
|
const float btnW2 = std::min(300.0f, panelW * 0.30f);
|
|
|
|
|
const float btnH2 = 60.0f;
|
|
|
|
|
const float gap = 96.0f;
|
|
|
|
|
// Shift the image and buttons to the right for layout balance (reduced)
|
|
|
|
|
const float shiftX = 20.0f; // move right by 30px (moved 20px left from previous)
|
|
|
|
|
const float bx = panelBaseX + (panelW - (btnW2 * 2.0f + gap)) * 0.5f + shiftX;
|
|
|
|
|
// Move the buttons up by ~80px to sit closer under the logo
|
|
|
|
|
const float by = panelBaseY + (panelH - btnH2) * 0.5f - 80.0f;
|
|
|
|
|
|
|
|
|
|
coopSetupBtnRects[0] = SDL_FRect{ bx, by, btnW2, btnH2 };
|
|
|
|
|
coopSetupBtnRects[1] = SDL_FRect{ bx + btnW2 + gap, by, btnW2, btnH2 };
|
|
|
|
|
@ -1292,6 +1298,42 @@ void MenuState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect logi
|
|
|
|
|
|
|
|
|
|
SDL_Color bg{ 24, 36, 52, 220 };
|
|
|
|
|
SDL_Color border{ 110, 200, 255, 220 };
|
|
|
|
|
|
|
|
|
|
// Load coop info image once when the coop setup is first shown
|
|
|
|
|
if (!coopInfoTexture) {
|
|
|
|
|
const std::string resolved = AssetPath::resolveImagePath("assets/images/cooperate_info.png");
|
|
|
|
|
if (!resolved.empty()) {
|
|
|
|
|
SDL_Surface* surf = IMG_Load(resolved.c_str());
|
|
|
|
|
if (surf) {
|
|
|
|
|
// Save dimensions from surface then create texture
|
|
|
|
|
coopInfoTexW = surf->w;
|
|
|
|
|
coopInfoTexH = surf->h;
|
|
|
|
|
coopInfoTexture = SDL_CreateTextureFromSurface(renderer, surf);
|
|
|
|
|
SDL_DestroySurface(surf);
|
|
|
|
|
} else {
|
|
|
|
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "MenuState: failed to load %s: %s", resolved.c_str(), SDL_GetError());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the image loaded, render it centered above the two choice buttons
|
|
|
|
|
if (coopInfoTexture && coopInfoTexW > 0 && coopInfoTexH > 0) {
|
|
|
|
|
float totalW = btnW2 * 2.0f + gap;
|
|
|
|
|
// Increase allowed image width by ~15% (was 0.75 of totalW)
|
|
|
|
|
const float scaleFactor = 0.75f * 1.25f; // ~0.8625
|
|
|
|
|
float maxImgW = totalW * scaleFactor;
|
|
|
|
|
float targetW = std::min(maxImgW, static_cast<float>(coopInfoTexW));
|
|
|
|
|
float scale = targetW / static_cast<float>(coopInfoTexW);
|
|
|
|
|
float targetH = static_cast<float>(coopInfoTexH) * scale;
|
|
|
|
|
float imgX = bx + (totalW - targetW) * 0.5f;
|
|
|
|
|
float imgY = by - targetH - 8.0f; // keep the small gap above buttons
|
|
|
|
|
float minY = panelBaseY + 6.0f;
|
|
|
|
|
if (imgY < minY) imgY = minY;
|
|
|
|
|
SDL_FRect dst{ imgX, imgY, targetW, targetH };
|
|
|
|
|
SDL_SetTextureBlendMode(coopInfoTexture, SDL_BLENDMODE_BLEND);
|
|
|
|
|
SDL_RenderTexture(renderer, coopInfoTexture, nullptr, &dst);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UIRenderer::drawButton(renderer, ctx.pixelFont, coopSetupBtnRects[0].x + btnW2 * 0.5f, coopSetupBtnRects[0].y + btnH2 * 0.5f,
|
|
|
|
|
btnW2, btnH2, "2 PLAYERS", false, coopSetupSelected == 0, bg, border, false, nullptr);
|
|
|
|
|
UIRenderer::drawButton(renderer, ctx.pixelFont, coopSetupBtnRects[1].x + btnW2 * 0.5f, coopSetupBtnRects[1].y + btnH2 * 0.5f,
|
|
|
|
|
|