some problems fixed

This commit is contained in:
2025-08-17 21:13:58 +02:00
parent d75bfcf4d0
commit b5ef9172b3
18 changed files with 1139 additions and 231 deletions

View File

@ -187,15 +187,10 @@ void LevelSelectorState::handleEvent(const SDL_Event& e) {
if (ctx.startLevelSelection) *ctx.startLevelSelection = hoveredLevel;
} else if (e.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
if (e.button.button == SDL_BUTTON_LEFT) {
// compute visible logical viewport
float vw = (lastLogicalScale > 0.f) ? float(lastLogicalVP.w) / lastLogicalScale : float(LOGICAL_W);
float vh = (lastLogicalScale > 0.f) ? float(lastLogicalVP.h) / lastLogicalScale : float(LOGICAL_H);
float offX = 0.f;
if (lastLogicalScale > 0.f) offX = (vw / 2.f) - (float(LOGICAL_W) / 2.f);
// convert mouse to logical coords
// convert mouse to logical coords (viewport is already centered)
float lx = (float(e.button.x) - float(lastLogicalVP.x)) / (lastLogicalScale > 0.f ? lastLogicalScale : 1.f);
float ly = (float(e.button.y) - float(lastLogicalVP.y)) / (lastLogicalScale > 0.f ? lastLogicalScale : 1.f);
SDL_FRect panel = DrawPanel(nullptr, vw, vh, /*draw=*/false, offX, 0.f);
SDL_FRect panel = DrawPanel(nullptr, LOGICAL_W, LOGICAL_H, /*draw=*/false, 0.f, 0.f);
Grid g = MakeGrid(panel);
int hit = HitTest(g, int(lx), int(ly));
if (hit != -1) {
@ -205,14 +200,10 @@ void LevelSelectorState::handleEvent(const SDL_Event& e) {
}
}
} else if (e.type == SDL_EVENT_MOUSE_MOTION) {
// compute visible logical viewport and convert mouse coords once
float vw = (lastLogicalScale > 0.f) ? float(lastLogicalVP.w) / lastLogicalScale : float(LOGICAL_W);
float vh = (lastLogicalScale > 0.f) ? float(lastLogicalVP.h) / lastLogicalScale : float(LOGICAL_H);
float offX = 0.f;
if (lastLogicalScale > 0.f) offX = (vw / 2.f) - (float(LOGICAL_W) / 2.f);
// convert mouse to logical coords (viewport is already centered)
float lx = (float(e.motion.x) - float(lastLogicalVP.x)) / (lastLogicalScale > 0.f ? lastLogicalScale : 1.f);
float ly = (float(e.motion.y) - float(lastLogicalVP.y)) / (lastLogicalScale > 0.f ? lastLogicalScale : 1.f);
SDL_FRect panel = DrawPanel(nullptr, vw, vh, /*draw=*/false, offX, 0.f);
SDL_FRect panel = DrawPanel(nullptr, LOGICAL_W, LOGICAL_H, /*draw=*/false, 0.f, 0.f);
Grid g = MakeGrid(panel);
hoveredLevel = HitTest(g, int(lx), int(ly));
}
@ -233,18 +224,11 @@ void LevelSelectorState::render(SDL_Renderer* renderer, float logicalScale, SDL_
void LevelSelectorState::drawLevelSelectionPopup(SDL_Renderer* renderer) {
if (!renderer) return;
// Important: main sets viewport + logical scale before calling us.
// Draw in logical coordinates to avoid artifacts in fullscreen.
// Use the actual visible logical size (viewport in logical coords) instead of hardcoded constants
float vw = (lastLogicalScale > 0.f) ? float(lastLogicalVP.w) / lastLogicalScale : float(LOGICAL_W);
float vh = (lastLogicalScale > 0.f) ? float(lastLogicalVP.h) / lastLogicalScale : float(LOGICAL_H);
// compute horizontal offset so content centers within the visible logical viewport
float offX = 0.f;
if (lastLogicalScale > 0.f) {
float visibleLogicalW = float(lastLogicalVP.w) / lastLogicalScale;
offX = (visibleLogicalW / 2.f) - (vw / 2.f);
}
// Since ApplicationManager sets up a centered viewport, we draw directly in logical coordinates
// The viewport (LOGICAL_W x LOGICAL_H) is already centered within the window
float vw = float(LOGICAL_W);
float vh = float(LOGICAL_H);
float offX = 0.f; // No offset needed since viewport is centered
// Panel and title strip (in logical space)
SDL_FRect panel = DrawPanel(renderer, vw, vh-140.0f, /*draw=*/true, offX, 0.f);
@ -268,19 +252,14 @@ void LevelSelectorState::drawLevelSelectionPopup(SDL_Renderer* renderer) {
}
bool LevelSelectorState::isMouseInPopup(float mouseX, float mouseY, float& popupX, float& popupY, float& popupW, float& popupH) {
// Re-implement using new panel geometry in window coordinates
// Convert from window pixels to logical coords using cached viewport/scale
// Simplified: viewport is already centered, just convert mouse to logical coords
(void)mouseX; (void)mouseY;
float lx = 0.f, ly = 0.f;
if (lastLogicalScale > 0.0f) {
lx = (float(mouseX) - float(lastLogicalVP.x)) / lastLogicalScale;
ly = (float(mouseY) - float(lastLogicalVP.y)) / lastLogicalScale;
}
float vw = (lastLogicalScale > 0.f) ? float(lastLogicalVP.w) / lastLogicalScale : float(LOGICAL_W);
float vh = (lastLogicalScale > 0.f) ? float(lastLogicalVP.h) / lastLogicalScale : float(LOGICAL_H);
float offX = 0.f;
if (lastLogicalScale > 0.f) offX = (vw / 2.f) - (float(LOGICAL_W) / 2.f);
SDL_FRect p = DrawPanel(nullptr, vw, vh, /*draw=*/false, offX, 0.f);
SDL_FRect p = DrawPanel(nullptr, LOGICAL_W, LOGICAL_H, /*draw=*/false, 0.f, 0.f);
popupX = p.x; popupY = p.y; popupW = p.w; popupH = p.h;
return lx >= popupX && lx <= popupX + popupW && ly >= popupY && ly <= popupY + popupH;
}
@ -292,11 +271,7 @@ int LevelSelectorState::getLevelFromMouse(float mouseX, float mouseY, float popu
lx = (float(mouseX) - float(lastLogicalVP.x)) / lastLogicalScale;
ly = (float(mouseY) - float(lastLogicalVP.y)) / lastLogicalScale;
}
float vw = (lastLogicalScale > 0.f) ? float(lastLogicalVP.w) / lastLogicalScale : float(LOGICAL_W);
float vh = (lastLogicalScale > 0.f) ? float(lastLogicalVP.h) / lastLogicalScale : float(LOGICAL_H);
float offX = 0.f;
if (lastLogicalScale > 0.f) offX = (vw / 2.f) - (float(LOGICAL_W) / 2.f);
SDL_FRect p = DrawPanel(nullptr, vw, vh, /*draw=*/false, offX, 0.f);
SDL_FRect p = DrawPanel(nullptr, LOGICAL_W, LOGICAL_H, /*draw=*/false, 0.f, 0.f);
Grid g = MakeGrid(p);
return HitTest(g, (int)lx, (int)ly);
}

View File

@ -3,6 +3,7 @@
#include "persistence/Scores.h"
#include "graphics/Font.h"
#include "../core/GlobalState.h"
#include "../audio/Audio.h"
#include <SDL3/SDL.h>
#include <cstdio>
#include <algorithm>
@ -42,14 +43,10 @@ void MenuState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect logi
{
FILE* f = fopen("tetris_trace.log", "a"); if (f) { fprintf(f, "MenuState::render entry\n"); fclose(f); }
}
// 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;
// Since ApplicationManager sets up a centered viewport, we draw directly in logical coordinates
// No additional content offset is needed - the viewport itself handles centering
float contentOffsetX = 0.0f;
float contentOffsetY = 0.0f;
// Background is drawn by main (stretched to the full window) to avoid double-draw.
@ -119,16 +116,17 @@ void MenuState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect logi
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});
}
// 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 };
for (size_t i = 0; i < maxDisplay; ++i)
{
float baseY = scoresStartY + i * 25;
float wave = std::sin((float)GlobalState::instance().logoAnimCounter * 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});
@ -150,6 +148,8 @@ void MenuState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect logi
}
// Draw bottom action buttons with responsive sizing (reduced to match main mouse hit-test)
// Since we removed content offsets, calculate contentW directly from the scale and logical size
float contentW = LOGICAL_W * logicalScale;
bool isSmall = (contentW < 700.0f);
float btnW = isSmall ? (LOGICAL_W * 0.4f) : 300.0f;
float btnH = isSmall ? 60.0f : 70.0f;

