// 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 "core/graphics/shape_loader.hpp" #include "core/rendering/shape_renderer.hpp" #include "game/constants.hpp" #include #include #include 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) { // [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 centre_.x = static_cast((std::rand() % 580) + 30); // 30-610 centre_.y = static_cast((std::rand() % 420) + 30); // 30-450 // 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); } } 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 de la zona de joc float min_x, max_x, min_y, max_y; Constants::obtenir_limits_zona(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 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 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() }