feat(demo): el pilot IA retén el tret si té el company en la línia de tir (evita foc amic)
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
|
||||
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,
|
||||
|
||||
@@ -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<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
|
||||
|
||||
auto DemoPilot::compute(const Ship& ship,
|
||||
const Ship* teammate,
|
||||
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,
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<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,
|
||||
|
||||
Reference in New Issue
Block a user