Updated game speed

This commit is contained in:
2025-08-16 08:24:26 +02:00
parent d161b2c550
commit 71648fbaeb
20 changed files with 690 additions and 334 deletions

View File

@ -4,6 +4,32 @@
#include "../Font.h"
#include <SDL3/SDL.h>
#include <cstdio>
#include <algorithm>
#include <cmath>
// Local logical canvas size (matches main.cpp). Kept local to avoid changing many files.
static constexpr int LOGICAL_W = 1200;
static constexpr int LOGICAL_H = 1000;
extern bool showLevelPopup; // from main
extern bool showSettingsPopup; // from main
extern bool musicEnabled; // from main
extern int hoveredButton; // from main
// Call wrappers defined in main.cpp
extern void menu_drawFireworks(SDL_Renderer* renderer);
extern void menu_updateFireworks(double frameMs);
extern double menu_getLogoAnimCounter();
extern int menu_getHoveredButton();
extern void menu_drawEnhancedButton(SDL_Renderer* renderer, FontAtlas& font, float cx, float cy, float w, float h,
const std::string& label, bool isHovered, bool isSelected);
// Menu button wrapper implemented in main.cpp
extern void menu_drawMenuButton(SDL_Renderer* renderer, FontAtlas& font, float cx, float cy, float w, float h,
const std::string& label, SDL_Color bgColor, SDL_Color borderColor);
// wrappers for popups (defined in main.cpp)
extern void menu_drawLevelSelectionPopup(SDL_Renderer* renderer, FontAtlas& font, SDL_Texture* bgTex, int selectedLevel);
extern void menu_drawSettingsPopup(SDL_Renderer* renderer, FontAtlas& font, bool musicEnabled);
MenuState::MenuState(StateContext& ctx) : State(ctx) {}
@ -15,19 +41,125 @@ void MenuState::onExit() {
}
void MenuState::handleEvent(const SDL_Event& e) {
// Menu-specific key handling moved from main; main still handles mouse for now
if (e.type == SDL_EVENT_KEY_DOWN && !e.key.repeat) {
if (ctx.startLevelSelection && *ctx.startLevelSelection >= 0) {
// keep simple: allow L/S toggles handled globally in main for now
}
}
// Key-specific handling (allow main to handle global keys)
(void)e;
}
void MenuState::update(double frameMs) {
// Update logo animation counter and particles similar to main
(void)frameMs;
}
void MenuState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect logicalVP) {
(void)renderer; (void)logicalScale; (void)logicalVP;
// Main still performs actual rendering for now; this placeholder keeps the API.
// Compute content offset using the same math as main
float winW = float(logicalVP.w);
float winH = float(logicalVP.h);
float contentScale = logicalScale;
float contentW = LOGICAL_W * contentScale;
float contentH = LOGICAL_H * contentScale;
float contentOffsetX = (winW - contentW) * 0.5f / contentScale;
float contentOffsetY = (winH - contentH) * 0.5f / contentScale;
// Background is drawn by main (stretched to the full window) to avoid double-draw.
// Draw the animated logo and fireworks using the small logo if available (show whole image)
SDL_Texture* logoToUse = ctx.logoSmallTex ? ctx.logoSmallTex : ctx.logoTex;
if (logoToUse) {
// Use dimensions provided by the shared context when available
int texW = (logoToUse == ctx.logoSmallTex && ctx.logoSmallW > 0) ? ctx.logoSmallW : 872;
int texH = (logoToUse == ctx.logoSmallTex && ctx.logoSmallH > 0) ? ctx.logoSmallH : 273;
float maxW = LOGICAL_W * 0.6f;
float scale = std::min(1.0f, maxW / float(texW));
float dw = texW * scale;
float dh = texH * scale;
float logoX = (LOGICAL_W - dw) / 2.f + contentOffsetX;
float logoY = LOGICAL_H * 0.05f + contentOffsetY;
SDL_FRect dst{logoX, logoY, dw, dh};
SDL_RenderTexture(renderer, logoToUse, nullptr, &dst);
}
// Fireworks (draw above high scores / near buttons)
menu_drawFireworks(renderer);
// Score list and top players with a sine-wave vertical animation (use pixelFont for retro look)
float topPlayersY = LOGICAL_H * 0.30f + contentOffsetY; // more top padding
FontAtlas* useFont = ctx.pixelFont ? ctx.pixelFont : ctx.font;
if (useFont) {
useFont->draw(renderer, LOGICAL_W * 0.5f - 110 + contentOffsetX, topPlayersY, std::string("TOP PLAYERS"), 1.8f, SDL_Color{255, 220, 0, 255});
}
// High scores table with wave offset
float scoresStartY = topPlayersY + 70; // more spacing under title
const auto &hs = ctx.scores ? ctx.scores->all() : *(new std::vector<ScoreEntry>());
size_t maxDisplay = std::min(hs.size(), size_t(12));
// Draw table header
if (useFont) {
float cx = LOGICAL_W * 0.5f + contentOffsetX;
float colX[] = { cx - 280, cx - 180, cx - 20, cx + 90, cx + 200, cx + 300 };
useFont->draw(renderer, colX[0], scoresStartY - 28, "RANK", 1.1f, SDL_Color{200,200,220,255});
useFont->draw(renderer, colX[1], scoresStartY - 28, "PLAYER", 1.1f, SDL_Color{200,200,220,255});
useFont->draw(renderer, colX[2], scoresStartY - 28, "SCORE", 1.1f, SDL_Color{200,200,220,255});
useFont->draw(renderer, colX[3], scoresStartY - 28, "LINES", 1.1f, SDL_Color{200,200,220,255});
useFont->draw(renderer, colX[4], scoresStartY - 28, "LEVEL", 1.1f, SDL_Color{200,200,220,255});
useFont->draw(renderer, colX[5], scoresStartY - 28, "TIME", 1.1f, SDL_Color{200,200,220,255});
}
for (size_t i = 0; i < maxDisplay; ++i)
{
float baseY = scoresStartY + i * 25;
float wave = std::sin((float)menu_getLogoAnimCounter() * 0.006f + i * 0.25f) * 6.0f; // subtle wave
float y = baseY + wave;
// Center columns around mid X, wider
float cx = LOGICAL_W * 0.5f + contentOffsetX;
float colX[] = { cx - 280, cx - 180, cx - 20, cx + 90, cx + 200, cx + 300 };
char rankStr[8];
std::snprintf(rankStr, sizeof(rankStr), "%zu.", i + 1);
if (useFont) useFont->draw(renderer, colX[0], y, rankStr, 1.0f, SDL_Color{220, 220, 230, 255});
if (useFont) useFont->draw(renderer, colX[1], y, hs[i].name, 1.0f, SDL_Color{220, 220, 230, 255});
char scoreStr[16]; std::snprintf(scoreStr, sizeof(scoreStr), "%d", hs[i].score);
if (useFont) useFont->draw(renderer, colX[2], y, scoreStr, 1.0f, SDL_Color{220, 220, 230, 255});
char linesStr[8]; std::snprintf(linesStr, sizeof(linesStr), "%d", hs[i].lines);
if (useFont) useFont->draw(renderer, colX[3], y, linesStr, 1.0f, SDL_Color{220, 220, 230, 255});
char levelStr[8]; std::snprintf(levelStr, sizeof(levelStr), "%d", hs[i].level);
if (useFont) useFont->draw(renderer, colX[4], y, levelStr, 1.0f, SDL_Color{220, 220, 230, 255});
char timeStr[16]; int mins = int(hs[i].timeSec) / 60; int secs = int(hs[i].timeSec) % 60;
std::snprintf(timeStr, sizeof(timeStr), "%d:%02d", mins, secs);
if (useFont) useFont->draw(renderer, colX[5], y, timeStr, 1.0f, SDL_Color{220, 220, 230, 255});
}
// Draw bottom action buttons with responsive sizing (reduced to match main mouse hit-test)
bool isSmall = (contentW < 700.0f);
float btnW = isSmall ? (LOGICAL_W * 0.4f) : 300.0f;
float btnH = isSmall ? 60.0f : 70.0f;
float btnX = LOGICAL_W * 0.5f + contentOffsetX;
// Move buttons down by 40px to match original layout (user requested 30-50px)
const float btnYOffset = 40.0f;
float btnY = LOGICAL_H * 0.86f + contentOffsetY + btnYOffset; // align with main's button vertical position
if (ctx.pixelFont) {
char levelBtnText[32];
int startLevel = ctx.startLevelSelection ? *ctx.startLevelSelection : 0;
std::snprintf(levelBtnText, sizeof(levelBtnText), "LEVEL %d", startLevel);
// left = green, right = blue like original
menu_drawMenuButton(renderer, *ctx.pixelFont, btnX - btnW * 0.6f, btnY, btnW, btnH, std::string("PLAY"), SDL_Color{60,180,80,255}, SDL_Color{30,120,40,255});
menu_drawMenuButton(renderer, *ctx.pixelFont, btnX + btnW * 0.6f, btnY, btnW, btnH, std::string(levelBtnText), SDL_Color{40,140,240,255}, SDL_Color{20,100,200,255});
}
// Popups (level/settings) if requested
if (ctx.showLevelPopup && *ctx.showLevelPopup) {
// call wrapper which will internally draw on top of current content
// prefer pixelFont for retro look
FontAtlas* useFont = ctx.pixelFont ? ctx.pixelFont : ctx.font;
menu_drawLevelSelectionPopup(renderer, *useFont, ctx.backgroundTex, ctx.startLevelSelection ? *ctx.startLevelSelection : 0);
}
if (ctx.showSettingsPopup && *ctx.showSettingsPopup) {
menu_drawSettingsPopup(renderer, *ctx.font, ctx.musicEnabled ? *ctx.musicEnabled : false);
}
}