// escena_logo.cpp - Implementació de l'escena logo // © 2025 Port a C++20 #include "escena_logo.hpp" #include "../../core/system/gestor_escenes.hpp" #include "../../core/system/global_events.hpp" #include "../../core/graphics/shape_loader.hpp" #include "../../core/rendering/shape_renderer.hpp" #include #include #include EscenaLogo::EscenaLogo(SDLManager& sdl) : sdl_(sdl), temps_acumulat_(0.0f) { std::cout << "Escena Logo: Inicialitzant...\n"; inicialitzar_lletres(); } void EscenaLogo::executar() { SDL_Event event; Uint64 last_time = SDL_GetTicks(); while (GestorEscenes::actual == GestorEscenes::Escena::LOGO) { // Calcular delta_time real Uint64 current_time = SDL_GetTicks(); float delta_time = (current_time - last_time) / 1000.0f; last_time = current_time; // Limitar delta_time per evitar grans salts if (delta_time > 0.05f) { delta_time = 0.05f; } // Processar events SDL while (SDL_PollEvent(&event)) { // Manejo de finestra if (sdl_.handleWindowEvent(event)) { continue; } // Events globals (F1/F2/F3/ESC/QUIT) if (GlobalEvents::handle(event, sdl_)) { continue; } // Processar events de l'escena (qualsevol tecla/clic salta al joc) processar_events(event); } // Actualitzar lògica actualitzar(delta_time); // Actualitzar colors oscil·lats (efecte verd global) sdl_.updateColors(delta_time); // Dibuixar dibuixar(); } std::cout << "Escena Logo: Finalitzant...\n"; } void EscenaLogo::inicialitzar_lletres() { using namespace Graphics; // Llista de fitxers .shp (A repetida per a les dues A's) std::vector fitxers = { "letra_j.shp", "letra_a.shp", "letra_i.shp", "letra_l.shp", "letra_g.shp", "letra_a.shp", "letra_m.shp", "letra_e.shp", "letra_s.shp" }; // Pas 1: Carregar totes les formes i calcular amplades float ancho_total = 0.0f; for (const auto& fitxer : fitxers) { auto forma = ShapeLoader::load(fitxer); if (!forma || !forma->es_valida()) { std::cerr << "[EscenaLogo] Error carregant " << fitxer << std::endl; continue; } // Calcular bounding box de la forma (trobar ancho) float min_x = FLT_MAX; float max_x = -FLT_MAX; for (const auto& prim : forma->get_primitives()) { for (const auto& punt : prim.points) { min_x = std::min(min_x, punt.x); max_x = std::max(max_x, punt.x); } } float ancho = max_x - min_x; lletres_.push_back({ forma, {0.0f, 0.0f}, // Posició es calcularà després ancho }); ancho_total += ancho; } // Pas 2: Afegir espaiat entre lletres ancho_total += ESPAI_ENTRE_LLETRES * (lletres_.size() - 1); // Pas 3: Calcular posició inicial (centrat horitzontal) constexpr float PANTALLA_ANCHO = 640.0f; constexpr float PANTALLA_ALTO = 480.0f; float x_inicial = (PANTALLA_ANCHO - ancho_total) / 2.0f; float y_centre = PANTALLA_ALTO / 2.0f; // Pas 4: Assignar posicions a cada lletra float x_actual = x_inicial; for (auto& lletra : lletres_) { // Centre de la lletra en pantalla lletra.posicio.x = x_actual + lletra.ancho / 2.0f; lletra.posicio.y = y_centre; // Avançar per a següent lletra x_actual += lletra.ancho + ESPAI_ENTRE_LLETRES; } std::cout << "[EscenaLogo] " << lletres_.size() << " lletres carregades, ancho total: " << ancho_total << " px\n"; } float EscenaLogo::calcular_escala_zoom(float temps) const { if (temps >= DURACIO_ZOOM) { return ESCALA_FINAL; // Animació acabada } // Progrés normalitzat (0.0 a 1.0) float t = temps / DURACIO_ZOOM; // Ease-out quadràtic: y = 1 - (1-t)^2 // Comença ràpid, acaba suau float factor = 1.0f - (1.0f - t) * (1.0f - t); // Interpolar entre escala inicial i final return ESCALA_INICIAL + (ESCALA_FINAL - ESCALA_INICIAL) * factor; } void EscenaLogo::actualitzar(float delta_time) { temps_acumulat_ += delta_time; // Després de DURACIO_TOTAL segons, saltar al joc if (temps_acumulat_ >= DURACIO_TOTAL) { GestorEscenes::actual = GestorEscenes::Escena::JOC; } } void EscenaLogo::dibuixar() { // Fons negre sdl_.neteja(0, 0, 0); // Calcular escala actual del zoom float escala = calcular_escala_zoom(temps_acumulat_); // Dibuixar cada lletra amb l'escala animada for (const auto& lletra : lletres_) { Rendering::render_shape( sdl_.obte_renderer(), lletra.forma, lletra.posicio, // Posició en pantalla 0.0f, // Sense rotació escala, // Escala animada true // Dibuixar ); } sdl_.presenta(); } void EscenaLogo::processar_events(const SDL_Event& event) { // Qualsevol tecla o clic de ratolí salta al joc if (event.type == SDL_EVENT_KEY_DOWN || event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) { GestorEscenes::actual = GestorEscenes::Escena::JOC; } }