// demo_pilot.hpp - IA de piloto para el attract mode (demo jugándose sola) // © 2026 JailDesigner // // Calcula, cada frame, los controles de la nave (rotar/empujar/disparar) leyendo // el estado de juego en solo-lectura. No lee Input ni muta entidades: GameScene // aplica el Control resultante via Ship::applyMovement + fireBullet. // // El comportamiento busca parecer "humano", no óptimo: apuntado con lead y un // pequeño error, cadencia de disparo con cooldown, esquiva por radio de peligro // y sesgo hacia el centro para no pegarse a las paredes. #pragma once #include #include #include #include "core/system/scene_context.hpp" #include "game/constants.hpp" #include "game/entities/enemy.hpp" #include "game/entities/ship.hpp" namespace Systems::Demo { // Stages de arranque de cada escenario curado (se ciclan en attract mode). // Elegidos por variedad visual: pinwheels, stars, squares/mix. inline constexpr std::array SCENARIO_STAGES = {2, 5, 7}; // Stage de arranque para el índice de escenario dado. [[nodiscard]] inline auto scenarioStage(std::uint8_t index) -> std::uint8_t { return SCENARIO_STAGES.at(index % SCENARIO_STAGES.size()); } // Control de la nave para un frame. struct Control { bool left{false}; bool right{false}; bool thrust{false}; bool shoot{false}; }; class DemoPilot { public: [[nodiscard]] auto compute(const Ship& ship, const std::array& enemies, const SDL_FRect& play_area, float delta_time) -> Control; private: float retarget_timer_{0.0F}; // re-evalúa objetivo cada RETARGET_INTERVAL float fire_cooldown_{0.0F}; // tiempo restante hasta poder disparar float aim_jitter_{0.0F}; // error de apuntado, refrescado al retargetar int target_idx_{-1}; // índice del enemigo objetivo (o -1) }; } // namespace Systems::Demo