// ship_animator3d.hpp - Sistema d'animació de naus 3D per a l'escena de títol // © 2026 JailDesigner // // Equivalent 3D del `Title::ShipAnimator`. Manté la mateixa màquina d'estats // (ENTERING → FLOATING → EXITING) però treballa amb posicions Vec3 i emet // wireframes a través d'una `Camera3D`. La geometria s'extrau de `ship.shp` // (P1) i `ship2.shp` (P2) per extrusió en Z. #pragma once #include #include #include "core/graphics/camera3d.hpp" #include "core/graphics/wireframe3d.hpp" #include "core/rendering/render_context.hpp" #include "core/types.hpp" namespace Title { enum class ShipState3D : std::uint8_t { ENTERING, FLOATING, EXITING, }; struct TitleShip3D { int player_id{0}; ShipState3D state{ShipState3D::ENTERING}; float state_time{0.0F}; Vec3 initial_position{}; Vec3 target_position{}; Vec3 current_position{}; float initial_scale{1.0F}; float target_scale{1.0F}; float current_scale{1.0F}; float oscillation_phase{0.0F}; float entry_delay{0.0F}; float amplitude_x{0.0F}; float amplitude_y{0.0F}; float frequency_x{0.0F}; float frequency_y{0.0F}; Graphics::Mesh3D mesh; // Vector mundial cap a on apunta el front del shape. Recalculat a cada // transició d'estat perquè draw() oriente la nau (look-at) en la // direcció del seu path actual. Vec3 forward_dir{.x = 0.0F, .y = 0.0F, .z = 1.0F}; bool visible{false}; }; class ShipAnimator3D { public: ShipAnimator3D(Rendering::Renderer* renderer, const Graphics::Camera3D* camera); void init(); void update(float delta_time); void draw() const; void startEntryAnimation(); void triggerExitAnimation(); void triggerExitAnimationForPlayer(int player_id); void skipToFloatingState(); void setVisible(bool visible); [[nodiscard]] auto isAnimationComplete() const -> bool; [[nodiscard]] auto isVisible() const -> bool; private: Rendering::Renderer* renderer_; const Graphics::Camera3D* camera_; std::array ships_; static void updateEntering(TitleShip3D& ship, float delta_time); static void updateFloating(TitleShip3D& ship, float delta_time); static void updateExiting(TitleShip3D& ship, float delta_time); static void configureShipP1(TitleShip3D& ship); static void configureShipP2(TitleShip3D& ship); }; } // namespace Title