LOGO explota

This commit is contained in:
2025-12-02 08:50:38 +01:00
parent 73f222fcb7
commit 20538af4c6
22 changed files with 1754 additions and 1598 deletions

View File

@@ -2,302 +2,306 @@
// © 2025 Port a C++20 amb SDL3
#include "sdl_manager.hpp"
#include "core/defaults.hpp"
#include "core/rendering/line_renderer.hpp"
#include "game/options.hpp"
#include "project.h"
#include <algorithm>
#include <format>
#include <iostream>
#include "core/defaults.hpp"
#include "core/rendering/line_renderer.hpp"
#include "game/options.hpp"
#include "project.h"
SDLManager::SDLManager()
: finestra_(nullptr), renderer_(nullptr),
: finestra_(nullptr),
renderer_(nullptr),
current_width_(Defaults::Window::WIDTH),
current_height_(Defaults::Window::HEIGHT), is_fullscreen_(false),
max_width_(1920), max_height_(1080) {
// Inicialitzar SDL3
if (!SDL_Init(SDL_INIT_VIDEO)) {
std::cerr << "Error inicialitzant SDL3: " << SDL_GetError() << std::endl;
return;
}
current_height_(Defaults::Window::HEIGHT),
is_fullscreen_(false),
max_width_(1920),
max_height_(1080) {
// Inicialitzar SDL3
if (!SDL_Init(SDL_INIT_VIDEO)) {
std::cerr << "Error inicialitzant SDL3: " << SDL_GetError() << std::endl;
return;
}
// Calcular mida màxima des del display
calculateMaxWindowSize();
// Calcular mida màxima des del display
calculateMaxWindowSize();
// Construir títol dinàmic igual que en pollo
std::string window_title = std::format("{} v{} ({})", Project::LONG_NAME,
Project::VERSION, Project::COPYRIGHT);
// Construir títol dinàmic igual que en pollo
std::string window_title = std::format("{} v{} ({})", Project::LONG_NAME, Project::VERSION, Project::COPYRIGHT);
// Crear finestra CENTRADA (SDL ho fa automàticament amb CENTERED)
finestra_ =
SDL_CreateWindow(window_title.c_str(), current_width_, current_height_,
SDL_WINDOW_RESIZABLE // Permetre resize manual també
);
// Crear finestra CENTRADA (SDL ho fa automàticament amb CENTERED)
finestra_ =
SDL_CreateWindow(window_title.c_str(), current_width_, current_height_,
SDL_WINDOW_RESIZABLE // Permetre resize manual també
);
if (!finestra_) {
std::cerr << "Error creant finestra: " << SDL_GetError() << std::endl;
SDL_Quit();
return;
}
if (!finestra_) {
std::cerr << "Error creant finestra: " << SDL_GetError() << std::endl;
SDL_Quit();
return;
}
// IMPORTANT: Centrar explícitament la finestra
SDL_SetWindowPosition(finestra_, SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED);
// IMPORTANT: Centrar explícitament la finestra
SDL_SetWindowPosition(finestra_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
// Crear renderer amb acceleració
renderer_ = SDL_CreateRenderer(finestra_, nullptr);
// Crear renderer amb acceleració
renderer_ = SDL_CreateRenderer(finestra_, nullptr);
if (!renderer_) {
std::cerr << "Error creant renderer: " << SDL_GetError() << std::endl;
SDL_DestroyWindow(finestra_);
SDL_Quit();
return;
}
if (!renderer_) {
std::cerr << "Error creant renderer: " << SDL_GetError() << std::endl;
SDL_DestroyWindow(finestra_);
SDL_Quit();
return;
}
// CRÍTIC: Configurar viewport scaling
updateLogicalPresentation();
// CRÍTIC: Configurar viewport scaling
updateLogicalPresentation();
std::cout << "SDL3 inicialitzat: " << current_width_ << "x" << current_height_
<< " (logic: " << Defaults::Game::WIDTH << "x"
<< Defaults::Game::HEIGHT << ")" << std::endl;
std::cout << "SDL3 inicialitzat: " << current_width_ << "x" << current_height_
<< " (logic: " << Defaults::Game::WIDTH << "x"
<< Defaults::Game::HEIGHT << ")" << std::endl;
}
// Constructor amb configuració
SDLManager::SDLManager(int width, int height, bool fullscreen)
: finestra_(nullptr), renderer_(nullptr), current_width_(width),
current_height_(height), is_fullscreen_(fullscreen), max_width_(1920),
: finestra_(nullptr),
renderer_(nullptr),
current_width_(width),
current_height_(height),
is_fullscreen_(fullscreen),
max_width_(1920),
max_height_(1080) {
// Inicialitzar SDL3
if (!SDL_Init(SDL_INIT_VIDEO)) {
std::cerr << "Error inicialitzant SDL3: " << SDL_GetError() << std::endl;
return;
}
// Inicialitzar SDL3
if (!SDL_Init(SDL_INIT_VIDEO)) {
std::cerr << "Error inicialitzant SDL3: " << SDL_GetError() << std::endl;
return;
}
// Calcular mida màxima des del display
calculateMaxWindowSize();
// Calcular mida màxima des del display
calculateMaxWindowSize();
// Construir títol dinàmic
std::string window_title = std::format("{} v{} ({})", Project::LONG_NAME,
Project::VERSION, Project::COPYRIGHT);
// Construir títol dinàmic
std::string window_title = std::format("{} v{} ({})", Project::LONG_NAME, Project::VERSION, Project::COPYRIGHT);
// Configurar flags de la finestra
SDL_WindowFlags flags = SDL_WINDOW_RESIZABLE;
if (is_fullscreen_) {
flags = static_cast<SDL_WindowFlags>(flags | SDL_WINDOW_FULLSCREEN);
}
// Configurar flags de la finestra
SDL_WindowFlags flags = SDL_WINDOW_RESIZABLE;
if (is_fullscreen_) {
flags = static_cast<SDL_WindowFlags>(flags | SDL_WINDOW_FULLSCREEN);
}
// Crear finestra
finestra_ = SDL_CreateWindow(window_title.c_str(), current_width_,
current_height_, flags);
// Crear finestra
finestra_ = SDL_CreateWindow(window_title.c_str(), current_width_, current_height_, flags);
if (!finestra_) {
std::cerr << "Error creant finestra: " << SDL_GetError() << std::endl;
SDL_Quit();
return;
}
if (!finestra_) {
std::cerr << "Error creant finestra: " << SDL_GetError() << std::endl;
SDL_Quit();
return;
}
// Centrar explícitament la finestra (si no és fullscreen)
if (!is_fullscreen_) {
SDL_SetWindowPosition(finestra_, SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED);
}
// Centrar explícitament la finestra (si no és fullscreen)
if (!is_fullscreen_) {
SDL_SetWindowPosition(finestra_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
}
// Crear renderer amb acceleració
renderer_ = SDL_CreateRenderer(finestra_, nullptr);
// Crear renderer amb acceleració
renderer_ = SDL_CreateRenderer(finestra_, nullptr);
if (!renderer_) {
std::cerr << "Error creant renderer: " << SDL_GetError() << std::endl;
SDL_DestroyWindow(finestra_);
SDL_Quit();
return;
}
if (!renderer_) {
std::cerr << "Error creant renderer: " << SDL_GetError() << std::endl;
SDL_DestroyWindow(finestra_);
SDL_Quit();
return;
}
// Configurar viewport scaling
updateLogicalPresentation();
// Configurar viewport scaling
updateLogicalPresentation();
std::cout << "SDL3 inicialitzat: " << current_width_ << "x" << current_height_
<< " (logic: " << Defaults::Game::WIDTH << "x"
<< Defaults::Game::HEIGHT << ")";
if (is_fullscreen_) {
std::cout << " [FULLSCREEN]";
}
std::cout << std::endl;
std::cout << "SDL3 inicialitzat: " << current_width_ << "x" << current_height_
<< " (logic: " << Defaults::Game::WIDTH << "x"
<< Defaults::Game::HEIGHT << ")";
if (is_fullscreen_) {
std::cout << " [FULLSCREEN]";
}
std::cout << std::endl;
}
SDLManager::~SDLManager() {
if (renderer_) {
SDL_DestroyRenderer(renderer_);
renderer_ = nullptr;
}
if (renderer_) {
SDL_DestroyRenderer(renderer_);
renderer_ = nullptr;
}
if (finestra_) {
SDL_DestroyWindow(finestra_);
finestra_ = nullptr;
}
if (finestra_) {
SDL_DestroyWindow(finestra_);
finestra_ = nullptr;
}
SDL_Quit();
std::cout << "SDL3 netejat correctament" << std::endl;
SDL_Quit();
std::cout << "SDL3 netejat correctament" << std::endl;
}
void SDLManager::calculateMaxWindowSize() {
SDL_DisplayID display = SDL_GetPrimaryDisplay();
const SDL_DisplayMode *mode = SDL_GetCurrentDisplayMode(display);
SDL_DisplayID display = SDL_GetPrimaryDisplay();
const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(display);
if (mode) {
// Deixar marge de 100px per a decoracions de l'OS
max_width_ = mode->w - 100;
max_height_ = mode->h - 100;
std::cout << "Display detectat: " << mode->w << "x" << mode->h
<< " (max finestra: " << max_width_ << "x" << max_height_ << ")"
<< std::endl;
} else {
// Fallback conservador
max_width_ = 1920;
max_height_ = 1080;
std::cerr << "No s'ha pogut detectar el display, usant fallback: "
<< max_width_ << "x" << max_height_ << std::endl;
}
if (mode) {
// Deixar marge de 100px per a decoracions de l'OS
max_width_ = mode->w - 100;
max_height_ = mode->h - 100;
std::cout << "Display detectat: " << mode->w << "x" << mode->h
<< " (max finestra: " << max_width_ << "x" << max_height_ << ")"
<< std::endl;
} else {
// Fallback conservador
max_width_ = 1920;
max_height_ = 1080;
std::cerr << "No s'ha pogut detectar el display, usant fallback: "
<< max_width_ << "x" << max_height_ << std::endl;
}
}
void SDLManager::updateLogicalPresentation() {
// AIXÒ ÉS LA MÀGIA: El joc SEMPRE dibuixa en 640x480,
// SDL escala automàticament a la mida física de la finestra
SDL_SetRenderLogicalPresentation(
renderer_,
Defaults::Game::WIDTH, // 640 (lògic)
Defaults::Game::HEIGHT, // 480 (lògic)
SDL_LOGICAL_PRESENTATION_LETTERBOX // Mantenir aspect ratio 4:3
);
// AIXÒ ÉS LA MÀGIA: El joc SEMPRE dibuixa en 640x480,
// SDL escala automàticament a la mida física de la finestra
SDL_SetRenderLogicalPresentation(
renderer_,
Defaults::Game::WIDTH, // 640 (lògic)
Defaults::Game::HEIGHT, // 480 (lògic)
SDL_LOGICAL_PRESENTATION_LETTERBOX // Mantenir aspect ratio 4:3
);
}
void SDLManager::increaseWindowSize() {
if (is_fullscreen_)
return; // No operar en fullscreen
if (is_fullscreen_)
return; // No operar en fullscreen
int new_width = current_width_ + Defaults::Window::SIZE_INCREMENT;
int new_height = current_height_ + Defaults::Window::SIZE_INCREMENT;
int new_width = current_width_ + Defaults::Window::SIZE_INCREMENT;
int new_height = current_height_ + Defaults::Window::SIZE_INCREMENT;
// Clamp a màxim
new_width = std::min(new_width, max_width_);
new_height = std::min(new_height, max_height_);
// Clamp a màxim
new_width = std::min(new_width, max_width_);
new_height = std::min(new_height, max_height_);
if (new_width != current_width_ || new_height != current_height_) {
applyWindowSize(new_width, new_height);
if (new_width != current_width_ || new_height != current_height_) {
applyWindowSize(new_width, new_height);
// Persistir canvis a Options (es guardarà a config.yaml al tancar)
Options::window.width = current_width_;
Options::window.height = current_height_;
// Persistir canvis a Options (es guardarà a config.yaml al tancar)
Options::window.width = current_width_;
Options::window.height = current_height_;
std::cout << "F2: Finestra augmentada a " << new_width << "x" << new_height
<< std::endl;
}
std::cout << "F2: Finestra augmentada a " << new_width << "x" << new_height
<< std::endl;
}
}
void SDLManager::decreaseWindowSize() {
if (is_fullscreen_)
return;
if (is_fullscreen_)
return;
int new_width = current_width_ - Defaults::Window::SIZE_INCREMENT;
int new_height = current_height_ - Defaults::Window::SIZE_INCREMENT;
int new_width = current_width_ - Defaults::Window::SIZE_INCREMENT;
int new_height = current_height_ - Defaults::Window::SIZE_INCREMENT;
// Clamp a mínim
new_width = std::max(new_width, Defaults::Window::MIN_WIDTH);
new_height = std::max(new_height, Defaults::Window::MIN_HEIGHT);
// Clamp a mínim
new_width = std::max(new_width, Defaults::Window::MIN_WIDTH);
new_height = std::max(new_height, Defaults::Window::MIN_HEIGHT);
if (new_width != current_width_ || new_height != current_height_) {
applyWindowSize(new_width, new_height);
if (new_width != current_width_ || new_height != current_height_) {
applyWindowSize(new_width, new_height);
// Persistir canvis a Options (es guardarà a config.yaml al tancar)
Options::window.width = current_width_;
Options::window.height = current_height_;
// Persistir canvis a Options (es guardarà a config.yaml al tancar)
Options::window.width = current_width_;
Options::window.height = current_height_;
std::cout << "F1: Finestra reduïda a " << new_width << "x" << new_height
<< std::endl;
}
std::cout << "F1: Finestra reduïda a " << new_width << "x" << new_height
<< std::endl;
}
}
void SDLManager::applyWindowSize(int new_width, int new_height) {
// Obtenir posició actual ABANS del resize
int old_x, old_y;
SDL_GetWindowPosition(finestra_, &old_x, &old_y);
// Obtenir posició actual ABANS del resize
int old_x, old_y;
SDL_GetWindowPosition(finestra_, &old_x, &old_y);
int old_width = current_width_;
int old_height = current_height_;
int old_width = current_width_;
int old_height = current_height_;
// Actualitzar mida
SDL_SetWindowSize(finestra_, new_width, new_height);
current_width_ = new_width;
current_height_ = new_height;
// Actualitzar mida
SDL_SetWindowSize(finestra_, new_width, new_height);
current_width_ = new_width;
current_height_ = new_height;
// CENTRADO INTEL·LIGENT (algoritme de pollo)
// Calcular nova posició per mantenir la finestra centrada sobre si mateixa
int delta_width = old_width - new_width;
int delta_height = old_height - new_height;
// CENTRADO INTEL·LIGENT (algoritme de pollo)
// Calcular nova posició per mantenir la finestra centrada sobre si mateixa
int delta_width = old_width - new_width;
int delta_height = old_height - new_height;
int new_x = old_x + (delta_width / 2);
int new_y = old_y + (delta_height / 2);
int new_x = old_x + (delta_width / 2);
int new_y = old_y + (delta_height / 2);
// Evitar que la finestra surti de la pantalla
constexpr int TITLEBAR_HEIGHT = 35; // Alçada aproximada de la barra de títol
new_x = std::max(new_x, 0);
new_y = std::max(new_y, TITLEBAR_HEIGHT);
// Evitar que la finestra surti de la pantalla
constexpr int TITLEBAR_HEIGHT = 35; // Alçada aproximada de la barra de títol
new_x = std::max(new_x, 0);
new_y = std::max(new_y, TITLEBAR_HEIGHT);
SDL_SetWindowPosition(finestra_, new_x, new_y);
SDL_SetWindowPosition(finestra_, new_x, new_y);
// NO cal actualitzar el logical presentation aquí,
// SDL ho maneja automàticament
// NO cal actualitzar el logical presentation aquí,
// SDL ho maneja automàticament
}
void SDLManager::toggleFullscreen() {
is_fullscreen_ = !is_fullscreen_;
SDL_SetWindowFullscreen(finestra_, is_fullscreen_);
is_fullscreen_ = !is_fullscreen_;
SDL_SetWindowFullscreen(finestra_, is_fullscreen_);
// Persistir canvis a Options (es guardarà a config.yaml al tancar)
Options::window.fullscreen = is_fullscreen_;
// Persistir canvis a Options (es guardarà a config.yaml al tancar)
Options::window.fullscreen = is_fullscreen_;
std::cout << "F3: Fullscreen " << (is_fullscreen_ ? "activat" : "desactivat")
<< std::endl;
std::cout << "F3: Fullscreen " << (is_fullscreen_ ? "activat" : "desactivat")
<< std::endl;
// En fullscreen, SDL gestiona tot automàticament
// En sortir, restaura la mida anterior
// En fullscreen, SDL gestiona tot automàticament
// En sortir, restaura la mida anterior
}
bool SDLManager::handleWindowEvent(const SDL_Event &event) {
if (event.type == SDL_EVENT_WINDOW_RESIZED) {
// Usuari ha redimensionat manualment (arrossegar vora)
// Actualitzar el nostre tracking
SDL_GetWindowSize(finestra_, &current_width_, &current_height_);
std::cout << "Finestra redimensionada manualment a " << current_width_
<< "x" << current_height_ << std::endl;
return true;
}
return false;
bool SDLManager::handleWindowEvent(const SDL_Event& event) {
if (event.type == SDL_EVENT_WINDOW_RESIZED) {
// Usuari ha redimensionat manualment (arrossegar vora)
// Actualitzar el nostre tracking
SDL_GetWindowSize(finestra_, &current_width_, &current_height_);
std::cout << "Finestra redimensionada manualment a " << current_width_
<< "x" << current_height_ << std::endl;
return true;
}
return false;
}
void SDLManager::neteja(uint8_t r, uint8_t g, uint8_t b) {
if (!renderer_)
return;
if (!renderer_)
return;
// [MODIFICAT] Usar color oscil·lat del fons en lloc dels paràmetres
(void)r;
(void)g;
(void)b; // Suprimir warnings
SDL_Color bg = color_oscillator_.getCurrentBackgroundColor();
SDL_SetRenderDrawColor(renderer_, bg.r, bg.g, bg.b, 255);
SDL_RenderClear(renderer_);
// [MODIFICAT] Usar color oscil·lat del fons en lloc dels paràmetres
(void)r;
(void)g;
(void)b; // Suprimir warnings
SDL_Color bg = color_oscillator_.getCurrentBackgroundColor();
SDL_SetRenderDrawColor(renderer_, bg.r, bg.g, bg.b, 255);
SDL_RenderClear(renderer_);
}
void SDLManager::presenta() {
if (!renderer_)
return;
if (!renderer_)
return;
SDL_RenderPresent(renderer_);
SDL_RenderPresent(renderer_);
}
// [NUEVO] Actualitzar colors amb oscil·lació
void SDLManager::updateColors(float delta_time) {
color_oscillator_.update(delta_time);
color_oscillator_.update(delta_time);
// Actualitzar color global de línies
Rendering::setLineColor(color_oscillator_.getCurrentLineColor());
// Actualitzar color global de línies
Rendering::setLineColor(color_oscillator_.getCurrentLineColor());
}

View File

@@ -4,56 +4,58 @@
#ifndef SDL_MANAGER_HPP
#define SDL_MANAGER_HPP
#include "core/rendering/color_oscillator.hpp"
#include <SDL3/SDL.h>
#include <cstdint>
#include "core/rendering/color_oscillator.hpp"
class SDLManager {
public:
SDLManager(); // Constructor per defecte (usa Defaults::)
SDLManager(int width, int height,
bool fullscreen); // Constructor amb configuració
~SDLManager();
public:
SDLManager(); // Constructor per defecte (usa Defaults::)
SDLManager(int width, int height,
bool fullscreen); // Constructor amb configuració
~SDLManager();
// No permetre còpia ni assignació
SDLManager(const SDLManager &) = delete;
SDLManager &operator=(const SDLManager &) = delete;
// No permetre còpia ni assignació
SDLManager(const SDLManager&) = delete;
SDLManager& operator=(const SDLManager&) = delete;
// [NUEVO] Gestió de finestra dinàmica
void increaseWindowSize(); // F2: +100px
void decreaseWindowSize(); // F1: -100px
void toggleFullscreen(); // F3
bool
handleWindowEvent(const SDL_Event &event); // Per a SDL_EVENT_WINDOW_RESIZED
// [NUEVO] Gestió de finestra dinàmica
void increaseWindowSize(); // F2: +100px
void decreaseWindowSize(); // F1: -100px
void toggleFullscreen(); // F3
bool
handleWindowEvent(const SDL_Event& event); // Per a SDL_EVENT_WINDOW_RESIZED
// Funcions principals (renderitzat)
void neteja(uint8_t r = 0, uint8_t g = 0, uint8_t b = 0);
void presenta();
// Funcions principals (renderitzat)
void neteja(uint8_t r = 0, uint8_t g = 0, uint8_t b = 0);
void presenta();
// [NUEVO] Actualització de colors (oscil·lació)
void updateColors(float delta_time);
// [NUEVO] Actualització de colors (oscil·lació)
void updateColors(float delta_time);
// Getters
SDL_Renderer *obte_renderer() { return renderer_; }
// Getters
SDL_Renderer* obte_renderer() { return renderer_; }
private:
SDL_Window *finestra_;
SDL_Renderer *renderer_;
private:
SDL_Window* finestra_;
SDL_Renderer* renderer_;
// [NUEVO] Estat de la finestra
int current_width_; // Mida física actual
int current_height_;
bool is_fullscreen_;
int max_width_; // Calculat des del display
int max_height_;
// [NUEVO] Estat de la finestra
int current_width_; // Mida física actual
int current_height_;
bool is_fullscreen_;
int max_width_; // Calculat des del display
int max_height_;
// [NUEVO] Funcions internes
void calculateMaxWindowSize(); // Llegir resolució del display
void applyWindowSize(int width, int height); // Canviar mida + centrar
void updateLogicalPresentation(); // Actualitzar viewport
// [NUEVO] Funcions internes
void calculateMaxWindowSize(); // Llegir resolució del display
void applyWindowSize(int width, int height); // Canviar mida + centrar
void updateLogicalPresentation(); // Actualitzar viewport
// [NUEVO] Oscil·lador de colors
Rendering::ColorOscillator color_oscillator_;
// [NUEVO] Oscil·lador de colors
Rendering::ColorOscillator color_oscillator_;
};
#endif // SDL_MANAGER_HPP
#endif // SDL_MANAGER_HPP