refactor(debris): la bala impacta al cos O als trossos, mai a tots dos
This commit is contained in:
@@ -150,7 +150,9 @@ namespace Systems::Collision {
|
||||
const float DEATH_FACTOR = ctx.ships[i].getConfig().physics.death_impact_factor;
|
||||
const Vec2 IMPULSE = SHIP_VEL * (ctx.ships[i].getBody().mass * DEATH_FACTOR);
|
||||
touched_enemy->applyImpulse(IMPULSE);
|
||||
ctx.on_player_hit(i);
|
||||
// Sense bala: cap impuls de bala per als debris (mort per
|
||||
// col·lisió cos-cos). Els debris hereten la inèrcia del ship.
|
||||
ctx.on_player_hit(i, Vec2{});
|
||||
} else {
|
||||
// Primer impacte → estat HURT (rebot físic ja resolt per PhysicsWorld;
|
||||
// l'enemic no rep dany per decisió de disseny).
|
||||
@@ -197,13 +199,12 @@ namespace Systems::Collision {
|
||||
}
|
||||
|
||||
// *** TEAMMATE HIT (friendly fire) ***
|
||||
// Víctima perd 1 vida, atacant en guanya 1. Apliquem l'impuls
|
||||
// de la bala a la nau ABANS de on_player_hit perquè tocado()
|
||||
// captura la velocitat per als debris (si no, queden quiets).
|
||||
const Vec2 BULLET_IMPULSE = bullet.getBody().velocity *
|
||||
(bullet.getBody().mass * bullet.getConfig().physics.impact_momentum_factor);
|
||||
ctx.ships[player_id].getBody().applyImpulse(BULLET_IMPULSE);
|
||||
ctx.on_player_hit(player_id);
|
||||
// Víctima perd 1 vida, atacant en guanya 1. Friendly fire sempre
|
||||
// mata: el bullet va als debris (via tocado) i NO al cos del ship
|
||||
// — el cos està a punt de desactivar-se, qualsevol impuls seria
|
||||
// double-count amb la velocitat que ja reben els trossos.
|
||||
const Vec2 BULLET_VEL = bullet.getBody().velocity;
|
||||
ctx.on_player_hit(player_id, BULLET_VEL);
|
||||
ctx.lives_per_player[BULLET_OWNER]++;
|
||||
Audio::get()->playSound(Defaults::Sound::FRIENDLY_FIRE_HIT, Audio::Group::GAME);
|
||||
breakBullet(ctx.debris_manager, bullet);
|
||||
@@ -237,15 +238,20 @@ namespace Systems::Collision {
|
||||
}
|
||||
|
||||
// *** 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);
|
||||
// Regla "cos XOR trossos": l'impuls de la bala s'aplica al cos
|
||||
// només si el ship sobreviu (fereix). Si el ship mor, el bullet
|
||||
// va directament als trossos (via tocado) i el cos no rep impuls
|
||||
// — els trossos ja porten la força de la bala, qualsevol impuls
|
||||
// afegit al cos seria double-count.
|
||||
const Vec2 BULLET_VEL = bullet.getBody().velocity;
|
||||
if (ctx.ships[player_id].isHurt()) {
|
||||
// Segon impacte durant HURT → mort.
|
||||
ctx.on_player_hit(player_id);
|
||||
ctx.on_player_hit(player_id, BULLET_VEL);
|
||||
} else {
|
||||
// Fereix: el cos sobreviu, rep l'impuls. No hi ha debris encara.
|
||||
const Vec2 IMPULSE = BULLET_VEL *
|
||||
(bullet.getBody().mass * bullet.getConfig().physics.impact_momentum_factor);
|
||||
ctx.ships[player_id].getBody().applyImpulse(IMPULSE);
|
||||
ctx.ships[player_id].hurt();
|
||||
}
|
||||
breakBullet(ctx.debris_manager, bullet);
|
||||
|
||||
@@ -40,8 +40,11 @@ namespace Systems::Collision {
|
||||
Effects::FireworkManager& firework_manager;
|
||||
Effects::FloatingScoreManager& floating_score_manager;
|
||||
const GameConfig::MatchConfig& match_config;
|
||||
// Trigger de muerte del jugador (GameScene::tocado).
|
||||
std::function<void(uint8_t /*player_id*/)> on_player_hit;
|
||||
// Trigger de muerte del jugador (GameScene::tocado). bullet_velocity es
|
||||
// la velocitat de la bala que ha causat la mort (Vec2{} si la mort no
|
||||
// ve d'una bala — col·lisió ship-enemy, etc.). Es passa al debris perquè
|
||||
// els trossos volin en direcció de la bala.
|
||||
std::function<void(uint8_t /*player_id*/, const Vec2& /*bullet_velocity*/)> on_player_hit;
|
||||
};
|
||||
|
||||
// Detecta colisiones bullet → enemy. Si hit:
|
||||
|
||||
@@ -24,10 +24,11 @@ namespace Systems::EnemyEvents {
|
||||
ctx.floating_score_manager.crear(POINTS, enemy.getCenter());
|
||||
}
|
||||
|
||||
void doCreateDebris(Systems::Collision::Context& ctx, const Enemy& enemy) {
|
||||
void doCreateDebris(Systems::Collision::Context& ctx, const Enemy& enemy, const Bullet* bullet) {
|
||||
constexpr float SPEED_EXPLOSIO = 80.0F;
|
||||
const Vec2 INHERITED_VEL = enemy.getVelocityVector() *
|
||||
Defaults::Physics::Debris::ENEMY_VELOCITY_INHERITANCE;
|
||||
const Vec2 BULLET_VEL = (bullet != nullptr) ? bullet->getBody().velocity : Vec2{};
|
||||
ctx.debris_manager.explode(
|
||||
enemy.getShape(),
|
||||
enemy.getCenter(),
|
||||
@@ -42,7 +43,8 @@ namespace Systems::EnemyEvents {
|
||||
enemy.getConfig().colors.normal,
|
||||
Defaults::Physics::Debris::ENEMY_LIFETIME,
|
||||
Defaults::Physics::Debris::ENEMY_FRICTION,
|
||||
Defaults::Physics::Debris::ENEMY_SEGMENT_MULTIPLIER);
|
||||
Defaults::Physics::Debris::ENEMY_SEGMENT_MULTIPLIER,
|
||||
BULLET_VEL);
|
||||
}
|
||||
|
||||
void doCreateFireworks(Systems::Collision::Context& ctx, const Enemy& enemy) {
|
||||
@@ -67,6 +69,24 @@ namespace Systems::EnemyEvents {
|
||||
|
||||
void dispatchEvent(Systems::Collision::Context& ctx, Enemy& enemy, EnemyEventType event, uint8_t shooter_id, const Bullet* bullet) {
|
||||
const auto& actions = enemy.getConfig().events.getActions(event);
|
||||
|
||||
// Pre-scan: aquest event matarà l'enemic? Si sí, l'impuls de la bala
|
||||
// va directament als debris (via doCreateDebris) i NO s'aplica al cos
|
||||
// — així evitem el "double-count" on els trossos hereten la velocitat
|
||||
// del cos (boostat per la bala) I a més el seu propi impuls de bala.
|
||||
// Regla: el bullet impacta al cos O als trossos, mai a tots dos.
|
||||
bool will_die = false;
|
||||
for (const auto& action : actions) {
|
||||
if (action.type == EnemyActionType::DESTROY) {
|
||||
will_die = true;
|
||||
break;
|
||||
}
|
||||
if (action.type == EnemyActionType::SET_HURT && enemy.isWounded()) {
|
||||
will_die = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& action : actions) {
|
||||
switch (action.type) {
|
||||
case EnemyActionType::SET_HURT:
|
||||
@@ -86,13 +106,15 @@ namespace Systems::EnemyEvents {
|
||||
doAddScore(ctx, enemy, shooter_id);
|
||||
break;
|
||||
case EnemyActionType::CREATE_DEBRIS:
|
||||
doCreateDebris(ctx, enemy);
|
||||
doCreateDebris(ctx, enemy, bullet);
|
||||
break;
|
||||
case EnemyActionType::CREATE_FIREWORKS:
|
||||
doCreateFireworks(ctx, enemy);
|
||||
break;
|
||||
case EnemyActionType::APPLY_IMPULSE:
|
||||
doApplyImpulse(enemy, bullet);
|
||||
if (!will_die) {
|
||||
doApplyImpulse(enemy, bullet);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user