From e5e3729215801a04591e78bcaa4d391575026d1d Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Sun, 24 May 2026 07:40:54 +0200 Subject: [PATCH] refactor(enemies): renombra QUADRAT/MOLINILLO a SQUARE/PINWHEEL --- source/core/defaults/enemies.hpp | 18 +- source/core/defaults/palette.hpp | 12 +- source/core/graphics/vector_text.cpp | 4 +- source/game/entities/bullet.cpp | 2 +- source/game/entities/bullet.hpp | 2 +- source/game/entities/enemy.cpp | 70 ++--- source/game/entities/enemy.hpp | 12 +- source/game/entities/ship.cpp | 2 +- source/game/entities/ship.hpp | 2 +- source/game/scenes/game_scene.cpp | 4 +- source/game/stage_system/spawn_controller.cpp | 244 +++++++++--------- source/game/stage_system/stage_config.hpp | 2 +- source/game/systems/collision_system.cpp | 26 +- 13 files changed, 200 insertions(+), 200 deletions(-) diff --git a/source/core/defaults/enemies.hpp b/source/core/defaults/enemies.hpp index 1d6a960..2055cc7 100644 --- a/source/core/defaults/enemies.hpp +++ b/source/core/defaults/enemies.hpp @@ -1,4 +1,4 @@ -// enemies.hpp - Configuració per tipus d'enemic (Pentagon/Cuadrado/Molinillo), spawn i scoring +// enemies.hpp - Configuració per tipus d'enemic (Pentagon/Square/Molinillo), spawn i scoring // © 2026 JailDesigner #pragma once @@ -27,8 +27,8 @@ namespace Defaults::Enemies { constexpr const char* SHAPE_FILE = "enemy_pentagon.shp"; } // namespace Pentagon - // Cuadrado (perseguidor - tracks player) - namespace Cuadrado { + // Square (perseguidor - tracks player) + namespace Square { constexpr float VELOCITAT = 40.0F; // px/s (medium speed) constexpr float MASS = 8.0F; // Más pesado, "tanque" constexpr float TRACKING_STRENGTH = 0.5F; // Interpolation toward player (0.0-1.0) @@ -36,10 +36,10 @@ namespace Defaults::Enemies { constexpr float DROTACIO_MIN = 0.3F; // Slow rotation [+50%] constexpr float DROTACIO_MAX = 1.5F; // [+50%] constexpr const char* SHAPE_FILE = "enemy_square.shp"; - } // namespace Cuadrado + } // namespace Square // Molinillo (agressiu - fast straight lines, proximity spin-up) - namespace Molinillo { + namespace Pinwheel { constexpr float VELOCITAT = 50.0F; // px/s (fastest) constexpr float MASS = 4.0F; // Más liviano, ágil constexpr float CANVI_ANGLE_PROB = 0.05F; // 5% per wall hit (rare direction change) @@ -49,7 +49,7 @@ namespace Defaults::Enemies { constexpr float DROTACIO_PROXIMITY_MULTIPLIER = 3.0F; // Spin-up multiplier when near ship constexpr float PROXIMITY_DISTANCE = 100.0F; // Distance threshold (px) constexpr const char* SHAPE_FILE = "enemy_pinwheel.shp"; - } // namespace Molinillo + } // namespace Pinwheel // Animation parameters (shared) namespace Animation { @@ -93,9 +93,9 @@ namespace Defaults::Enemies { // Scoring system (puntuación per type de enemy) namespace Scoring { - constexpr int PENTAGON_SCORE = 100; // Pentágono (esquivador, 35 px/s) - constexpr int QUADRAT_SCORE = 150; // Cuadrado (perseguidor, 40 px/s) - constexpr int MOLINILLO_SCORE = 200; // Molinillo (agressiu, 50 px/s) + constexpr int PENTAGON_SCORE = 100; // Pentágono (esquivador, 35 px/s) + constexpr int SQUARE_SCORE = 150; // Square (perseguidor, 40 px/s) + constexpr int PINWHEEL_SCORE = 200; // Molinillo (agressiu, 50 px/s) } // namespace Scoring } // namespace Defaults::Enemies diff --git a/source/core/defaults/palette.hpp b/source/core/defaults/palette.hpp index 6aef5b7..310ea8c 100644 --- a/source/core/defaults/palette.hpp +++ b/source/core/defaults/palette.hpp @@ -14,11 +14,11 @@ namespace Defaults::Palette { // brillantor perceptual sota el bloom (sense alterar la identitat de color). // El canal dominant es manté a 255 a cada color per maximitzar la saturació // visible quan el halo s'expandeix. - constexpr SDL_Color SHIP = {.r = 255, .g = 255, .b = 255, .a = 255}; // Blanco neutro - constexpr SDL_Color BULLET = {.r = 155, .g = 255, .b = 175, .a = 255}; // Verde laser - constexpr SDL_Color PENTAGON = {.r = 0, .g = 255, .b = 255, .a = 255}; // Cyan pur "esquivador" - constexpr SDL_Color QUADRAT = {.r = 255, .g = 0, .b = 0, .a = 255}; // Roig pur "tank" - constexpr SDL_Color MOLINILLO = {.r = 255, .g = 0, .b = 255, .a = 255}; // Magenta pur "agressiu" - constexpr SDL_Color WOUNDED = {.r = 255, .g = 220, .b = 60, .a = 255}; // Dorado: enemigo herido + constexpr SDL_Color SHIP = {.r = 255, .g = 255, .b = 255, .a = 255}; // Blanco neutro + constexpr SDL_Color BULLET = {.r = 155, .g = 255, .b = 175, .a = 255}; // Verde laser + constexpr SDL_Color PENTAGON = {.r = 0, .g = 255, .b = 255, .a = 255}; // Cyan pur "esquivador" + constexpr SDL_Color SQUARE = {.r = 255, .g = 0, .b = 0, .a = 255}; // Roig pur "tank" + constexpr SDL_Color PINWHEEL = {.r = 255, .g = 0, .b = 255, .a = 255}; // Magenta pur "agressiu" + constexpr SDL_Color WOUNDED = {.r = 255, .g = 220, .b = 60, .a = 255}; // Dorado: enemigo herido } // namespace Defaults::Palette diff --git a/source/core/graphics/vector_text.cpp b/source/core/graphics/vector_text.cpp index c89c383..27a289b 100644 --- a/source/core/graphics/vector_text.cpp +++ b/source/core/graphics/vector_text.cpp @@ -242,12 +242,12 @@ namespace Graphics { // Calcular posición de l'esquina superior izquierda // restant la meitat de las dimensions del point central - Vec2 posicio_esquerra = { + Vec2 top_left_position = { .x = centre_punt.x - (text_width / 2.0F), .y = centre_punt.y - (text_height / 2.0F)}; // Delegar al método render() existent - render(text, posicio_esquerra, scale, spacing, brightness, color); + render(text, top_left_position, scale, spacing, brightness, color); } auto VectorText::getTextWidth(const std::string& text, float scale, float spacing) -> float { diff --git a/source/game/entities/bullet.cpp b/source/game/entities/bullet.cpp index dc77574..cc661bd 100644 --- a/source/game/entities/bullet.cpp +++ b/source/game/entities/bullet.cpp @@ -53,7 +53,7 @@ void Bullet::init() { body_.clearAccumulators(); } -void Bullet::disparar(const Vec2& position, float angle, uint8_t owner_id) { +void Bullet::fire(const Vec2& position, float angle, uint8_t owner_id) { // Activar bullet is_active_ = true; diff --git a/source/game/entities/bullet.hpp b/source/game/entities/bullet.hpp index 7d9c8be..72c1a81 100644 --- a/source/game/entities/bullet.hpp +++ b/source/game/entities/bullet.hpp @@ -17,7 +17,7 @@ class Bullet : public Entities::Entity { explicit Bullet(Rendering::Renderer* renderer); void init() override; - void disparar(const Vec2& position, float angle, uint8_t owner_id); + void fire(const Vec2& position, float angle, uint8_t owner_id); void update(float delta_time) override; void postUpdate(float delta_time) override; void draw() const override; diff --git a/source/game/entities/enemy.cpp b/source/game/entities/enemy.cpp index b739635..d3596fa 100644 --- a/source/game/entities/enemy.cpp +++ b/source/game/entities/enemy.cpp @@ -41,7 +41,7 @@ namespace { Enemy::Enemy(Rendering::Renderer* renderer) : Entity(renderer), - tracking_strength_(Defaults::Enemies::Cuadrado::TRACKING_STRENGTH) { + tracking_strength_(Defaults::Enemies::Square::TRACKING_STRENGTH) { brightness_ = Defaults::Brightness::ENEMIC; // Configuración del cuerpo físico — defaults para enemy genérico. @@ -71,21 +71,21 @@ void Enemy::init(EnemyType type, const Vec2* ship_pos) { type_mass = Defaults::Enemies::Pentagon::MASS; break; - case EnemyType::QUADRAT: - shape_file = Defaults::Enemies::Cuadrado::SHAPE_FILE; - base_speed = Defaults::Enemies::Cuadrado::VELOCITAT; - drotacio_min = Defaults::Enemies::Cuadrado::DROTACIO_MIN; - drotacio_max = Defaults::Enemies::Cuadrado::DROTACIO_MAX; - type_mass = Defaults::Enemies::Cuadrado::MASS; + case EnemyType::SQUARE: + shape_file = Defaults::Enemies::Square::SHAPE_FILE; + base_speed = Defaults::Enemies::Square::VELOCITAT; + drotacio_min = Defaults::Enemies::Square::DROTACIO_MIN; + drotacio_max = Defaults::Enemies::Square::DROTACIO_MAX; + type_mass = Defaults::Enemies::Square::MASS; tracking_timer_ = 0.0F; break; - case EnemyType::MOLINILLO: - shape_file = Defaults::Enemies::Molinillo::SHAPE_FILE; - base_speed = Defaults::Enemies::Molinillo::VELOCITAT; - drotacio_min = Defaults::Enemies::Molinillo::DROTACIO_MIN; - drotacio_max = Defaults::Enemies::Molinillo::DROTACIO_MAX; - type_mass = Defaults::Enemies::Molinillo::MASS; + case EnemyType::PINWHEEL: + shape_file = Defaults::Enemies::Pinwheel::SHAPE_FILE; + base_speed = Defaults::Enemies::Pinwheel::VELOCITAT; + drotacio_min = Defaults::Enemies::Pinwheel::DROTACIO_MIN; + drotacio_max = Defaults::Enemies::Pinwheel::DROTACIO_MAX; + type_mass = Defaults::Enemies::Pinwheel::MASS; break; default: @@ -209,11 +209,11 @@ void Enemy::update(float delta_time) { case EnemyType::PENTAGON: behaviorPentagon(delta_time); break; - case EnemyType::QUADRAT: - behaviorQuadrat(delta_time); + case EnemyType::SQUARE: + behaviorSquare(delta_time); break; - case EnemyType::MOLINILLO: - behaviorMolinillo(delta_time); + case EnemyType::PINWHEEL: + behaviorPinwheel(delta_time); break; } } @@ -242,11 +242,11 @@ void Enemy::draw() const { case EnemyType::PENTAGON: color = Defaults::Palette::PENTAGON; break; - case EnemyType::QUADRAT: - color = Defaults::Palette::QUADRAT; + case EnemyType::SQUARE: + color = Defaults::Palette::SQUARE; break; - case EnemyType::MOLINILLO: - color = Defaults::Palette::MOLINILLO; + case EnemyType::PINWHEEL: + color = Defaults::Palette::PINWHEEL; break; } @@ -263,7 +263,7 @@ void Enemy::draw() const { Rendering::renderShape(renderer_, shape_, center_, rotacio_, SCALE, 1.0F, brightness_, color); } -void Enemy::destruir() { +void Enemy::destroy() { esta_ = false; body_.velocity = Vec2{}; body_.angular_velocity = 0.0F; @@ -273,7 +273,7 @@ void Enemy::destruir() { last_hit_by_ = 0xFF; } -void Enemy::herir(uint8_t shooter_id) { +void Enemy::hurt(uint8_t shooter_id) { wounded_timer_ = Defaults::Enemies::Wounded::DURATION; last_hit_by_ = shooter_id; // El so HIT ara el reprodueix la bala quan es trenca en debris @@ -320,12 +320,12 @@ void Enemy::behaviorPentagon(float delta_time) { } } -// QUADRAT: tracking discreto cada TRACKING_INTERVAL. Ajusta dirección +// SQUARE: tracking discreto cada TRACKING_INTERVAL. Ajusta dirección // hacia el ship mezclando con tracking_strength_. -void Enemy::behaviorQuadrat(float delta_time) { +void Enemy::behaviorSquare(float delta_time) { tracking_timer_ += delta_time; - if (tracking_timer_ >= Defaults::Enemies::Cuadrado::TRACKING_INTERVAL && ship_position_ != nullptr) { + if (tracking_timer_ >= Defaults::Enemies::Square::TRACKING_INTERVAL && ship_position_ != nullptr) { tracking_timer_ = 0.0F; const Vec2 TO_SHIP = *ship_position_ - center_; @@ -348,16 +348,16 @@ void Enemy::behaviorQuadrat(float delta_time) { } } -// MOLINILLO: movimiento recto + boost de rotación visual cerca del ship. +// PINWHEEL: movimiento recto + boost de rotación visual cerca del ship. // Sin tracking — solo cambios de dirección raros (igual que Pentagon pero // con probabilidad mucho menor). -void Enemy::behaviorMolinillo(float /*delta_time*/) { +void Enemy::behaviorPinwheel(float /*delta_time*/) { // Boost de rotación visual por proximidad al ship if (ship_position_ != nullptr) { const Vec2 TO_SHIP = *ship_position_ - center_; const float DIST = TO_SHIP.length(); - if (DIST < Defaults::Enemies::Molinillo::PROXIMITY_DISTANCE) { - drotacio_ = animacio_.drotacio_base * Defaults::Enemies::Molinillo::DROTACIO_PROXIMITY_MULTIPLIER; + if (DIST < Defaults::Enemies::Pinwheel::PROXIMITY_DISTANCE) { + drotacio_ = animacio_.drotacio_base * Defaults::Enemies::Pinwheel::DROTACIO_PROXIMITY_MULTIPLIER; } else { drotacio_ = animacio_.drotacio_base; } @@ -455,10 +455,10 @@ auto Enemy::getBaseVelocity() const -> float { switch (type_) { case EnemyType::PENTAGON: return Defaults::Enemies::Pentagon::VELOCITAT; - case EnemyType::QUADRAT: - return Defaults::Enemies::Cuadrado::VELOCITAT; - case EnemyType::MOLINILLO: - return Defaults::Enemies::Molinillo::VELOCITAT; + case EnemyType::SQUARE: + return Defaults::Enemies::Square::VELOCITAT; + case EnemyType::PINWHEEL: + return Defaults::Enemies::Pinwheel::VELOCITAT; default: return Defaults::Enemies::Pentagon::VELOCITAT; } @@ -469,7 +469,7 @@ auto Enemy::getBaseRotation() const -> float { } void Enemy::setTrackingStrength(float strength) { - if (type_ == EnemyType::QUADRAT) { + if (type_ == EnemyType::SQUARE) { tracking_strength_ = strength; } } diff --git a/source/game/entities/enemy.hpp b/source/game/entities/enemy.hpp index 0fd600f..0701b3f 100644 --- a/source/game/entities/enemy.hpp +++ b/source/game/entities/enemy.hpp @@ -13,8 +13,8 @@ // Tipo de enemy enum class EnemyType : uint8_t { PENTAGON = 0, // Pentágono esquivador (zigzag) - QUADRAT = 1, // Cuadrado perseguidor (tracks ship) - MOLINILLO = 2 // Molinillo agresivo (rápido, girando) + SQUARE = 1, // Square perseguidor (tracks ship) + PINWHEEL = 2 // Molinillo agresivo (rápido, girando) }; // Estado de animación (palpitación + rotación acelerada) @@ -60,7 +60,7 @@ class Enemy : public Entities::Entity { } // Marcar destruido (desactiva el cuerpo físicamente: radius=0) - void destruir(); + void destroy(); // Getters [[nodiscard]] auto getRotationDelta() const -> float { return drotacio_; } @@ -90,7 +90,7 @@ class Enemy : public Entities::Entity { // Estado "herido": entre primer impacto de bala y explosión diferida. // shooter_id: id del jugador que herí; 0xFF = sin atribución (cadena, etc.). - void herir(uint8_t shooter_id = 0xFF); + void hurt(uint8_t shooter_id = 0xFF); [[nodiscard]] auto isWounded() const -> bool { return wounded_timer_ > 0.0F; } [[nodiscard]] auto getWoundedTimer() const -> float { return wounded_timer_; } [[nodiscard]] auto woundExpiredThisFrame() const -> bool { return wound_expired_this_frame_; } @@ -130,8 +130,8 @@ class Enemy : public Entities::Entity { void updatePalpitation(float delta_time); void updateRotationAcceleration(float delta_time); void behaviorPentagon(float delta_time); - void behaviorQuadrat(float delta_time); - void behaviorMolinillo(float delta_time); + void behaviorSquare(float delta_time); + void behaviorPinwheel(float delta_time); [[nodiscard]] auto computeCurrentScale() const -> float; // Estático: solo opera sobre ship_pos pasado; no consulta estado del enemy. static auto attemptSafeSpawn(const Vec2& ship_pos, float& out_x, float& out_y) -> bool; diff --git a/source/game/entities/ship.cpp b/source/game/entities/ship.cpp index 996948d..1b98dbf 100644 --- a/source/game/entities/ship.cpp +++ b/source/game/entities/ship.cpp @@ -180,7 +180,7 @@ void Ship::draw() const { Rendering::renderShape(renderer_, shape_, center_, angle_, SCALE, 1.0F, brightness_, color); } -void Ship::herir() { +void Ship::hurt() { hurt_timer_ = Defaults::Ship::Hurt::DURATION; Audio::get()->playSound(Defaults::Sound::HURT, Audio::Group::GAME); } diff --git a/source/game/entities/ship.hpp b/source/game/entities/ship.hpp index 2ff1696..a5b64cc 100644 --- a/source/game/entities/ship.hpp +++ b/source/game/entities/ship.hpp @@ -54,7 +54,7 @@ class Ship : public Entities::Entity { } // Estat "ferit": primera col·lisió amb enemic dispara HURT; segona durant HURT mata. - void herir(); + void hurt(); [[nodiscard]] auto isHurt() const -> bool { return hurt_timer_ > 0.0F; } [[nodiscard]] auto getHurtTimer() const -> float { return hurt_timer_; } diff --git a/source/game/scenes/game_scene.cpp b/source/game/scenes/game_scene.cpp index 87cd6c0..a4d2f0b 100644 --- a/source/game/scenes/game_scene.cpp +++ b/source/game/scenes/game_scene.cpp @@ -927,7 +927,7 @@ void GameScene::fireBullet(uint8_t player_id) { float sin_a = std::sin(ship_angle); float tip_x = (LOCAL_TIP_X * cos_a) - (LOCAL_TIP_Y * sin_a) + ship_centre.x; float tip_y = (LOCAL_TIP_X * sin_a) + (LOCAL_TIP_Y * cos_a) + ship_centre.y; - Vec2 posicio_dispar = {.x = tip_x, .y = tip_y}; + Vec2 fire_position = {.x = tip_x, .y = tip_y}; // Buscar primera bullet inactiva en el pool del player. // El pool global té MAX_BALES slots per jugador (P1=[0..MAX-1], P2=[MAX..2*MAX-1]). @@ -935,7 +935,7 @@ void GameScene::fireBullet(uint8_t player_id) { const int START_IDX = player_id * SLOTS_PER_PLAYER; for (int i = START_IDX; i < START_IDX + SLOTS_PER_PLAYER; i++) { if (!bullets_[i].isActive()) { - bullets_[i].disparar(posicio_dispar, ship_angle, player_id); + bullets_[i].fire(fire_position, ship_angle, player_id); break; } } diff --git a/source/game/stage_system/spawn_controller.cpp b/source/game/stage_system/spawn_controller.cpp index 1aa67b6..82a769a 100644 --- a/source/game/stage_system/spawn_controller.cpp +++ b/source/game/stage_system/spawn_controller.cpp @@ -16,152 +16,152 @@ namespace StageSystem { -SpawnController::SpawnController() = default; + SpawnController::SpawnController() = default; -void SpawnController::configure(const StageConfig* config) { - config_ = config; -} - -void SpawnController::start() { - if (config_ == nullptr) { - std::cerr << "[SpawnController] Error: config_ es null" << '\n'; - return; + void SpawnController::configure(const StageConfig* config) { + config_ = config; } - reset(); - generateSpawnEvents(); - - std::cout << "[SpawnController] Stage " << static_cast(config_->stage_id) - << ": generats " << spawn_queue_.size() << " spawn events" << '\n'; -} - -void SpawnController::reset() { - spawn_queue_.clear(); - temps_transcorregut_ = 0.0F; - index_spawn_actual_ = 0; -} - -void SpawnController::update(float delta_time, std::array& orni_array, bool pausar) { - if ((config_ == nullptr) || spawn_queue_.empty()) { - return; - } - - // Increment timer only when not paused - if (!pausar) { - temps_transcorregut_ += delta_time; - } - - // Process spawn events - while (index_spawn_actual_ < spawn_queue_.size()) { - SpawnEvent& event = spawn_queue_[index_spawn_actual_]; - - if (event.spawnejat) { - index_spawn_actual_++; - continue; + void SpawnController::start() { + if (config_ == nullptr) { + std::cerr << "[SpawnController] Error: config_ es null" << '\n'; + return; } - if (temps_transcorregut_ >= event.temps_spawn) { - // Find first inactive enemy - for (auto& enemy : orni_array) { - if (!enemy.isActive()) { - spawnEnemy(enemy, event.type, ship_position_); - event.spawnejat = true; - index_spawn_actual_++; + reset(); + generateSpawnEvents(); + + std::cout << "[SpawnController] Stage " << static_cast(config_->stage_id) + << ": generats " << spawn_queue_.size() << " spawn events" << '\n'; + } + + void SpawnController::reset() { + spawn_queue_.clear(); + temps_transcorregut_ = 0.0F; + index_spawn_actual_ = 0; + } + + void SpawnController::update(float delta_time, std::array& orni_array, bool pausar) { + if ((config_ == nullptr) || spawn_queue_.empty()) { + return; + } + + // Increment timer only when not paused + if (!pausar) { + temps_transcorregut_ += delta_time; + } + + // Process spawn events + while (index_spawn_actual_ < spawn_queue_.size()) { + SpawnEvent& event = spawn_queue_[index_spawn_actual_]; + + if (event.spawnejat) { + index_spawn_actual_++; + continue; + } + + if (temps_transcorregut_ >= event.temps_spawn) { + // Find first inactive enemy + for (auto& enemy : orni_array) { + if (!enemy.isActive()) { + spawnEnemy(enemy, event.type, ship_position_); + event.spawnejat = true; + index_spawn_actual_++; + break; + } + } + + // If no slot available, try next frame + if (!event.spawnejat) { break; } - } - - // If no slot available, try next frame - if (!event.spawnejat) { + } else { + // Not yet time for this spawn break; } - } else { - // Not yet time for this spawn - break; } } -} -auto SpawnController::allEnemiesSpawned() const -> bool { - return index_spawn_actual_ >= spawn_queue_.size(); -} - -auto SpawnController::allEnemiesDestroyed(const std::array& orni_array) const -> bool { - if (!allEnemiesSpawned()) { - return false; + auto SpawnController::allEnemiesSpawned() const -> bool { + return index_spawn_actual_ >= spawn_queue_.size(); } - return std::ranges::all_of(orni_array, [](const Enemy& enemy) { return !enemy.isActive(); }); -} -auto SpawnController::getAliveEnemyCount(const std::array& orni_array) -> uint8_t { - uint8_t count = 0; - for (const auto& enemy : orni_array) { - if (enemy.isActive()) { - count++; + auto SpawnController::allEnemiesDestroyed(const std::array& orni_array) const -> bool { + if (!allEnemiesSpawned()) { + return false; + } + return std::ranges::all_of(orni_array, [](const Enemy& enemy) { return !enemy.isActive(); }); + } + + auto SpawnController::getAliveEnemyCount(const std::array& orni_array) -> uint8_t { + uint8_t count = 0; + for (const auto& enemy : orni_array) { + if (enemy.isActive()) { + count++; + } + } + return count; + } + + auto SpawnController::countSpawnedEnemies() const -> uint8_t { + return static_cast(index_spawn_actual_); + } + + void SpawnController::generateSpawnEvents() { + if (config_ == nullptr) { + return; + } + + for (uint8_t i = 0; i < config_->total_enemies; i++) { + float spawn_time = config_->config_spawn.delay_inicial + + (i * config_->config_spawn.interval_spawn); + + EnemyType type = selectRandomType(); + + spawn_queue_.push_back({spawn_time, type, false}); } } - return count; -} -auto SpawnController::countSpawnedEnemies() const -> uint8_t { - return static_cast(index_spawn_actual_); -} + auto SpawnController::selectRandomType() const -> EnemyType { + if (config_ == nullptr) { + return EnemyType::PENTAGON; + } -void SpawnController::generateSpawnEvents() { - if (config_ == nullptr) { - return; + // Weighted random selection based on distribution + int rand_val = std::rand() % 100; + + if (std::cmp_less(rand_val, config_->distribucio.pentagon)) { + return EnemyType::PENTAGON; + } + if (rand_val < config_->distribucio.pentagon + config_->distribucio.cuadrado) { + return EnemyType::SQUARE; + } + return EnemyType::PINWHEEL; } - for (uint8_t i = 0; i < config_->total_enemies; i++) { - float spawn_time = config_->config_spawn.delay_inicial + - (i * config_->config_spawn.interval_spawn); + void SpawnController::spawnEnemy(Enemy& enemy, EnemyType type, const Vec2* ship_pos) { + // Initialize enemy (with safe spawn if ship_pos provided) + enemy.init(type, ship_pos); - EnemyType type = selectRandomType(); - - spawn_queue_.push_back({spawn_time, type, false}); - } -} - -auto SpawnController::selectRandomType() const -> EnemyType { - if (config_ == nullptr) { - return EnemyType::PENTAGON; + // Apply difficulty multipliers + applyMultipliers(enemy); } - // Weighted random selection based on distribution - int rand_val = std::rand() % 100; + void SpawnController::applyMultipliers(Enemy& enemy) const { + if (config_ == nullptr) { + return; + } - if (std::cmp_less(rand_val, config_->distribucio.pentagon)) { - return EnemyType::PENTAGON; + // Apply velocity multiplier + float base_vel = enemy.getBaseVelocity(); + enemy.setVelocity(base_vel * config_->multiplicadors.velocity); + + // Apply rotation multiplier + float base_rot = enemy.getBaseRotation(); + enemy.setRotation(base_rot * config_->multiplicadors.rotation); + + // Apply tracking strength (only affects SQUARE) + enemy.setTrackingStrength(config_->multiplicadors.tracking_strength); } - if (rand_val < config_->distribucio.pentagon + config_->distribucio.cuadrado) { - return EnemyType::QUADRAT; - } - return EnemyType::MOLINILLO; -} - -void SpawnController::spawnEnemy(Enemy& enemy, EnemyType type, const Vec2* ship_pos) { - // Initialize enemy (with safe spawn if ship_pos provided) - enemy.init(type, ship_pos); - - // Apply difficulty multipliers - applyMultipliers(enemy); -} - -void SpawnController::applyMultipliers(Enemy& enemy) const { - if (config_ == nullptr) { - return; - } - - // Apply velocity multiplier - float base_vel = enemy.getBaseVelocity(); - enemy.setVelocity(base_vel * config_->multiplicadors.velocity); - - // Apply rotation multiplier - float base_rot = enemy.getBaseRotation(); - enemy.setRotation(base_rot * config_->multiplicadors.rotation); - - // Apply tracking strength (only affects QUADRAT) - enemy.setTrackingStrength(config_->multiplicadors.tracking_strength); -} } // namespace StageSystem diff --git a/source/game/stage_system/stage_config.hpp b/source/game/stage_system/stage_config.hpp index c8665db..9616e43 100644 --- a/source/game/stage_system/stage_config.hpp +++ b/source/game/stage_system/stage_config.hpp @@ -36,7 +36,7 @@ namespace StageSystem { struct MultiplicadorsDificultat { float velocity; // 0.5-2.0 típic float rotation; // 0.5-2.0 típic - float tracking_strength; // 0.0-1.5 (aplicat a Cuadrado) + float tracking_strength; // 0.0-1.5 (aplicat a Square) }; // Metadades del file YAML diff --git a/source/game/systems/collision_system.cpp b/source/game/systems/collision_system.cpp index 2185b35..a59292b 100644 --- a/source/game/systems/collision_system.cpp +++ b/source/game/systems/collision_system.cpp @@ -20,10 +20,10 @@ namespace Systems::Collision { switch (type) { case EnemyType::PENTAGON: return Defaults::Enemies::Scoring::PENTAGON_SCORE; - case EnemyType::QUADRAT: - return Defaults::Enemies::Scoring::QUADRAT_SCORE; - case EnemyType::MOLINILLO: - return Defaults::Enemies::Scoring::MOLINILLO_SCORE; + case EnemyType::SQUARE: + return Defaults::Enemies::Scoring::SQUARE_SCORE; + case EnemyType::PINWHEEL: + return Defaults::Enemies::Scoring::PINWHEEL_SCORE; } return 0; } @@ -32,10 +32,10 @@ namespace Systems::Collision { switch (type) { case EnemyType::PENTAGON: return Defaults::Palette::PENTAGON; - case EnemyType::QUADRAT: - return Defaults::Palette::QUADRAT; - case EnemyType::MOLINILLO: - return Defaults::Palette::MOLINILLO; + case EnemyType::SQUARE: + return Defaults::Palette::SQUARE; + case EnemyType::PINWHEEL: + return Defaults::Palette::PINWHEEL; } return SDL_Color{}; } @@ -58,7 +58,7 @@ namespace Systems::Collision { } ctx.floating_score_manager.crear(POINTS, ENEMY_POS); - enemy.destruir(); + enemy.destroy(); constexpr float VELOCITAT_EXPLOSIO = 80.0F; // px/s (explosión suave) const Vec2 INHERITED_VEL = ENEMY_VEL * Defaults::Physics::Debris::ENEMY_VELOCITY_INHERITANCE; @@ -141,7 +141,7 @@ namespace Systems::Collision { explodeNow(ctx, enemy, SHOOTER); } else { // Primer impacto → entra en estado herido (explosión diferida). - enemy.herir(SHOOTER); + enemy.hurt(SHOOTER); } breakBullet(ctx.debris_manager, bullet); @@ -182,9 +182,9 @@ namespace Systems::Collision { } // El sano queda herido, propagando el shooter original. if (A_WOUNDED) { - b.herir(a.getLastHitBy()); + b.hurt(a.getLastHitBy()); } else { - a.herir(b.getLastHitBy()); + a.hurt(b.getLastHitBy()); } } } @@ -230,7 +230,7 @@ namespace Systems::Collision { } else { // Primer impacte → estat HURT (rebot físic ja resolt per PhysicsWorld; // l'enemic no rep dany per decisió de disseny). - ctx.ships[i].herir(); + ctx.ships[i].hurt(); } } ctx.ships[i].setTouchingEnemyPrevFrame(TOUCHING_NOW);