diff --git a/CMakeLists.txt b/CMakeLists.txt index eef6346..8fcf3be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # CMakeLists.txt cmake_minimum_required(VERSION 3.10) -project(orni VERSION 0.1.0) +project(orni VERSION 0.2.0) # Info del proyecto set(PROJECT_LONG_NAME "Orni Attack") diff --git a/source/core/rendering/sdl_manager.hpp b/source/core/rendering/sdl_manager.hpp index 52788e5..0af3ac6 100644 --- a/source/core/rendering/sdl_manager.hpp +++ b/source/core/rendering/sdl_manager.hpp @@ -4,9 +4,9 @@ #ifndef SDL_MANAGER_HPP #define SDL_MANAGER_HPP +#include "core/rendering/color_oscillator.hpp" #include #include -#include "core/rendering/color_oscillator.hpp" class SDLManager { public: diff --git a/source/game/constants.hpp b/source/game/constants.hpp index 961ce92..c8fed3a 100644 --- a/source/game/constants.hpp +++ b/source/game/constants.hpp @@ -7,10 +7,12 @@ namespace Constants { // Marges de l'àrea de joc (derivats de Defaults::Zones::GAME) -constexpr int MARGE_ESQ = static_cast(Defaults::Zones::GAME.x); -constexpr int MARGE_DRET = static_cast(Defaults::Zones::GAME.x + Defaults::Zones::GAME.w); -constexpr int MARGE_DALT = static_cast(Defaults::Zones::GAME.y); -constexpr int MARGE_BAIX = static_cast(Defaults::Zones::GAME.y + Defaults::Zones::GAME.h); +constexpr int MARGE_ESQ = static_cast(Defaults::Zones::PLAYAREA.x); +constexpr int MARGE_DRET = + static_cast(Defaults::Zones::PLAYAREA.x + Defaults::Zones::PLAYAREA.w); +constexpr int MARGE_DALT = static_cast(Defaults::Zones::PLAYAREA.y); +constexpr int MARGE_BAIX = + static_cast(Defaults::Zones::PLAYAREA.y + Defaults::Zones::PLAYAREA.h); // Límits de polígons i objectes constexpr int MAX_IPUNTS = Defaults::Entities::MAX_IPUNTS; @@ -27,11 +29,12 @@ constexpr float PI = Defaults::Math::PI; // Helpers per comprovar límits de zona inline bool dins_zona_joc(float x, float y) { const SDL_FPoint punt = {x, y}; - return SDL_PointInRectFloat(&punt, &Defaults::Zones::GAME); + return SDL_PointInRectFloat(&punt, &Defaults::Zones::PLAYAREA); } -inline void obtenir_limits_zona(float& min_x, float& max_x, float& min_y, float& max_y) { - const auto& zona = Defaults::Zones::GAME; +inline void obtenir_limits_zona(float &min_x, float &max_x, float &min_y, + float &max_y) { + const auto &zona = Defaults::Zones::PLAYAREA; min_x = zona.x; max_x = zona.x + zona.w; min_y = zona.y; diff --git a/source/game/entities/enemic.cpp b/source/game/entities/enemic.cpp index b12da8e..297ffa1 100644 --- a/source/game/entities/enemic.cpp +++ b/source/game/entities/enemic.cpp @@ -27,8 +27,8 @@ void Enemic::inicialitzar() { // Inicialitzar enemic (pentàgon) // Copiat de joc_asteroides.cpp línies 41-54 - // [NUEVO] Ja no cal crear_poligon_regular - la geometria es carrega del fitxer - // Només inicialitzem l'estat de la instància + // [NUEVO] Ja no cal crear_poligon_regular - la geometria es carrega del + // fitxer Només inicialitzem l'estat de la instància // Posició aleatòria dins de l'àrea de joc centre_.x = static_cast((std::rand() % 580) + 30); // 30-610 diff --git a/source/game/entities/enemic.hpp b/source/game/entities/enemic.hpp index 59ce624..ec90d4e 100644 --- a/source/game/entities/enemic.hpp +++ b/source/game/entities/enemic.hpp @@ -30,10 +30,10 @@ private: // [NUEVO] Estat de la instància (separat de la geometria) Punt centre_; - float angle_; // Angle de moviment + float angle_; // Angle de moviment float velocitat_; - float drotacio_; // Delta rotació visual (rad/s) - float rotacio_; // Rotació visual acumulada + float drotacio_; // Delta rotació visual (rad/s) + float rotacio_; // Rotació visual acumulada bool esta_; void mou(float delta_time); diff --git a/source/game/entities/nau.cpp b/source/game/entities/nau.cpp index dd54286..d5d7404 100644 --- a/source/game/entities/nau.cpp +++ b/source/game/entities/nau.cpp @@ -28,8 +28,8 @@ void Nau::inicialitzar() { // Basat en el codi Pascal original: lines 380-384 // Copiat de joc_asteroides.cpp línies 30-44 - // [NUEVO] Ja no cal configurar punts polars - la geometria es carrega del fitxer - // Només inicialitzem l'estat de la instància + // [NUEVO] Ja no cal configurar punts polars - la geometria es carrega del + // fitxer Només inicialitzem l'estat de la instància // Posició inicial al centre de la pantalla centre_.x = 320.0f; diff --git a/source/game/entities/nau.hpp b/source/game/entities/nau.hpp index aca373d..9dc431d 100644 --- a/source/game/entities/nau.hpp +++ b/source/game/entities/nau.hpp @@ -29,13 +29,14 @@ public: private: SDL_Renderer *renderer_; - // [NUEVO] Forma vectorial (compartida, només 1 instància de Nau però preparat per reutilització) + // [NUEVO] Forma vectorial (compartida, només 1 instància de Nau però preparat + // per reutilització) std::shared_ptr forma_; // [NUEVO] Estat de la instància (separat de la geometria) Punt centre_; - float angle_; // Angle d'orientació - float velocitat_; // Velocitat (px/s) + float angle_; // Angle d'orientació + float velocitat_; // Velocitat (px/s) bool esta_tocada_; void aplicar_fisica(float delta_time); diff --git a/source/game/escenes/escena_joc.cpp b/source/game/escenes/escena_joc.cpp index bac48f8..85c6185 100644 --- a/source/game/escenes/escena_joc.cpp +++ b/source/game/escenes/escena_joc.cpp @@ -11,8 +11,9 @@ #include #include -EscenaJoc::EscenaJoc(SDLManager& sdl) - : sdl_(sdl), nau_(sdl.obte_renderer()), itocado_(0), text_(sdl.obte_renderer()) { +EscenaJoc::EscenaJoc(SDLManager &sdl) + : sdl_(sdl), nau_(sdl.obte_renderer()), itocado_(0), + text_(sdl.obte_renderer()) { // Inicialitzar bales amb renderer for (auto &bala : bales_) { bala = Bala(sdl.obte_renderer()); @@ -171,7 +172,7 @@ void EscenaJoc::tocado() { void EscenaJoc::dibuixar_marges() const { // Dibuixar rectangle de la zona de joc - const SDL_FRect& zona = Defaults::Zones::GAME; + const SDL_FRect &zona = Defaults::Zones::PLAYAREA; // Coordenades dels cantons int x1 = static_cast(zona.x); @@ -188,25 +189,22 @@ void EscenaJoc::dibuixar_marges() const { void EscenaJoc::dibuixar_marcador() { // Text estàtic (hardcoded) - const std::string text = "SCORE: 00000 LIFE: 3 LEVEL: 01"; + const std::string text = "SCORE: 01000 LIFE: 3 LEVEL: 01"; - // Escala ajustada per cabre en 640px d'amplada - // Zona marcador: width = 640 px, height = 64 px - // Text: 34 caràcters → necessitem ~487 px amb escala 1.2 - // Altura caràcter: 20 * 1.2 = 24 px (37.5% de 64px) - const float escala = 1.2f; - const float spacing = 2.0f; + // Paràmetres de renderització + const float escala = 0.85f; + const float spacing = 0.0f; - // Calcular amplada total del text + // Calcular dimensions del text float text_width = text_.get_text_width(text, escala, spacing); + float text_height = text_.get_text_height(escala); - // Centrat horitzontal + // Centrat horitzontal dins de la zona del marcador float x = (Defaults::Zones::SCOREBOARD.w - text_width) / 2.0f; - // Centrat vertical - // Altura del caràcter escalat: 20 * 1.2 = 24 px - // Marge superior: (64 - 24) / 2 = 20 px - float y = Defaults::Zones::SCOREBOARD.y + 20.0f; + // Centrat vertical dins de la zona del marcador + float y = Defaults::Zones::SCOREBOARD.y + + (Defaults::Zones::SCOREBOARD.h - text_height) / 2.0f; // Renderitzar text_.render(text, {x, y}, escala, spacing); diff --git a/source/game/escenes/escena_joc.hpp b/source/game/escenes/escena_joc.hpp index 2338b43..aa835dc 100644 --- a/source/game/escenes/escena_joc.hpp +++ b/source/game/escenes/escena_joc.hpp @@ -19,17 +19,17 @@ // Classe principal del joc (escena) class EscenaJoc { public: - explicit EscenaJoc(SDLManager& sdl); + explicit EscenaJoc(SDLManager &sdl); ~EscenaJoc() = default; - void executar(); // Bucle principal de l'escena + void executar(); // Bucle principal de l'escena void inicialitzar(); void actualitzar(float delta_time); void dibuixar(); void processar_input(const SDL_Event &event); private: - SDLManager& sdl_; + SDLManager &sdl_; // Estat del joc Nau nau_; diff --git a/source/game/escenes/escena_logo.cpp b/source/game/escenes/escena_logo.cpp index 0b97695..9a46a6e 100644 --- a/source/game/escenes/escena_logo.cpp +++ b/source/game/escenes/escena_logo.cpp @@ -2,20 +2,18 @@ // © 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 "../../core/system/gestor_escenes.hpp" +#include "../../core/system/global_events.hpp" #include +#include +#include // Helper: calcular el progrés individual d'una lletra // en funció del progrés global (efecte seqüencial) -static float calcular_progress_letra(size_t letra_index, - size_t num_letras, - float global_progress, - float threshold) { +static float calcular_progress_letra(size_t letra_index, size_t num_letras, + float global_progress, float threshold) { if (num_letras == 0) return 1.0f; @@ -27,18 +25,17 @@ static float calcular_progress_letra(size_t letra_index, // Interpolar progrés if (global_progress < start) { - return 0.0f; // Encara no ha començat + return 0.0f; // Encara no ha començat } else if (global_progress >= end) { - return 1.0f; // Completament apareguda + return 1.0f; // Completament apareguda } else { return (global_progress - start) / (end - start); } } -EscenaLogo::EscenaLogo(SDLManager& sdl) - : sdl_(sdl), - estat_actual_(EstatAnimacio::PRE_ANIMATION), - temps_estat_actual_(0.0f) { +EscenaLogo::EscenaLogo(SDLManager &sdl) + : sdl_(sdl), estat_actual_(EstatAnimacio::PRE_ANIMATION), + temps_estat_actual_(0.0f) { std::cout << "Escena Logo: Inicialitzant...\n"; inicialitzar_lletres(); } @@ -92,14 +89,14 @@ void EscenaLogo::inicialitzar_lletres() { // Llista de fitxers .shp (A repetida per a les dues A's) std::vector fitxers = { - "logo/letra_j.shp", "logo/letra_a.shp", "logo/letra_i.shp", "logo/letra_l.shp", - "logo/letra_g.shp", "logo/letra_a.shp", "logo/letra_m.shp", "logo/letra_e.shp", "logo/letra_s.shp" - }; + "logo/letra_j.shp", "logo/letra_a.shp", "logo/letra_i.shp", + "logo/letra_l.shp", "logo/letra_g.shp", "logo/letra_a.shp", + "logo/letra_m.shp", "logo/letra_e.shp", "logo/letra_s.shp"}; // Pas 1: Carregar totes les formes i calcular amplades float ancho_total = 0.0f; - for (const auto& fitxer : fitxers) { + for (const auto &fitxer : fitxers) { auto forma = ShapeLoader::load(fitxer); if (!forma || !forma->es_valida()) { std::cerr << "[EscenaLogo] Error carregant " << fitxer << std::endl; @@ -110,8 +107,8 @@ void EscenaLogo::inicialitzar_lletres() { float min_x = FLT_MAX; float max_x = -FLT_MAX; - for (const auto& prim : forma->get_primitives()) { - for (const auto& punt : prim.points) { + 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); } @@ -124,12 +121,10 @@ void EscenaLogo::inicialitzar_lletres() { float ancho = ancho_sin_escalar * ESCALA_FINAL; float offset_centre = (forma->get_centre().x - min_x) * ESCALA_FINAL; - lletres_.push_back({ - forma, - {0.0f, 0.0f}, // Posició es calcularà després - ancho, - offset_centre - }); + lletres_.push_back({forma, + {0.0f, 0.0f}, // Posició es calcularà després + ancho, + offset_centre}); ancho_total += ancho; } @@ -147,7 +142,7 @@ void EscenaLogo::inicialitzar_lletres() { // Pas 4: Assignar posicions a cada lletra float x_actual = x_inicial; - for (auto& lletra : lletres_) { + for (auto &lletra : lletres_) { // Posicionar el centre de la forma (shape_centre) en pantalla // Usar offset_centre en lloc de ancho/2 perquè shape_centre // pot no estar exactament al mig del bounding box @@ -164,8 +159,9 @@ void EscenaLogo::inicialitzar_lletres() { void EscenaLogo::canviar_estat(EstatAnimacio nou_estat) { estat_actual_ = nou_estat; - temps_estat_actual_ = 0.0f; // Reset temps - std::cout << "[EscenaLogo] Canvi a estat: " << static_cast(nou_estat) << "\n"; + temps_estat_actual_ = 0.0f; // Reset temps + std::cout << "[EscenaLogo] Canvi a estat: " << static_cast(nou_estat) + << "\n"; } bool EscenaLogo::totes_lletres_completes() const { @@ -177,23 +173,23 @@ void EscenaLogo::actualitzar(float delta_time) { temps_estat_actual_ += delta_time; switch (estat_actual_) { - case EstatAnimacio::PRE_ANIMATION: - if (temps_estat_actual_ >= DURACIO_PRE) { - canviar_estat(EstatAnimacio::ANIMATION); - } - break; + case EstatAnimacio::PRE_ANIMATION: + if (temps_estat_actual_ >= DURACIO_PRE) { + canviar_estat(EstatAnimacio::ANIMATION); + } + break; - case EstatAnimacio::ANIMATION: - if (totes_lletres_completes()) { - canviar_estat(EstatAnimacio::POST_ANIMATION); - } - break; + case EstatAnimacio::ANIMATION: + if (totes_lletres_completes()) { + canviar_estat(EstatAnimacio::POST_ANIMATION); + } + break; - case EstatAnimacio::POST_ANIMATION: - if (temps_estat_actual_ >= DURACIO_POST) { - GestorEscenes::actual = GestorEscenes::Escena::JOC; - } - break; + case EstatAnimacio::POST_ANIMATION: + if (temps_estat_actual_ >= DURACIO_POST) { + GestorEscenes::actual = GestorEscenes::Escena::JOC; + } + break; } } @@ -204,23 +200,25 @@ void EscenaLogo::dibuixar() { // PRE_ANIMATION: Només pantalla negra if (estat_actual_ == EstatAnimacio::PRE_ANIMATION) { sdl_.presenta(); - return; // No renderitzar lletres + return; // No renderitzar lletres } // ANIMATION o POST_ANIMATION: Calcular progrés - float global_progress = (estat_actual_ == EstatAnimacio::ANIMATION) - ? std::min(temps_estat_actual_ / DURACIO_ZOOM, 1.0f) - : 1.0f; // POST: mantenir al 100% + float global_progress = + (estat_actual_ == EstatAnimacio::ANIMATION) + ? std::min(temps_estat_actual_ / DURACIO_ZOOM, 1.0f) + : 1.0f; // POST: mantenir al 100% // Punt inicial del zoom (configurable amb ORIGEN_ZOOM_X/Y) const Punt ORIGEN_ZOOM = {ORIGEN_ZOOM_X, ORIGEN_ZOOM_Y}; // Dibuixar cada lletra amb animació seqüencial for (size_t i = 0; i < lletres_.size(); i++) { - const auto& lletra = lletres_[i]; + const auto &lletra = lletres_[i]; // Calcular progrés individual d'aquesta lletra (0.0 → 1.0) - float letra_progress = calcular_progress_letra(i, lletres_.size(), global_progress, THRESHOLD_LETRA); + float letra_progress = calcular_progress_letra( + i, lletres_.size(), global_progress, THRESHOLD_LETRA); // Si la lletra encara no ha començat, saltar-la if (letra_progress <= 0.0f) { @@ -229,32 +227,34 @@ void EscenaLogo::dibuixar() { // Interpolar posició: des del origen zoom cap a posició final Punt pos_actual; - pos_actual.x = ORIGEN_ZOOM.x + (lletra.posicio.x - ORIGEN_ZOOM.x) * letra_progress; - pos_actual.y = ORIGEN_ZOOM.y + (lletra.posicio.y - ORIGEN_ZOOM.y) * letra_progress; + pos_actual.x = + ORIGEN_ZOOM.x + (lletra.posicio.x - ORIGEN_ZOOM.x) * letra_progress; + pos_actual.y = + ORIGEN_ZOOM.y + (lletra.posicio.y - ORIGEN_ZOOM.y) * letra_progress; // Aplicar ease-out quadràtic per suavitat float t = letra_progress; float ease_factor = 1.0f - (1.0f - t) * (1.0f - t); // Interpolar escala amb ease-out: des de ESCALA_INICIAL cap a ESCALA_FINAL - float escala_actual = ESCALA_INICIAL + (ESCALA_FINAL - ESCALA_INICIAL) * ease_factor; + float escala_actual = + ESCALA_INICIAL + (ESCALA_FINAL - ESCALA_INICIAL) * ease_factor; // Renderitzar la lletra Rendering::render_shape( - sdl_.obte_renderer(), - lletra.forma, - pos_actual, // Posició interpolada - 0.0f, // Sense rotació - escala_actual, // Escala interpolada amb ease-out - true, // Dibuixar - 1.0f // Progress = 1.0 (lletra completa, sense animació de primitives) + sdl_.obte_renderer(), lletra.forma, + pos_actual, // Posició interpolada + 0.0f, // Sense rotació + escala_actual, // Escala interpolada amb ease-out + true, // Dibuixar + 1.0f // Progress = 1.0 (lletra completa, sense animació de primitives) ); } sdl_.presenta(); } -void EscenaLogo::processar_events(const SDL_Event& event) { +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) { diff --git a/source/game/escenes/escena_logo.hpp b/source/game/escenes/escena_logo.hpp index dedec66..36a6ff3 100644 --- a/source/game/escenes/escena_logo.hpp +++ b/source/game/escenes/escena_logo.hpp @@ -4,29 +4,30 @@ #pragma once -#include "../../core/rendering/sdl_manager.hpp" #include "../../core/graphics/shape.hpp" +#include "../../core/rendering/sdl_manager.hpp" #include "../../core/types.hpp" #include -#include #include +#include class EscenaLogo { public: - explicit EscenaLogo(SDLManager& sdl); - void executar(); // Bucle principal de l'escena + explicit EscenaLogo(SDLManager &sdl); + void executar(); // Bucle principal de l'escena private: // Màquina d'estats per l'animació enum class EstatAnimacio { - PRE_ANIMATION, // Pantalla negra inicial - ANIMATION, // Animació de zoom de lletres - POST_ANIMATION // Logo complet visible + PRE_ANIMATION, // Pantalla negra inicial + ANIMATION, // Animació de zoom de lletres + POST_ANIMATION // Logo complet visible }; - SDLManager& sdl_; - EstatAnimacio estat_actual_; // Estat actual de la màquina - float temps_estat_actual_; // Temps en l'estat actual (reset en cada transició) + SDLManager &sdl_; + EstatAnimacio estat_actual_; // Estat actual de la màquina + float + temps_estat_actual_; // Temps en l'estat actual (reset en cada transició) // Estructura per a cada lletra del logo struct LetraLogo { @@ -36,26 +37,31 @@ private: float offset_centre; // Distància de min_x a shape_centre.x }; - std::vector lletres_; // 9 lletres: J-A-I-L-G-A-M-E-S + std::vector lletres_; // 9 lletres: J-A-I-L-G-A-M-E-S // Constants d'animació - static constexpr float DURACIO_PRE = 1.5f; // Duració PRE_ANIMATION (pantalla negra) - static constexpr float DURACIO_ZOOM = 4.0f; // Duració del zoom (segons) - static constexpr float DURACIO_POST = 4.0f; // Duració POST_ANIMATION (logo complet) - static constexpr float ESCALA_INICIAL = 0.1f; // Escala inicial (10%) - static constexpr float ESCALA_FINAL = 0.8f; // Escala final (80%) - static constexpr float ESPAI_ENTRE_LLETRES = 10.0f; // Espaiat entre lletres + static constexpr float DURACIO_PRE = + 1.5f; // Duració PRE_ANIMATION (pantalla negra) + static constexpr float DURACIO_ZOOM = 4.0f; // Duració del zoom (segons) + static constexpr float DURACIO_POST = + 4.0f; // Duració POST_ANIMATION (logo complet) + static constexpr float ESCALA_INICIAL = 0.1f; // Escala inicial (10%) + static constexpr float ESCALA_FINAL = 0.8f; // Escala final (80%) + static constexpr float ESPAI_ENTRE_LLETRES = 10.0f; // Espaiat entre lletres // Constants d'animació seqüencial - static constexpr float THRESHOLD_LETRA = 0.6f; // Umbral per activar següent lletra (0.0-1.0) - static constexpr float ORIGEN_ZOOM_X = 640.0f / 2.0f; // Punt inicial X del zoom (320) - static constexpr float ORIGEN_ZOOM_Y = 480.0f * 0.4f; // Punt inicial Y del zoom (240) + static constexpr float THRESHOLD_LETRA = + 0.6f; // Umbral per activar següent lletra (0.0-1.0) + static constexpr float ORIGEN_ZOOM_X = + 640.0f / 2.0f; // Punt inicial X del zoom (320) + static constexpr float ORIGEN_ZOOM_Y = + 480.0f * 0.4f; // Punt inicial Y del zoom (240) // Mètodes privats void inicialitzar_lletres(); void actualitzar(float delta_time); void dibuixar(); - void processar_events(const SDL_Event& event); + void processar_events(const SDL_Event &event); // Mètodes de gestió d'estats void canviar_estat(EstatAnimacio nou_estat);