// nau.cpp - Implementació de la nave del jugador // © 1999 Visente i Sergi (versió Pascal) // © 2025 Port a C++20 amb SDL3 #include "game/entities/nau.hpp" #include "core/defaults.hpp" #include "core/rendering/polygon_renderer.hpp" #include "game/constants.hpp" #include #include Nau::Nau(SDL_Renderer *renderer) : renderer_(renderer), esta_tocada_(false) {} void Nau::inicialitzar() { // Inicialització de la nau (triangle) // Basat en el codi Pascal original: lines 380-384 // Copiat de joc_asteroides.cpp línies 30-44 // Configurar triangle amb 3 punts polars dades_.p1.r = 12.0f; dades_.p1.angle = 3.0f * Constants::PI / 2.0f; // Apunta amunt (270°) dades_.p2.r = 12.0f; dades_.p2.angle = Constants::PI / 4.0f; // 45° dades_.p3.r = 12.0f; dades_.p3.angle = (3.0f * Constants::PI) / 4.0f; // 135° // Posició inicial al centre de la pantalla dades_.centre.x = 320.0f; dades_.centre.y = 240.0f; // Estat inicial dades_.angle = 0.0f; dades_.velocitat = 0.0f; esta_tocada_ = false; } void Nau::processar_input(float delta_time) { // 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_) return; // Obtenir estat actual del teclat (no events, sinó estat continu) const bool *keyboard_state = SDL_GetKeyboardState(nullptr); // Rotació if (keyboard_state[SDL_SCANCODE_RIGHT]) { dades_.angle += Defaults::Physics::ROTATION_SPEED * delta_time; } if (keyboard_state[SDL_SCANCODE_LEFT]) { dades_.angle -= Defaults::Physics::ROTATION_SPEED * delta_time; } // Acceleració if (keyboard_state[SDL_SCANCODE_UP]) { if (dades_.velocitat < Defaults::Physics::MAX_VELOCITY) { dades_.velocitat += Defaults::Physics::ACCELERATION * delta_time; if (dades_.velocitat > Defaults::Physics::MAX_VELOCITY) { dades_.velocitat = Defaults::Physics::MAX_VELOCITY; } } } } void Nau::actualitzar(float delta_time) { // Només actualitzar si la nau està viva if (esta_tocada_) return; // Aplicar física (moviment + fricció) aplicar_fisica(delta_time); } void Nau::dibuixar() const { // Només dibuixar si la nau està viva if (esta_tocada_) return; // Escalar velocitat per l'efecte visual (200 px/s → ~6 px d'efecte) // El codi Pascal original sumava velocitat (0-6) al radi per donar // sensació de "empenta". Ara velocitat està en px/s (0-200). // Basat en joc_asteroides.cpp línies 127-134 float velocitat_visual = dades_.velocitat / 33.33f; Rendering::rota_tri(renderer_, dades_, dades_.angle, velocitat_visual, true); } void Nau::aplicar_fisica(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 float dy = (dades_.velocitat * delta_time) * std::sin(dades_.angle - Constants::PI / 2.0f) + dades_.centre.y; float dx = (dades_.velocitat * delta_time) * std::cos(dades_.angle - Constants::PI / 2.0f) + dades_.centre.x; // Boundary checking - només actualitzar si dins dels marges // Acumulació directa amb precisió subpíxel if (dy > Constants::MARGE_DALT && dy < Constants::MARGE_BAIX) { dades_.centre.y = dy; } if (dx > Constants::MARGE_ESQ && dx < Constants::MARGE_DRET) { dades_.centre.x = dx; } // Fricció - desacceleració gradual (time-based) if (dades_.velocitat > 0.1f) { dades_.velocitat -= Defaults::Physics::FRICTION * delta_time; if (dades_.velocitat < 0.0f) { dades_.velocitat = 0.0f; } } }