feat(enemy): migrar el moviment dels enemics a un sistema d'IA declaratiu
This commit is contained in:
@@ -28,14 +28,6 @@ namespace {
|
||||
};
|
||||
}
|
||||
|
||||
// Recupera el "ángulo equivalente" de un body en movimiento (para zigzag).
|
||||
auto velocityToAngle(const Vec2& velocity) -> float {
|
||||
if (velocity.lengthSquared() < 0.0001F) {
|
||||
return 0.0F;
|
||||
}
|
||||
return std::atan2(velocity.y, velocity.x) + (Constants::PI / 2.0F);
|
||||
}
|
||||
|
||||
// Random float [0..1).
|
||||
auto randFloat01() -> float {
|
||||
return static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX);
|
||||
@@ -62,10 +54,8 @@ void Enemy::init(EnemyType type, const Vec2* ship_pos) {
|
||||
config_ = &EnemyRegistry::get(type);
|
||||
const EnemyConfig& cfg = *config_;
|
||||
|
||||
if (type_ == EnemyType::SQUARE) {
|
||||
tracking_timer_ = 0.0F;
|
||||
tracking_strength_ = cfg.behavior.tracking_strength;
|
||||
}
|
||||
ai_state_ = EnemyAiState{};
|
||||
ai_state_.tracking_strength = cfg.ai.movement.tracking_strength;
|
||||
|
||||
shape_ = Graphics::ShapeLoader::load(cfg.shape.path);
|
||||
if (!shape_ || !shape_->isValid()) {
|
||||
@@ -136,8 +126,6 @@ void Enemy::init(EnemyType type, const Vec2* ship_pos) {
|
||||
invulnerability_timer_ = cfg.spawn.invulnerability_duration;
|
||||
brightness_ = cfg.spawn.invulnerability_brightness_start;
|
||||
|
||||
direction_change_timer_ = 0.0F;
|
||||
|
||||
is_active_ = true;
|
||||
}
|
||||
|
||||
@@ -167,22 +155,9 @@ void Enemy::update(float delta_time) {
|
||||
brightness_ = START + ((END - START) * SMOOTH_T);
|
||||
}
|
||||
|
||||
if (!isWounded()) {
|
||||
switch (type_) {
|
||||
case EnemyType::PENTAGON:
|
||||
case EnemyType::STAR:
|
||||
// STAR reusa el zigzag esquivador de Pentagon. Si en el futur
|
||||
// vol comportament propi, separa-li el cas.
|
||||
behaviorPentagon(delta_time);
|
||||
break;
|
||||
case EnemyType::SQUARE:
|
||||
behaviorSquare(delta_time);
|
||||
break;
|
||||
case EnemyType::PINWHEEL:
|
||||
behaviorPinwheel(delta_time);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// El moviment es delega a Systems::EnemyAi::tick, invocat des de l'scene
|
||||
// ABANS d'aquest update (manté l'ordre: AI escriu velocity/rotation_delta,
|
||||
// després animation pot modular rotation_delta via rotation_accel).
|
||||
|
||||
updateAnimation(delta_time);
|
||||
|
||||
@@ -246,59 +221,6 @@ void Enemy::setVelocityFromAngle(float angle_movement, float speed) {
|
||||
body_.velocity = angleToDirection(angle_movement) * speed;
|
||||
}
|
||||
|
||||
// PENTAGON: zigzag esquivador. Canvis de direcció periòdics (probabilístics)
|
||||
// en lloc de detectar parets; el rebot contra murs el fa PhysicsWorld.
|
||||
void Enemy::behaviorPentagon(float delta_time) {
|
||||
direction_change_timer_ += delta_time;
|
||||
|
||||
if (randFloat01() < config_->behavior.zigzag_prob_per_second * delta_time) {
|
||||
const float CURRENT_ANGLE = velocityToAngle(body_.velocity);
|
||||
const float DELTA = randFloat01() * config_->behavior.angle_change_max;
|
||||
const float NEW_ANGLE = CURRENT_ANGLE + ((std::rand() % 2 == 0) ? DELTA : -DELTA);
|
||||
const float SPEED = body_.velocity.length();
|
||||
setVelocityFromAngle(NEW_ANGLE, SPEED);
|
||||
direction_change_timer_ = 0.0F;
|
||||
}
|
||||
}
|
||||
|
||||
// SQUARE: tracking discret cap a la nau cada N segons.
|
||||
void Enemy::behaviorSquare(float delta_time) {
|
||||
tracking_timer_ += delta_time;
|
||||
|
||||
if (tracking_timer_ >= config_->behavior.tracking_interval && ship_position_ != nullptr) {
|
||||
tracking_timer_ = 0.0F;
|
||||
|
||||
const Vec2 TO_SHIP = *ship_position_ - center_;
|
||||
const float DIST = TO_SHIP.length();
|
||||
if (DIST > 0.0F) {
|
||||
const Vec2 DESIRED_DIR = TO_SHIP / DIST;
|
||||
const float SPEED = body_.velocity.length();
|
||||
const Vec2 DESIRED_VEL = DESIRED_DIR * SPEED;
|
||||
|
||||
body_.velocity = (body_.velocity * (1.0F - tracking_strength_)) +
|
||||
(DESIRED_VEL * tracking_strength_);
|
||||
|
||||
const float NEW_SPEED = body_.velocity.length();
|
||||
if (NEW_SPEED > 0.0F) {
|
||||
body_.velocity = body_.velocity * (SPEED / NEW_SPEED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PINWHEEL: movement rectilini + boost de rotació visual prop del ship.
|
||||
void Enemy::behaviorPinwheel(float /*delta_time*/) {
|
||||
if (ship_position_ != nullptr) {
|
||||
const Vec2 TO_SHIP = *ship_position_ - center_;
|
||||
const float DIST = TO_SHIP.length();
|
||||
if (DIST < config_->behavior.proximity_distance) {
|
||||
rotation_delta_ = animation_.rotation_delta_base * config_->behavior.rotation_proximity_multiplier;
|
||||
} else {
|
||||
rotation_delta_ = animation_.rotation_delta_base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Enemy::updateAnimation(float delta_time) {
|
||||
updatePulse(delta_time);
|
||||
updateRotationAcceleration(delta_time);
|
||||
@@ -373,7 +295,7 @@ auto Enemy::getBaseRotation() const -> float {
|
||||
|
||||
void Enemy::setTrackingStrength(float strength) {
|
||||
if (type_ == EnemyType::SQUARE) {
|
||||
tracking_strength_ = strength;
|
||||
ai_state_.tracking_strength = strength;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user