feat(bullet): debris en trencar-se amb so HIT mogut des d'enemy.herir()
This commit is contained in:
@@ -80,26 +80,10 @@ void Bullet::disparar(const Vec2& position, float angle, uint8_t owner_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Bullet::update(float /*delta_time*/) {
|
void Bullet::update(float /*delta_time*/) {
|
||||||
if (!is_active_) {
|
// No-op: la desactivació per fora-de-zona viu a
|
||||||
return;
|
// Systems::Collision::desactivateOutOfBoundsBullets() perquè així té accés
|
||||||
}
|
// al DebrisManager i pot generar el "trencament" visual de la bala alhora.
|
||||||
|
// El moviment l'integra PhysicsWorld; postUpdate sincronitza center_ i prev_position_.
|
||||||
// El movimiento real lo hace PhysicsWorld::update() (integración).
|
|
||||||
// Aquí solo lógica de estado: detectar salida del PLAYAREA i desactivar.
|
|
||||||
// Sense marge de seguretat: la bala mor quan la seva aresta toca el border visual
|
|
||||||
// (centre a BULLET_RADIUS del límit). El MARGE_SEGURETAT de getSafePlayAreaBounds
|
|
||||||
// és per a spawn d'enemics, no per a desactivació de bales.
|
|
||||||
float min_x;
|
|
||||||
float max_x;
|
|
||||||
float min_y;
|
|
||||||
float max_y;
|
|
||||||
Constants::getPlayAreaBounds(min_x, max_x, min_y, max_y);
|
|
||||||
constexpr float R = Defaults::Entities::BULLET_RADIUS;
|
|
||||||
|
|
||||||
if (body_.position.x < min_x + R || body_.position.x > max_x - R ||
|
|
||||||
body_.position.y < min_y + R || body_.position.y > max_y - R) {
|
|
||||||
desactivar();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bullet::postUpdate(float /*delta_time*/) {
|
void Bullet::postUpdate(float /*delta_time*/) {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "core/audio/audio.hpp"
|
|
||||||
#include "core/defaults.hpp"
|
#include "core/defaults.hpp"
|
||||||
#include "core/entities/entity.hpp"
|
#include "core/entities/entity.hpp"
|
||||||
#include "core/graphics/shape_loader.hpp"
|
#include "core/graphics/shape_loader.hpp"
|
||||||
@@ -277,7 +276,8 @@ void Enemy::destruir() {
|
|||||||
void Enemy::herir(uint8_t shooter_id) {
|
void Enemy::herir(uint8_t shooter_id) {
|
||||||
wounded_timer_ = Defaults::Enemies::Wounded::DURATION;
|
wounded_timer_ = Defaults::Enemies::Wounded::DURATION;
|
||||||
last_hit_by_ = shooter_id;
|
last_hit_by_ = shooter_id;
|
||||||
Audio::get()->playSound(Defaults::Sound::HIT, Audio::Group::GAME);
|
// El so HIT ara el reprodueix la bala quan es trenca en debris
|
||||||
|
// (Systems::Collision::breakBullet), no l'enemic en entrar a HURT.
|
||||||
}
|
}
|
||||||
|
|
||||||
void Enemy::applyImpulse(const Vec2& impulse) {
|
void Enemy::applyImpulse(const Vec2& impulse) {
|
||||||
|
|||||||
@@ -296,6 +296,7 @@ auto GameScene::stepContinueScreen(float delta_time) -> bool {
|
|||||||
for (auto& bullet : bullets_) {
|
for (auto& bullet : bullets_) {
|
||||||
bullet.update(delta_time);
|
bullet.update(delta_time);
|
||||||
}
|
}
|
||||||
|
Systems::Collision::desactivateOutOfBoundsBullets(bullets_, debris_manager_);
|
||||||
debris_manager_.update(delta_time);
|
debris_manager_.update(delta_time);
|
||||||
firework_manager_.update(delta_time);
|
firework_manager_.update(delta_time);
|
||||||
floating_score_manager_.update(delta_time);
|
floating_score_manager_.update(delta_time);
|
||||||
@@ -321,6 +322,7 @@ auto GameScene::stepGameOver(float delta_time) -> bool {
|
|||||||
for (auto& bullet : bullets_) {
|
for (auto& bullet : bullets_) {
|
||||||
bullet.update(delta_time);
|
bullet.update(delta_time);
|
||||||
}
|
}
|
||||||
|
Systems::Collision::desactivateOutOfBoundsBullets(bullets_, debris_manager_);
|
||||||
debris_manager_.update(delta_time);
|
debris_manager_.update(delta_time);
|
||||||
firework_manager_.update(delta_time);
|
firework_manager_.update(delta_time);
|
||||||
floating_score_manager_.update(delta_time);
|
floating_score_manager_.update(delta_time);
|
||||||
@@ -438,6 +440,7 @@ void GameScene::runStageLevelStart(float delta_time) {
|
|||||||
for (auto& bullet : bullets_) {
|
for (auto& bullet : bullets_) {
|
||||||
bullet.update(delta_time);
|
bullet.update(delta_time);
|
||||||
}
|
}
|
||||||
|
Systems::Collision::desactivateOutOfBoundsBullets(bullets_, debris_manager_);
|
||||||
debris_manager_.update(delta_time);
|
debris_manager_.update(delta_time);
|
||||||
firework_manager_.update(delta_time);
|
firework_manager_.update(delta_time);
|
||||||
}
|
}
|
||||||
@@ -466,13 +469,14 @@ void GameScene::runStagePlaying(float delta_time) {
|
|||||||
enemy.update(delta_time);
|
enemy.update(delta_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Col·lisions primer, després `bullet.update()`: si una bala el mateix frame xoca
|
// Col·lisions primer, després desactivació per fora-de-zona: així una bala que
|
||||||
// amb un enemic i alhora surt del PLAYAREA, ha de comptar com a impacte abans de
|
// el mateix frame xoca amb un enemic i alhora surt del PLAYAREA es compta com a
|
||||||
// ser desactivada per fora-de-zona.
|
// impacte abans no se la trenqui per sortir.
|
||||||
runCollisionDetections();
|
runCollisionDetections();
|
||||||
for (auto& bullet : bullets_) {
|
for (auto& bullet : bullets_) {
|
||||||
bullet.update(delta_time);
|
bullet.update(delta_time);
|
||||||
}
|
}
|
||||||
|
Systems::Collision::desactivateOutOfBoundsBullets(bullets_, debris_manager_);
|
||||||
debris_manager_.update(delta_time);
|
debris_manager_.update(delta_time);
|
||||||
firework_manager_.update(delta_time);
|
firework_manager_.update(delta_time);
|
||||||
floating_score_manager_.update(delta_time);
|
floating_score_manager_.update(delta_time);
|
||||||
@@ -490,6 +494,7 @@ void GameScene::runStageLevelCompleted(float delta_time) {
|
|||||||
for (auto& bullet : bullets_) {
|
for (auto& bullet : bullets_) {
|
||||||
bullet.update(delta_time);
|
bullet.update(delta_time);
|
||||||
}
|
}
|
||||||
|
Systems::Collision::desactivateOutOfBoundsBullets(bullets_, debris_manager_);
|
||||||
debris_manager_.update(delta_time);
|
debris_manager_.update(delta_time);
|
||||||
firework_manager_.update(delta_time);
|
firework_manager_.update(delta_time);
|
||||||
floating_score_manager_.update(delta_time);
|
floating_score_manager_.update(delta_time);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "core/audio/audio.hpp"
|
#include "core/audio/audio.hpp"
|
||||||
#include "core/physics/collision.hpp"
|
#include "core/physics/collision.hpp"
|
||||||
#include "core/types.hpp"
|
#include "core/types.hpp"
|
||||||
|
#include "game/constants.hpp"
|
||||||
|
|
||||||
namespace Systems::Collision {
|
namespace Systems::Collision {
|
||||||
|
|
||||||
@@ -81,6 +82,29 @@ namespace Systems::Collision {
|
|||||||
// No heretem color: el burst usa el blanc per defecte per a un feel més lluminós.
|
// No heretem color: el burst usa el blanc per defecte per a un feel més lluminós.
|
||||||
ctx.firework_manager.spawn(ENEMY_POS);
|
ctx.firework_manager.spawn(ENEMY_POS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
// o sortida del PLAYAREA) per a un feedback visual i sonor consistent.
|
||||||
|
void breakBullet(Effects::DebrisManager& debris_manager, Bullet& bullet) {
|
||||||
|
constexpr float DEBRIS_VELOCITY = 60.0F;
|
||||||
|
debris_manager.explode(
|
||||||
|
bullet.getShape(),
|
||||||
|
bullet.getCenter(),
|
||||||
|
bullet.getAngle(),
|
||||||
|
1.0F, // scale
|
||||||
|
DEBRIS_VELOCITY,
|
||||||
|
bullet.getBrightness(),
|
||||||
|
Vec2{}, // sense herència de velocitat (fragments radials)
|
||||||
|
0.0F, // sense velocity angular heretada
|
||||||
|
0.0F, // sense rotació visual heretada
|
||||||
|
Defaults::Sound::HIT,
|
||||||
|
Defaults::Palette::BULLET,
|
||||||
|
Defaults::Physics::Debris::TEMPS_VIDA,
|
||||||
|
Defaults::Physics::Debris::ACCELERACIO,
|
||||||
|
1); // sense duplicat de segments
|
||||||
|
bullet.desactivar();
|
||||||
|
}
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
void detectBulletEnemy(Context& ctx) {
|
void detectBulletEnemy(Context& ctx) {
|
||||||
@@ -114,7 +138,7 @@ namespace Systems::Collision {
|
|||||||
enemy.herir(SHOOTER);
|
enemy.herir(SHOOTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
bullet.desactivar();
|
breakBullet(ctx.debris_manager, bullet);
|
||||||
break; // Una bala impacta a un enemy y muere
|
break; // Una bala impacta a un enemy y muere
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,7 +266,7 @@ namespace Systems::Collision {
|
|||||||
ctx.on_player_hit(player_id);
|
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);
|
||||||
bullet.desactivar();
|
breakBullet(ctx.debris_manager, bullet);
|
||||||
break; // Una bullet solo impacta una vez por frame
|
break; // Una bullet solo impacta una vez por frame
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,4 +280,26 @@ namespace Systems::Collision {
|
|||||||
detectBulletPlayer(ctx);
|
detectBulletPlayer(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void desactivateOutOfBoundsBullets(
|
||||||
|
std::array<Bullet, static_cast<std::size_t>(Defaults::Entities::MAX_BALES) * 2>& bullets,
|
||||||
|
Effects::DebrisManager& debris_manager) {
|
||||||
|
float min_x;
|
||||||
|
float max_x;
|
||||||
|
float min_y;
|
||||||
|
float max_y;
|
||||||
|
Constants::getPlayAreaBounds(min_x, max_x, min_y, max_y);
|
||||||
|
constexpr float R = Defaults::Entities::BULLET_RADIUS;
|
||||||
|
|
||||||
|
for (auto& bullet : bullets) {
|
||||||
|
if (!bullet.isActive()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const Vec2& pos = bullet.getCenter();
|
||||||
|
if (pos.x < min_x + R || pos.x > max_x - R ||
|
||||||
|
pos.y < min_y + R || pos.y > max_y - R) {
|
||||||
|
breakBullet(debris_manager, bullet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Systems::Collision
|
} // namespace Systems::Collision
|
||||||
|
|||||||
@@ -70,4 +70,11 @@ namespace Systems::Collision {
|
|||||||
// Las tres en orden lógico del frame.
|
// Las tres en orden lógico del frame.
|
||||||
void detectAll(Context& ctx);
|
void detectAll(Context& ctx);
|
||||||
|
|
||||||
|
// Desactiva les bales que han sortit del PLAYAREA, generant debris visual
|
||||||
|
// (8 fragments de l'octàgon) i el so HIT. Cal cridar-la després de detectAll()
|
||||||
|
// perquè una bala que el mateix frame xoca i alhora surt es comptabilitzi com a impacte.
|
||||||
|
void desactivateOutOfBoundsBullets(
|
||||||
|
std::array<Bullet, static_cast<std::size_t>(Defaults::Entities::MAX_BALES) * 2>& bullets,
|
||||||
|
Effects::DebrisManager& debris_manager);
|
||||||
|
|
||||||
} // namespace Systems::Collision
|
} // namespace Systems::Collision
|
||||||
|
|||||||
Reference in New Issue
Block a user