fix(viewport): deslligar el viewport de zoom_factor_ (aspect-fit per pantalla física)

El viewport del pase final es calculava com `Game::WIDTH * zoom_factor_`. Però
`zoom_factor_` està capat a `max_zoom_`, que es deriva de `display - 100px`
(marge per a decoracions). En fullscreen això deixa marc negre als 4 costats:
amb display 1920×1080 max_zoom_≈1.25 → viewport 1600×900 dins de 1920×1080.

Ara l'escala es calcula directament de la finestra física actual com a
aspect-fit (`min(curW/1280, curH/720)`), de manera que el viewport sempre
omple un eix i lletraboxeja l'altre, independentment del zoom_factor_. El
zoom_factor_ continua dimensionant la finestra en mode windowed (F1/F2).
This commit is contained in:
2026-05-20 20:10:10 +02:00
parent cf4fbf7153
commit 20cfadeb0b
+11 -4
View File
@@ -173,10 +173,17 @@ void SDLManager::applyZoom(float new_zoom) {
}
void SDLManager::updateViewport() {
// Cálculo de letterbox: el juego se renderiza a 1280×720 lógicos, pero
// la swapchain tiene el tamaño físico de la ventana. Aplicamos un viewport
// centrado con la proporción 16:9 para preservar aspect ratio.
float scale = zoom_factor_;
// Càlcul de letterbox: el joc es renderitza a 1280×720 lògics, però la
// swapchain té la mida física de la finestra. Apliquem un viewport
// centrat amb aspect-fit (omple un eix, lletrabox a l'altre).
//
// IMPORTANT: l'escala del viewport es deriva de la mida física actual,
// NO del zoom_factor_. El zoom_factor_ només dimensiona la finestra en
// mode windowed (F1/F2). Si l'enllacéssim, en fullscreen el viewport
// quedaria capat per max_zoom_ (display-100px) i no ompliria la pantalla.
float scale_w = static_cast<float>(current_width_) / Defaults::Game::WIDTH;
float scale_h = static_cast<float>(current_height_) / Defaults::Game::HEIGHT;
float scale = std::min(scale_w, scale_h);
int scaled_width = static_cast<int>(std::round(Defaults::Game::WIDTH * scale));
int scaled_height = static_cast<int>(std::round(Defaults::Game::HEIGHT * scale));