updated main menu for cooperate mode
This commit is contained in:
BIN
assets/images/cooperate_info.png
Normal file
BIN
assets/images/cooperate_info.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 416 KiB |
@ -14,7 +14,7 @@ SmoothScroll=1
|
|||||||
UpRotateClockwise=0
|
UpRotateClockwise=0
|
||||||
|
|
||||||
[Player]
|
[Player]
|
||||||
Name=GREGOR
|
Name=P2
|
||||||
|
|
||||||
[Debug]
|
[Debug]
|
||||||
Enabled=1
|
Enabled=1
|
||||||
|
|||||||
@ -307,10 +307,9 @@ void CoopGame::spawn(PlayerState& ps) {
|
|||||||
pieceSequence++;
|
pieceSequence++;
|
||||||
if (collides(ps, ps.cur)) {
|
if (collides(ps, ps.cur)) {
|
||||||
ps.toppedOut = true;
|
ps.toppedOut = true;
|
||||||
if (left.toppedOut && right.toppedOut) {
|
// Cooperative mode: game ends when any player tops out.
|
||||||
gameOver = true;
|
gameOver = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CoopGame::collides(const PlayerState& ps, const Piece& p) const {
|
bool CoopGame::collides(const PlayerState& ps, const Piece& p) const {
|
||||||
|
|||||||
@ -9,6 +9,8 @@
|
|||||||
#include "../audio/Audio.h"
|
#include "../audio/Audio.h"
|
||||||
#include "../audio/SoundEffect.h"
|
#include "../audio/SoundEffect.h"
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
#include <SDL3/SDL_render.h>
|
||||||
|
#include <SDL3/SDL_surface.h>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
@ -256,7 +258,7 @@ void MenuState::renderMainButtonTop(SDL_Renderer* renderer, float logicalScale,
|
|||||||
ui::BottomMenu menu = ui::buildBottomMenu(params, startLevel, coopVsAI);
|
ui::BottomMenu menu = ui::buildBottomMenu(params, startLevel, coopVsAI);
|
||||||
|
|
||||||
const int hovered = (ctx.hoveredButton ? *ctx.hoveredButton : -1);
|
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.
|
// Pulse is encoded as a signed delta so PLAY can dim/brighten while focused.
|
||||||
const double pulseDelta = (buttonPulseAlpha - 1.0);
|
const double pulseDelta = (buttonPulseAlpha - 1.0);
|
||||||
const double flashDelta = buttonFlash * buttonFlashAmount;
|
const double flashDelta = buttonFlash * buttonFlashAmount;
|
||||||
@ -274,6 +276,7 @@ void MenuState::onExit() {
|
|||||||
if (optionsIcon) { SDL_DestroyTexture(optionsIcon); optionsIcon = nullptr; }
|
if (optionsIcon) { SDL_DestroyTexture(optionsIcon); optionsIcon = nullptr; }
|
||||||
if (exitIcon) { SDL_DestroyTexture(exitIcon); exitIcon = nullptr; }
|
if (exitIcon) { SDL_DestroyTexture(exitIcon); exitIcon = nullptr; }
|
||||||
if (helpIcon) { SDL_DestroyTexture(helpIcon); helpIcon = nullptr; }
|
if (helpIcon) { SDL_DestroyTexture(helpIcon); helpIcon = nullptr; }
|
||||||
|
if (coopInfoTexture) { SDL_DestroyTexture(coopInfoTexture); coopInfoTexture = nullptr; }
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuState::handleEvent(const SDL_Event& e) {
|
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
|
// Small label under the logo — show "COOPERATE" when coop setup is active
|
||||||
const std::string smallTitle = "TOP PLAYER";
|
const std::string smallTitle = (coopSetupAnimating || coopSetupVisible) ? "COOPERATE" : "TOP PLAYER";
|
||||||
float titleScale = 0.9f;
|
float titleScale = 0.9f;
|
||||||
int tW = 0, tH = 0;
|
int tW = 0, tH = 0;
|
||||||
useFont->measure(smallTitle, titleScale, tW, tH);
|
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).
|
// highscores area (not sliding offscreen with the scores).
|
||||||
const float panelBaseY = scoresStartY - 20.0f;
|
const float panelBaseY = scoresStartY - 20.0f;
|
||||||
|
|
||||||
// Make the choice buttons larger and center them vertically in the highscores area
|
// Make the choice buttons smaller, add more spacing, and raise them higher
|
||||||
const float btnW2 = std::min(420.0f, panelW * 0.44f);
|
const float btnW2 = std::min(300.0f, panelW * 0.30f);
|
||||||
const float btnH2 = 84.0f;
|
const float btnH2 = 60.0f;
|
||||||
const float gap = 28.0f;
|
const float gap = 96.0f;
|
||||||
const float bx = panelBaseX + (panelW - (btnW2 * 2.0f + gap)) * 0.5f;
|
// Shift the image and buttons to the right for layout balance (reduced)
|
||||||
const float by = panelBaseY + (panelH - btnH2) * 0.5f;
|
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[0] = SDL_FRect{ bx, by, btnW2, btnH2 };
|
||||||
coopSetupBtnRects[1] = SDL_FRect{ bx + btnW2 + gap, 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 bg{ 24, 36, 52, 220 };
|
||||||
SDL_Color border{ 110, 200, 255, 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,
|
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);
|
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,
|
UIRenderer::drawButton(renderer, ctx.pixelFont, coopSetupBtnRects[1].x + btnW2 * 0.5f, coopSetupBtnRects[1].y + btnH2 * 0.5f,
|
||||||
|
|||||||
@ -107,4 +107,8 @@ private:
|
|||||||
int coopSetupSelected = 0; // 0 = 2 players, 1 = AI
|
int coopSetupSelected = 0; // 0 = 2 players, 1 = AI
|
||||||
SDL_FRect coopSetupBtnRects[2]{};
|
SDL_FRect coopSetupBtnRects[2]{};
|
||||||
bool coopSetupRectsValid = false;
|
bool coopSetupRectsValid = false;
|
||||||
|
// Optional cooperative info image shown when coop setup panel is active
|
||||||
|
SDL_Texture* coopInfoTexture = nullptr;
|
||||||
|
int coopInfoTexW = 0;
|
||||||
|
int coopInfoTexH = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -22,7 +22,8 @@ BottomMenu buildBottomMenu(const MenuLayoutParams& params, int startLevel, bool
|
|||||||
std::snprintf(levelBtnText, sizeof(levelBtnText), "LEVEL %d", startLevel);
|
std::snprintf(levelBtnText, sizeof(levelBtnText), "LEVEL %d", startLevel);
|
||||||
|
|
||||||
menu.buttons[0] = Button{ BottomMenuItem::Play, rects[0], "PLAY", false };
|
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[2] = Button{ BottomMenuItem::Challenge, rects[2], "CHALLENGE", false };
|
||||||
menu.buttons[3] = Button{ BottomMenuItem::Level, rects[3], levelBtnText, true };
|
menu.buttons[3] = Button{ BottomMenuItem::Level, rects[3], levelBtnText, true };
|
||||||
menu.buttons[4] = Button{ BottomMenuItem::Options, rects[4], "OPTIONS", true };
|
menu.buttons[4] = Button{ BottomMenuItem::Options, rects[4], "OPTIONS", true };
|
||||||
|
|||||||
Reference in New Issue
Block a user