From d1d5679d1474da57ad06ad2fba0938862188fcf1 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Tue, 12 May 2026 21:12:06 +0200 Subject: [PATCH] feat(game_scene): wire lighting pass entre actors i HUD --- source/game/scenes/game_scene.cpp | 37 +++++++++++++++++++++++++++++++ source/game/scenes/game_scene.hpp | 7 ++++++ 2 files changed, 44 insertions(+) diff --git a/source/game/scenes/game_scene.cpp b/source/game/scenes/game_scene.cpp index 22deca0..2d807bb 100644 --- a/source/game/scenes/game_scene.cpp +++ b/source/game/scenes/game_scene.cpp @@ -16,6 +16,7 @@ #include "core/input/global_inputs.hpp" #include "core/input/key_config.hpp" #include "core/locale/locale.hpp" +#include "core/rendering/lighting.hpp" #include "core/rendering/notifier.hpp" #include "core/rendering/render_info.hpp" #include "core/rendering/screen.hpp" @@ -1005,6 +1006,36 @@ void GameScene::updateRoomTransition(int delta_ms) { } } +void GameScene::applyLightingPass() { + // Atajo: si la sala està totalment il·luminada i ningú emet, + // `Lighting::apply` ja s'autosalta amb les mateixes condicions. + // Recollim igualment perquè el cas comú durant el desenvolupament + // serà tocar `Map::light_level` per sales concretes. + std::vector emitters; + emitters.reserve(players_.size() + entity_manager_.entityCount()); + const int PLAYER_R = Player::getLightRadius(); + // Quan el YAML del jugador no declara `light:`, `PLAYER_R` és 0 i + // `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). + 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}); + } + for (const auto* e : entity_manager_.getEntities()) { + const int R = e->getLightRadius(); + if (R <= 0) { continue; } + const auto C = e->getLightCenter(); + emitters.push_back({.cx = C.x, .cy = C.y, .radius = R}); + } + Lighting::apply(Screen::get().getCanvasArgb(), + Screen::get().getCanvasWidth(), + Screen::get().getCanvasHeight(), + Map::light_level, + emitters); +} + void GameScene::renderRoomFade() { // Delegació als FadeToBlack: les durades, la direcció i el progrés // viuen dins de cada instància. Comportament: @@ -1708,6 +1739,12 @@ void GameScene::render() { } } + // Pasada d'il·luminació: oscureix el canvas segons `Map::light_level` + // i hi obre cercles brillants al voltant dels emissors (jugadors, + // antorxes, mòmies, ...). Va abans del fade i del HUD perquè el + // fade pinta negre encima i la UI ha de quedar llegible. + applyLightingPass(); + // Fade del món: pintat ENTRE actors i HUD perquè el marcador, les // notificacions i el service menu queden per damunt sense afectar-se. // Inactiu si l'estat és PLAYING. diff --git a/source/game/scenes/game_scene.hpp b/source/game/scenes/game_scene.hpp index c137899..602ad73 100644 --- a/source/game/scenes/game_scene.hpp +++ b/source/game/scenes/game_scene.hpp @@ -271,6 +271,13 @@ class GameScene : public Scene { void renderRoomFade(); void renderRoomText(); + // Pasada d'il·luminació CPU sobre el canvas, entre els actors i el + // HUD: recull els emissors actius (jugadors + entitats amb + // `light_radius>0`) i aplica el gradient amb `Map::light_level` + // com a llum de sala. El HUD/notificacions queden fora de la + // multiplicació perquè es pinten després. + void applyLightingPass(); + // Configuració, estat i transició de la sub-FSM de game over // (CONTINUE? + GAME OVER). Lligada al mateix `game.yaml` que la // RoomFsm via `GameOverFsm::loadConfig`.