feat(enemy): afegir behaviors WANDER/CHASE/FLEE i target multi-ship

This commit is contained in:
2026-05-25 18:08:11 +02:00
parent 61e40e88f4
commit 5ad433e63a
6 changed files with 108 additions and 16 deletions
+9 -5
View File
@@ -4,12 +4,15 @@
#pragma once
#include <SDL3/SDL.h>
#include <array>
#include <cstdint>
#include "core/entities/entity.hpp"
#include "core/types.hpp"
#include "game/entities/enemy_ai.hpp"
class Ship;
// Tipo de enemy
enum class EnemyType : uint8_t {
PENTAGON = 0, // Pentágono esquivador (zigzag)
@@ -71,9 +74,10 @@ class Enemy : public Entities::Entity {
// ha estat inicialitzat almenys un cop; abans és nullptr.
[[nodiscard]] auto getConfig() const -> const EnemyConfig& { return *config_; }
// Set ship position reference for tracking behavior
void setShipPosition(const Vec2* ship_pos) { ship_position_ = ship_pos; }
[[nodiscard]] auto getShipPosition() const -> const Vec2* { return ship_position_; }
// Referències als 2 ships per a AI de tracking/proximity/chase/flee.
// nullptr = ship inexistent al match. El sistema d'IA filtra per ship->isActive().
void setShips(const Ship* p1, const Ship* p2) { ships_ = {p1, p2}; }
[[nodiscard]] auto getShips() const -> const std::array<const Ship*, 2>& { return ships_; }
// Accessors per al sistema d'IA (Systems::EnemyAi).
[[nodiscard]] auto getAiState() -> EnemyAiState& { return ai_state_; }
@@ -132,8 +136,8 @@ class Enemy : public Entities::Entity {
// Estat per-instància que la primitiva de moviment manté entre frames.
EnemyAiState ai_state_;
// Referència a la posició del ship per a AI de tracking/proximity.
const Vec2* ship_position_{nullptr};
// Referències als 2 ships per a AI de tracking/proximity/chase/flee.
std::array<const Ship*, 2> ships_{nullptr, nullptr};
// Invulnerabilidad post-spawn
float invulnerability_timer_{0.0F};
+10 -4
View File
@@ -15,11 +15,12 @@
// Primitiva de moviment activa per a un enemic. Substitueix el switch
// hardcoded sobre EnemyType.
enum class MovementType : uint8_t {
ZIGZAG, // Canvi de direcció probabilístic (Pentagon/Star)
ZIGZAG, // Canvi de direcció probabilístic agressiu (Pentagon/Star)
TRACKING, // LERP discret cap al ship cada N segons (Square)
RECTILINEAR_PROXIMITY, // Rectilini + boost rotació visual prop del ship (Pinwheel)
// Futurs (Fase B):
// WANDER, CHASE, FLEE
WANDER, // Canvi de direcció probabilístic suau, sense target
CHASE, // Steering continu cap al ship més proper
FLEE, // Steering continu allunyant-se del ship més proper
};
// Accions que s'executen periòdicament (un timer per acció). Futur (Fase C):
@@ -39,7 +40,7 @@ enum class AimMode : uint8_t {
struct MovementConfig {
MovementType type{MovementType::ZIGZAG};
// ZIGZAG
// ZIGZAG i WANDER (canvi de direcció probabilístic; comparteixen camps).
float angle_change_max{0.0F};
float zigzag_prob_per_second{0.0F};
@@ -50,6 +51,11 @@ struct MovementConfig {
// RECTILINEAR_PROXIMITY
float rotation_proximity_multiplier{0.0F};
float proximity_distance{0.0F};
// CHASE / FLEE: força del steering per segon (LERP velocity ↔ direcció ideal).
// 1.0 = en ~1s la velocitat queda totalment realineada cap al target.
float chase_strength{0.0F};
float flee_strength{0.0F};
};
// Acció periòdica. interval = segons entre disparades; el dispatcher manté un
+5
View File
@@ -226,6 +226,9 @@ namespace {
if (s == "zigzag") { return MovementType::ZIGZAG; }
if (s == "tracking") { return MovementType::TRACKING; }
if (s == "rectilinear_proximity") { return MovementType::RECTILINEAR_PROXIMITY; }
if (s == "wander") { return MovementType::WANDER; }
if (s == "chase") { return MovementType::CHASE; }
if (s == "flee") { return MovementType::FLEE; }
return std::nullopt;
}
@@ -264,6 +267,8 @@ namespace {
READ_OPT("tracking_interval", out.tracking_interval);
READ_OPT("rotation_proximity_multiplier", out.rotation_proximity_multiplier);
READ_OPT("proximity_distance", out.proximity_distance);
READ_OPT("chase_strength", out.chase_strength);
READ_OPT("flee_strength", out.flee_strength);
return true;
}