// playfield.hpp - Fons del playfield (graella + sub-graella amb animació de creació) // © 2026 JailDesigner // // La graella es construeix una sola vegada al constructor. El draw és stateless: // rep un `creation_progress` global ∈ [0, 1] i cada línia computa quina porció // li toca dibuixar segons el seu slot a la timeline. // // Disseny preparat per a futures capacitats: // - Línies "vives" que reaccionen a explosions / pas de la nau (reaction_intensity). // - Capes addicionals al fons (estrelles, gradients, scanlines). #pragma once #include #include #include "core/defaults/playfield.hpp" #include "core/rendering/render_context.hpp" #include "core/types.hpp" namespace Graphics { class Playfield { public: explicit Playfield(Rendering::Renderer* renderer); // Avança timers interns (creació + reaccions). void update(float delta_time); // Pinta la graella. La porció dibuixada de cada línia depèn del timer intern. void draw() const; // Notifica que una nau ha passat per (pos) a velocitat (speed_px_s). // Si està prop d'alguna línia i va prou ràpida, la línia entra en orbit. void notifyShipPass(Vec2 pos, float speed_px_s); // Notifica el spawn d'un firework a (pos). Les línies V i H més properes // generen un pulse brillant que es propaga. void notifyFireworkSpawn(Vec2 pos); private: struct Pulse { bool active{false}; float center_t{0.5F}; // posició al llarg de la línia (0..1) float age_s{0.0F}; }; struct Line { Vec2 start; // top (verticals) o left (horitzontals) Vec2 end; // bottom (verticals) o right (horitzontals) float brightness; // base (GRID_BRIGHTNESS o SUBGRID_BRIGHTNESS) float spawn_time_s; // moment de naixement bool is_vertical; // direcció (per saber el perpendicular de l'orbit) float orbit_amplitude; // amplitud actual de l'orbit (px, ≥ 0) float orbit_phase; // fase del sin (avança contínuament) std::array pulses; }; void buildLines(); [[nodiscard]] auto computeLineProgress(const Line& line) const -> float; static void spawnPulseAt(Line& line, float center_t); Rendering::Renderer* renderer_; std::vector lines_; float elapsed_s_{0.0F}; }; } // namespace Graphics