updated main menu for cooperate mode

This commit is contained in:
2025-12-23 12:21:33 +01:00
parent 953d6af701
commit dac312ef2b
6 changed files with 60 additions and 14 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 KiB

View File

@ -14,7 +14,7 @@ SmoothScroll=1
UpRotateClockwise=0
[Player]
Name=GREGOR
Name=P2
[Debug]
Enabled=1

View File

@ -307,9 +307,8 @@ void CoopGame::spawn(PlayerState& ps) {
pieceSequence++;
if (collides(ps, ps.cur)) {
ps.toppedOut = true;
if (left.toppedOut && right.toppedOut) {
gameOver = true;
}
// Cooperative mode: game ends when any player tops out.
gameOver = true;
}
}

View File

@ -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,

View File

@ -107,4 +107,8 @@ private:
int coopSetupSelected = 0; // 0 = 2 players, 1 = AI
SDL_FRect coopSetupBtnRects[2]{};
bool coopSetupRectsValid = false;
// Optional cooperative info image shown when coop setup panel is active
SDL_Texture* coopInfoTexture = nullptr;
int coopInfoTexW = 0;
int coopInfoTexH = 0;
};

View File

@ -22,7 +22,8 @@ BottomMenu buildBottomMenu(const MenuLayoutParams& params, int startLevel, bool
std::snprintf(levelBtnText, sizeof(levelBtnText), "LEVEL %d", startLevel);
menu.buttons[0] = Button{ BottomMenuItem::Play, rects[0], "PLAY", false };
menu.buttons[1] = Button{ BottomMenuItem::Cooperate, rects[1], coopVsAI ? "COOPERATE (AI)" : "COOPERATE (2P)", false };
// Always show a neutral "COOPERATE" label (remove per-mode suffixes)
menu.buttons[1] = Button{ BottomMenuItem::Cooperate, rects[1], "COOPERATE", false };
menu.buttons[2] = Button{ BottomMenuItem::Challenge, rects[2], "CHALLENGE", false };
menu.buttons[3] = Button{ BottomMenuItem::Level, rects[3], levelBtnText, true };
menu.buttons[4] = Button{ BottomMenuItem::Options, rects[4], "OPTIONS", true };