afegit friendly fire

This commit is contained in:
2025-12-17 19:39:33 +01:00
parent 8b9d26a02c
commit 54031e3520
6 changed files with 103 additions and 4 deletions

View File

@@ -19,6 +19,7 @@ Bala::Bala(SDL_Renderer* renderer)
angle_(0.0f),
velocitat_(0.0f),
esta_(false),
grace_timer_(0.0f),
brightness_(Defaults::Brightness::BALA) {
// [NUEVO] Carregar forma compartida des de fitxer
forma_ = Graphics::ShapeLoader::load("bullet.shp");
@@ -34,6 +35,7 @@ void Bala::inicialitzar() {
centre_ = {0.0f, 0.0f};
angle_ = 0.0f;
velocitat_ = 0.0f;
grace_timer_ = 0.0f;
}
void Bala::disparar(const Punt& posicio, float angle, uint8_t owner_id) {
@@ -57,12 +59,23 @@ void Bala::disparar(const Punt& posicio, float angle, uint8_t owner_id) {
// 7 px/frame × 20 FPS = 140 px/s
velocitat_ = 140.0f;
// Activar grace period (prevents instant self-collision)
grace_timer_ = Defaults::Game::BULLET_GRACE_PERIOD;
// Reproducir sonido de disparo láser
Audio::get()->playSound(Defaults::Sound::LASER, Audio::Group::GAME);
}
void Bala::actualitzar(float delta_time) {
if (esta_) {
// Decrementar grace timer
if (grace_timer_ > 0.0f) {
grace_timer_ -= delta_time;
if (grace_timer_ < 0.0f) {
grace_timer_ = 0.0f;
}
}
mou(delta_time);
}
}

View File

@@ -25,6 +25,7 @@ class Bala {
bool esta_activa() const { return esta_; }
const Punt& get_centre() const { return centre_; }
uint8_t get_owner_id() const { return owner_id_; }
float get_grace_timer() const { return grace_timer_; }
void desactivar() { esta_ = false; }
private:
@@ -38,8 +39,9 @@ class Bala {
float angle_;
float velocitat_;
bool esta_;
uint8_t owner_id_; // 0=P1, 1=P2
float brightness_; // Factor de brillantor (0.0-1.0)
uint8_t owner_id_; // 0=P1, 1=P2
float grace_timer_; // Grace period timer (0.0 = vulnerable)
float brightness_; // Factor de brillantor (0.0-1.0)
void mou(float delta_time);
};

View File

@@ -476,6 +476,7 @@ void EscenaJoc::actualitzar(float delta_time) {
detectar_col·lisions_bales_enemics();
detectar_col·lisio_naus_enemics();
detectar_col·lisions_bales_jugadors();
debris_manager_.actualitzar(delta_time);
gestor_puntuacio_.actualitzar(delta_time);
break;
@@ -1068,6 +1069,81 @@ void EscenaJoc::detectar_col·lisio_naus_enemics() {
}
}
void EscenaJoc::detectar_col·lisions_bales_jugadors() {
// Skip if friendly fire disabled
if (!Defaults::Game::FRIENDLY_FIRE_ENABLED) {
return;
}
// Collision constants (exact hitbox, 1.0x amplification)
constexpr float RADI_NAU = Defaults::Entities::SHIP_RADIUS;
constexpr float RADI_BALA = Defaults::Entities::BULLET_RADIUS;
constexpr float SUMA_RADIS = (RADI_NAU + RADI_BALA) *
Defaults::Game::COLLISION_BULLET_PLAYER_AMPLIFIER; // 15.0 px
constexpr float SUMA_RADIS_QUADRAT = SUMA_RADIS * SUMA_RADIS; // 225.0
// Check all active bullets
for (auto& bala : bales_) {
if (!bala.esta_activa()) {
continue;
}
// Skip bullets in grace period (prevents instant self-collision)
if (bala.get_grace_timer() > 0.0f) {
continue;
}
const Punt& pos_bala = bala.get_centre();
uint8_t bullet_owner = bala.get_owner_id();
// Check collision with BOTH players
for (uint8_t player_id = 0; player_id < 2; player_id++) {
// Skip if player is dead, invulnerable, or inactive
if (itocado_per_jugador_[player_id] > 0.0f) continue;
if (!naus_[player_id].esta_viva()) continue;
if (naus_[player_id].es_invulnerable()) continue;
// Skip inactive players
bool jugador_actiu = (player_id == 0) ? config_partida_.jugador1_actiu
: config_partida_.jugador2_actiu;
if (!jugador_actiu) continue;
const Punt& pos_nau = naus_[player_id].get_centre();
// Calculate squared distance (avoid sqrt)
float dx = pos_bala.x - pos_nau.x;
float dy = pos_bala.y - pos_nau.y;
float distancia_quadrada = dx * dx + dy * dy;
// Check collision
if (distancia_quadrada <= SUMA_RADIS_QUADRAT) {
// *** FRIENDLY FIRE HIT ***
if (bullet_owner == player_id) {
// CASE 1: Self-hit (own bullet)
// Player loses 1 life, no gain
tocado(player_id);
} else {
// CASE 2: Teammate hit
// Victim loses 1 life
tocado(player_id);
// Attacker gains 1 life (no cap)
vides_per_jugador_[bullet_owner]++;
}
// Play distinct sound
Audio::get()->playSound(Defaults::Sound::FRIENDLY_FIRE_HIT, Audio::Group::GAME);
// Deactivate bullet
bala.desactivar();
break; // Bullet only hits once per frame
}
}
}
}
// [NEW] Stage system helper methods
void EscenaJoc::dibuixar_missatge_stage(const std::string& missatge) {

View File

@@ -83,6 +83,7 @@ class EscenaJoc {
void tocado(uint8_t player_id);
void detectar_col·lisions_bales_enemics(); // Col·lisions bala-enemic
void detectar_col·lisio_naus_enemics(); // Ship-enemy collision detection (plural)
void detectar_col·lisions_bales_jugadors(); // Bullet-player collision detection (friendly fire)
void dibuixar_marges() const; // Dibuixar vores de la zona de joc
void dibuixar_marcador(); // Dibuixar marcador de puntuació
void disparar_bala(uint8_t player_id); // Shoot bullet from player