refactor(debris): la bala impacta al cos O als trossos, mai a tots dos
This commit is contained in:
@@ -43,6 +43,13 @@ namespace Defaults::Physics::Debris {
|
|||||||
// 1.0 = inèrcia completa; >1.0 amplifica la deriva; <1.0 la atenua.
|
// 1.0 = inèrcia completa; >1.0 amplifica la deriva; <1.0 la atenua.
|
||||||
constexpr float ENEMY_VELOCITY_INHERITANCE = 1.0F;
|
constexpr float ENEMY_VELOCITY_INHERITANCE = 1.0F;
|
||||||
|
|
||||||
|
// Velocitat de la bala traspassada a cada fragment de debris al moment
|
||||||
|
// de l'impacte. Separat de la inèrcia del cos (velocitat_objecte): permet
|
||||||
|
// que els trossos volin "amb la força de la bala" encara que el cos pesi
|
||||||
|
// molt i amb prou feines es mogui. 0.4 a 700 px/s = ~280 px/s extra per
|
||||||
|
// fragment, molt visible sense ser excessiu.
|
||||||
|
constexpr float BULLET_IMPULSE_FACTOR = 0.4F;
|
||||||
|
|
||||||
// Tuneig específic de l'explosió d'enemic (overrides als defaults
|
// Tuneig específic de l'explosió d'enemic (overrides als defaults
|
||||||
// que es passen com a paràmetres opcionals a explode()).
|
// que es passen com a paràmetres opcionals a explode()).
|
||||||
constexpr float ENEMY_LIFETIME = 2.5F; // Vida mínima del debris (s) — els que segueixen movent-se viuen més
|
constexpr float ENEMY_LIFETIME = 2.5F; // Vida mínima del debris (s) — els que segueixen movent-se viuen més
|
||||||
|
|||||||
@@ -57,7 +57,8 @@ namespace Effects {
|
|||||||
SDL_Color color,
|
SDL_Color color,
|
||||||
float lifetime,
|
float lifetime,
|
||||||
float friction,
|
float friction,
|
||||||
int segment_multiplier) {
|
int segment_multiplier,
|
||||||
|
const Vec2& bullet_impulse_velocity) {
|
||||||
if (!shape || !shape->isValid()) {
|
if (!shape || !shape->isValid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -84,7 +85,7 @@ namespace Effects {
|
|||||||
Vec2 world_p2 = transformPoint(local_p2, shape_centre, centro, angle, scale);
|
Vec2 world_p2 = transformPoint(local_p2, shape_centre, centro, angle, scale);
|
||||||
|
|
||||||
// Si el pool es ple, no té sentit continuar amb la resta de segments
|
// Si el pool es ple, no té sentit continuar amb la resta de segments
|
||||||
if (!spawnDebris(world_p1, world_p2, centro, velocitat_base, brightness, velocitat_objecte, velocitat_angular, factor_herencia_visual, color, lifetime, friction)) {
|
if (!spawnDebris(world_p1, world_p2, centro, velocitat_base, brightness, velocitat_objecte, velocitat_angular, factor_herencia_visual, color, lifetime, friction, bullet_impulse_velocity)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,7 +111,7 @@ namespace Effects {
|
|||||||
return segments;
|
return segments;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto DebrisManager::spawnDebris(const Vec2& world_p1, const Vec2& world_p2, const Vec2& centro, float velocitat_base, float brightness, const Vec2& velocitat_objecte, float velocitat_angular, float factor_herencia_visual, SDL_Color color, float lifetime, float friction) -> bool {
|
auto DebrisManager::spawnDebris(const Vec2& world_p1, const Vec2& world_p2, const Vec2& centro, float velocitat_base, float brightness, const Vec2& velocitat_objecte, float velocitat_angular, float factor_herencia_visual, SDL_Color color, float lifetime, float friction, const Vec2& bullet_impulse_velocity) -> bool {
|
||||||
Debris* debris = findFreeSlot();
|
Debris* debris = findFreeSlot();
|
||||||
if (debris == nullptr) {
|
if (debris == nullptr) {
|
||||||
std::cerr << "[DebrisManager] Warning: no debris slots disponibles\n";
|
std::cerr << "[DebrisManager] Warning: no debris slots disponibles\n";
|
||||||
@@ -131,13 +132,16 @@ namespace Effects {
|
|||||||
// Direcció radial (desde el centro hacia el segment)
|
// Direcció radial (desde el centro hacia el segment)
|
||||||
Vec2 direccio = computeExplosionDirection(world_p1, world_p2, centro);
|
Vec2 direccio = computeExplosionDirection(world_p1, world_p2, centro);
|
||||||
|
|
||||||
// Velocidad inicial (base ± variació aleatòria + velocity heretada de l'objecte)
|
// Velocidad inicial (base ± variació aleatòria + velocity heretada de l'objecte +
|
||||||
|
// velocitat de la bala escalada per BULLET_IMPULSE_FACTOR).
|
||||||
float speed =
|
float speed =
|
||||||
velocitat_base +
|
velocitat_base +
|
||||||
(((std::rand() / static_cast<float>(RAND_MAX)) * 2.0F - 1.0F) *
|
(((std::rand() / static_cast<float>(RAND_MAX)) * 2.0F - 1.0F) *
|
||||||
Defaults::Physics::Debris::VARIACIO_SPEED);
|
Defaults::Physics::Debris::VARIACIO_SPEED);
|
||||||
debris->velocity.x = (direccio.x * speed) + velocitat_objecte.x;
|
debris->velocity.x = (direccio.x * speed) + velocitat_objecte.x +
|
||||||
debris->velocity.y = (direccio.y * speed) + velocitat_objecte.y;
|
(bullet_impulse_velocity.x * Defaults::Physics::Debris::BULLET_IMPULSE_FACTOR);
|
||||||
|
debris->velocity.y = (direccio.y * speed) + velocitat_objecte.y +
|
||||||
|
(bullet_impulse_velocity.y * Defaults::Physics::Debris::BULLET_IMPULSE_FACTOR);
|
||||||
debris->acceleration = friction;
|
debris->acceleration = friction;
|
||||||
|
|
||||||
// Rotación de trayectoria (con conversió a tangencial si excedeix cap)
|
// Rotación de trayectoria (con conversió a tangencial si excedeix cap)
|
||||||
|
|||||||
@@ -47,6 +47,11 @@ namespace Effects {
|
|||||||
// - lifetime: temps de vida del debris (s, per defecte TEMPS_VIDA = 2s)
|
// - lifetime: temps de vida del debris (s, per defecte TEMPS_VIDA = 2s)
|
||||||
// - friction: desacceleració del debris (px/s², per defecte ACCELERACIO = -60)
|
// - friction: desacceleració del debris (px/s², per defecte ACCELERACIO = -60)
|
||||||
// - segment_multiplier: nombre de còpies per segment (per defecte 1 = sense duplicar)
|
// - segment_multiplier: nombre de còpies per segment (per defecte 1 = sense duplicar)
|
||||||
|
// - bullet_impulse_velocity: velocitat de la bala que ha causat l'impacte (px/s,
|
||||||
|
// per defecte 0). S'aplica a cada fragment escalada per
|
||||||
|
// Defaults::Physics::Debris::BULLET_IMPULSE_FACTOR, independent de
|
||||||
|
// velocitat_objecte. Permet que els trossos "salten amb la força de la bala"
|
||||||
|
// encara que el cos sigui pesat i amb prou feines es mogui.
|
||||||
void explode(const std::shared_ptr<Graphics::Shape>& shape,
|
void explode(const std::shared_ptr<Graphics::Shape>& shape,
|
||||||
const Vec2& centro,
|
const Vec2& centro,
|
||||||
float angle,
|
float angle,
|
||||||
@@ -60,7 +65,8 @@ namespace Effects {
|
|||||||
SDL_Color color = {0, 0, 0, 0}, // alpha==0 → fragmentos usan oscilador global
|
SDL_Color color = {0, 0, 0, 0}, // alpha==0 → fragmentos usan oscilador global
|
||||||
float lifetime = Defaults::Physics::Debris::TEMPS_VIDA,
|
float lifetime = Defaults::Physics::Debris::TEMPS_VIDA,
|
||||||
float friction = Defaults::Physics::Debris::ACCELERACIO,
|
float friction = Defaults::Physics::Debris::ACCELERACIO,
|
||||||
int segment_multiplier = 1);
|
int segment_multiplier = 1,
|
||||||
|
const Vec2& bullet_impulse_velocity = {.x = 0.0F, .y = 0.0F});
|
||||||
|
|
||||||
// Actualitzar todos los fragments active
|
// Actualitzar todos los fragments active
|
||||||
void update(float delta_time);
|
void update(float delta_time);
|
||||||
@@ -97,7 +103,7 @@ namespace Effects {
|
|||||||
-> std::vector<std::pair<Vec2, Vec2>>;
|
-> std::vector<std::pair<Vec2, Vec2>>;
|
||||||
// Inicialitza un debris en un slot lliure i el deixa actiu. Retorna
|
// Inicialitza un debris en un slot lliure i el deixa actiu. Retorna
|
||||||
// false si el pool está ple (la cridadora ha d'aturar el bucle).
|
// false si el pool está ple (la cridadora ha d'aturar el bucle).
|
||||||
auto spawnDebris(const Vec2& world_p1, const Vec2& world_p2, const Vec2& centro, float velocitat_base, float brightness, const Vec2& velocitat_objecte, float velocitat_angular, float factor_herencia_visual, SDL_Color color, float lifetime, float friction) -> bool;
|
auto spawnDebris(const Vec2& world_p1, const Vec2& world_p2, const Vec2& centro, float velocitat_base, float brightness, const Vec2& velocitat_objecte, float velocitat_angular, float factor_herencia_visual, SDL_Color color, float lifetime, float friction, const Vec2& bullet_impulse_velocity) -> bool;
|
||||||
static void applyAngularVelocity(Debris& debris, const Vec2& direccio, float velocitat_angular);
|
static void applyAngularVelocity(Debris& debris, const Vec2& direccio, float velocitat_angular);
|
||||||
static void applyVisualRotation(Debris& debris, float velocitat_angular, float factor_herencia_visual);
|
static void applyVisualRotation(Debris& debris, float velocitat_angular, float factor_herencia_visual);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -580,7 +580,7 @@ auto GameScene::buildCollisionContext() -> Systems::Collision::Context {
|
|||||||
.firework_manager = firework_manager_,
|
.firework_manager = firework_manager_,
|
||||||
.floating_score_manager = floating_score_manager_,
|
.floating_score_manager = floating_score_manager_,
|
||||||
.match_config = match_config_,
|
.match_config = match_config_,
|
||||||
.on_player_hit = [this](uint8_t pid) { tocado(pid); },
|
.on_player_hit = [this](uint8_t pid, const Vec2& bv) { tocado(pid, bv); },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -764,7 +764,7 @@ void GameScene::drawLevelCompletedState() {
|
|||||||
drawScoreboard();
|
drawScoreboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameScene::tocado(uint8_t player_id) {
|
void GameScene::tocado(uint8_t player_id, const Vec2& bullet_velocity) {
|
||||||
// Death sequence: 3 phases
|
// Death sequence: 3 phases
|
||||||
// Phase 1: First call (hit_timer_per_player_[player_id] == 0) - trigger explosion
|
// Phase 1: First call (hit_timer_per_player_[player_id] == 0) - trigger explosion
|
||||||
// Phase 2: Animation (0 < itocado_ < 3.0s) - debris animation
|
// Phase 2: Animation (0 < itocado_ < 3.0s) - debris animation
|
||||||
@@ -788,6 +788,9 @@ void GameScene::tocado(uint8_t player_id) {
|
|||||||
|
|
||||||
// Mateixa dispersió i efecte que els debris d'enemic (lifetime,
|
// Mateixa dispersió i efecte que els debris d'enemic (lifetime,
|
||||||
// friction, segment_multiplier alineats); només canvien sound i color.
|
// friction, segment_multiplier alineats); només canvien sound i color.
|
||||||
|
// bullet_velocity arriba a explode() com a impuls extra independent
|
||||||
|
// de la inèrcia del cos del ship — els trossos volen amb la força
|
||||||
|
// de la bala encara que el ship estiga quiet.
|
||||||
debris_manager_.explode(
|
debris_manager_.explode(
|
||||||
ships_[player_id].getShape(),
|
ships_[player_id].getShape(),
|
||||||
SHIP_POS,
|
SHIP_POS,
|
||||||
@@ -802,7 +805,8 @@ void GameScene::tocado(uint8_t player_id) {
|
|||||||
ships_[player_id].getConfig().colors.normal,
|
ships_[player_id].getConfig().colors.normal,
|
||||||
Defaults::Physics::Debris::ENEMY_LIFETIME,
|
Defaults::Physics::Debris::ENEMY_LIFETIME,
|
||||||
Defaults::Physics::Debris::ENEMY_FRICTION,
|
Defaults::Physics::Debris::ENEMY_FRICTION,
|
||||||
Defaults::Physics::Debris::ENEMY_SEGMENT_MULTIPLIER);
|
Defaults::Physics::Debris::ENEMY_SEGMENT_MULTIPLIER,
|
||||||
|
bullet_velocity);
|
||||||
|
|
||||||
// Start death timer (non-zero to avoid re-triggering)
|
// Start death timer (non-zero to avoid re-triggering)
|
||||||
hit_timer_per_player_[player_id] = Defaults::Game::HIT_TIMER_TRIGGER_DEATH;
|
hit_timer_per_player_[player_id] = Defaults::Game::HIT_TIMER_TRIGGER_DEATH;
|
||||||
|
|||||||
@@ -101,7 +101,10 @@ class GameScene final : public Scene {
|
|||||||
bool init_hud_rect_sound_played_{false}; // Flag para evitar repetir sonido del rectángulo
|
bool init_hud_rect_sound_played_{false}; // Flag para evitar repetir sonido del rectángulo
|
||||||
|
|
||||||
// Funciones privades
|
// Funciones privades
|
||||||
void tocado(uint8_t player_id);
|
// bullet_velocity: velocitat de la bala que ha causat la mort (Vec2{} si no
|
||||||
|
// ve d'una bala). Es passa al debris perquè els fragments volin en direcció
|
||||||
|
// de la bala (independent de la inèrcia del cos del ship).
|
||||||
|
void tocado(uint8_t player_id, const Vec2& bullet_velocity = {.x = 0.0F, .y = 0.0F});
|
||||||
void drawScoreboard(); // Dibuixar marcador de puntuación
|
void drawScoreboard(); // Dibuixar marcador de puntuación
|
||||||
void fireBullet(uint8_t player_id); // Shoot bullet from player
|
void fireBullet(uint8_t player_id); // Shoot bullet from player
|
||||||
[[nodiscard]] auto getSpawnPoint(uint8_t player_id) const -> Vec2; // Get spawn position for player
|
[[nodiscard]] auto getSpawnPoint(uint8_t player_id) const -> Vec2; // Get spawn position for player
|
||||||
|
|||||||
@@ -150,7 +150,9 @@ namespace Systems::Collision {
|
|||||||
const float DEATH_FACTOR = ctx.ships[i].getConfig().physics.death_impact_factor;
|
const float DEATH_FACTOR = ctx.ships[i].getConfig().physics.death_impact_factor;
|
||||||
const Vec2 IMPULSE = SHIP_VEL * (ctx.ships[i].getBody().mass * DEATH_FACTOR);
|
const Vec2 IMPULSE = SHIP_VEL * (ctx.ships[i].getBody().mass * DEATH_FACTOR);
|
||||||
touched_enemy->applyImpulse(IMPULSE);
|
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 {
|
} else {
|
||||||
// Primer impacte → estat HURT (rebot físic ja resolt per PhysicsWorld;
|
// Primer impacte → estat HURT (rebot físic ja resolt per PhysicsWorld;
|
||||||
// l'enemic no rep dany per decisió de disseny).
|
// l'enemic no rep dany per decisió de disseny).
|
||||||
@@ -197,13 +199,12 @@ namespace Systems::Collision {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// *** TEAMMATE HIT (friendly fire) ***
|
// *** TEAMMATE HIT (friendly fire) ***
|
||||||
// Víctima perd 1 vida, atacant en guanya 1. Apliquem l'impuls
|
// Víctima perd 1 vida, atacant en guanya 1. Friendly fire sempre
|
||||||
// de la bala a la nau ABANS de on_player_hit perquè tocado()
|
// mata: el bullet va als debris (via tocado) i NO al cos del ship
|
||||||
// captura la velocitat per als debris (si no, queden quiets).
|
// — el cos està a punt de desactivar-se, qualsevol impuls seria
|
||||||
const Vec2 BULLET_IMPULSE = bullet.getBody().velocity *
|
// double-count amb la velocitat que ja reben els trossos.
|
||||||
(bullet.getBody().mass * bullet.getConfig().physics.impact_momentum_factor);
|
const Vec2 BULLET_VEL = bullet.getBody().velocity;
|
||||||
ctx.ships[player_id].getBody().applyImpulse(BULLET_IMPULSE);
|
ctx.on_player_hit(player_id, BULLET_VEL);
|
||||||
ctx.on_player_hit(player_id);
|
|
||||||
ctx.lives_per_player[BULLET_OWNER]++;
|
ctx.lives_per_player[BULLET_OWNER]++;
|
||||||
Audio::get()->playSound(Defaults::Sound::FRIENDLY_FIRE_HIT, Audio::Group::GAME);
|
Audio::get()->playSound(Defaults::Sound::FRIENDLY_FIRE_HIT, Audio::Group::GAME);
|
||||||
breakBullet(ctx.debris_manager, bullet);
|
breakBullet(ctx.debris_manager, bullet);
|
||||||
@@ -237,15 +238,20 @@ namespace Systems::Collision {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// *** BALA D'ENEMIC → SHIP ***
|
// *** BALA D'ENEMIC → SHIP ***
|
||||||
// Apliquem l'impuls de la bala abans del hurt/death perquè la
|
// Regla "cos XOR trossos": l'impuls de la bala s'aplica al cos
|
||||||
// velocitat de la nau quedi capturada per als debris.
|
// només si el ship sobreviu (fereix). Si el ship mor, el bullet
|
||||||
const Vec2 IMPULSE = bullet.getBody().velocity *
|
// va directament als trossos (via tocado) i el cos no rep impuls
|
||||||
(bullet.getBody().mass * bullet.getConfig().physics.impact_momentum_factor);
|
// — els trossos ja porten la força de la bala, qualsevol impuls
|
||||||
ctx.ships[player_id].getBody().applyImpulse(IMPULSE);
|
// afegit al cos seria double-count.
|
||||||
|
const Vec2 BULLET_VEL = bullet.getBody().velocity;
|
||||||
if (ctx.ships[player_id].isHurt()) {
|
if (ctx.ships[player_id].isHurt()) {
|
||||||
// Segon impacte durant HURT → mort.
|
// Segon impacte durant HURT → mort.
|
||||||
ctx.on_player_hit(player_id);
|
ctx.on_player_hit(player_id, BULLET_VEL);
|
||||||
} else {
|
} 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();
|
ctx.ships[player_id].hurt();
|
||||||
}
|
}
|
||||||
breakBullet(ctx.debris_manager, bullet);
|
breakBullet(ctx.debris_manager, bullet);
|
||||||
|
|||||||
@@ -40,8 +40,11 @@ namespace Systems::Collision {
|
|||||||
Effects::FireworkManager& firework_manager;
|
Effects::FireworkManager& firework_manager;
|
||||||
Effects::FloatingScoreManager& floating_score_manager;
|
Effects::FloatingScoreManager& floating_score_manager;
|
||||||
const GameConfig::MatchConfig& match_config;
|
const GameConfig::MatchConfig& match_config;
|
||||||
// Trigger de muerte del jugador (GameScene::tocado).
|
// Trigger de muerte del jugador (GameScene::tocado). bullet_velocity es
|
||||||
std::function<void(uint8_t /*player_id*/)> on_player_hit;
|
// 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:
|
// Detecta colisiones bullet → enemy. Si hit:
|
||||||
|
|||||||
@@ -24,10 +24,11 @@ namespace Systems::EnemyEvents {
|
|||||||
ctx.floating_score_manager.crear(POINTS, enemy.getCenter());
|
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;
|
constexpr float SPEED_EXPLOSIO = 80.0F;
|
||||||
const Vec2 INHERITED_VEL = enemy.getVelocityVector() *
|
const Vec2 INHERITED_VEL = enemy.getVelocityVector() *
|
||||||
Defaults::Physics::Debris::ENEMY_VELOCITY_INHERITANCE;
|
Defaults::Physics::Debris::ENEMY_VELOCITY_INHERITANCE;
|
||||||
|
const Vec2 BULLET_VEL = (bullet != nullptr) ? bullet->getBody().velocity : Vec2{};
|
||||||
ctx.debris_manager.explode(
|
ctx.debris_manager.explode(
|
||||||
enemy.getShape(),
|
enemy.getShape(),
|
||||||
enemy.getCenter(),
|
enemy.getCenter(),
|
||||||
@@ -42,7 +43,8 @@ namespace Systems::EnemyEvents {
|
|||||||
enemy.getConfig().colors.normal,
|
enemy.getConfig().colors.normal,
|
||||||
Defaults::Physics::Debris::ENEMY_LIFETIME,
|
Defaults::Physics::Debris::ENEMY_LIFETIME,
|
||||||
Defaults::Physics::Debris::ENEMY_FRICTION,
|
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) {
|
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) {
|
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);
|
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) {
|
for (const auto& action : actions) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case EnemyActionType::SET_HURT:
|
case EnemyActionType::SET_HURT:
|
||||||
@@ -86,13 +106,15 @@ namespace Systems::EnemyEvents {
|
|||||||
doAddScore(ctx, enemy, shooter_id);
|
doAddScore(ctx, enemy, shooter_id);
|
||||||
break;
|
break;
|
||||||
case EnemyActionType::CREATE_DEBRIS:
|
case EnemyActionType::CREATE_DEBRIS:
|
||||||
doCreateDebris(ctx, enemy);
|
doCreateDebris(ctx, enemy, bullet);
|
||||||
break;
|
break;
|
||||||
case EnemyActionType::CREATE_FIREWORKS:
|
case EnemyActionType::CREATE_FIREWORKS:
|
||||||
doCreateFireworks(ctx, enemy);
|
doCreateFireworks(ctx, enemy);
|
||||||
break;
|
break;
|
||||||
case EnemyActionType::APPLY_IMPULSE:
|
case EnemyActionType::APPLY_IMPULSE:
|
||||||
doApplyImpulse(enemy, bullet);
|
if (!will_die) {
|
||||||
|
doApplyImpulse(enemy, bullet);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user