respawn de nau i invulnerabilitat

This commit is contained in:
2025-12-10 11:35:45 +01:00
parent 9a5adcbcc5
commit 3b638f4715
5 changed files with 55 additions and 8 deletions

View File

@@ -105,6 +105,17 @@ constexpr float ENEMY_RADIUS = 20.0f;
constexpr float BULLET_RADIUS = 3.0f;
} // namespace Entities
// Ship (nave del jugador)
namespace Ship {
// Invulnerabilidad post-respawn
constexpr float INVULNERABILITY_DURATION = 3.0f; // Segundos de invulnerabilidad
// Parpadeo visual durante invulnerabilidad
constexpr float BLINK_VISIBLE_TIME = 0.1f; // Tiempo visible (segundos)
constexpr float BLINK_INVISIBLE_TIME = 0.1f; // Tiempo invisible (segundos)
// Frecuencia total: 0.2s/ciclo = 5 Hz (~15 parpadeos en 3s)
} // namespace Ship
// Game rules (lives, respawn, game over)
namespace Game {
constexpr int STARTING_LIVES = 3; // Initial lives

View File

@@ -20,7 +20,8 @@ Nau::Nau(SDL_Renderer* renderer)
angle_(0.0f),
velocitat_(0.0f),
esta_tocada_(false),
brightness_(Defaults::Brightness::NAU) {
brightness_(Defaults::Brightness::NAU),
invulnerable_timer_(0.0f) {
// [NUEVO] Carregar forma compartida des de fitxer
forma_ = Graphics::ShapeLoader::load("ship.shp");
@@ -29,7 +30,7 @@ Nau::Nau(SDL_Renderer* renderer)
}
}
void Nau::inicialitzar(const Punt* spawn_point) {
void Nau::inicialitzar(const Punt* spawn_point, bool activar_invulnerabilitat) {
// Inicialització de la nau (triangle)
// Basat en el codi Pascal original: lines 380-384
// Copiat de joc_asteroides.cpp línies 30-44
@@ -52,6 +53,14 @@ void Nau::inicialitzar(const Punt* spawn_point) {
// Estat inicial
angle_ = 0.0f;
velocitat_ = 0.0f;
// Activar invulnerabilidad solo si es respawn
if (activar_invulnerabilitat) {
invulnerable_timer_ = Defaults::Ship::INVULNERABILITY_DURATION;
} else {
invulnerable_timer_ = 0.0f;
}
esta_tocada_ = false;
}
@@ -90,6 +99,14 @@ void Nau::actualitzar(float delta_time) {
if (esta_tocada_)
return;
// Decrementar timer de invulnerabilidad
if (invulnerable_timer_ > 0.0f) {
invulnerable_timer_ -= delta_time;
if (invulnerable_timer_ < 0.0f) {
invulnerable_timer_ = 0.0f;
}
}
// Aplicar física (moviment + fricció)
aplicar_fisica(delta_time);
}
@@ -99,6 +116,19 @@ void Nau::dibuixar() const {
if (esta_tocada_)
return;
// Si invulnerable, parpadear (toggle on/off)
if (es_invulnerable()) {
// Calcular ciclo de parpadeo
float blink_cycle = Defaults::Ship::BLINK_VISIBLE_TIME +
Defaults::Ship::BLINK_INVISIBLE_TIME;
float time_in_cycle = std::fmod(invulnerable_timer_, blink_cycle);
// Si estamos en fase invisible, no dibujar
if (time_in_cycle < Defaults::Ship::BLINK_INVISIBLE_TIME) {
return; // No dibujar durante fase invisible
}
}
if (!forma_)
return;

View File

@@ -17,7 +17,7 @@ class Nau {
: renderer_(nullptr) {}
Nau(SDL_Renderer* renderer);
void inicialitzar(const Punt* spawn_point = nullptr);
void inicialitzar(const Punt* spawn_point = nullptr, bool activar_invulnerabilitat = false);
void processar_input(float delta_time);
void actualitzar(float delta_time);
void dibuixar() const;
@@ -27,6 +27,7 @@ class Nau {
float get_angle() const { return angle_; }
bool esta_viva() const { return !esta_tocada_; }
bool esta_tocada() const { return esta_tocada_; }
bool es_invulnerable() const { return invulnerable_timer_ > 0.0f; }
const std::shared_ptr<Graphics::Shape>& get_forma() const { return forma_; }
float get_brightness() const { return brightness_; }
Punt get_velocitat_vector() const {
@@ -54,7 +55,8 @@ class Nau {
float angle_; // Angle d'orientació
float velocitat_; // Velocitat (px/s)
bool esta_tocada_;
float brightness_; // Factor de brillantor (0.0-1.0)
float brightness_; // Factor de brillantor (0.0-1.0)
float invulnerable_timer_; // 0.0f = vulnerable, >0.0f = invulnerable
void aplicar_fisica(float delta_time);
};

View File

@@ -214,8 +214,8 @@ void EscenaJoc::actualitzar(float delta_time) {
num_vides_--;
if (num_vides_ > 0) {
// Respawn ship
nau_.inicialitzar(&punt_spawn_);
// Respawn ship en posición de muerte con invulnerabilidad
nau_.inicialitzar(&punt_mort_, true);
itocado_ = 0.0f;
} else {
// Game over
@@ -560,6 +560,9 @@ void EscenaJoc::tocado() {
if (itocado_ == 0.0f) {
// *** PHASE 1: TRIGGER DEATH ***
// Guardar posición de muerte para respawn
punt_mort_ = nau_.get_centre();
// Mark ship as dead (stops rendering and input)
nau_.marcar_tocada();
@@ -859,8 +862,8 @@ void EscenaJoc::detectar_col·lisions_bales_enemics() {
}
void EscenaJoc::detectar_col·lisio_nau_enemics() {
// Only check collisions if ship is alive
if (!nau_.esta_viva()) {
// Skip collisions if ship is dead or invulnerable
if (!nau_.esta_viva() || nau_.es_invulnerable()) {
return;
}

View File

@@ -56,6 +56,7 @@ class EscenaJoc {
bool game_over_; // Game over state flag
float game_over_timer_; // Countdown timer for auto-return (seconds)
Punt punt_spawn_; // Configurable spawn point
Punt punt_mort_; // Death position (for respawn)
int puntuacio_total_; // Current score
// Text vectorial