feat(enemy): sistema d'events declaratius via YAML

This commit is contained in:
2026-05-25 13:34:48 +02:00
parent 9b3da3a6e7
commit 9c0502eefb
10 changed files with 299 additions and 71 deletions
+6 -71
View File
@@ -9,61 +9,11 @@
#include "core/types.hpp"
#include "game/constants.hpp"
#include "game/entities/bullet_config.hpp"
#include "game/entities/enemy_config.hpp"
#include "game/systems/enemy_event_dispatcher.hpp"
namespace Systems::Collision {
namespace {
constexpr uint8_t NO_SHOOTER = 0xFF;
// Mata al enemy con explosión: floating score, debris con velocity heredada,
// sonido. Si shooter_id ≠ NO_SHOOTER, suma puntos a ese jugador.
// CRUCIAL: leer velocity/datos ANTES de destruir() (que zera la velocity).
void explodeNow(Context& ctx, Enemy& enemy, uint8_t shooter_id) {
const Vec2 ENEMY_POS = enemy.getCenter();
const Vec2 ENEMY_VEL = enemy.getVelocityVector();
const float BRIGHTNESS = enemy.getBrightness();
const auto SHAPE = enemy.getShape();
const int POINTS = enemy.getConfig().score;
const SDL_Color COLOR = enemy.getConfig().colors.normal;
const SDL_Color WOUNDED_COLOR = enemy.getConfig().colors.wounded;
if (shooter_id != NO_SHOOTER) {
ctx.score_per_player[shooter_id] += POINTS;
}
ctx.floating_score_manager.crear(POINTS, ENEMY_POS);
enemy.destroy();
constexpr float SPEED_EXPLOSIO = 80.0F; // px/s (explosión suave)
const Vec2 INHERITED_VEL = ENEMY_VEL * Defaults::Physics::Debris::ENEMY_VELOCITY_INHERITANCE;
ctx.debris_manager.explode(
SHAPE,
ENEMY_POS,
0.0F, // angle (rotación interna del enemy)
1.0F, // escala
SPEED_EXPLOSIO,
BRIGHTNESS,
INHERITED_VEL,
0.0F, // sense herència angular: evita que els 5 trossos curvin en bloc
0.0F, // sin herencia visual
Defaults::Sound::EXPLOSION,
COLOR,
Defaults::Physics::Debris::ENEMY_LIFETIME,
Defaults::Physics::Debris::ENEMY_FRICTION,
Defaults::Physics::Debris::ENEMY_SEGMENT_MULTIPLIER);
// Firework burst radial des del centro de l'enemic (efecte adicional al debris).
// Línia blanca + halo daurat (WOUNDED) per a feel d'espurnes.
ctx.firework_manager.spawn(ENEMY_POS,
Defaults::FX::Firework::DEFAULT_COLOR,
Defaults::FX::Firework::SPEED,
Defaults::FX::Firework::N_POINTS,
Defaults::FX::Firework::INITIAL_BRIGHTNESS,
/*glow=*/true,
WOUNDED_COLOR);
}
// Trenca una bala en debris (8 fragments de l'octàgon) + so HIT + desactiva.
// S'invoca des de qualsevol desactivació de bala (impacte amb enemic, amb jugador,
@@ -102,26 +52,11 @@ namespace Systems::Collision {
}
// *** COLISIÓN bullet → enemy ***
// Empuje físico cuasi-realista: el impulse és el moment de la bala
// (m·v) multiplicat pel factor de transferència. Direcció = vector
// velocity de la bala (cap a on viatjava).
const Vec2 IMPULSE = bullet.getBody().velocity *
(bullet.getBody().mass * bullet.getConfig().physics.impact_momentum_factor);
enemy.applyImpulse(IMPULSE);
const uint8_t SHOOTER = bullet.getOwnerId();
if (enemy.isWounded()) {
// Segundo impacto sobre enemy ya herido → muerte instantánea,
// puntos al nuevo shooter.
explodeNow(ctx, enemy, SHOOTER);
} else {
// Primer impacto → entra en estado herido (explosión diferida).
enemy.hurt(SHOOTER);
}
// 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);
breakBullet(ctx.debris_manager, bullet);
break; // Una bala impacta a un enemy y muere
break;
}
}
}
@@ -132,7 +67,7 @@ namespace Systems::Collision {
continue;
}
enemy.consumeWoundExpired();
explodeNow(ctx, enemy, enemy.getLastHitBy());
Systems::EnemyEvents::dispatchEvent(ctx, enemy, EnemyEventType::ON_HURT_END, enemy.getLastHitBy());
}
}