74 lines
2.8 KiB
C++
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
|