From 0046d526b0dcf605150f968d697bf2a5c3ad6fa0 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Tue, 12 May 2026 22:26:17 +0200 Subject: [PATCH] fix(lighting): llig flicker tambe del YAML del jugador --- source/game/entities/player.cpp | 17 +++++++++++------ source/game/entities/player.hpp | 14 +++++++++++--- source/game/scenes/game_scene.cpp | 3 ++- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/source/game/entities/player.cpp b/source/game/entities/player.cpp index 3fab317..e23564b 100644 --- a/source/game/entities/player.cpp +++ b/source/game/entities/player.cpp @@ -142,13 +142,18 @@ void Player::loadFrom(const std::string& yaml_path) { // desactivada i els hazards toquen al primer frame, com abans. readImmunityBlock(yaml); - // Bloc opcional `light: { radius: N }` — radi en píxels del cercle - // de llum emès pel jugador. 0 = no emet. La forma del gradient és - // global (data/config/lighting.yaml), no per jugador. + // Bloc opcional `light:` — radi i flicker. Extret a un mètode per + // mantenir `loadFrom` sota el llindar de complexitat de clang-tidy. + readLightBlock(yaml); +} + +void Player::readLightBlock(const fkyaml::node& yaml) { light_radius = 0; - if (yaml.contains("light") && yaml["light"].contains("radius")) { - light_radius = yaml["light"]["radius"].get_value(); - } + light_flicker = false; + if (!yaml.contains("light")) { return; } + const auto& l = yaml["light"]; + if (l.contains("radius")) { light_radius = l["radius"].get_value(); } + if (l.contains("flicker")) { light_flicker = l["flicker"].get_value(); } } void Player::readCollisionBlock(const fkyaml::node& yaml, const std::string& yaml_path) { diff --git a/source/game/entities/player.hpp b/source/game/entities/player.hpp index b311c60..776f8d1 100644 --- a/source/game/entities/player.hpp +++ b/source/game/entities/player.hpp @@ -125,10 +125,12 @@ class Player : public AnimatedSprite { inline static int body_height = 0; // Radi de la llum emesa pel jugador (en píxels del canvas), llegit - // del bloc opcional `light: { radius: N }` del YAML. 0 = no emet. - // Es declara estàtic com la resta de configs del jugador (immunity, - // jump, ...): tots els jugadors del mateix YAML comparteixen el valor. + // del bloc opcional `light: { radius: N, flicker: bool }` del YAML. + // 0 = no emet. Es declara estàtic com la resta de configs del jugador + // (immunity, jump, ...): tots els jugadors del mateix YAML comparteixen + // el valor. `light_flicker` activa la modulació "tipus foc" del radi. inline static int light_radius = 0; + inline static bool light_flicker = false; // Ha de cridar-se abans d'instanciar Player; GameScene ho fa al ctor. static void loadFrom(const std::string& yaml_path); @@ -143,6 +145,7 @@ class Player : public AnimatedSprite { // sprite es dibuixa amb `pos_.y - jump_z_`, i la llum ha de seguir-lo // per a que el cercle "salti" amb el jugador, no es quedi al sòl. [[nodiscard]] static auto getLightRadius() -> int { return light_radius; } + [[nodiscard]] static auto getLightFlicker() -> bool { return light_flicker; } [[nodiscard]] auto getLightCenter() const -> SDL_FPoint; Player(const std::string& anim_key, int id, float x, float y, const Controls& controls, const Map::Info& map_info, int paint_tile_index = -1); @@ -755,6 +758,11 @@ class Player : public AnimatedSprite { // readers — `loadFrom` el crida al final. static void readImmunityBlock(const fkyaml::node& yaml); + // Llig el bloc opcional `light: { radius: N, flicker: bool }` del + // YAML i pobla `light_radius` / `light_flicker`. Si manca, els + // valors queden a 0 / false (jugador sense llum). + static void readLightBlock(const fkyaml::node& yaml); + // Activa l'estat ATTACKING en la direcció cardinal indicada (la // direcció cap on mira el jugador) i publica `whip_spawn` al bus // perquè el GameScene cree el `WhipAttack` corresponent. Posa el diff --git a/source/game/scenes/game_scene.cpp b/source/game/scenes/game_scene.cpp index 2ffda5c..bcb433b 100644 --- a/source/game/scenes/game_scene.cpp +++ b/source/game/scenes/game_scene.cpp @@ -1018,10 +1018,11 @@ void GameScene::applyLightingPass() { // `Lighting::apply` salta el cercle al filtre intern. No fem un // gating extern aquí (els jugadors són només 1-2 actors i el cost // d'afegir-los al vector és menyspreable). + const bool PLAYER_FLICKER = Player::getLightFlicker(); for (const auto& p : players_) { if (p->isOutOfPlay()) { continue; } const auto C = p->getLightCenter(); - emitters.push_back({.cx = C.x, .cy = C.y, .radius = PLAYER_R, .flicker = false}); + emitters.push_back({.cx = C.x, .cy = C.y, .radius = PLAYER_R, .flicker = PLAYER_FLICKER}); } for (const auto* e : entity_manager_.getEntities()) { const int R = e->getLightRadius();