Files
orni-attack/source/game/systems/demo_pilot.hpp
T

74 lines
2.8 KiB
C++

// 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 <SDL3/SDL.h>
#include <array>
#include <cstddef>
#include <cstdint>
#include "core/defaults/entities.hpp"
#include "core/system/scene_context.hpp"
#include "game/constants.hpp"
#include "game/entities/bullet.hpp"
#include "game/entities/enemy.hpp"
#include "game/entities/ship.hpp"
namespace Systems::Demo {
// Escenari curat del attract mode: stage de arranque + nombre de naus IA.
// Tots inclouen estrelles (que disparen) per donar feina al pilot.
struct Scenario {
std::uint8_t stage; // stage_id de stages.yaml on arrenca la demo
std::uint8_t players; // 1 o 2 naus controlades per la IA
};
inline constexpr std::array<Scenario, SceneManager::SceneContext::DEMO_SCENARIO_COUNT>
SCENARIOS = {{
{.stage = 5, .players = 1}, // estrelles + mix, 1 jugador
{.stage = 8, .players = 1}, // pressió alta, 1 jugador
{.stage = 6, .players = 2}, // densitat alta, 2 jugadors (foc amic ON)
{.stage = 10, .players = 2}, // repte final, 2 jugadors (foc amic ON)
}};
// Escenari per a l'índex donat (cíclic).
[[nodiscard]] inline auto scenario(std::uint8_t index) -> Scenario {
return SCENARIOS.at(index % SCENARIOS.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 Ship* teammate, // altra nau (nullptr si no n'hi ha): evita foc amic
const std::array<Enemy, Constants::MAX_ORNIS>& enemies,
const std::array<Bullet, static_cast<std::size_t>(Defaults::Entities::MAX_BULLETS_TOTAL)>& bullets,
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