diff --git a/source/core/entities/entitat.hpp b/source/core/entities/entitat.hpp deleted file mode 100644 index a9882bb..0000000 --- a/source/core/entities/entitat.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// entitat.hpp - Classe base abstracta per a totes les entitats del joc -// © 2025 Orni Attack - Arquitectura d'entitats - -#pragma once - -#include - -#include - -#include "core/graphics/shape.hpp" -#include "core/types.hpp" - -namespace Entities { - -class Entitat { - public: - virtual ~Entitat() = default; - - // Interfície principal (virtual pur) - virtual void inicialitzar() = 0; - virtual void actualitzar(float delta_time) = 0; - virtual void dibuixar() const = 0; - [[nodiscard]] virtual bool esta_actiu() const = 0; - - // Interfície de col·lisió (override opcional) - [[nodiscard]] virtual float get_collision_radius() const { return 0.0F; } - [[nodiscard]] virtual bool es_collidable() const { return false; } - - // Getters comuns (inline, sense overhead) - [[nodiscard]] const Vec2& get_centre() const { return centre_; } - [[nodiscard]] float get_angle() const { return angle_; } - [[nodiscard]] float get_brightness() const { return brightness_; } - [[nodiscard]] const std::shared_ptr& get_forma() const { return forma_; } - - protected: - // Estat comú (accés directe, sense overhead) - SDL_Renderer* renderer_; - std::shared_ptr forma_; - Vec2 centre_; - float angle_{0.0F}; - float brightness_{1.0F}; - - // Constructor protegit (classe abstracta) - Entitat(SDL_Renderer* renderer = nullptr) - : renderer_(renderer), - centre_({.x = 0.0F, .y = 0.0F}) {} -}; - -} // namespace Entities diff --git a/source/core/entities/entity.hpp b/source/core/entities/entity.hpp new file mode 100644 index 0000000..52b085e --- /dev/null +++ b/source/core/entities/entity.hpp @@ -0,0 +1,49 @@ +// entitat.hpp - Classe base abstracta per a totes les entitats del joc +// © 2025 Orni Attack - Arquitectura d'entitats + +#pragma once + +#include + +#include + +#include "core/graphics/shape.hpp" +#include "core/types.hpp" + +namespace Entities { + +class Entity { + public: + virtual ~Entity() = default; + + // Interfície principal (virtual pur) + virtual void init() = 0; + virtual void update(float delta_time) = 0; + virtual void draw() const = 0; + [[nodiscard]] virtual bool isActive() const = 0; + + // Interfície de col·lisió (override opcional) + [[nodiscard]] virtual float getCollisionRadius() const { return 0.0F; } + [[nodiscard]] virtual bool isCollidable() const { return false; } + + // Getters comuns (inline, sense overhead) + [[nodiscard]] const Vec2& getCenter() const { return center_; } + [[nodiscard]] float getAngle() const { return angle_; } + [[nodiscard]] float getBrightness() const { return brightness_; } + [[nodiscard]] const std::shared_ptr& getShape() const { return shape_; } + + protected: + // Estat comú (accés directe, sense overhead) + SDL_Renderer* renderer_; + std::shared_ptr shape_; + Vec2 center_; + float angle_{0.0F}; + float brightness_{1.0F}; + + // Constructor protegit (classe abstracta) + Entity(SDL_Renderer* renderer = nullptr) + : renderer_(renderer), + center_({.x = 0.0F, .y = 0.0F}) {} +}; + +} // namespace Entities diff --git a/source/core/graphics/shape.cpp b/source/core/graphics/shape.cpp index c69ac70..b7f0af9 100644 --- a/source/core/graphics/shape.cpp +++ b/source/core/graphics/shape.cpp @@ -11,7 +11,7 @@ namespace Graphics { Shape::Shape(const std::string& filepath) - : centre_({.x = 0.0F, .y = 0.0F}), + : center_({.x = 0.0F, .y = 0.0F}), escala_defecte_(1.0F), nom_("unnamed") { carregar(filepath); @@ -124,11 +124,11 @@ void Shape::parse_center(const std::string& value) { size_t comma = val.find(','); if (comma != std::string::npos) { try { - centre_.x = std::stof(trim(val.substr(0, comma))); - centre_.y = std::stof(trim(val.substr(comma + 1))); + center_.x = std::stof(trim(val.substr(0, comma))); + center_.y = std::stof(trim(val.substr(comma + 1))); } catch (...) { std::cerr << "[Shape] Warning: centre invàlid, usant (0,0)" << '\n'; - centre_ = {.x = 0.0F, .y = 0.0F}; + center_ = {.x = 0.0F, .y = 0.0F}; } } } diff --git a/source/core/graphics/shape.hpp b/source/core/graphics/shape.hpp index c206813..f20ffdd 100644 --- a/source/core/graphics/shape.hpp +++ b/source/core/graphics/shape.hpp @@ -39,7 +39,7 @@ class Shape { [[nodiscard]] const std::vector& get_primitives() const { return primitives_; } - [[nodiscard]] const Vec2& get_centre() const { return centre_; } + [[nodiscard]] const Vec2& getCenter() const { return center_; } [[nodiscard]] float get_escala_defecte() const { return escala_defecte_; } [[nodiscard]] bool es_valida() const { return !primitives_.empty(); } @@ -49,7 +49,7 @@ class Shape { private: std::vector primitives_; - Vec2 centre_; // Centre/origen de la forma + Vec2 center_; // Centre/origen de la forma float escala_defecte_; // Escala per defecte (normalment 1.0) std::string nom_; // Nom de la forma (per depuració) diff --git a/source/core/graphics/starfield.cpp b/source/core/graphics/starfield.cpp index 6f5fa79..4f4044a 100644 --- a/source/core/graphics/starfield.cpp +++ b/source/core/graphics/starfield.cpp @@ -113,7 +113,7 @@ float Starfield::calcular_brightness(const Estrella& estrella) const { } // Actualitzar posicions de les estrelles -void Starfield::actualitzar(float delta_time) { +void Starfield::update(float delta_time) { for (auto& estrella : estrelles_) { // Obtenir configuració de la capa const CapaConfig& capa = capes_[estrella.capa]; @@ -145,7 +145,7 @@ void Starfield::set_brightness(float multiplier) { } // Dibuixar totes les estrelles -void Starfield::dibuixar() { +void Starfield::draw() { if (!shape_estrella_->es_valida()) { return; } diff --git a/source/core/graphics/starfield.hpp b/source/core/graphics/starfield.hpp index 34e71cf..6304154 100644 --- a/source/core/graphics/starfield.hpp +++ b/source/core/graphics/starfield.hpp @@ -35,10 +35,10 @@ class Starfield { int densitat = 150); // Actualitzar posicions de les estrelles - void actualitzar(float delta_time); + void update(float delta_time); // Dibuixar totes les estrelles - void dibuixar(); + void draw(); // Setters per ajustar paràmetres en temps real void set_punt_fuga(const Vec2& punt) { punt_fuga_ = punt; } diff --git a/source/core/physics/collision.hpp b/source/core/physics/collision.hpp index 2a67483..0891fd4 100644 --- a/source/core/physics/collision.hpp +++ b/source/core/physics/collision.hpp @@ -3,25 +3,25 @@ #pragma once -#include "core/entities/entitat.hpp" +#include "core/entities/entity.hpp" #include "core/types.hpp" namespace Physics { // Comprovació genèrica de col·lisió entre dues entitats -inline bool check_collision(const Entities::Entitat& a, const Entities::Entitat& b, float amplifier = 1.0F) { +inline bool check_collision(const Entities::Entity& a, const Entities::Entity& b, float amplifier = 1.0F) { // Comprovar si ambdós són col·lisionables - if (!a.es_collidable() || !b.es_collidable()) { + if (!a.isCollidable() || !b.isCollidable()) { return false; } // Calcular radi combinat (amb amplificador per hitbox generós) - float suma_radis = (a.get_collision_radius() + b.get_collision_radius()) * amplifier; + float suma_radis = (a.getCollisionRadius() + b.getCollisionRadius()) * amplifier; float suma_radis_sq = suma_radis * suma_radis; // Comprovació distància al quadrat (sense sqrt) - const Vec2& pos_a = a.get_centre(); - const Vec2& pos_b = b.get_centre(); + const Vec2& pos_a = a.getCenter(); + const Vec2& pos_b = b.getCenter(); float dx = pos_a.x - pos_b.x; float dy = pos_a.y - pos_b.y; float dist_sq = (dx * dx) + (dy * dy); diff --git a/source/core/rendering/shape_renderer.cpp b/source/core/rendering/shape_renderer.cpp index a35a809..5873bfb 100644 --- a/source/core/rendering/shape_renderer.cpp +++ b/source/core/rendering/shape_renderer.cpp @@ -85,13 +85,13 @@ void render_shape(SDL_Renderer* renderer, return; } - // Si progress < 1.0, no dibuixar (tot o res) + // Si progress < 1.0, no draw (tot o res) if (progress < 1.0F) { return; } // Obtenir el centre de la forma per a transformacions - const Vec2& shape_centre = shape->get_centre(); + const Vec2& shape_centre = shape->getCenter(); // Iterar sobre totes les primitives for (const auto& primitive : shape->get_primitives()) { diff --git a/source/core/rendering/shape_renderer.hpp b/source/core/rendering/shape_renderer.hpp index 72f8242..64e838b 100644 --- a/source/core/rendering/shape_renderer.hpp +++ b/source/core/rendering/shape_renderer.hpp @@ -34,7 +34,7 @@ struct Rotation3D { // Renderitzar forma amb transformacions // - renderer: SDL renderer -// - shape: forma vectorial a dibuixar +// - shape: forma vectorial a draw // - posicio: posició del centre en coordenades mundials // - angle: rotació en radians (0 = amunt, sentit horari) // - escala: factor d'escala (1.0 = mida original) diff --git a/source/game/effects/debris_manager.cpp b/source/game/effects/debris_manager.cpp index 10865c1..da3977f 100644 --- a/source/game/effects/debris_manager.cpp +++ b/source/game/effects/debris_manager.cpp @@ -62,7 +62,7 @@ void DebrisManager::explotar(const std::shared_ptr& shape, Audio::get()->playSound(sound, Audio::Group::GAME); // Obtenir centre de la forma per a transformacions - const Vec2& shape_centre = shape->get_centre(); + const Vec2& shape_centre = shape->getCenter(); // Iterar sobre totes les primitives de la forma for (const auto& primitive : shape->get_primitives()) { @@ -204,7 +204,7 @@ void DebrisManager::explotar(const std::shared_ptr& shape, } } -void DebrisManager::actualitzar(float delta_time) { +void DebrisManager::update(float delta_time) { for (auto& debris : debris_pool_) { if (!debris.actiu) { continue; @@ -302,7 +302,7 @@ void DebrisManager::actualitzar(float delta_time) { } } -void DebrisManager::dibuixar() const { +void DebrisManager::draw() const { for (const auto& debris : debris_pool_) { if (!debris.actiu) { continue; diff --git a/source/game/effects/debris_manager.hpp b/source/game/effects/debris_manager.hpp index 4020ab5..93fe099 100644 --- a/source/game/effects/debris_manager.hpp +++ b/source/game/effects/debris_manager.hpp @@ -42,10 +42,10 @@ class DebrisManager { const std::string& sound = Defaults::Sound::EXPLOSION); // Actualitzar tots els fragments actius - void actualitzar(float delta_time); + void update(float delta_time); // Dibuixar tots els fragments actius - void dibuixar() const; + void draw() const; // Reiniciar tots els fragments (neteja) void reiniciar(); diff --git a/source/game/effects/gestor_puntuacio_flotant.cpp b/source/game/effects/gestor_puntuacio_flotant.cpp index 4376f7a..2f0156e 100644 --- a/source/game/effects/gestor_puntuacio_flotant.cpp +++ b/source/game/effects/gestor_puntuacio_flotant.cpp @@ -33,7 +33,7 @@ void GestorPuntuacioFlotant::crear(int punts, const Vec2& posicio) { pf->actiu = true; } -void GestorPuntuacioFlotant::actualitzar(float delta_time) { +void GestorPuntuacioFlotant::update(float delta_time) { for (auto& pf : pool_) { if (!pf.actiu) { continue; @@ -57,7 +57,7 @@ void GestorPuntuacioFlotant::actualitzar(float delta_time) { } } -void GestorPuntuacioFlotant::dibuixar() { +void GestorPuntuacioFlotant::draw() { for (const auto& pf : pool_) { if (!pf.actiu) { continue; diff --git a/source/game/effects/gestor_puntuacio_flotant.hpp b/source/game/effects/gestor_puntuacio_flotant.hpp index 0b4b1b8..f276bb4 100644 --- a/source/game/effects/gestor_puntuacio_flotant.hpp +++ b/source/game/effects/gestor_puntuacio_flotant.hpp @@ -26,10 +26,10 @@ class GestorPuntuacioFlotant { void crear(int punts, const Vec2& posicio); // Actualitzar tots els números actius - void actualitzar(float delta_time); + void update(float delta_time); // Dibuixar tots els números actius - void dibuixar(); + void draw(); // Reiniciar tots (neteja) void reiniciar(); diff --git a/source/game/entities/bala.cpp b/source/game/entities/bullet.cpp similarity index 73% rename from source/game/entities/bala.cpp rename to source/game/entities/bullet.cpp index b3d2bc7..c195b93 100644 --- a/source/game/entities/bala.cpp +++ b/source/game/entities/bullet.cpp @@ -2,7 +2,7 @@ // © 1999 Visente i Sergi (versió Pascal) // © 2025 Port a C++20 amb SDL3 -#include "game/entities/bala.hpp" +#include "game/entities/bullet.hpp" #include #include @@ -11,15 +11,15 @@ #include "core/audio/audio.hpp" #include "core/defaults.hpp" -#include "core/entities/entitat.hpp" +#include "core/entities/entity.hpp" #include "core/graphics/shape_loader.hpp" #include "core/rendering/shape_renderer.hpp" #include "core/types.hpp" #include "game/constants.hpp" -Bala::Bala(SDL_Renderer* renderer) - : Entitat(renderer), - velocitat_(0.0F), +Bullet::Bullet(SDL_Renderer* renderer) + : Entity(renderer), + velocity_(0.0F), esta_(false), owner_id_(0), grace_timer_(0.0F) { @@ -27,23 +27,23 @@ Bala::Bala(SDL_Renderer* renderer) brightness_ = Defaults::Brightness::BALA; // [NUEVO] Carregar forma compartida des de fitxer - forma_ = Graphics::ShapeLoader::load("bullet.shp"); + shape_ = Graphics::ShapeLoader::load("bullet.shp"); - if (!forma_ || !forma_->es_valida()) { - std::cerr << "[Bala] Error: no s'ha pogut carregar bullet.shp" << '\n'; + if (!shape_ || !shape_->es_valida()) { + std::cerr << "[Bullet] Error: no s'ha pogut carregar bullet.shp" << '\n'; } } -void Bala::inicialitzar() { +void Bullet::init() { // Inicialment inactiva esta_ = false; - centre_ = {.x = 0.0F, .y = 0.0F}; + center_ = {.x = 0.0F, .y = 0.0F}; angle_ = 0.0F; - velocitat_ = 0.0F; + velocity_ = 0.0F; grace_timer_ = 0.0F; } -void Bala::disparar(const Vec2& posicio, float angle, uint8_t owner_id) { +void Bullet::disparar(const Vec2& posicio, float angle, uint8_t owner_id) { // Activar bala i posicionar-la a la nau // Basat en joc_asteroides.cpp línies 188-200 @@ -51,8 +51,8 @@ void Bala::disparar(const Vec2& posicio, float angle, uint8_t owner_id) { esta_ = true; // Posició inicial = centre de la nau - centre_.x = posicio.x; - centre_.y = posicio.y; + center_.x = posicio.x; + center_.y = posicio.y; // Angle = angle de la nau (dispara en la direcció que apunta) angle_ = angle; @@ -62,7 +62,7 @@ void Bala::disparar(const Vec2& posicio, float angle, uint8_t owner_id) { // Velocitat alta (el joc Pascal original usava 7 px/frame) // 7 px/frame × 20 FPS = 140 px/s - velocitat_ = 140.0F; + velocity_ = 140.0F; // Activar grace period (prevents instant self-collision) grace_timer_ = Defaults::Game::BULLET_GRACE_PERIOD; @@ -71,7 +71,7 @@ void Bala::disparar(const Vec2& posicio, float angle, uint8_t owner_id) { Audio::get()->playSound(Defaults::Sound::LASER, Audio::Group::GAME); } -void Bala::actualitzar(float delta_time) { +void Bullet::update(float delta_time) { if (esta_) { // Decrementar grace timer if (grace_timer_ > 0.0F) { @@ -83,30 +83,30 @@ void Bala::actualitzar(float delta_time) { } } -void Bala::dibuixar() const { - if (esta_ && forma_) { +void Bullet::draw() const { + if (esta_ && shape_) { // [NUEVO] Usar render_shape en lloc de rota_pol // Les bales roten segons l'angle de trajectòria - Rendering::render_shape(renderer_, forma_, centre_, angle_, 1.0F, 1.0F, brightness_); + Rendering::render_shape(renderer_, shape_, center_, angle_, 1.0F, 1.0F, brightness_); } } -void Bala::mou(float delta_time) { +void Bullet::mou(float delta_time) { // Moviment rectilini de la bala // Basat en el codi Pascal original: procedure mou_bales // Copiat EXACTAMENT de joc_asteroides.cpp línies 396-419 // Calcular nova posició (moviment polar time-based) // velocitat ja està en px/s (140 px/s), només cal multiplicar per delta_time - float velocitat_efectiva = velocitat_ * delta_time; + float velocitat_efectiva = velocity_ * delta_time; // Calcular desplaçament (angle-PI/2 perquè angle=0 apunta amunt) float dy = velocitat_efectiva * std::sin(angle_ - (Constants::PI / 2.0F)); float dx = velocitat_efectiva * std::cos(angle_ - (Constants::PI / 2.0F)); // Acumulació directa amb precisió subpíxel - centre_.y += dy; - centre_.x += dx; + center_.y += dy; + center_.x += dx; // Desactivar si surt de la zona de joc (no rebota com els ORNIs) // CORRECCIÓ: Usar límits segurs amb radi de la bala @@ -120,8 +120,8 @@ void Bala::mou(float delta_time) { min_y, max_y); - if (centre_.x < min_x || centre_.x > max_x || - centre_.y < min_y || centre_.y > max_y) { + if (center_.x < min_x || center_.x > max_x || + center_.y < min_y || center_.y > max_y) { esta_ = false; } } diff --git a/source/game/entities/bala.hpp b/source/game/entities/bullet.hpp similarity index 59% rename from source/game/entities/bala.hpp rename to source/game/entities/bullet.hpp index e83660d..0448a16 100644 --- a/source/game/entities/bala.hpp +++ b/source/game/entities/bullet.hpp @@ -8,28 +8,28 @@ #include #include "core/defaults.hpp" -#include "core/entities/entitat.hpp" +#include "core/entities/entity.hpp" #include "core/types.hpp" -class Bala : public Entities::Entitat { +class Bullet : public Entities::Entity { public: - Bala() - : Entitat(nullptr) {} - Bala(SDL_Renderer* renderer); + Bullet() + : Entity(nullptr) {} + Bullet(SDL_Renderer* renderer); - void inicialitzar() override; + void init() override; void disparar(const Vec2& posicio, float angle, uint8_t owner_id); - void actualitzar(float delta_time) override; - void dibuixar() const override; + void update(float delta_time) override; + void draw() const override; - // Override: Interfície d'Entitat - [[nodiscard]] bool esta_actiu() const override { return esta_; } + // Override: Interfície d'Entity + [[nodiscard]] bool isActive() const override { return esta_; } // Override: Interfície de col·lisió - [[nodiscard]] float get_collision_radius() const override { + [[nodiscard]] float getCollisionRadius() const override { return Defaults::Entities::BULLET_RADIUS; } - [[nodiscard]] bool es_collidable() const override { + [[nodiscard]] bool isCollidable() const override { return esta_ && grace_timer_ <= 0.0F; } @@ -40,8 +40,8 @@ class Bala : public Entities::Entitat { void desactivar() { esta_ = false; } private: - // Membres específics de Bala (heretats: renderer_, forma_, centre_, angle_, brightness_) - float velocitat_; + // Membres específics de Bullet (heretats: renderer_, shape_, center_, angle_, brightness_) + float velocity_; bool esta_; uint8_t owner_id_; // 0=P1, 1=P2 float grace_timer_; // Grace period timer (0.0 = vulnerable) diff --git a/source/game/entities/enemic.cpp b/source/game/entities/enemy.cpp similarity index 83% rename from source/game/entities/enemic.cpp rename to source/game/entities/enemy.cpp index b21489c..e77eb70 100644 --- a/source/game/entities/enemic.cpp +++ b/source/game/entities/enemy.cpp @@ -2,7 +2,7 @@ // © 1999 Visente i Sergi (versió Pascal) // © 2025 Port a C++20 amb SDL3 -#include "game/entities/enemic.hpp" +#include "game/entities/enemy.hpp" #include #include @@ -10,19 +10,19 @@ #include #include "core/defaults.hpp" -#include "core/entities/entitat.hpp" +#include "core/entities/entity.hpp" #include "core/graphics/shape_loader.hpp" #include "core/rendering/shape_renderer.hpp" #include "core/types.hpp" #include "game/constants.hpp" -Enemic::Enemic(SDL_Renderer* renderer) - : Entitat(renderer), - velocitat_(0.0F), +Enemy::Enemy(SDL_Renderer* renderer) + : Entity(renderer), + velocity_(0.0F), drotacio_(0.0F), rotacio_(0.0F), esta_(false), - tipus_(TipusEnemic::PENTAGON), + type_(EnemyType::PENTAGON), tracking_timer_(0.0F), ship_position_(nullptr), tracking_strength_(0.5F), // Default tracking strength @@ -30,57 +30,57 @@ Enemic::Enemic(SDL_Renderer* renderer) // [NUEVO] Brightness específic per enemics brightness_ = Defaults::Brightness::ENEMIC; - // [NUEVO] Forma es carrega a inicialitzar() segons el tipus + // [NUEVO] Forma es carrega a init() segons el tipus // Constructor no carrega forma per permetre tipus diferents } -void Enemic::inicialitzar(TipusEnemic tipus, const Vec2* ship_pos) { +void Enemy::init(EnemyType tipus, const Vec2* ship_pos) { // Guardar tipus - tipus_ = tipus; + type_ = tipus; // Carregar forma segons el tipus const char* shape_file; float drotacio_min; float drotacio_max; - switch (tipus_) { - case TipusEnemic::PENTAGON: + switch (type_) { + case EnemyType::PENTAGON: shape_file = Defaults::Enemies::Pentagon::SHAPE_FILE; - velocitat_ = Defaults::Enemies::Pentagon::VELOCITAT; + velocity_ = Defaults::Enemies::Pentagon::VELOCITAT; drotacio_min = Defaults::Enemies::Pentagon::DROTACIO_MIN; drotacio_max = Defaults::Enemies::Pentagon::DROTACIO_MAX; break; - case TipusEnemic::QUADRAT: + case EnemyType::QUADRAT: shape_file = Defaults::Enemies::Quadrat::SHAPE_FILE; - velocitat_ = Defaults::Enemies::Quadrat::VELOCITAT; + velocity_ = Defaults::Enemies::Quadrat::VELOCITAT; drotacio_min = Defaults::Enemies::Quadrat::DROTACIO_MIN; drotacio_max = Defaults::Enemies::Quadrat::DROTACIO_MAX; tracking_timer_ = 0.0F; break; - case TipusEnemic::MOLINILLO: + case EnemyType::MOLINILLO: shape_file = Defaults::Enemies::Molinillo::SHAPE_FILE; - velocitat_ = Defaults::Enemies::Molinillo::VELOCITAT; + velocity_ = Defaults::Enemies::Molinillo::VELOCITAT; drotacio_min = Defaults::Enemies::Molinillo::DROTACIO_MIN; drotacio_max = Defaults::Enemies::Molinillo::DROTACIO_MAX; break; default: // Fallback segur: usar valors de PENTAGON - std::cerr << "[Enemic] Error: tipus desconegut (" - << static_cast(tipus_) << "), utilitzant PENTAGON\n"; + std::cerr << "[Enemy] Error: tipus desconegut (" + << static_cast(type_) << "), utilitzant PENTAGON\n"; shape_file = Defaults::Enemies::Pentagon::SHAPE_FILE; - velocitat_ = Defaults::Enemies::Pentagon::VELOCITAT; + velocity_ = Defaults::Enemies::Pentagon::VELOCITAT; drotacio_min = Defaults::Enemies::Pentagon::DROTACIO_MIN; drotacio_max = Defaults::Enemies::Pentagon::DROTACIO_MAX; break; } // Carregar forma - forma_ = Graphics::ShapeLoader::load(shape_file); - if (!forma_ || !forma_->es_valida()) { - std::cerr << "[Enemic] Error: no s'ha pogut carregar " << shape_file << '\n'; + shape_ = Graphics::ShapeLoader::load(shape_file); + if (!shape_ || !shape_->es_valida()) { + std::cerr << "[Enemy] Error: no s'ha pogut carregar " << shape_file << '\n'; } // [MODIFIED] Posició aleatòria amb comprovació de seguretat @@ -103,8 +103,8 @@ void Enemic::inicialitzar(TipusEnemic tipus, const Vec2* ship_pos) { float candidate_y; if (intent_spawn_safe(*ship_pos, candidate_x, candidate_y)) { - centre_.x = candidate_x; - centre_.y = candidate_y; + center_.x = candidate_x; + center_.y = candidate_y; found_safe_position = true; break; } @@ -114,18 +114,18 @@ void Enemic::inicialitzar(TipusEnemic tipus, const Vec2* ship_pos) { // Fallback: spawn anywhere (user's preference) int range_x = static_cast(max_x - min_x); int range_y = static_cast(max_y - min_y); - centre_.x = static_cast((std::rand() % range_x) + static_cast(min_x)); - centre_.y = static_cast((std::rand() % range_y) + static_cast(min_y)); + center_.x = static_cast((std::rand() % range_x) + static_cast(min_x)); + center_.y = static_cast((std::rand() % range_y) + static_cast(min_y)); - std::cout << "[Enemic] Advertència: spawn sense zona segura després de " + std::cout << "[Enemy] Advertència: spawn sense zona segura després de " << Defaults::Enemies::Spawn::MAX_SPAWN_ATTEMPTS << " intents" << '\n'; } } else { // [EXISTING] No ship position: spawn anywhere (backward compatibility) int range_x = static_cast(max_x - min_x); int range_y = static_cast(max_y - min_y); - centre_.x = static_cast((std::rand() % range_x) + static_cast(min_x)); - centre_.y = static_cast((std::rand() % range_y) + static_cast(min_y)); + center_.x = static_cast((std::rand() % range_x) + static_cast(min_x)); + center_.y = static_cast((std::rand() % range_y) + static_cast(min_y)); } // Angle aleatori de moviment @@ -137,7 +137,7 @@ void Enemic::inicialitzar(TipusEnemic tipus, const Vec2* ship_pos) { rotacio_ = 0.0F; // Inicialitzar estat d'animació - animacio_ = AnimacioEnemic(); // Reset to defaults + animacio_ = EnemyAnimation(); // Reset to defaults animacio_.drotacio_base = drotacio_; animacio_.drotacio_objetivo = drotacio_; animacio_.drotacio_t = 1.0F; // Start without interpolating @@ -150,7 +150,7 @@ void Enemic::inicialitzar(TipusEnemic tipus, const Vec2* ship_pos) { esta_ = true; } -void Enemic::actualitzar(float delta_time) { +void Enemy::update(float delta_time) { if (esta_) { // [NEW] Update invulnerability timer and brightness if (timer_invulnerabilitat_ > 0.0F) { @@ -179,26 +179,26 @@ void Enemic::actualitzar(float delta_time) { } } -void Enemic::dibuixar() const { - if (esta_ && forma_) { +void Enemy::draw() const { + if (esta_ && shape_) { // Calculate animated scale (includes invulnerability LERP) float escala = calcular_escala_actual(); - // brightness_ is already updated in actualitzar() - Rendering::render_shape(renderer_, forma_, centre_, rotacio_, escala, 1.0F, brightness_); + // brightness_ is already updated in update() + Rendering::render_shape(renderer_, shape_, center_, rotacio_, escala, 1.0F, brightness_); } } -void Enemic::mou(float delta_time) { +void Enemy::mou(float delta_time) { // Dispatcher: crida el comportament específic segons el tipus - switch (tipus_) { - case TipusEnemic::PENTAGON: + switch (type_) { + case EnemyType::PENTAGON: comportament_pentagon(delta_time); break; - case TipusEnemic::QUADRAT: + case EnemyType::QUADRAT: comportament_quadrat(delta_time); break; - case TipusEnemic::MOLINILLO: + case EnemyType::MOLINILLO: comportament_molinillo(delta_time); break; default: @@ -208,18 +208,18 @@ void Enemic::mou(float delta_time) { } } -void Enemic::comportament_pentagon(float delta_time) { +void Enemy::comportament_pentagon(float delta_time) { // Pentagon: zigzag esquivador (frequent direction changes) // Similar a comportament original però amb probabilitat més alta - float velocitat_efectiva = velocitat_ * delta_time; + float velocitat_efectiva = velocity_ * delta_time; // Calcular desplaçament (angle-PI/2 perquè angle=0 apunta amunt) float dy = velocitat_efectiva * std::sin(angle_ - (Constants::PI / 2.0F)); float dx = velocitat_efectiva * std::cos(angle_ - (Constants::PI / 2.0F)); - float new_y = centre_.y + dy; - float new_x = centre_.x + dx; + float new_y = center_.y + dy; + float new_x = center_.x + dx; // Obtenir límits segurs float min_x; @@ -234,7 +234,7 @@ void Enemic::comportament_pentagon(float delta_time) { // Zigzag: canvi d'angle més freqüent en tocar límits if (new_y >= min_y && new_y <= max_y) { - centre_.y = new_y; + center_.y = new_y; } else { // Probabilitat més alta de canvi d'angle if (static_cast(std::rand()) / RAND_MAX < Defaults::Enemies::Pentagon::CANVI_ANGLE_PROB) { @@ -245,7 +245,7 @@ void Enemic::comportament_pentagon(float delta_time) { } if (new_x >= min_x && new_x <= max_x) { - centre_.x = new_x; + center_.x = new_x; } else { if (static_cast(std::rand()) / RAND_MAX < Defaults::Enemies::Pentagon::CANVI_ANGLE_PROB) { float rand_angle = (static_cast(std::rand()) / RAND_MAX) * @@ -255,7 +255,7 @@ void Enemic::comportament_pentagon(float delta_time) { } } -void Enemic::comportament_quadrat(float delta_time) { +void Enemy::comportament_quadrat(float delta_time) { // Quadrat: perseguidor (tracks player position) // Update tracking timer @@ -267,8 +267,8 @@ void Enemic::comportament_quadrat(float delta_time) { if (ship_position_ != nullptr) { // Calculate angle to ship - float dx = ship_position_->x - centre_.x; - float dy = ship_position_->y - centre_.y; + float dx = ship_position_->x - center_.x; + float dy = ship_position_->y - center_.y; float target_angle = std::atan2(dy, dx) + (Constants::PI / 2.0F); // Interpolate toward target angle @@ -288,12 +288,12 @@ void Enemic::comportament_quadrat(float delta_time) { } // Move in current direction - float velocitat_efectiva = velocitat_ * delta_time; + float velocitat_efectiva = velocity_ * delta_time; float dy = velocitat_efectiva * std::sin(angle_ - (Constants::PI / 2.0F)); float dx = velocitat_efectiva * std::cos(angle_ - (Constants::PI / 2.0F)); - float new_y = centre_.y + dy; - float new_x = centre_.x + dx; + float new_y = center_.y + dy; + float new_x = center_.x + dx; // Obtenir límits segurs float min_x; @@ -308,25 +308,25 @@ void Enemic::comportament_quadrat(float delta_time) { // Bounce on walls (simple reflection) if (new_y >= min_y && new_y <= max_y) { - centre_.y = new_y; + center_.y = new_y; } else { angle_ = -angle_; // Vertical reflection } if (new_x >= min_x && new_x <= max_x) { - centre_.x = new_x; + center_.x = new_x; } else { angle_ = Constants::PI - angle_; // Horizontal reflection } } -void Enemic::comportament_molinillo(float delta_time) { +void Enemy::comportament_molinillo(float delta_time) { // Molinillo: agressiu (fast, straight lines, proximity spin-up) // Check proximity to ship for spin-up effect if (ship_position_ != nullptr) { - float dx = ship_position_->x - centre_.x; - float dy = ship_position_->y - centre_.y; + float dx = ship_position_->x - center_.x; + float dy = ship_position_->y - center_.y; float distance = std::sqrt((dx * dx) + (dy * dy)); if (distance < Defaults::Enemies::Molinillo::PROXIMITY_DISTANCE) { @@ -340,12 +340,12 @@ void Enemic::comportament_molinillo(float delta_time) { } // Fast straight-line movement - float velocitat_efectiva = velocitat_ * delta_time; + float velocitat_efectiva = velocity_ * delta_time; float dy = velocitat_efectiva * std::sin(angle_ - (Constants::PI / 2.0F)); float dx = velocitat_efectiva * std::cos(angle_ - (Constants::PI / 2.0F)); - float new_y = centre_.y + dy; - float new_x = centre_.x + dx; + float new_y = center_.y + dy; + float new_x = center_.x + dx; // Obtenir límits segurs float min_x; @@ -360,7 +360,7 @@ void Enemic::comportament_molinillo(float delta_time) { // Rare angle changes on wall hits if (new_y >= min_y && new_y <= max_y) { - centre_.y = new_y; + center_.y = new_y; } else { if (static_cast(std::rand()) / RAND_MAX < Defaults::Enemies::Molinillo::CANVI_ANGLE_PROB) { float rand_angle = (static_cast(std::rand()) / RAND_MAX) * @@ -370,7 +370,7 @@ void Enemic::comportament_molinillo(float delta_time) { } if (new_x >= min_x && new_x <= max_x) { - centre_.x = new_x; + center_.x = new_x; } else { if (static_cast(std::rand()) / RAND_MAX < Defaults::Enemies::Molinillo::CANVI_ANGLE_PROB) { float rand_angle = (static_cast(std::rand()) / RAND_MAX) * @@ -380,12 +380,12 @@ void Enemic::comportament_molinillo(float delta_time) { } } -void Enemic::actualitzar_animacio(float delta_time) { +void Enemy::actualitzar_animacio(float delta_time) { actualitzar_palpitacio(delta_time); actualitzar_rotacio_accelerada(delta_time); } -void Enemic::actualitzar_palpitacio(float delta_time) { +void Enemy::actualitzar_palpitacio(float delta_time) { if (animacio_.palpitacio_activa) { // Advance phase (2π * frequency * dt) animacio_.palpitacio_fase += 2.0F * Constants::PI * animacio_.palpitacio_frequencia * delta_time; @@ -426,7 +426,7 @@ void Enemic::actualitzar_palpitacio(float delta_time) { } } -void Enemic::actualitzar_rotacio_accelerada(float delta_time) { +void Enemy::actualitzar_rotacio_accelerada(float delta_time) { if (animacio_.drotacio_t < 1.0F) { // Transitioning to new target animacio_.drotacio_t += delta_time / animacio_.drotacio_duracio; @@ -471,7 +471,7 @@ void Enemic::actualitzar_rotacio_accelerada(float delta_time) { } } -float Enemic::calcular_escala_actual() const { +float Enemy::calcular_escala_actual() const { float escala = 1.0F; // [NEW] Invulnerability LERP prioritza sobre palpitació @@ -497,33 +497,33 @@ float Enemic::calcular_escala_actual() const { // [NEW] Stage system API implementations -float Enemic::get_base_velocity() const { - switch (tipus_) { - case TipusEnemic::PENTAGON: +float Enemy::get_base_velocity() const { + switch (type_) { + case EnemyType::PENTAGON: return Defaults::Enemies::Pentagon::VELOCITAT; - case TipusEnemic::QUADRAT: + case EnemyType::QUADRAT: return Defaults::Enemies::Quadrat::VELOCITAT; - case TipusEnemic::MOLINILLO: + case EnemyType::MOLINILLO: return Defaults::Enemies::Molinillo::VELOCITAT; default: return Defaults::Enemies::Pentagon::VELOCITAT; // Fallback segur } } -float Enemic::get_base_rotation() const { +float Enemy::get_base_rotation() const { // Return the base rotation speed (drotacio_base if available, otherwise current drotacio_) return animacio_.drotacio_base != 0.0F ? animacio_.drotacio_base : drotacio_; } -void Enemic::set_tracking_strength(float strength) { +void Enemy::set_tracking_strength(float strength) { // Only applies to QUADRAT type - if (tipus_ == TipusEnemic::QUADRAT) { + if (type_ == EnemyType::QUADRAT) { tracking_strength_ = strength; } } // [NEW] Safe spawn helper - checks if position is away from ship -bool Enemic::intent_spawn_safe(const Vec2& ship_pos, float& out_x, float& out_y) { +bool Enemy::intent_spawn_safe(const Vec2& ship_pos, float& out_x, float& out_y) { // Generate random position within safe bounds float min_x; float max_x; diff --git a/source/game/entities/enemic.hpp b/source/game/entities/enemy.hpp similarity index 72% rename from source/game/entities/enemic.hpp rename to source/game/entities/enemy.hpp index 18c25b3..9669e3d 100644 --- a/source/game/entities/enemic.hpp +++ b/source/game/entities/enemy.hpp @@ -9,19 +9,19 @@ #include #include "core/defaults.hpp" -#include "core/entities/entitat.hpp" +#include "core/entities/entity.hpp" #include "core/types.hpp" #include "game/constants.hpp" // Tipus d'enemic -enum class TipusEnemic : uint8_t { +enum class EnemyType : uint8_t { PENTAGON = 0, // Pentàgon esquivador (zigzag) QUADRAT = 1, // Quadrat perseguidor (tracks ship) MOLINILLO = 2 // Molinillo agressiu (fast, spinning) }; // Estat d'animació (palpitació i rotació accelerada) -struct AnimacioEnemic { +struct EnemyAnimation { // Palpitation (breathing effect) bool palpitacio_activa = false; float palpitacio_fase = 0.0F; // Phase in cycle (0.0-2π) @@ -36,35 +36,35 @@ struct AnimacioEnemic { float drotacio_duracio = 0.0F; // Duration of transition (seconds) }; -class Enemic : public Entities::Entitat { +class Enemy : public Entities::Entity { public: - Enemic() - : Entitat(nullptr) {} - Enemic(SDL_Renderer* renderer); + Enemy() + : Entity(nullptr) {} + Enemy(SDL_Renderer* renderer); - void inicialitzar() override { inicialitzar(TipusEnemic::PENTAGON, nullptr); } - void inicialitzar(TipusEnemic tipus, const Vec2* ship_pos = nullptr); - void actualitzar(float delta_time) override; - void dibuixar() const override; + void init() override { init(EnemyType::PENTAGON, nullptr); } + void init(EnemyType tipus, const Vec2* ship_pos = nullptr); + void update(float delta_time) override; + void draw() const override; - // Override: Interfície d'Entitat - [[nodiscard]] bool esta_actiu() const override { return esta_; } + // Override: Interfície d'Entity + [[nodiscard]] bool isActive() const override { return esta_; } // Override: Interfície de col·lisió - [[nodiscard]] float get_collision_radius() const override { + [[nodiscard]] float getCollisionRadius() const override { return Defaults::Entities::ENEMY_RADIUS; } - [[nodiscard]] bool es_collidable() const override { + [[nodiscard]] bool isCollidable() const override { return esta_ && timer_invulnerabilitat_ <= 0.0F; } // Getters (API pública sense canvis) void destruir() { esta_ = false; } [[nodiscard]] float get_drotacio() const { return drotacio_; } - [[nodiscard]] Vec2 get_velocitat_vector() const { + [[nodiscard]] Vec2 getVelocityVector() const { return { - .x = velocitat_ * std::cos(angle_ - (Constants::PI / 2.0F)), - .y = velocitat_ * std::sin(angle_ - (Constants::PI / 2.0F))}; + .x = velocity_ * std::cos(angle_ - (Constants::PI / 2.0F)), + .y = velocity_ * std::sin(angle_ - (Constants::PI / 2.0F))}; } // Set ship position reference for tracking behavior @@ -73,10 +73,10 @@ class Enemic : public Entities::Entitat { // [NEW] Getters for stage system (base stats) [[nodiscard]] float get_base_velocity() const; [[nodiscard]] float get_base_rotation() const; - [[nodiscard]] TipusEnemic get_tipus() const { return tipus_; } + [[nodiscard]] EnemyType getType() const { return type_; } // [NEW] Setters for difficulty multipliers (stage system) - void set_velocity(float vel) { velocitat_ = vel; } + void set_velocity(float vel) { velocity_ = vel; } void set_rotation(float rot) { drotacio_ = rot; animacio_.drotacio_base = rot; @@ -84,21 +84,21 @@ class Enemic : public Entities::Entitat { void set_tracking_strength(float strength); // [NEW] Invulnerability queries - [[nodiscard]] bool es_invulnerable() const { return timer_invulnerabilitat_ > 0.0F; } + [[nodiscard]] bool isInvulnerable() const { return timer_invulnerabilitat_ > 0.0F; } [[nodiscard]] float get_temps_invulnerabilitat() const { return timer_invulnerabilitat_; } private: - // Membres específics d'Enemic (heretats: renderer_, forma_, centre_, angle_, brightness_) - float velocitat_; + // Membres específics d'Enemy (heretats: renderer_, shape_, center_, angle_, brightness_) + float velocity_; float drotacio_; // Delta rotació visual (rad/s) float rotacio_; // Rotació visual acumulada bool esta_; // [NEW] Enemy type and configuration - TipusEnemic tipus_; + EnemyType type_; // [NEW] Animation state - AnimacioEnemic animacio_; + EnemyAnimation animacio_; // [NEW] Behavior state (type-specific) float tracking_timer_; // For Quadrat: time since last angle update diff --git a/source/game/entities/nau.hpp b/source/game/entities/nau.hpp deleted file mode 100644 index ca4dc91..0000000 --- a/source/game/entities/nau.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// nau.hpp - Classe per a la nave del jugador -// © 1999 Visente i Sergi (versió Pascal) -// © 2025 Port a C++20 amb SDL3 - -#pragma once -#include - -#include -#include - -#include "core/defaults.hpp" -#include "core/entities/entitat.hpp" -#include "core/types.hpp" -#include "game/constants.hpp" - -class Nau : public Entities::Entitat { - public: - Nau() - : Entitat(nullptr) {} - Nau(SDL_Renderer* renderer, const char* shape_file = "ship.shp"); - - void inicialitzar() override { inicialitzar(nullptr, false); } - void inicialitzar(const Vec2* spawn_point, bool activar_invulnerabilitat = false); - void processar_input(float delta_time, uint8_t player_id); - void actualitzar(float delta_time) override; - void dibuixar() const override; - - // Override: Interfície d'Entitat - [[nodiscard]] bool esta_actiu() const override { return !esta_tocada_; } - - // Override: Interfície de col·lisió - [[nodiscard]] float get_collision_radius() const override { - return Defaults::Entities::SHIP_RADIUS; - } - [[nodiscard]] bool es_collidable() const override { - return !esta_tocada_ && invulnerable_timer_ <= 0.0F; - } - - // Getters (API pública sense canvis) - [[nodiscard]] bool esta_viva() const { return !esta_tocada_; } - [[nodiscard]] bool esta_tocada() const { return esta_tocada_; } - [[nodiscard]] bool es_invulnerable() const { return invulnerable_timer_ > 0.0F; } - [[nodiscard]] Vec2 get_velocitat_vector() const { - return { - .x = velocitat_ * std::cos(angle_ - (Constants::PI / 2.0F)), - .y = velocitat_ * std::sin(angle_ - (Constants::PI / 2.0F))}; - } - - // Setters - void set_centre(const Vec2& nou_centre) { centre_ = nou_centre; } - - // Col·lisions (Fase 10) - void marcar_tocada() { esta_tocada_ = true; } - - private: - // Membres específics de Nau (heretats: renderer_, forma_, centre_, angle_, brightness_) - float velocitat_; // Velocitat (px/s) - bool esta_tocada_; - float invulnerable_timer_; // 0.0f = vulnerable, >0.0f = invulnerable - - void aplicar_fisica(float delta_time); -}; diff --git a/source/game/entities/nau.cpp b/source/game/entities/ship.cpp similarity index 69% rename from source/game/entities/nau.cpp rename to source/game/entities/ship.cpp index de86098..28eb4ca 100644 --- a/source/game/entities/nau.cpp +++ b/source/game/entities/ship.cpp @@ -2,7 +2,7 @@ // © 1999 Visente i Sergi (versió Pascal) // © 2025 Port a C++20 amb SDL3 -#include "game/entities/nau.hpp" +#include "game/entities/ship.hpp" #include @@ -12,7 +12,7 @@ #include #include "core/defaults.hpp" -#include "core/entities/entitat.hpp" +#include "core/entities/entity.hpp" #include "core/graphics/shape_loader.hpp" #include "core/input/input.hpp" #include "core/input/input_types.hpp" @@ -20,23 +20,23 @@ #include "core/types.hpp" #include "game/constants.hpp" -Nau::Nau(SDL_Renderer* renderer, const char* shape_file) - : Entitat(renderer), - velocitat_(0.0F), - esta_tocada_(false), +Ship::Ship(SDL_Renderer* renderer, const char* shape_file) + : Entity(renderer), + velocity_(0.0F), + is_hit_(false), invulnerable_timer_(0.0F) { // [NUEVO] Brightness específic per naus brightness_ = Defaults::Brightness::NAU; // [NUEVO] Carregar forma compartida des de fitxer - forma_ = Graphics::ShapeLoader::load(shape_file); + shape_ = Graphics::ShapeLoader::load(shape_file); - if (!forma_ || !forma_->es_valida()) { - std::cerr << "[Nau] Error: no s'ha pogut carregar " << shape_file << '\n'; + if (!shape_ || !shape_->es_valida()) { + std::cerr << "[Ship] Error: no s'ha pogut carregar " << shape_file << '\n'; } } -void Nau::inicialitzar(const Vec2* spawn_point, bool activar_invulnerabilitat) { +void Ship::init(const Vec2* spawn_point, bool activar_invulnerabilitat) { // Inicialització de la nau (triangle) // Basat en el codi Pascal original: lines 380-384 // Copiat de joc_asteroides.cpp línies 30-44 @@ -46,20 +46,20 @@ void Nau::inicialitzar(const Vec2* spawn_point, bool activar_invulnerabilitat) { // Use custom spawn point if provided, otherwise use center if (spawn_point != nullptr) { - centre_.x = spawn_point->x; - centre_.y = spawn_point->y; + center_.x = spawn_point->x; + center_.y = spawn_point->y; } else { // Default: center of play area float centre_x; float centre_y; Constants::obtenir_centre_zona(centre_x, centre_y); - centre_.x = static_cast(centre_x); - centre_.y = static_cast(centre_y); + center_.x = static_cast(centre_x); + center_.y = static_cast(centre_y); } // Estat inicial angle_ = 0.0F; - velocitat_ = 0.0F; + velocity_ = 0.0F; // Activar invulnerabilidad solo si es respawn if (activar_invulnerabilitat) { @@ -68,14 +68,14 @@ void Nau::inicialitzar(const Vec2* spawn_point, bool activar_invulnerabilitat) { invulnerable_timer_ = 0.0F; } - esta_tocada_ = false; + is_hit_ = false; } -void Nau::processar_input(float delta_time, uint8_t player_id) { +void Ship::processInput(float delta_time, uint8_t player_id) { // Processar input continu (com teclapuls() del Pascal original) // Basat en joc_asteroides.cpp línies 66-85 // Només processa input si la nau està viva - if (esta_tocada_) { + if (is_hit_) { return; } @@ -93,9 +93,9 @@ void Nau::processar_input(float delta_time, uint8_t player_id) { } if (input->checkActionPlayer1(InputAction::THRUST, Input::ALLOW_REPEAT)) { - if (velocitat_ < Defaults::Physics::MAX_VELOCITY) { - velocitat_ += Defaults::Physics::ACCELERATION * delta_time; - velocitat_ = std::min(velocitat_, Defaults::Physics::MAX_VELOCITY); + if (velocity_ < Defaults::Physics::MAX_VELOCITY) { + velocity_ += Defaults::Physics::ACCELERATION * delta_time; + velocity_ = std::min(velocity_, Defaults::Physics::MAX_VELOCITY); } } } else { @@ -109,17 +109,17 @@ void Nau::processar_input(float delta_time, uint8_t player_id) { } if (input->checkActionPlayer2(InputAction::THRUST, Input::ALLOW_REPEAT)) { - if (velocitat_ < Defaults::Physics::MAX_VELOCITY) { - velocitat_ += Defaults::Physics::ACCELERATION * delta_time; - velocitat_ = std::min(velocitat_, Defaults::Physics::MAX_VELOCITY); + if (velocity_ < Defaults::Physics::MAX_VELOCITY) { + velocity_ += Defaults::Physics::ACCELERATION * delta_time; + velocity_ = std::min(velocity_, Defaults::Physics::MAX_VELOCITY); } } } } -void Nau::actualitzar(float delta_time) { - // Només actualitzar si la nau està viva - if (esta_tocada_) { +void Ship::update(float delta_time) { + // Només update si la nau està viva + if (is_hit_) { return; } @@ -130,17 +130,17 @@ void Nau::actualitzar(float delta_time) { } // Aplicar física (moviment + fricció) - aplicar_fisica(delta_time); + applyPhysics(delta_time); } -void Nau::dibuixar() const { - // Només dibuixar si la nau està viva - if (esta_tocada_) { +void Ship::draw() const { + // Només draw si la nau està viva + if (is_hit_) { return; } // Si invulnerable, parpadear (toggle on/off) - if (es_invulnerable()) { + if (isInvulnerable()) { // Calcular ciclo de parpadeo float blink_cycle = Defaults::Ship::BLINK_VISIBLE_TIME + Defaults::Ship::BLINK_INVISIBLE_TIME; @@ -152,7 +152,7 @@ void Nau::dibuixar() const { } } - if (!forma_) { + if (!shape_) { return; } @@ -164,25 +164,25 @@ void Nau::dibuixar() const { // [NUEVO] Convertir suma de velocitat_visual a escala multiplicativa // Radio base del ship = 12 px // velocitat_visual = 0-6 → r = 12-18 → escala = 1.0-1.5 - float velocitat_visual = velocitat_ / 33.33F; + float velocitat_visual = velocity_ / 33.33F; float escala = 1.0F + (velocitat_visual / 12.0F); - Rendering::render_shape(renderer_, forma_, centre_, angle_, escala, 1.0F, brightness_); + Rendering::render_shape(renderer_, shape_, center_, angle_, escala, 1.0F, brightness_); } -void Nau::aplicar_fisica(float delta_time) { +void Ship::applyPhysics(float delta_time) { // Aplicar física de moviment // Basat en joc_asteroides.cpp línies 87-113 // Calcular nova posició basada en velocitat i angle // S'usa (angle - PI/2) perquè angle=0 apunta cap amunt, no cap a la dreta - // velocitat_ està en px/s, així que multipliquem per delta_time + // velocity_ està en px/s, així que multipliquem per delta_time float dy = - ((velocitat_ * delta_time) * std::sin(angle_ - (Constants::PI / 2.0F))) + - centre_.y; + ((velocity_ * delta_time) * std::sin(angle_ - (Constants::PI / 2.0F))) + + center_.y; float dx = - ((velocitat_ * delta_time) * std::cos(angle_ - (Constants::PI / 2.0F))) + - centre_.x; + ((velocity_ * delta_time) * std::cos(angle_ - (Constants::PI / 2.0F))) + + center_.x; // Boundary checking amb radi de la nau // CORRECCIÓ: Usar límits segurs i inequalitats inclusives @@ -198,16 +198,16 @@ void Nau::aplicar_fisica(float delta_time) { // Inequalitats inclusives (>= i <=) if (dy >= min_y && dy <= max_y) { - centre_.y = dy; + center_.y = dy; } if (dx >= min_x && dx <= max_x) { - centre_.x = dx; + center_.x = dx; } // Fricció - desacceleració gradual (time-based) - if (velocitat_ > 0.1F) { - velocitat_ -= Defaults::Physics::FRICTION * delta_time; - velocitat_ = std::max(velocitat_, 0.0F); + if (velocity_ > 0.1F) { + velocity_ -= Defaults::Physics::FRICTION * delta_time; + velocity_ = std::max(velocity_, 0.0F); } } diff --git a/source/game/entities/ship.hpp b/source/game/entities/ship.hpp new file mode 100644 index 0000000..a94caaa --- /dev/null +++ b/source/game/entities/ship.hpp @@ -0,0 +1,62 @@ +// nau.hpp - Classe per a la nave del jugador +// © 1999 Visente i Sergi (versió Pascal) +// © 2025 Port a C++20 amb SDL3 + +#pragma once +#include + +#include +#include + +#include "core/defaults.hpp" +#include "core/entities/entity.hpp" +#include "core/types.hpp" +#include "game/constants.hpp" + +class Ship : public Entities::Entity { + public: + Ship() + : Entity(nullptr) {} + Ship(SDL_Renderer* renderer, const char* shape_file = "ship.shp"); + + void init() override { init(nullptr, false); } + void init(const Vec2* spawn_point, bool activar_invulnerabilitat = false); + void processInput(float delta_time, uint8_t player_id); + void update(float delta_time) override; + void draw() const override; + + // Override: Interfície d'Entity + [[nodiscard]] bool isActive() const override { return !is_hit_; } + + // Override: Interfície de col·lisió + [[nodiscard]] float getCollisionRadius() const override { + return Defaults::Entities::SHIP_RADIUS; + } + [[nodiscard]] bool isCollidable() const override { + return !is_hit_ && invulnerable_timer_ <= 0.0F; + } + + // Getters (API pública sense canvis) + [[nodiscard]] bool isAlive() const { return !is_hit_; } + [[nodiscard]] bool isHit() const { return is_hit_; } + [[nodiscard]] bool isInvulnerable() const { return invulnerable_timer_ > 0.0F; } + [[nodiscard]] Vec2 getVelocityVector() const { + return { + .x = velocity_ * std::cos(angle_ - (Constants::PI / 2.0F)), + .y = velocity_ * std::sin(angle_ - (Constants::PI / 2.0F))}; + } + + // Setters + void setCenter(const Vec2& nou_centre) { center_ = nou_centre; } + + // Col·lisions (Fase 10) + void markHit() { is_hit_ = true; } + + private: + // Membres específics de Ship (heretats: renderer_, shape_, center_, angle_, brightness_) + float velocity_; // Velocitat (px/s) + bool is_hit_; + float invulnerable_timer_; // 0.0f = vulnerable, >0.0f = invulnerable + + void applyPhysics(float delta_time); +}; diff --git a/source/game/escenes/escena_joc.cpp b/source/game/escenes/escena_joc.cpp index 7f2dbda..4c76348 100644 --- a/source/game/escenes/escena_joc.cpp +++ b/source/game/escenes/escena_joc.cpp @@ -12,7 +12,7 @@ #include #include "core/audio/audio.hpp" -#include "core/entities/entitat.hpp" +#include "core/entities/entity.hpp" #include "core/input/input.hpp" #include "core/input/mouse.hpp" #include "core/math/easing.hpp" @@ -49,17 +49,17 @@ EscenaJoc::EscenaJoc(SDLManager& sdl, ContextEscenes& context) (void)opcio; // Suprimir warning de variable no usada // Inicialitzar naus amb renderer (P1=ship.shp, P2=ship2.shp) - naus_[0] = Nau(sdl.obte_renderer(), "ship.shp"); // Jugador 1: nave estàndar - naus_[1] = Nau(sdl.obte_renderer(), "ship2.shp"); // Jugador 2: interceptor amb ales + naus_[0] = Ship(sdl.obte_renderer(), "ship.shp"); // Jugador 1: nave estàndar + naus_[1] = Ship(sdl.obte_renderer(), "ship2.shp"); // Jugador 2: interceptor amb ales // Inicialitzar bales amb renderer for (auto& bala : bales_) { - bala = Bala(sdl.obte_renderer()); + bala = Bullet(sdl.obte_renderer()); } // Inicialitzar enemics amb renderer for (auto& enemy : orni_) { - enemy = Enemic(sdl.obte_renderer()); + enemy = Enemy(sdl.obte_renderer()); } } @@ -67,7 +67,7 @@ void EscenaJoc::executar() { std::cout << "Escena Joc: Inicialitzant...\n"; // Inicialitzar estat del joc - inicialitzar(); + init(); SDL_Event event; Uint64 last_time = SDL_GetTicks(); @@ -102,7 +102,7 @@ void EscenaJoc::executar() { } // Actualitzar física del joc amb delta_time real - actualitzar(delta_time); + update(delta_time); // Actualitzar sistema d'audio Audio::update(); @@ -117,7 +117,7 @@ void EscenaJoc::executar() { sdl_.updateRenderingContext(); // Dibuixar joc - dibuixar(); + draw(); // Presentar renderer (swap buffers) sdl_.presenta(); @@ -126,7 +126,7 @@ void EscenaJoc::executar() { std::cout << "Escena Joc: Finalitzant...\n"; } -void EscenaJoc::inicialitzar() { +void EscenaJoc::init() { // Inicialitzar generador de números aleatoris // Basat en el codi Pascal original: line 376 std::srand(static_cast(std::time(nullptr))); @@ -142,10 +142,10 @@ void EscenaJoc::inicialitzar() { // [NEW] Initialize stage manager stage_manager_ = std::make_unique(stage_config_.get()); - stage_manager_->inicialitzar(); + stage_manager_->init(); // [NEW] Set ship position reference for safe spawn (P1 for now, TODO: dual tracking) - stage_manager_->get_spawn_controller().set_ship_position(&naus_[0].get_centre()); + stage_manager_->get_spawn_controller().set_ship_position(&naus_[0].getCenter()); // Inicialitzar timers de muerte per jugador itocado_per_jugador_[0] = 0.0F; @@ -175,13 +175,13 @@ void EscenaJoc::inicialitzar() { bool jugador_actiu = (i == 0) ? config_partida_.jugador1_actiu : config_partida_.jugador2_actiu; if (jugador_actiu) { - // Jugador actiu: inicialitzar normalment + // Jugador actiu: init normalment Vec2 spawn_pos = obtenir_punt_spawn(i); - naus_[i].inicialitzar(&spawn_pos, false); // No invulnerability at start + naus_[i].init(&spawn_pos, false); // No invulnerability at start std::cout << "[EscenaJoc] Jugador " << (i + 1) << " inicialitzat\n"; } else { // Jugador inactiu: marcar com a mort permanent - naus_[i].marcar_tocada(); + naus_[i].markHit(); itocado_per_jugador_[i] = 999.0F; // Valor sentinella (permanent inactiu) vides_per_jugador_[i] = 0; // Sense vides std::cout << "[EscenaJoc] Jugador " << (i + 1) << " inactiu\n"; @@ -190,14 +190,14 @@ void EscenaJoc::inicialitzar() { // [MODIFIED] Initialize enemies as inactive (stage system will spawn them) for (auto& enemy : orni_) { - enemy = Enemic(sdl_.obte_renderer()); - enemy.set_ship_position(&naus_[0].get_centre()); // Set ship reference (P1 for now) - // DON'T call enemy.inicialitzar() here - stage system handles spawning + enemy = Enemy(sdl_.obte_renderer()); + enemy.set_ship_position(&naus_[0].getCenter()); // Set ship reference (P1 for now) + // DON'T call enemy.init() here - stage system handles spawning } // Inicialitzar bales (now 6 instead of 3) for (auto& bala : bales_) { - bala.inicialitzar(); + bala.init(); } // [ELIMINAT] Iniciar música de joc (ara es gestiona en stage_manager) @@ -208,7 +208,7 @@ void EscenaJoc::inicialitzar() { init_hud_rect_sound_played_ = false; } -void EscenaJoc::actualitzar(float delta_time) { +void EscenaJoc::update(float delta_time) { // Processar disparos (state-based, no event-based) if (estat_game_over_ == EstatGameOver::NONE) { auto* input = Input::get(); @@ -271,13 +271,13 @@ void EscenaJoc::actualitzar(float delta_time) { // Still update enemies, bullets, and effects during continue screen for (auto& enemy : orni_) { - enemy.actualitzar(delta_time); + enemy.update(delta_time); } for (auto& bala : bales_) { - bala.actualitzar(delta_time); + bala.update(delta_time); } - debris_manager_.actualitzar(delta_time); - gestor_puntuacio_.actualitzar(delta_time); + debris_manager_.update(delta_time); + gestor_puntuacio_.update(delta_time); return; } @@ -297,15 +297,15 @@ void EscenaJoc::actualitzar(float delta_time) { // Enemies and bullets continue moving during game over for (auto& enemy : orni_) { - enemy.actualitzar(delta_time); + enemy.update(delta_time); } for (auto& bala : bales_) { - bala.actualitzar(delta_time); + bala.update(delta_time); } - debris_manager_.actualitzar(delta_time); - gestor_puntuacio_.actualitzar(delta_time); + debris_manager_.update(delta_time); + gestor_puntuacio_.update(delta_time); return; } @@ -327,7 +327,7 @@ void EscenaJoc::actualitzar(float delta_time) { if (vides_per_jugador_[i] > 0) { // Respawn ship en spawn position con invulnerabilidad Vec2 spawn_pos = obtenir_punt_spawn(i); - naus_[i].inicialitzar(&spawn_pos, true); + naus_[i].init(&spawn_pos, true); itocado_per_jugador_[i] = 0.0F; } else { // Player is permanently dead (out of lives) @@ -352,15 +352,15 @@ void EscenaJoc::actualitzar(float delta_time) { if (algun_jugador_mort) { // Enemies and bullets continue moving during death sequence for (auto& enemy : orni_) { - enemy.actualitzar(delta_time); + enemy.update(delta_time); } for (auto& bala : bales_) { - bala.actualitzar(delta_time); + bala.update(delta_time); } - debris_manager_.actualitzar(delta_time); - gestor_puntuacio_.actualitzar(delta_time); + debris_manager_.update(delta_time); + gestor_puntuacio_.update(delta_time); // Don't return - allow alive players to continue playing } @@ -372,9 +372,9 @@ void EscenaJoc::actualitzar(float delta_time) { switch (estat) { case StageSystem::EstatStage::INIT_HUD: { // Update stage manager timer (pot canviar l'estat!) - stage_manager_->actualitzar(delta_time); + stage_manager_->update(delta_time); - // [FIX] Si l'estat ha canviat durant actualitzar(), sortir immediatament + // [FIX] Si l'estat ha canviat durant update(), sortir immediatament // per evitar recalcular la posició de la nau amb el nou timer if (stage_manager_->get_estat() != StageSystem::EstatStage::INIT_HUD) { break; @@ -398,12 +398,12 @@ void EscenaJoc::actualitzar(float delta_time) { // [MODIFICAT] Animar AMBAS naus con sus progress respectivos if (config_partida_.jugador1_actiu && ship1_progress < 1.0F) { Vec2 pos_p1 = calcular_posicio_nau_init_hud(ship1_progress, 0); - naus_[0].set_centre(pos_p1); + naus_[0].setCenter(pos_p1); } if (config_partida_.jugador2_actiu && ship2_progress < 1.0F) { Vec2 pos_p2 = calcular_posicio_nau_init_hud(ship2_progress, 1); - naus_[1].set_centre(pos_p2); + naus_[1].setCenter(pos_p2); } // Una vegada l'animació acaba, permetre control normal @@ -416,36 +416,36 @@ void EscenaJoc::actualitzar(float delta_time) { // [DEBUG] Log entrada a LEVEL_START static bool first_entry = true; if (first_entry) { - std::cout << "[LEVEL_START] ENTERED with P1 pos.y=" << naus_[0].get_centre().y << '\n'; + std::cout << "[LEVEL_START] ENTERED with P1 pos.y=" << naus_[0].getCenter().y << '\n'; first_entry = false; } // Update countdown timer - stage_manager_->actualitzar(delta_time); + stage_manager_->update(delta_time); // [NEW] Allow both ships movement and shooting during intro for (uint8_t i = 0; i < 2; i++) { bool jugador_actiu = (i == 0) ? config_partida_.jugador1_actiu : config_partida_.jugador2_actiu; if (jugador_actiu && itocado_per_jugador_[i] == 0.0F) { // Only active, alive players - naus_[i].processar_input(delta_time, i); - naus_[i].actualitzar(delta_time); + naus_[i].processInput(delta_time, i); + naus_[i].update(delta_time); } } // [NEW] Update bullets for (auto& bala : bales_) { - bala.actualitzar(delta_time); + bala.update(delta_time); } // [NEW] Update debris - debris_manager_.actualitzar(delta_time); + debris_manager_.update(delta_time); break; } case StageSystem::EstatStage::PLAYING: { // [NEW] Update stage manager (spawns enemies, pause if BOTH dead) bool pausar_spawn = (itocado_per_jugador_[0] > 0.0F && itocado_per_jugador_[1] > 0.0F); - stage_manager_->get_spawn_controller().actualitzar(delta_time, orni_, pausar_spawn); + stage_manager_->get_spawn_controller().update(delta_time, orni_, pausar_spawn); // [NEW] Check stage completion (only when at least one player alive) bool algun_jugador_viu = (itocado_per_jugador_[0] == 0.0F || itocado_per_jugador_[1] == 0.0F); @@ -462,68 +462,68 @@ void EscenaJoc::actualitzar(float delta_time) { for (uint8_t i = 0; i < 2; i++) { bool jugador_actiu = (i == 0) ? config_partida_.jugador1_actiu : config_partida_.jugador2_actiu; if (jugador_actiu && itocado_per_jugador_[i] == 0.0F) { // Only active, alive players - naus_[i].processar_input(delta_time, i); - naus_[i].actualitzar(delta_time); + naus_[i].processInput(delta_time, i); + naus_[i].update(delta_time); } } for (auto& enemy : orni_) { - enemy.actualitzar(delta_time); + enemy.update(delta_time); } for (auto& bala : bales_) { - bala.actualitzar(delta_time); + bala.update(delta_time); } detectar_col·lisions_bales_enemics(); detectar_col·lisio_naus_enemics(); detectar_col·lisions_bales_jugadors(); - debris_manager_.actualitzar(delta_time); - gestor_puntuacio_.actualitzar(delta_time); + debris_manager_.update(delta_time); + gestor_puntuacio_.update(delta_time); break; } case StageSystem::EstatStage::LEVEL_COMPLETED: // Update countdown timer - stage_manager_->actualitzar(delta_time); + stage_manager_->update(delta_time); // [NEW] Allow both ships movement and shooting during outro for (uint8_t i = 0; i < 2; i++) { bool jugador_actiu = (i == 0) ? config_partida_.jugador1_actiu : config_partida_.jugador2_actiu; if (jugador_actiu && itocado_per_jugador_[i] == 0.0F) { // Only active, alive players - naus_[i].processar_input(delta_time, i); - naus_[i].actualitzar(delta_time); + naus_[i].processInput(delta_time, i); + naus_[i].update(delta_time); } } // [NEW] Update bullets (allow last shots to continue) for (auto& bala : bales_) { - bala.actualitzar(delta_time); + bala.update(delta_time); } // [NEW] Update debris (from last destroyed enemies) - debris_manager_.actualitzar(delta_time); - gestor_puntuacio_.actualitzar(delta_time); + debris_manager_.update(delta_time); + gestor_puntuacio_.update(delta_time); break; } } -void EscenaJoc::dibuixar() { +void EscenaJoc::draw() { // Handle CONTINUE screen if (estat_game_over_ == EstatGameOver::CONTINUE) { // Draw game background elements first dibuixar_marges(); for (const auto& enemy : orni_) { - enemy.dibuixar(); + enemy.draw(); } for (const auto& bala : bales_) { - bala.dibuixar(); + bala.draw(); } - debris_manager_.dibuixar(); - gestor_puntuacio_.dibuixar(); + debris_manager_.draw(); + gestor_puntuacio_.draw(); dibuixar_marcador(); // Draw CONTINUE screen overlay @@ -537,15 +537,15 @@ void EscenaJoc::dibuixar() { dibuixar_marges(); for (const auto& enemy : orni_) { - enemy.dibuixar(); + enemy.draw(); } for (const auto& bala : bales_) { - bala.dibuixar(); + bala.draw(); } - debris_manager_.dibuixar(); - gestor_puntuacio_.dibuixar(); + debris_manager_.draw(); + gestor_puntuacio_.draw(); // Draw centered "GAME OVER" text const std::string game_over_text = "GAME OVER"; @@ -610,12 +610,12 @@ void EscenaJoc::dibuixar() { } // [MODIFICAT] Dibuixar naus amb progress independent - if (ship1_progress > 0.0F && config_partida_.jugador1_actiu && !naus_[0].esta_tocada()) { - naus_[0].dibuixar(); + if (ship1_progress > 0.0F && config_partida_.jugador1_actiu && !naus_[0].isHit()) { + naus_[0].draw(); } - if (ship2_progress > 0.0F && config_partida_.jugador2_actiu && !naus_[1].esta_tocada()) { - naus_[1].dibuixar(); + if (ship2_progress > 0.0F && config_partida_.jugador2_actiu && !naus_[1].isHit()) { + naus_[1].draw(); } break; @@ -627,18 +627,18 @@ void EscenaJoc::dibuixar() { for (uint8_t i = 0; i < 2; i++) { bool jugador_actiu = (i == 0) ? config_partida_.jugador1_actiu : config_partida_.jugador2_actiu; if (jugador_actiu && itocado_per_jugador_[i] == 0.0F) { - naus_[i].dibuixar(); + naus_[i].draw(); } } // [NEW] Draw bullets for (const auto& bala : bales_) { - bala.dibuixar(); + bala.draw(); } // [NEW] Draw debris - debris_manager_.dibuixar(); - gestor_puntuacio_.dibuixar(); + debris_manager_.draw(); + gestor_puntuacio_.draw(); // [EXISTING] Draw intro message and score dibuixar_missatge_stage(stage_manager_->get_missatge_level_start()); @@ -652,20 +652,20 @@ void EscenaJoc::dibuixar() { for (uint8_t i = 0; i < 2; i++) { bool jugador_actiu = (i == 0) ? config_partida_.jugador1_actiu : config_partida_.jugador2_actiu; if (jugador_actiu && itocado_per_jugador_[i] == 0.0F) { - naus_[i].dibuixar(); + naus_[i].draw(); } } for (const auto& enemy : orni_) { - enemy.dibuixar(); + enemy.draw(); } for (const auto& bala : bales_) { - bala.dibuixar(); + bala.draw(); } - debris_manager_.dibuixar(); - gestor_puntuacio_.dibuixar(); + debris_manager_.draw(); + gestor_puntuacio_.draw(); dibuixar_marcador(); break; @@ -675,18 +675,18 @@ void EscenaJoc::dibuixar() { for (uint8_t i = 0; i < 2; i++) { bool jugador_actiu = (i == 0) ? config_partida_.jugador1_actiu : config_partida_.jugador2_actiu; if (jugador_actiu && itocado_per_jugador_[i] == 0.0F) { - naus_[i].dibuixar(); + naus_[i].draw(); } } // [NEW] Draw bullets (allow last shots to be visible) for (const auto& bala : bales_) { - bala.dibuixar(); + bala.draw(); } // [NEW] Draw debris (from last destroyed enemies) - debris_manager_.dibuixar(); - gestor_puntuacio_.dibuixar(); + debris_manager_.draw(); + gestor_puntuacio_.draw(); // [EXISTING] Draw completion message and score dibuixar_missatge_stage(StageSystem::Constants::MISSATGE_LEVEL_COMPLETED); @@ -699,28 +699,28 @@ void EscenaJoc::tocado(uint8_t player_id) { // Death sequence: 3 phases // Phase 1: First call (itocado_per_jugador_[player_id] == 0) - trigger explosion // Phase 2: Animation (0 < itocado_ < 3.0s) - debris animation - // Phase 3: Respawn or game over (itocado_ >= 3.0s) - handled in actualitzar() + // Phase 3: Respawn or game over (itocado_ >= 3.0s) - handled in update() if (itocado_per_jugador_[player_id] == 0.0F) { // *** PHASE 1: TRIGGER DEATH *** // Mark ship as dead (stops rendering and input) - naus_[player_id].marcar_tocada(); + naus_[player_id].markHit(); // Create ship explosion - const Vec2& ship_pos = naus_[player_id].get_centre(); - float ship_angle = naus_[player_id].get_angle(); - Vec2 vel_nau = naus_[player_id].get_velocitat_vector(); + const Vec2& ship_pos = naus_[player_id].getCenter(); + float ship_angle = naus_[player_id].getAngle(); + Vec2 vel_nau = naus_[player_id].getVelocityVector(); // Reduir a 80% la velocitat heretada per la nau (més realista) Vec2 vel_nau_80 = {.x = vel_nau.x * 0.8F, .y = vel_nau.y * 0.8F}; debris_manager_.explotar( - naus_[player_id].get_forma(), // Ship shape (3 lines) + naus_[player_id].getShape(), // Ship shape (3 lines) ship_pos, // Center position ship_angle, // Ship orientation 1.0F, // Normal scale Defaults::Physics::Debris::VELOCITAT_BASE, // 80 px/s - naus_[player_id].get_brightness(), // Heredar brightness + naus_[player_id].getBrightness(), // Heredar brightness vel_nau_80, // Heredar 80% velocitat 0.0F, // Nave: trayectorias rectas (sin drotacio) 0.0F, // Sin herencia visual (rotación aleatoria) @@ -730,8 +730,8 @@ void EscenaJoc::tocado(uint8_t player_id) { // Start death timer (non-zero to avoid re-triggering) itocado_per_jugador_[player_id] = 0.001F; } - // Phase 2 is automatic (debris updates in actualitzar()) - // Phase 3 is handled in actualitzar() when itocado_per_jugador_ >= DEATH_DURATION + // Phase 2 is automatic (debris updates in update()) + // Phase 3 is handled in update() when itocado_per_jugador_ >= DEATH_DURATION } void EscenaJoc::dibuixar_marges() const { @@ -957,18 +957,18 @@ void EscenaJoc::detectar_col·lisions_bales_enemics() { if (Physics::check_collision(bala, enemic, AMPLIFIER)) { // *** COL·LISIÓ DETECTADA *** - const Vec2& pos_enemic = enemic.get_centre(); + const Vec2& pos_enemic = enemic.getCenter(); // 1. Calculate score for enemy type int punts = 0; - switch (enemic.get_tipus()) { - case TipusEnemic::PENTAGON: + switch (enemic.getType()) { + case EnemyType::PENTAGON: punts = Defaults::Enemies::Scoring::PENTAGON_SCORE; break; - case TipusEnemic::QUADRAT: + case EnemyType::QUADRAT: punts = Defaults::Enemies::Scoring::QUADRAT_SCORE; break; - case TipusEnemic::MOLINILLO: + case EnemyType::MOLINILLO: punts = Defaults::Enemies::Scoring::MOLINILLO_SCORE; break; } @@ -984,14 +984,14 @@ void EscenaJoc::detectar_col·lisions_bales_enemics() { enemic.destruir(); // 2. Crear explosió de fragments - Vec2 vel_enemic = enemic.get_velocitat_vector(); + Vec2 vel_enemic = enemic.getVelocityVector(); debris_manager_.explotar( - enemic.get_forma(), // Forma vectorial del pentàgon + enemic.getShape(), // Forma vectorial del pentàgon pos_enemic, // Posició central 0.0F, // Angle (enemic té rotació interna) 1.0F, // Escala normal VELOCITAT_EXPLOSIO, // 50 px/s (explosió suau) - enemic.get_brightness(), // Heredar brightness + enemic.getBrightness(), // Heredar brightness vel_enemic, // Heredar velocitat enemic.get_drotacio(), // Heredar velocitat angular (trayectorias curvas) 0.0F // Sin herencia visual (rotación aleatoria) @@ -1017,17 +1017,17 @@ void EscenaJoc::detectar_col·lisio_naus_enemics() { if (itocado_per_jugador_[i] > 0.0F) { continue; } - if (!naus_[i].esta_viva()) { + if (!naus_[i].isAlive()) { continue; } - if (naus_[i].es_invulnerable()) { + if (naus_[i].isInvulnerable()) { continue; } // Check collision with all active enemies for (const auto& enemic : orni_) { // Skip collision if enemy is invulnerable - if (enemic.es_invulnerable()) { + if (enemic.isInvulnerable()) { continue; } @@ -1068,10 +1068,10 @@ void EscenaJoc::detectar_col·lisions_bales_jugadors() { if (itocado_per_jugador_[player_id] > 0.0F) { continue; } - if (!naus_[player_id].esta_viva()) { + if (!naus_[player_id].isAlive()) { continue; } - if (naus_[player_id].es_invulnerable()) { + if (naus_[player_id].isInvulnerable()) { continue; } @@ -1206,13 +1206,13 @@ void EscenaJoc::disparar_bala(uint8_t player_id) { if (itocado_per_jugador_[player_id] > 0.0F) { return; } - if (!naus_[player_id].esta_viva()) { + if (!naus_[player_id].isAlive()) { return; } // Calcular posición en la punta de la nave - const Vec2& ship_centre = naus_[player_id].get_centre(); - float ship_angle = naus_[player_id].get_angle(); + const Vec2& ship_centre = naus_[player_id].getCenter(); + float ship_angle = naus_[player_id].getAngle(); constexpr float LOCAL_TIP_X = 0.0F; constexpr float LOCAL_TIP_Y = -12.0F; @@ -1296,7 +1296,7 @@ void EscenaJoc::processar_input_continue() { // Spawn with invulnerability Vec2 spawn_pos = obtenir_punt_spawn(player_to_revive); - naus_[player_to_revive].inicialitzar(&spawn_pos, true); + naus_[player_to_revive].init(&spawn_pos, true); // Check if other player wants to continue too if (p1_start && p2_start) { @@ -1306,7 +1306,7 @@ void EscenaJoc::processar_input_continue() { itocado_per_jugador_[other_player] = 0.0F; config_partida_.jugador2_actiu = true; Vec2 spawn_pos2 = obtenir_punt_spawn(other_player); - naus_[other_player].inicialitzar(&spawn_pos2, true); + naus_[other_player].init(&spawn_pos2, true); } // Resume game @@ -1392,7 +1392,7 @@ void EscenaJoc::unir_jugador(uint8_t player_id) { // Spawn with invulnerability Vec2 spawn_pos = obtenir_punt_spawn(player_id); - naus_[player_id].inicialitzar(&spawn_pos, true); + naus_[player_id].init(&spawn_pos, true); // No visual message, just spawn (per user requirement) diff --git a/source/game/escenes/escena_joc.hpp b/source/game/escenes/escena_joc.hpp index fcd1cda..25dad6d 100644 --- a/source/game/escenes/escena_joc.hpp +++ b/source/game/escenes/escena_joc.hpp @@ -18,9 +18,9 @@ #include "game/constants.hpp" #include "game/effects/debris_manager.hpp" #include "game/effects/gestor_puntuacio_flotant.hpp" -#include "game/entities/bala.hpp" -#include "game/entities/enemic.hpp" -#include "game/entities/nau.hpp" +#include "game/entities/bullet.hpp" +#include "game/entities/enemy.hpp" +#include "game/entities/ship.hpp" #include "game/stage_system/stage_config.hpp" #include "game/stage_system/stage_manager.hpp" @@ -38,9 +38,9 @@ class EscenaJoc { ~EscenaJoc() = default; void executar(); // Bucle principal de l'escena - void inicialitzar(); - void actualitzar(float delta_time); - void dibuixar(); + void init(); + void update(float delta_time); + void draw(); private: SDLManager& sdl_; @@ -52,9 +52,9 @@ class EscenaJoc { Effects::GestorPuntuacioFlotant gestor_puntuacio_; // Estat del joc - std::array naus_; // [0]=P1, [1]=P2 - std::array orni_; - std::array bales_; // 6 balas: P1=[0,1,2], P2=[3,4,5] + std::array naus_; // [0]=P1, [1]=P2 + std::array orni_; + std::array bales_; // 6 balas: P1=[0,1,2], P2=[3,4,5] std::array itocado_per_jugador_; // Death timers per player (seconds) // Lives and game over system diff --git a/source/game/escenes/escena_logo.cpp b/source/game/escenes/escena_logo.cpp index 494bad5..2d99c91 100644 --- a/source/game/escenes/escena_logo.cpp +++ b/source/game/escenes/escena_logo.cpp @@ -108,7 +108,7 @@ void EscenaLogo::executar() { } // Actualitzar lògica - actualitzar(delta_time); + update(delta_time); // Actualitzar colors oscil·lats (efecte verd global) sdl_.updateColors(delta_time); @@ -117,7 +117,7 @@ void EscenaLogo::executar() { sdl_.updateRenderingContext(); // Dibuixar - dibuixar(); + draw(); } std::cout << "Escena Logo: Finalitzant...\n"; @@ -164,7 +164,7 @@ void EscenaLogo::inicialitzar_lletres() { // IMPORTANT: Escalar ancho i offset amb ESCALA_FINAL // per que les posicions finals coincideixin amb la mida real de les lletres float ancho = ancho_sin_escalar * ESCALA_FINAL; - float offset_centre = (forma->get_centre().x - min_x) * ESCALA_FINAL; + float offset_centre = (forma->getCenter().x - min_x) * ESCALA_FINAL; lletres_.push_back({forma, {.x = 0.0F, .y = 0.0F}, // Posició es calcularà després @@ -264,7 +264,7 @@ void EscenaLogo::actualitzar_explosions(float delta_time) { } } -void EscenaLogo::actualitzar(float delta_time) { +void EscenaLogo::update(float delta_time) { temps_estat_actual_ += delta_time; switch (estat_actual_) { @@ -326,10 +326,10 @@ void EscenaLogo::actualitzar(float delta_time) { } // Actualitzar animacions de debris - debris_manager_->actualitzar(delta_time); + debris_manager_->update(delta_time); } -void EscenaLogo::dibuixar() { +void EscenaLogo::draw() { // Fons negre sdl_.neteja(0, 0, 0); @@ -407,10 +407,10 @@ void EscenaLogo::dibuixar() { } } - // POST_EXPLOSION: No dibuixar lletres, només debris (a baix) + // POST_EXPLOSION: No draw lletres, només debris (a baix) - // Sempre dibuixar debris (si n'hi ha d'actius) - debris_manager_->dibuixar(); + // Sempre draw debris (si n'hi ha d'actius) + debris_manager_->draw(); sdl_.presenta(); } @@ -420,5 +420,5 @@ auto EscenaLogo::checkSkipButtonPressed() -> bool { } void EscenaLogo::processar_events(const SDL_Event& event) { - // No procesar eventos genéricos aquí - la lógica se movió a actualitzar() + // No procesar eventos genéricos aquí - la lógica se movió a update() } diff --git a/source/game/escenes/escena_logo.hpp b/source/game/escenes/escena_logo.hpp index 360bfc2..9b685b7 100644 --- a/source/game/escenes/escena_logo.hpp +++ b/source/game/escenes/escena_logo.hpp @@ -79,9 +79,9 @@ class EscenaLogo { // Mètodes privats void inicialitzar_lletres(); - void actualitzar(float delta_time); + void update(float delta_time); void actualitzar_explosions(float delta_time); - void dibuixar(); + void draw(); void processar_events(const SDL_Event& event); auto checkSkipButtonPressed() -> bool; diff --git a/source/game/escenes/escena_titol.cpp b/source/game/escenes/escena_titol.cpp index 2d8ecec..e260b39 100644 --- a/source/game/escenes/escena_titol.cpp +++ b/source/game/escenes/escena_titol.cpp @@ -79,7 +79,7 @@ EscenaTitol::EscenaTitol(SDLManager& sdl, ContextEscenes& context) // Inicialitzar animador de naus 3D ship_animator_ = std::make_unique(sdl_.obte_renderer()); - ship_animator_->inicialitzar(); + ship_animator_->init(); if (estat_actual_ == EstatTitol::MAIN) { // Jump to MAIN: empezar entrada inmediatamente @@ -145,7 +145,7 @@ void EscenaTitol::inicialitzar_titol() { // Escalar ancho, altura i offset amb LOGO_SCALE float ancho = ancho_sin_escalar * Defaults::Title::Layout::LOGO_SCALE; float altura = altura_sin_escalar * Defaults::Title::Layout::LOGO_SCALE; - float offset_centre = (forma->get_centre().x - min_x) * Defaults::Title::Layout::LOGO_SCALE; + float offset_centre = (forma->getCenter().x - min_x) * Defaults::Title::Layout::LOGO_SCALE; lletres_orni_.push_back({forma, {.x = 0.0F, .y = 0.0F}, ancho, altura, offset_centre}); @@ -219,7 +219,7 @@ void EscenaTitol::inicialitzar_titol() { // Escalar ancho, altura i offset amb LOGO_SCALE float ancho = ancho_sin_escalar * Defaults::Title::Layout::LOGO_SCALE; float altura = altura_sin_escalar * Defaults::Title::Layout::LOGO_SCALE; - float offset_centre = (forma->get_centre().x - min_x) * Defaults::Title::Layout::LOGO_SCALE; + float offset_centre = (forma->getCenter().x - min_x) * Defaults::Title::Layout::LOGO_SCALE; lletres_attack_.push_back({forma, {.x = 0.0F, .y = 0.0F}, ancho, altura, offset_centre}); @@ -295,7 +295,7 @@ void EscenaTitol::executar() { } // Actualitzar lògica - actualitzar(delta_time); + update(delta_time); // Actualitzar sistema d'audio Audio::update(); @@ -310,7 +310,7 @@ void EscenaTitol::executar() { sdl_.updateRenderingContext(); // Dibuixar - dibuixar(); + draw(); // Presentar renderer (swap buffers) sdl_.presenta(); @@ -319,10 +319,10 @@ void EscenaTitol::executar() { std::cout << "Escena Titol: Finalitzant...\n"; } -void EscenaTitol::actualitzar(float delta_time) { +void EscenaTitol::update(float delta_time) { // Actualitzar starfield (sempre actiu) if (starfield_) { - starfield_->actualitzar(delta_time); + starfield_->update(delta_time); } // Actualitzar naus (quan visibles) @@ -331,7 +331,7 @@ void EscenaTitol::actualitzar(float delta_time) { estat_actual_ == EstatTitol::STARFIELD || estat_actual_ == EstatTitol::MAIN || estat_actual_ == EstatTitol::PLAYER_JOIN_PHASE)) { - ship_animator_->actualitzar(delta_time); + ship_animator_->update(delta_time); } switch (estat_actual_) { @@ -541,10 +541,10 @@ void EscenaTitol::actualitzar_animacio_logo(float delta_time) { } } -void EscenaTitol::dibuixar() { +void EscenaTitol::draw() { // Dibuixar starfield de fons (en tots els estats excepte BLACK_SCREEN) if (starfield_ && estat_actual_ != EstatTitol::BLACK_SCREEN) { - starfield_->dibuixar(); + starfield_->draw(); } // Dibuixar naus (després starfield, abans logo) @@ -553,7 +553,7 @@ void EscenaTitol::dibuixar() { estat_actual_ == EstatTitol::STARFIELD || estat_actual_ == EstatTitol::MAIN || estat_actual_ == EstatTitol::PLAYER_JOIN_PHASE)) { - ship_animator_->dibuixar(); + ship_animator_->draw(); } // En els estats STARFIELD_FADE_IN i STARFIELD, només mostrar starfield (sense text) @@ -562,7 +562,7 @@ void EscenaTitol::dibuixar() { } // Estat MAIN i PLAYER_JOIN_PHASE: Dibuixar títol i text (sobre el starfield) - // BLACK_SCREEN: no dibuixar res (fons negre ja està netejat) + // BLACK_SCREEN: no draw res (fons negre ja està netejat) if (estat_actual_ == EstatTitol::MAIN || estat_actual_ == EstatTitol::PLAYER_JOIN_PHASE) { // === Calcular i renderitzar ombra (només si animació activa) === if (animacio_activa_) { @@ -726,5 +726,5 @@ auto EscenaTitol::checkStartGameButtonPressed() -> bool { } void EscenaTitol::processar_events(const SDL_Event& event) { - // No procesar eventos genéricos aquí - la lógica se movió a actualitzar() + // No procesar eventos genéricos aquí - la lógica se movió a update() } diff --git a/source/game/escenes/escena_titol.hpp b/source/game/escenes/escena_titol.hpp index 1b0d216..7f6ee0c 100644 --- a/source/game/escenes/escena_titol.hpp +++ b/source/game/escenes/escena_titol.hpp @@ -102,9 +102,9 @@ class EscenaTitol { static constexpr float DURACIO_LERP = 2.0F; // 2s per arribar a amplitud completa // Mètodes privats - void actualitzar(float delta_time); + void update(float delta_time); void actualitzar_animacio_logo(float delta_time); // Actualitza l'animació orbital del logo - void dibuixar(); + void draw(); void processar_events(const SDL_Event& event); auto checkSkipButtonPressed() -> bool; auto checkStartGameButtonPressed() -> bool; diff --git a/source/game/stage_system/spawn_controller.cpp b/source/game/stage_system/spawn_controller.cpp index 70872c8..844f053 100644 --- a/source/game/stage_system/spawn_controller.cpp +++ b/source/game/stage_system/spawn_controller.cpp @@ -10,7 +10,7 @@ #include #include "core/types.hpp" -#include "game/entities/enemic.hpp" +#include "game/entities/enemy.hpp" #include "stage_config.hpp" namespace StageSystem { @@ -44,7 +44,7 @@ void SpawnController::reset() { index_spawn_actual_ = 0; } -void SpawnController::actualitzar(float delta_time, std::array& orni_array, bool pausar) { +void SpawnController::update(float delta_time, std::array& orni_array, bool pausar) { if ((config_ == nullptr) || spawn_queue_.empty()) { return; } @@ -66,7 +66,7 @@ void SpawnController::actualitzar(float delta_time, std::array& orni if (temps_transcorregut_ >= event.temps_spawn) { // Find first inactive enemy for (auto& enemic : orni_array) { - if (!enemic.esta_actiu()) { + if (!enemic.isActive()) { spawn_enemic(enemic, event.tipus, ship_position_); event.spawnejat = true; index_spawn_actual_++; @@ -89,13 +89,13 @@ bool SpawnController::tots_enemics_spawnejats() const { return index_spawn_actual_ >= spawn_queue_.size(); } -bool SpawnController::tots_enemics_destruits(const std::array& orni_array) const { +bool SpawnController::tots_enemics_destruits(const std::array& orni_array) const { if (!tots_enemics_spawnejats()) { return false; } for (const auto& enemic : orni_array) { - if (enemic.esta_actiu()) { + if (enemic.isActive()) { return false; } } @@ -103,10 +103,10 @@ bool SpawnController::tots_enemics_destruits(const std::array& orni_ return true; } -uint8_t SpawnController::get_enemics_vius(const std::array& orni_array) const { +uint8_t SpawnController::get_enemics_vius(const std::array& orni_array) const { uint8_t count = 0; for (const auto& enemic : orni_array) { - if (enemic.esta_actiu()) { + if (enemic.isActive()) { count++; } } @@ -126,38 +126,38 @@ void SpawnController::generar_spawn_events() { float spawn_time = config_->config_spawn.delay_inicial + (i * config_->config_spawn.interval_spawn); - TipusEnemic tipus = seleccionar_tipus_aleatori(); + EnemyType tipus = seleccionar_tipus_aleatori(); spawn_queue_.push_back({spawn_time, tipus, false}); } } -TipusEnemic SpawnController::seleccionar_tipus_aleatori() const { +EnemyType SpawnController::seleccionar_tipus_aleatori() const { if (config_ == nullptr) { - return TipusEnemic::PENTAGON; + return EnemyType::PENTAGON; } // Weighted random selection based on distribution int rand_val = std::rand() % 100; if (std::cmp_less(rand_val, config_->distribucio.pentagon)) { - return TipusEnemic::PENTAGON; + return EnemyType::PENTAGON; } if (rand_val < config_->distribucio.pentagon + config_->distribucio.quadrat) { - return TipusEnemic::QUADRAT; + return EnemyType::QUADRAT; } - return TipusEnemic::MOLINILLO; + return EnemyType::MOLINILLO; } -void SpawnController::spawn_enemic(Enemic& enemic, TipusEnemic tipus, const Vec2* ship_pos) { +void SpawnController::spawn_enemic(Enemy& enemic, EnemyType tipus, const Vec2* ship_pos) { // Initialize enemy (with safe spawn if ship_pos provided) - enemic.inicialitzar(tipus, ship_pos); + enemic.init(tipus, ship_pos); // Apply difficulty multipliers aplicar_multiplicadors(enemic); } -void SpawnController::aplicar_multiplicadors(Enemic& enemic) const { +void SpawnController::aplicar_multiplicadors(Enemy& enemic) const { if (config_ == nullptr) { return; } diff --git a/source/game/stage_system/spawn_controller.hpp b/source/game/stage_system/spawn_controller.hpp index adff60c..f5cf23b 100644 --- a/source/game/stage_system/spawn_controller.hpp +++ b/source/game/stage_system/spawn_controller.hpp @@ -8,7 +8,7 @@ #include #include "core/types.hpp" -#include "game/entities/enemic.hpp" +#include "game/entities/enemy.hpp" #include "stage_config.hpp" namespace StageSystem { @@ -16,7 +16,7 @@ namespace StageSystem { // Informació de spawn planificat struct SpawnEvent { float temps_spawn; // Temps absolut (segons) per spawnejar - TipusEnemic tipus; // Tipus d'enemic + EnemyType tipus; // Tipus d'enemic bool spawnejat; // Ja s'ha processat? }; @@ -30,12 +30,12 @@ class SpawnController { void reset(); // Clear all pending spawns // Update - void actualitzar(float delta_time, std::array& orni_array, bool pausar = false); + void update(float delta_time, std::array& orni_array, bool pausar = false); // Status queries [[nodiscard]] bool tots_enemics_spawnejats() const; - [[nodiscard]] bool tots_enemics_destruits(const std::array& orni_array) const; - [[nodiscard]] uint8_t get_enemics_vius(const std::array& orni_array) const; + [[nodiscard]] bool tots_enemics_destruits(const std::array& orni_array) const; + [[nodiscard]] uint8_t get_enemics_vius(const std::array& orni_array) const; [[nodiscard]] uint8_t get_enemics_spawnejats() const; // [NEW] Set ship position reference for safe spawn @@ -49,9 +49,9 @@ class SpawnController { // Spawn generation void generar_spawn_events(); - [[nodiscard]] TipusEnemic seleccionar_tipus_aleatori() const; - void spawn_enemic(Enemic& enemic, TipusEnemic tipus, const Vec2* ship_pos = nullptr); - void aplicar_multiplicadors(Enemic& enemic) const; + [[nodiscard]] EnemyType seleccionar_tipus_aleatori() const; + void spawn_enemic(Enemy& enemic, EnemyType tipus, const Vec2* ship_pos = nullptr); + void aplicar_multiplicadors(Enemy& enemic) const; const Vec2* ship_position_; // [NEW] Non-owning pointer to ship position }; diff --git a/source/game/stage_system/stage_manager.cpp b/source/game/stage_system/stage_manager.cpp index 6fb3d2f..00fb32b 100644 --- a/source/game/stage_system/stage_manager.cpp +++ b/source/game/stage_system/stage_manager.cpp @@ -24,7 +24,7 @@ StageManager::StageManager(const ConfigSistemaStages* config) } } -void StageManager::inicialitzar() { +void StageManager::init() { stage_actual_ = 1; carregar_stage(stage_actual_); canviar_estat(EstatStage::INIT_HUD); @@ -33,7 +33,7 @@ void StageManager::inicialitzar() { << '\n'; } -void StageManager::actualitzar(float delta_time, bool pausar_spawn) { +void StageManager::update(float delta_time, bool pausar_spawn) { switch (estat_) { case EstatStage::INIT_HUD: processar_init_hud(delta_time); @@ -129,10 +129,10 @@ void StageManager::processar_level_start(float delta_time) { void StageManager::processar_playing(float delta_time, bool pausar_spawn) { // Update spawn controller (pauses when pausar_spawn = true) - // Note: The actual enemy array update happens in EscenaJoc::actualitzar() + // Note: The actual enemy array update happens in EscenaJoc::update() // This is just for internal timekeeping (void)delta_time; // Spawn controller is updated externally - (void)pausar_spawn; // Passed to spawn_controller_.actualitzar() by EscenaJoc + (void)pausar_spawn; // Passed to spawn_controller_.update() by EscenaJoc } void StageManager::processar_level_completed(float delta_time) { diff --git a/source/game/stage_system/stage_manager.hpp b/source/game/stage_system/stage_manager.hpp index 96371de..bcf7ee9 100644 --- a/source/game/stage_system/stage_manager.hpp +++ b/source/game/stage_system/stage_manager.hpp @@ -24,8 +24,8 @@ class StageManager { explicit StageManager(const ConfigSistemaStages* config); // Lifecycle - void inicialitzar(); // Reset to stage 1 - void actualitzar(float delta_time, bool pausar_spawn = false); + void init(); // Reset to stage 1 + void update(float delta_time, bool pausar_spawn = false); // Stage progression void stage_completat(); // Call when all enemies destroyed diff --git a/source/game/title/ship_animator.cpp b/source/game/title/ship_animator.cpp index 945136a..dff2f83 100644 --- a/source/game/title/ship_animator.cpp +++ b/source/game/title/ship_animator.cpp @@ -17,7 +17,7 @@ ShipAnimator::ShipAnimator(SDL_Renderer* renderer) : renderer_(renderer) { } -void ShipAnimator::inicialitzar() { +void ShipAnimator::init() { // Carregar formes de naus amb perspectiva pre-calculada auto forma_p1 = Graphics::ShapeLoader::load("ship_perspective.shp"); // Perspectiva esquerra auto forma_p2 = Graphics::ShapeLoader::load("ship2_perspective.shp"); // Perspectiva dreta @@ -33,7 +33,7 @@ void ShipAnimator::inicialitzar() { configurar_nau_p2(naus_[1]); } -void ShipAnimator::actualitzar(float delta_time) { +void ShipAnimator::update(float delta_time) { // Dispatcher segons estat de cada nau for (auto& nau : naus_) { if (!nau.visible) { @@ -54,7 +54,7 @@ void ShipAnimator::actualitzar(float delta_time) { } } -void ShipAnimator::dibuixar() const { +void ShipAnimator::draw() const { for (const auto& nau : naus_) { if (!nau.visible) { continue; diff --git a/source/game/title/ship_animator.hpp b/source/game/title/ship_animator.hpp index efdf577..4245ace 100644 --- a/source/game/title/ship_animator.hpp +++ b/source/game/title/ship_animator.hpp @@ -64,9 +64,9 @@ class ShipAnimator { explicit ShipAnimator(SDL_Renderer* renderer); // Cicle de vida - void inicialitzar(); - void actualitzar(float delta_time); - void dibuixar() const; + void init(); + void update(float delta_time); + void draw() const; // Control d'estat (cridat per EscenaTitol) void start_entry_animation();