// bullet.cpp - Implementació de projectils de la ship // © 1999 Visente i Sergi (versión Pascal) // © 2025 Port a C++20 con SDL3 #include "game/entities/bullet.hpp" #include #include #include #include #include "core/audio/audio.hpp" #include "core/defaults.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" Bullet::Bullet(SDL_Renderer* renderer) : Entity(renderer), velocity_(0.0F), esta_(false), owner_id_(0), grace_timer_(0.0F) { // [NUEVO] Brightness específic per balas brightness_ = Defaults::Brightness::BALA; // [NUEVO] Carregar shape compartida desde file shape_ = Graphics::ShapeLoader::load("bullet.shp"); if (!shape_ || !shape_->isValid()) { std::cerr << "[Bullet] Error: no s'ha pogut load bullet.shp" << '\n'; } } void Bullet::init() { // Inicialment inactiva esta_ = false; center_ = {.x = 0.0F, .y = 0.0F}; angle_ = 0.0F; velocity_ = 0.0F; grace_timer_ = 0.0F; } void Bullet::disparar(const Vec2& position, float angle, uint8_t owner_id) { // Activar bullet i posicionar-la a la ship // Basat en joc_asteroides.cpp línies 188-200 // Activar bullet esta_ = true; // Posición inicial = centro de la ship center_.x = position.x; center_.y = position.y; // Angle = angle de la ship (dispara en la direcció que apunta) angle_ = angle; // Almacenar propietario (0=P1, 1=P2) owner_id_ = owner_id; // Velocidad alta (el juego Pascal original usava 7 px/frame) // 7 px/frame × 20 FPS = 140 px/s velocity_ = 140.0F; // Activar grace period (prevents instant self-collision) grace_timer_ = Defaults::Game::BULLET_GRACE_PERIOD; // Reproducir sonido de disparo láser Audio::get()->playSound(Defaults::Sound::LASER, Audio::Group::GAME); } void Bullet::update(float delta_time) { if (esta_) { // Decrementar grace timer if (grace_timer_ > 0.0F) { grace_timer_ -= delta_time; grace_timer_ = std::max(grace_timer_, 0.0F); } mou(delta_time); } } void Bullet::draw() const { if (esta_ && shape_) { // [NUEVO] Usar render_shape en lloc de rota_pol // Les balas roten segons l'angle de trajectòria Rendering::render_shape(renderer_, shape_, center_, angle_, 1.0F, 1.0F, brightness_); } } void Bullet::mou(float delta_time) { // Moviment rectilini de la bullet // Basat en el codi Pascal original: procedure mou_bales // Copiat EXACTAMENT de joc_asteroides.cpp línies 396-419 // Calcular nueva posición (movement polar time-based) // velocity ya está en px/s (140 px/s), solo necesario multiplicar per 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 con precisió subpíxel center_.y += dy; center_.x += dx; // Desactivar si surt de la zona de juego (no rebota como los ORNIs) // CORRECCIÓ: Usar límits segurs con radi de la bullet float min_x; float max_x; float min_y; float max_y; Constants::obtenir_limits_zona_segurs(Defaults::Entities::BULLET_RADIUS, min_x, max_x, min_y, max_y); if (center_.x < min_x || center_.x > max_x || center_.y < min_y || center_.y > max_y) { esta_ = false; } }