View File

@ -3,12 +3,18 @@
#include "gameplay/Game.h"
#include "gameplay/LineEffect.h"
#include "persistence/Scores.h"
#include "../audio/Audio.h"
#include <SDL3/SDL.h>
PlayingState::PlayingState(StateContext& ctx) : State(ctx) {}
void PlayingState::onEnter() {
// Nothing yet; main still owns game creation
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "[PLAYING] Entering Playing state");
// Initialize the game with the selected starting level
if (ctx.game && ctx.startLevelSelection) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "[PLAYING] Resetting game with level %d", *ctx.startLevelSelection);
ctx.game->reset(*ctx.startLevelSelection);
}
}
void PlayingState::onExit() {
@ -54,12 +60,40 @@ void PlayingState::handleEvent(const SDL_Event& e) {
return;
}
// Other gameplay keys already registered by main's Playing handler for now
// Tetris controls (only when not paused)
if (!ctx.game->isPaused()) {
// Rotation (still event-based for precise timing)
if (e.key.scancode == SDL_SCANCODE_UP || e.key.scancode == SDL_SCANCODE_W ||
e.key.scancode == SDL_SCANCODE_Z) {
ctx.game->rotate(1); // Clockwise rotation
return;
}
if (e.key.scancode == SDL_SCANCODE_X) {
ctx.game->rotate(-1); // Counter-clockwise rotation
return;
}
// Hard drop (space)
if (e.key.scancode == SDL_SCANCODE_SPACE) {
ctx.game->hardDrop();
return;
}
}
}
// Note: Left/Right movement and soft drop are now handled by
// ApplicationManager's update handler for proper DAS/ARR timing
}
void PlayingState::update(double frameMs) {
if (!ctx.game) return;
static bool debugPrinted = false;
if (!debugPrinted) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "[PLAYING] Starting updates, frameMs=%.2f, paused=%d", frameMs, ctx.game->isPaused());
debugPrinted = true;
}
// forward per-frame gameplay updates (gravity, elapsed)
if (!ctx.game->isPaused()) {
ctx.game->tickGravity(frameMs);
@ -71,11 +105,8 @@ void PlayingState::update(double frameMs) {
}
}
}
if (ctx.game->isGameOver()) {
if (ctx.scores) ctx.scores->submit(ctx.game->score(), ctx.game->lines(), ctx.game->level(), ctx.game->elapsed());
// Transitioning state must be done by the owner (main via StateManager hooks). We can't set state here.
}
// Note: Game over detection and state transition is now handled by ApplicationManager
}
void PlayingState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect logicalVP) {

View File

@ -40,6 +40,8 @@ struct StateContext {
// Audio / SFX - forward declared types in main
// Pointers to booleans/flags used by multiple states
bool* musicEnabled = nullptr;
bool* musicStarted = nullptr;
bool* musicLoaded = nullptr;
int* startLevelSelection = nullptr;
int* hoveredButton = nullptr;
// Menu popups (exposed from main)