feat(enemy): els enemics poden disparar bales via tick d'IA
This commit is contained in:
@@ -41,20 +41,32 @@ namespace Systems::Collision {
|
||||
|
||||
void detectBulletEnemy(Context& ctx) {
|
||||
constexpr float AMPLIFIER = Defaults::Game::COLLISION_BULLET_ENEMY_AMPLIFIER;
|
||||
constexpr uint8_t NO_SHOOTER = 0xFF;
|
||||
constexpr uint8_t ENEMY_BASE = Defaults::Entities::ENEMY_OWNER_BASE;
|
||||
|
||||
for (auto& bullet : ctx.bullets) {
|
||||
if (!bullet.isActive()) {
|
||||
continue;
|
||||
}
|
||||
for (auto& enemy : ctx.enemies) {
|
||||
const uint8_t BULLET_OWNER = bullet.getOwnerId();
|
||||
const bool IS_ENEMY_BULLET = BULLET_OWNER >= ENEMY_BASE;
|
||||
|
||||
for (std::size_t i = 0; i < ctx.enemies.size(); ++i) {
|
||||
Enemy& enemy = ctx.enemies[i];
|
||||
// Self-shot: una bala d'enemic mai no impacta el seu propi creador.
|
||||
if (IS_ENEMY_BULLET && BULLET_OWNER == static_cast<uint8_t>(ENEMY_BASE + i)) {
|
||||
continue;
|
||||
}
|
||||
if (!Physics::checkCollisionSwept(bullet.getPrevPosition(), bullet.getCenter(), bullet.getCollisionRadius(), enemy, AMPLIFIER)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// *** COLISIÓN bullet → enemy ***
|
||||
// La cadena d'efectes (impulse, hurt, destroy, debris, score...) viu
|
||||
// al YAML de l'enemic via la secció `events:`. Aquí només dispatchem.
|
||||
Systems::EnemyEvents::dispatchEvent(ctx, enemy, EnemyEventType::ON_HIT, bullet.getOwnerId(), &bullet);
|
||||
// al YAML de l'enemic via la secció `events:`. Si la bala és d'enemic,
|
||||
// no atribuïm el kill a cap player (NO_SHOOTER).
|
||||
const uint8_t SHOOTER = IS_ENEMY_BULLET ? NO_SHOOTER : BULLET_OWNER;
|
||||
Systems::EnemyEvents::dispatchEvent(ctx, enemy, EnemyEventType::ON_HIT, SHOOTER, &bullet);
|
||||
breakBullet(ctx.debris_manager, bullet);
|
||||
break;
|
||||
}
|
||||
@@ -200,16 +212,59 @@ namespace Systems::Collision {
|
||||
}
|
||||
}
|
||||
|
||||
void detectEnemyBulletShip(Context& ctx) {
|
||||
constexpr float AMPLIFIER = Defaults::Game::COLLISION_BULLET_PLAYER_AMPLIFIER;
|
||||
constexpr uint8_t ENEMY_BASE = Defaults::Entities::ENEMY_OWNER_BASE;
|
||||
|
||||
for (auto& bullet : ctx.bullets) {
|
||||
if (!bullet.isActive() || bullet.getOwnerId() < ENEMY_BASE) {
|
||||
continue;
|
||||
}
|
||||
for (uint8_t player_id = 0; player_id < 2; player_id++) {
|
||||
if (ctx.hit_timer_per_player[player_id] > 0.0F ||
|
||||
!ctx.ships[player_id].isActive() ||
|
||||
ctx.ships[player_id].isInvulnerable()) {
|
||||
continue;
|
||||
}
|
||||
const bool JUGADOR_ACTIU = (player_id == 0)
|
||||
? ctx.match_config.player1_active
|
||||
: ctx.match_config.player2_active;
|
||||
if (!JUGADOR_ACTIU) {
|
||||
continue;
|
||||
}
|
||||
if (!Physics::checkCollisionSwept(bullet.getPrevPosition(), bullet.getCenter(), bullet.getCollisionRadius(), ctx.ships[player_id], AMPLIFIER)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// *** BALA D'ENEMIC → SHIP ***
|
||||
// Apliquem l'impuls de la bala abans del hurt/death perquè la
|
||||
// velocitat de la nau quedi capturada per als debris.
|
||||
const Vec2 IMPULSE = bullet.getBody().velocity *
|
||||
(bullet.getBody().mass * bullet.getConfig().physics.impact_momentum_factor);
|
||||
ctx.ships[player_id].getBody().applyImpulse(IMPULSE);
|
||||
if (ctx.ships[player_id].isHurt()) {
|
||||
// Segon impacte durant HURT → mort.
|
||||
ctx.on_player_hit(player_id);
|
||||
} else {
|
||||
ctx.ships[player_id].hurt();
|
||||
}
|
||||
breakBullet(ctx.debris_manager, bullet);
|
||||
break; // una bala impacta una vegada per frame
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void detectAll(Context& ctx) {
|
||||
processWoundedDeaths(ctx); // expiran ANTES de ser tocadas por bala este frame
|
||||
detectBulletEnemy(ctx);
|
||||
detectWoundedChain(ctx); // un herit pot ferir a un sa al fregar-lo
|
||||
detectShipEnemy(ctx);
|
||||
detectBulletPlayer(ctx);
|
||||
detectEnemyBulletShip(ctx);
|
||||
}
|
||||
|
||||
void desactivateOutOfBoundsBullets(
|
||||
std::array<Bullet, static_cast<std::size_t>(Defaults::Entities::MAX_BULLETS) * 2>& bullets,
|
||||
std::array<Bullet, static_cast<std::size_t>(Defaults::Entities::MAX_BULLETS_TOTAL)>& bullets,
|
||||
Effects::DebrisManager& debris_manager) {
|
||||
float min_x;
|
||||
float max_x;
|
||||
|
||||
Reference in New Issue
Block a user