Merge branch 'feat/demo-no-friendly-fire': el pilot IA de la demo no dispara si té el company en la línia de tir
This commit is contained in:
@@ -408,8 +408,15 @@ auto GameScene::stepDemo(float delta_time, bool input_blocked) -> bool {
|
|||||||
demo_ctrls_[i] = {}; // nau inactiva/morta: sense control
|
demo_ctrls_[i] = {}; // nau inactiva/morta: sense control
|
||||||
continue;
|
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(
|
demo_ctrls_[i] = demo_pilots_[i].compute(
|
||||||
ships_[i],
|
ships_[i],
|
||||||
|
teammate,
|
||||||
enemies_,
|
enemies_,
|
||||||
bullets_,
|
bullets_,
|
||||||
Defaults::Zones::PLAYAREA,
|
Defaults::Zones::PLAYAREA,
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ namespace Systems::Demo {
|
|||||||
constexpr float DODGE_SCAN_RADIUS = 190.0F; // px: distancia a la que reacciona
|
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
|
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).
|
// [-1, 1] aleatorio (estética: jitter de apuntado; no afecta a la simulación).
|
||||||
auto randSigned() -> float {
|
auto randSigned() -> float {
|
||||||
return (static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX) * 2.0F) - 1.0F;
|
return (static_cast<float>(std::rand()) / static_cast<float>(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
|
} // namespace
|
||||||
|
|
||||||
auto DemoPilot::compute(const Ship& ship,
|
auto DemoPilot::compute(const Ship& ship,
|
||||||
|
const Ship* teammate,
|
||||||
const std::array<Enemy, Constants::MAX_ORNIS>& enemies,
|
const std::array<Enemy, Constants::MAX_ORNIS>& enemies,
|
||||||
const std::array<Bullet, static_cast<std::size_t>(Defaults::Entities::MAX_BULLETS_TOTAL)>& bullets,
|
const std::array<Bullet, static_cast<std::size_t>(Defaults::Entities::MAX_BULLETS_TOTAL)>& bullets,
|
||||||
const SDL_FRect& play_area,
|
const SDL_FRect& play_area,
|
||||||
@@ -218,12 +239,20 @@ namespace Systems::Demo {
|
|||||||
std::fabs(ERROR) < FIRE_TOLERANCE) {
|
std::fabs(ERROR) < FIRE_TOLERANCE) {
|
||||||
ctrl.thrust = true;
|
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) {
|
if (std::fabs(ERROR) < FIRE_TOLERANCE && fire_cooldown_ <= 0.0F) {
|
||||||
|
const bool FRIENDLY_BLOCK = (teammate != nullptr) &&
|
||||||
|
teammate->isActive() && !teammate->isInvulnerable() &&
|
||||||
|
teammateInLineOfFire(ship, *teammate);
|
||||||
|
if (!FRIENDLY_BLOCK) {
|
||||||
ctrl.shoot = true;
|
ctrl.shoot = true;
|
||||||
fire_cooldown_ = FIRE_COOLDOWN;
|
fire_cooldown_ = FIRE_COOLDOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ctrl;
|
return ctrl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ namespace Systems::Demo {
|
|||||||
class DemoPilot {
|
class DemoPilot {
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] auto compute(const Ship& ship,
|
[[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<Enemy, Constants::MAX_ORNIS>& enemies,
|
||||||
const std::array<Bullet, static_cast<std::size_t>(Defaults::Entities::MAX_BULLETS_TOTAL)>& bullets,
|
const std::array<Bullet, static_cast<std::size_t>(Defaults::Entities::MAX_BULLETS_TOTAL)>& bullets,
|
||||||
const SDL_FRect& play_area,
|
const SDL_FRect& play_area,
|
||||||
|
|||||||
Reference in New Issue
Block a user