From 8d659c44e539db5e8e14ab8014364c6c649f8b9c Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Sat, 30 May 2026 10:06:30 +0200 Subject: [PATCH] =?UTF-8?q?feat(demo):=20el=20pilot=20IA=20ret=C3=A9n=20el?= =?UTF-8?q?=20tret=20si=20t=C3=A9=20el=20company=20en=20la=20l=C3=ADnia=20?= =?UTF-8?q?de=20tir=20(evita=20foc=20amic)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/game/scenes/game_scene.cpp | 7 ++++++ source/game/systems/demo_pilot.cpp | 35 +++++++++++++++++++++++++++--- source/game/systems/demo_pilot.hpp | 1 + 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/source/game/scenes/game_scene.cpp b/source/game/scenes/game_scene.cpp index 2e86219..22203b8 100644 --- a/source/game/scenes/game_scene.cpp +++ b/source/game/scenes/game_scene.cpp @@ -408,8 +408,15 @@ auto GameScene::stepDemo(float delta_time, bool input_blocked) -> bool { demo_ctrls_[i] = {}; // nau inactiva/morta: sense control continue; } + // Company per a evitar foc amic en demo de 2 naus: només es passa si l'altre + // jugador està actiu al match (un slot no usat tindria isActive()==true). + const uint8_t OTHER = 1U - i; + const bool OTHER_ACTIVE = (OTHER == 0) ? match_config_.player1_active + : match_config_.player2_active; + const Ship* teammate = OTHER_ACTIVE ? &ships_[OTHER] : nullptr; demo_ctrls_[i] = demo_pilots_[i].compute( ships_[i], + teammate, enemies_, bullets_, Defaults::Zones::PLAYAREA, diff --git a/source/game/systems/demo_pilot.cpp b/source/game/systems/demo_pilot.cpp index 468907e..b126532 100644 --- a/source/game/systems/demo_pilot.cpp +++ b/source/game/systems/demo_pilot.cpp @@ -36,6 +36,10 @@ namespace Systems::Demo { constexpr float DODGE_SCAN_RADIUS = 190.0F; // px: distancia a la que reacciona constexpr float DODGE_HEADING_MIN = 0.25F; // dot mínimo: la bala viene hacia la nave + // Foc amic: retindre el tret si el company està en la línia de tir. + constexpr float FRIENDLY_BLOCK_RANGE = 1200.0F; // px endavant que es vigilen + constexpr float FRIENDLY_BLOCK_MARGIN = 22.0F; // px: marge sobre el radi del company + // [-1, 1] aleatorio (estética: jitter de apuntado; no afecta a la simulación). auto randSigned() -> float { return (static_cast(std::rand()) / static_cast(RAND_MAX) * 2.0F) - 1.0F; @@ -136,9 +140,26 @@ namespace Systems::Demo { } } + // ¿El company està en la línia de tir? (davant del morro, dins de l'abast i + // a prou poca distància perpendicular de la trajectòria recta de la bala). + // La bala ix en la direcció del morro: (cos, sin)(angle - PI/2). + auto teammateInLineOfFire(const Ship& ship, const Ship& mate) -> bool { + const float NOSE = ship.getAngle() - (PI / 2.0F); + const Vec2 FORWARD{.x = std::cos(NOSE), .y = std::sin(NOSE)}; + const Vec2 TO_MATE = mate.getCenter() - ship.getCenter(); + const float ALONG = TO_MATE.dot(FORWARD); // distància al llarg del tret + if (ALONG <= 0.0F || ALONG > FRIENDLY_BLOCK_RANGE) { + return false; // darrere de la nau o massa lluny + } + const float PERP2 = TO_MATE.lengthSquared() - (ALONG * ALONG); + const float CLEAR = mate.getCollisionRadius() + FRIENDLY_BLOCK_MARGIN; + return PERP2 < CLEAR * CLEAR; + } + } // namespace auto DemoPilot::compute(const Ship& ship, + const Ship* teammate, const std::array& enemies, const std::array(Defaults::Entities::MAX_BULLETS_TOTAL)>& bullets, const SDL_FRect& play_area, @@ -218,10 +239,18 @@ namespace Systems::Demo { std::fabs(ERROR) < FIRE_TOLERANCE) { ctrl.thrust = true; } - // Disparar cuando está bien encarada y el cooldown lo permite. + // Disparar cuando está bien encarada y el cooldown lo permite, però NO + // si el company està en la línia de tir (i seria víctima vàlida de foc + // amic): es retén el tret sense gastar cooldown, així dispara tan prompte + // com l'altra nau isca de la línia. if (std::fabs(ERROR) < FIRE_TOLERANCE && fire_cooldown_ <= 0.0F) { - ctrl.shoot = true; - fire_cooldown_ = FIRE_COOLDOWN; + const bool FRIENDLY_BLOCK = (teammate != nullptr) && + teammate->isActive() && !teammate->isInvulnerable() && + teammateInLineOfFire(ship, *teammate); + if (!FRIENDLY_BLOCK) { + ctrl.shoot = true; + fire_cooldown_ = FIRE_COOLDOWN; + } } } diff --git a/source/game/systems/demo_pilot.hpp b/source/game/systems/demo_pilot.hpp index c1bb816..0aa384e 100644 --- a/source/game/systems/demo_pilot.hpp +++ b/source/game/systems/demo_pilot.hpp @@ -57,6 +57,7 @@ namespace Systems::Demo { 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& enemies, const std::array(Defaults::Entities::MAX_BULLETS_TOTAL)>& bullets, const SDL_FRect& play_area,