// enemic.cpp - Implementació d'enemics (ORNIs) // © 1999 Visente i Sergi (versió Pascal) // © 2025 Port a C++20 amb SDL3 #include "game/entities/enemic.hpp" #include #include #include #include "core/defaults.hpp" #include "core/graphics/shape_loader.hpp" #include "core/rendering/shape_renderer.hpp" #include "game/constants.hpp" Enemic::Enemic(SDL_Renderer* renderer) : renderer_(renderer), centre_({0.0f, 0.0f}), angle_(0.0f), velocitat_(0.0f), drotacio_(0.0f), rotacio_(0.0f), esta_(false), brightness_(Defaults::Brightness::ENEMIC) { // [NUEVO] Carregar forma compartida des de fitxer forma_ = Graphics::ShapeLoader::load("enemy_pentagon.shp"); if (!forma_ || !forma_->es_valida()) { std::cerr << "[Enemic] Error: no s'ha pogut carregar enemy_pentagon.shp" << std::endl; } } void Enemic::inicialitzar() { // Inicialitzar enemic (pentàgon) // Copiat de joc_asteroides.cpp línies 41-54 // [NUEVO] Ja no cal crear_poligon_regular - la geometria es carrega del // fitxer Només inicialitzem l'estat de la instància // Posició aleatòria dins de l'àrea de joc // Calcular rangs segurs amb radi de l'enemic float min_x, max_x, min_y, max_y; Constants::obtenir_limits_zona_segurs(Defaults::Entities::ENEMY_RADIUS, min_x, max_x, min_y, max_y); // Spawn aleatori dins dels límits segurs 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)); // Angle aleatori de moviment angle_ = (std::rand() % 360) * Constants::PI / 180.0f; // Velocitat (2 px/frame original * 20 FPS = 40 px/s) velocitat_ = 40.0f; // Rotació visual aleatòria (rad/s) // Original Pascal: random * 0.1 rad/frame * 20 FPS ≈ 2 rad/s drotacio_ = (static_cast(std::rand()) / RAND_MAX) * 2.0f; rotacio_ = 0.0f; // Activar esta_ = true; } void Enemic::actualitzar(float delta_time) { if (esta_) { // Moviment autònom mou(delta_time); // Rotació visual (time-based: drotacio_ està en rad/s) rotacio_ += drotacio_ * delta_time; } } void Enemic::dibuixar() const { if (esta_ && forma_) { // [NUEVO] Usar render_shape en lloc de rota_pol Rendering::render_shape(renderer_, forma_, centre_, rotacio_, 1.0f, true, 1.0f, brightness_); } } void Enemic::mou(float delta_time) { // Moviment autònom d'ORNI (enemic pentàgon) // Basat EXACTAMENT en el codi Pascal original: ASTEROID.PAS lines 279-293 // Copiat EXACTAMENT de joc_asteroides.cpp línies 348-394 // // IMPORTANT: El Pascal original NO té canvi aleatori continu! // Només ajusta l'angle quan toca una paret. // Calcular nova posició PROPUESTA (time-based, però lògica Pascal) // velocitat_ ja està en px/s (40 px/s), multiplicar per delta_time float velocitat_efectiva = velocitat_ * 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; // Obtenir límits segurs compensant el radi de l'enemic float min_x, max_x, min_y, max_y; Constants::obtenir_limits_zona_segurs(Defaults::Entities::ENEMY_RADIUS, min_x, max_x, min_y, max_y); // Lògica Pascal: Actualitza Y si dins, sinó ajusta angle aleatòriament // if (dy>marge_dalt) and (dy= i <=) per evitar fugides if (new_y >= min_y && new_y <= max_y) { centre_.y = new_y; } else { // Pequeño ajuste aleatorio: (random(256)/512)*(random(3)-1) // random(256) = 0..255, /512 = 0..0.498 // random(3) = 0,1,2, -1 = -1,0,1 // Resultado: ±0.5 rad aprox float rand1 = (static_cast(std::rand() % 256) / 512.0f); int rand2 = (std::rand() % 3) - 1; // -1, 0, o 1 angle_ += rand1 * static_cast(rand2); } // Lògica Pascal: Actualitza X si dins, sinó ajusta angle aleatòriament // if (dx>marge_esq) and (dx= i <=) per evitar fugides if (new_x >= min_x && new_x <= max_x) { centre_.x = new_x; } else { float rand1 = (static_cast(std::rand() % 256) / 512.0f); int rand2 = (std::rand() % 3) - 1; angle_ += rand1 * static_cast(rand2); } // Nota: La rotació visual (rotacio_ += drotacio_) ja es fa a actualitzar() }