From 88b1f3b0a88ccd2b5dc0322def8bce88122853d2 Mon Sep 17 00:00:00 2001 From: Nutzzz Date: Mon, 3 Oct 2022 23:22:42 -0700 Subject: [PATCH 1/3] Darken background drawing to improve player/enemy/item visibility Based on Calinou's request and WIP branch, this improves the game's accessibility by adding an option that emphasizes dynamic objects in the game. ( Issue #833 ) --- src/data/game_options.hpp | 13 +++++ src/engine/map_renderer.cpp | 40 +++++++++++-- src/engine/map_renderer.hpp | 11 ++-- src/engine/sprite_rendering_system.cpp | 55 ++++++++++++++---- src/engine/sprite_rendering_system.hpp | 15 ++++- src/engine/visual_components.hpp | 6 ++ src/frontend/user_profile.cpp | 21 +++++++ src/game_logic/entity_configuration.ipp | 6 ++ src/game_logic/game_world.cpp | 20 +++++-- src/game_logic/world_state.cpp | 1 + src/ui/options_menu.cpp | 74 ++++++++++++++++++++++++- 11 files changed, 232 insertions(+), 30 deletions(-) diff --git a/src/data/game_options.hpp b/src/data/game_options.hpp index fd3a4a0ff..a7d36be8c 100644 --- a/src/data/game_options.hpp +++ b/src/data/game_options.hpp @@ -45,6 +45,12 @@ namespace rigel::data constexpr auto ENABLE_VSYNC_DEFAULT = true; constexpr auto MUSIC_VOLUME_DEFAULT = 1.0f; constexpr auto SOUND_VOLUME_DEFAULT = 1.0f; +constexpr auto FOREGROUND_SPRITE_BRIGHTNESS_DEFAULT = 1.0f; +constexpr auto REGULAR_SPRITE_BRIGHTNESS_DEFAULT = 1.0f; +constexpr auto BACKGROUND_SPRITE_BRIGHTNESS_DEFAULT = 1.0f; +constexpr auto FOREGROUND_TILE_BRIGHTNESS_DEFAULT = 1.0f; +constexpr auto BACKGROUND_TILE_BRIGHTNESS_DEFAULT = 1.0f; +constexpr auto BACKDROP_TILE_BRIGHTNESS_DEFAULT = 1.0f; enum class WindowMode { @@ -156,6 +162,13 @@ struct GameOptions bool mQuickSavingEnabled = false; bool mSkipIntro = false; bool mMotionSmoothing = false; + float mForeSpriteBrightness = FOREGROUND_SPRITE_BRIGHTNESS_DEFAULT; + float mRegSpriteBrightness = REGULAR_SPRITE_BRIGHTNESS_DEFAULT; + float mBackSpriteBrightness = BACKGROUND_SPRITE_BRIGHTNESS_DEFAULT; + bool mPrisonerIsBackground = false; + float mForeTileBrightness = FOREGROUND_TILE_BRIGHTNESS_DEFAULT; + float mBackTileBrightness = BACKGROUND_TILE_BRIGHTNESS_DEFAULT; + float mDropTileBrightness = BACKDROP_TILE_BRIGHTNESS_DEFAULT; // Internal options // diff --git a/src/engine/map_renderer.cpp b/src/engine/map_renderer.cpp index 652982f56..e3fa6a21f 100644 --- a/src/engine/map_renderer.cpp +++ b/src/engine/map_renderer.cpp @@ -287,17 +287,39 @@ void MapRenderer::switchBackdrops() void MapRenderer::renderBackground( const base::Vec2& sectionStart, - const base::Size& sectionSize) const + const base::Size& sectionSize, + const float backColorMod) const { + if (backColorMod < 1.0f) + { + // const auto saved = renderer::saveState(mpRenderer); + mpRenderer->setColorModulation(base::Color{ + base::roundTo(255 * backColorMod), + base::roundTo(255 * backColorMod), + base::roundTo(255 * backColorMod), + 255}); + } renderMapTiles(sectionStart, sectionSize, DrawMode::Background); + mpRenderer->setColorModulation(base::Color{255, 255, 255, 255}); } void MapRenderer::renderForeground( const base::Vec2& sectionStart, - const base::Size& sectionSize) const + const base::Size& sectionSize, + const float foreColorMod) const { + if (foreColorMod < 1.0f) + { + // const auto saved = renderer::saveState(mpRenderer); + mpRenderer->setColorModulation(base::Color{ + base::roundTo(255 * foreColorMod), + base::roundTo(255 * foreColorMod), + base::roundTo(255 * foreColorMod), + 255}); + } renderMapTiles(sectionStart, sectionSize, DrawMode::Foreground); + mpRenderer->setColorModulation(base::Color{255, 255, 255, 255}); } @@ -397,14 +419,24 @@ renderer::TexCoords MapRenderer::calculateBackdropTexCoords( void MapRenderer::renderBackdrop( const base::Vec2f& cameraPosition, - const base::Size& viewportSize) const + const base::Size& viewportSize, + const float dropColorMod) const { - const auto saved = renderer::saveState(mpRenderer); + if (dropColorMod < 1.0f) + { + // const auto saved = renderer::saveState(mpRenderer); + mpRenderer->setColorModulation(base::Color{ + base::roundTo(255 * dropColorMod), + base::roundTo(255 * dropColorMod), + base::roundTo(255 * dropColorMod), + 255}); + } mpRenderer->setTextureRepeatEnabled(true); mpRenderer->drawTexture( mBackdropTexture.data(), calculateBackdropTexCoords(cameraPosition, viewportSize), {{}, data::tilesToPixels(viewportSize)}); + mpRenderer->setColorModulation(base::Color{255, 255, 255, 255}); } diff --git a/src/engine/map_renderer.hpp b/src/engine/map_renderer.hpp index 22deb207e..215bcd08c 100644 --- a/src/engine/map_renderer.hpp +++ b/src/engine/map_renderer.hpp @@ -108,13 +108,16 @@ class MapRenderer void renderBackdrop( const base::Vec2f& cameraPosition, - const base::Size& viewportSize) const; + const base::Size& viewportSize, + const float dropColorMod) const; void renderBackground( const base::Vec2& sectionStart, - const base::Size& sectionSize) const; + const base::Size& sectionSize, + const float backColorMod) const; void renderForeground( const base::Vec2& sectionStart, - const base::Size& sectionSize) const; + const base::Size& sectionSize, + const float foreColorMod) const; void updateAnimatedMapTiles(); void updateBackdropAutoScrolling(engine::TimeDelta dt); @@ -141,7 +144,7 @@ class MapRenderer void renderMapTiles( const base::Vec2& sectionStart, const base::Size& sectionSize, - DrawMode drawMode) const; + const DrawMode drawMode) const; data::map::TileIndex animatedTileIndex(data::map::TileIndex) const; private: diff --git a/src/engine/sprite_rendering_system.cpp b/src/engine/sprite_rendering_system.cpp index 01e311cad..1538c83af 100644 --- a/src/engine/sprite_rendering_system.cpp +++ b/src/engine/sprite_rendering_system.cpp @@ -79,6 +79,7 @@ void collectVisibleSprites( using components::DrawTopMost; using components::ExtendedFrameList; using components::OverrideDrawOrder; + using components::SpriteBackground; using components::SpriteStrip; const auto screenBox = BoundingBox{{}, viewportSize}; @@ -99,7 +100,8 @@ void collectVisibleSprites( const bool flashingWhite, const bool useCloakEffect, const bool drawTopmost, - const int drawOrder) { + const int drawOrder, + const bool background) { const auto topLeft = drawPosition(frame, position); // Discard sprites outside visible area @@ -115,8 +117,8 @@ void collectVisibleSprites( engine::interpolatedPixelPosition( previousTopLeft, topLeft, interpolationFactor), data::tilesToPixels(frame.mDimensions)}; - const auto drawSpec = - SpriteDrawSpec{destRect, frame.mImageId, flashingWhite, useCloakEffect}; + const auto drawSpec = SpriteDrawSpec{ + destRect, frame.mImageId, flashingWhite, useCloakEffect, background}; output.push_back({drawSpec, drawOrder, drawTopmost}); }; @@ -138,6 +140,7 @@ void collectVisibleSprites( const auto drawOrder = entity.has_component() ? entity.component()->mDrawOrder : sprite.mpDrawData->mDrawOrder; + const auto background = entity.has_component(); auto slotIndex = 0; for (const auto& baseFrameIndex : sprite.mFramesToRender) @@ -158,7 +161,8 @@ void collectVisibleSprites( sprite.mFlashingWhiteStates.test(slotIndex), sprite.mUseCloakEffect, drawTopmost, - drawOrder); + drawOrder, + background); ++slotIndex; } @@ -177,7 +181,8 @@ void collectVisibleSprites( false, sprite.mUseCloakEffect, drawTopmost, - drawOrder); + drawOrder, + background); } } @@ -210,8 +215,8 @@ void collectVisibleSprites( base::Rect{data::tilesToPixels(topLeft), {width, height}}; const auto useCloakEffect = sprite.mUseCloakEffect; - const auto drawSpec = - SpriteDrawSpec{destRect, frame.mImageId, false, useCloakEffect}; + const auto drawSpec = SpriteDrawSpec{ + destRect, frame.mImageId, false, useCloakEffect, background}; output.push_back({drawSpec, drawOrder, drawTopmost}); } }); @@ -354,29 +359,45 @@ void SpriteRenderingSystem::update( } +void SpriteRenderingSystem::renderBackgroundSprites( + const SpecialEffectsRenderer& fx, + const float backColorMod) const +{ + for (auto it = mSprites.begin(); it != miForegroundSprites; ++it) + { + if (it->mBackground) + renderSprite(*it, fx, backColorMod); + } +} + + void SpriteRenderingSystem::renderRegularSprites( - const SpecialEffectsRenderer& fx) const + const SpecialEffectsRenderer& fx, + const float regColorMod) const { for (auto it = mSprites.begin(); it != miForegroundSprites; ++it) { - renderSprite(*it, fx); + if (!(it->mBackground)) + renderSprite(*it, fx, regColorMod); } } void SpriteRenderingSystem::renderForegroundSprites( - const SpecialEffectsRenderer& fx) const + const SpecialEffectsRenderer& fx, + const float foreColorMod) const { for (auto it = miForegroundSprites; it != mSprites.end(); ++it) { - renderSprite(*it, fx); + renderSprite(*it, fx, foreColorMod); } } void SpriteRenderingSystem::renderSprite( const SpriteDrawSpec& spec, - const SpecialEffectsRenderer& fx) const + const SpecialEffectsRenderer& fx, + const float colorMod) const { // White flash takes priority over translucency if (spec.mIsFlashingWhite) @@ -393,7 +414,17 @@ void SpriteRenderingSystem::renderSprite( } else { + if (colorMod < 1.0f) + { + // const auto saved = renderer::saveState(mpRenderer); + mpRenderer->setColorModulation(base::Color{ + base::roundTo(255 * colorMod), + base::roundTo(255 * colorMod), + base::roundTo(255 * colorMod), + 255}); + } mpTextureAtlas->draw(spec.mImageId, spec.mDestRect); + mpRenderer->setColorModulation(base::Color{255, 255, 255, 255}); } } diff --git a/src/engine/sprite_rendering_system.hpp b/src/engine/sprite_rendering_system.hpp index 053ea799b..c3c62038a 100644 --- a/src/engine/sprite_rendering_system.hpp +++ b/src/engine/sprite_rendering_system.hpp @@ -57,6 +57,7 @@ struct SpriteDrawSpec int mImageId; bool mIsFlashingWhite; bool mUseCloakEffect; + bool mBackground; }; @@ -90,13 +91,21 @@ class SpriteRenderingSystem bool cloakEffectSpritesVisible() const { return mCloakEffectSpritesVisible; } - void renderRegularSprites(const SpecialEffectsRenderer& fx) const; - void renderForegroundSprites(const SpecialEffectsRenderer& fx) const; + void renderBackgroundSprites( + const SpecialEffectsRenderer& fx, + const float backColorMod) const; + void renderRegularSprites( + const SpecialEffectsRenderer& fx, + const float regColorMod) const; + void renderForegroundSprites( + const SpecialEffectsRenderer& fx, + const float foreColorMod) const; private: void renderSprite( const SpriteDrawSpec& spec, - const SpecialEffectsRenderer& fx) const; + const SpecialEffectsRenderer& fx, + const float colorMod) const; // Temporary storage used for sorting sprites by draw order during sprite // collection. Scope-wise, this is only needed during update(), but in order diff --git a/src/engine/visual_components.hpp b/src/engine/visual_components.hpp index 19ed5e95b..d854fe006 100644 --- a/src/engine/visual_components.hpp +++ b/src/engine/visual_components.hpp @@ -181,6 +181,7 @@ struct Sprite std::bitset mFlashingWhiteStates; bool mUseCloakEffect = false; bool mShow = true; + bool mBackground = false; }; @@ -203,6 +204,11 @@ struct ExtendedFrameList }; +struct SpriteBackground +{ +}; + + struct SpriteStrip { explicit SpriteStrip(const base::Vec2& start, int frame) diff --git a/src/frontend/user_profile.cpp b/src/frontend/user_profile.cpp index fc239a448..a25c1f40b 100644 --- a/src/frontend/user_profile.cpp +++ b/src/frontend/user_profile.cpp @@ -440,6 +440,13 @@ nlohmann::ordered_json serialize(const data::GameOptions& options) serialized["quickSavingEnabled"] = options.mQuickSavingEnabled; serialized["skipIntro"] = options.mSkipIntro; serialized["motionSmoothing"] = options.mMotionSmoothing; + serialized["foregroundSpriteBrightness"] = options.mForeSpriteBrightness; + serialized["regularSpriteBrightness"] = options.mRegSpriteBrightness; + serialized["backgroundSpriteBrightness"] = options.mBackSpriteBrightness; + serialized["prisonerIsBackground"] = options.mPrisonerIsBackground; + serialized["foregroundTileBrightness"] = options.mForeTileBrightness; + serialized["backgroundTileBrightness"] = options.mBackTileBrightness; + serialized["parallaxTileBrightness"] = options.mDropTileBrightness; return serialized; } @@ -661,6 +668,20 @@ data::GameOptions deserialize(const nlohmann::json& json) extractValueIfExists("quickSavingEnabled", result.mQuickSavingEnabled, json); extractValueIfExists("skipIntro", result.mSkipIntro, json); extractValueIfExists("motionSmoothing", result.mMotionSmoothing, json); + extractValueIfExists( + "foregroundSpriteBrightness", result.mForeSpriteBrightness, json); + extractValueIfExists( + "regularSpriteBrightness", result.mRegSpriteBrightness, json); + extractValueIfExists( + "backgroundSpriteBrightness", result.mBackSpriteBrightness, json); + extractValueIfExists( + "prisonerIsBackground", result.mPrisonerIsBackground, json); + extractValueIfExists( + "foregroundTileBrightness", result.mForeTileBrightness, json); + extractValueIfExists( + "backgroundTileBrightness", result.mBackTileBrightness, json); + extractValueIfExists( + "parallaxTileBrightness", result.mDropTileBrightness, json); removeInvalidKeybindings(result); diff --git a/src/game_logic/entity_configuration.ipp b/src/game_logic/entity_configuration.ipp index b3ec31cf7..f40850825 100644 --- a/src/game_logic/entity_configuration.ipp +++ b/src/game_logic/entity_configuration.ipp @@ -1669,6 +1669,8 @@ void EntityFactory::configureEntity( entity.component()->mInvincible = true; entity.component()->mDestroyWhenKilled = false; entity.assign(); + if (mpOptions->mPrisonerIsBackground) + entity.assign(); break; case ActorID::Passive_prisoner: // Monster in prison cell, passive @@ -1676,6 +1678,8 @@ void EntityFactory::configureEntity( entity.assign(boundingBox); entity.assign(ActivationSettings::Policy::Always); entity.assign(); + if (mpOptions->mPrisonerIsBackground) + entity.assign(); break; case ActorID::Rigelatin_soldier: // Rigelatin soldier @@ -1917,6 +1921,7 @@ void EntityFactory::configureEntity( case ActorID::Water_on_floor_1: // Shallow water (variant 1) case ActorID::Water_on_floor_2: // Shallow water (variant 2) entity.assign(1); + entity.assign(); break; case ActorID::Messenger_drone_1: // "Your brain is ours!" @@ -1961,6 +1966,7 @@ void EntityFactory::configureEntity( case ActorID::Flame_jet_3: // Small rocket exhaust flame left case ActorID::Flame_jet_4: // Small rocket exhaust flame right entity.assign(2); + entity.assign(); break; case ActorID::Exit_trigger: diff --git a/src/game_logic/game_world.cpp b/src/game_logic/game_world.cpp index 006c2acae..6809647a6 100644 --- a/src/game_logic/game_world.cpp +++ b/src/game_logic/game_world.cpp @@ -991,7 +991,9 @@ void GameWorld::drawMapAndSprites( else { state.mMapRenderer.renderBackdrop( - params.mInterpolatedCameraPosition, params.mViewportSize); + params.mInterpolatedCameraPosition, + params.mViewportSize, + mpOptions->mDropTileBrightness); } }; @@ -1009,18 +1011,26 @@ void GameWorld::drawMapAndSprites( auto renderBackgroundLayers = [&]() { state.mMapRenderer.renderBackground( - params.mRenderStartPosition, params.mViewportSize); + params.mRenderStartPosition, + params.mViewportSize, + mpOptions->mBackTileBrightness); state.mDynamicGeometrySystem.renderDynamicBackgroundSections( params.mRenderStartPosition, params.mViewportSize, interpolationFactor); - state.mSpriteRenderingSystem.renderRegularSprites(mSpecialEffects); + state.mSpriteRenderingSystem.renderBackgroundSprites( + mSpecialEffects, mpOptions->mBackSpriteBrightness); + state.mSpriteRenderingSystem.renderRegularSprites( + mSpecialEffects, mpOptions->mRegSpriteBrightness); }; auto renderForegroundLayers = [&]() { state.mMapRenderer.renderForeground( - params.mRenderStartPosition, params.mViewportSize); + params.mRenderStartPosition, + params.mViewportSize, + mpOptions->mForeTileBrightness); state.mDynamicGeometrySystem.renderDynamicForegroundSections( params.mRenderStartPosition, params.mViewportSize, interpolationFactor); - state.mSpriteRenderingSystem.renderForegroundSprites(mSpecialEffects); + state.mSpriteRenderingSystem.renderForegroundSprites( + mSpecialEffects, mpOptions->mForeSpriteBrightness); renderTileDebris(); }; diff --git a/src/game_logic/world_state.cpp b/src/game_logic/world_state.cpp index 472d40f4a..8b9427011 100644 --- a/src/game_logic/world_state.cpp +++ b/src/game_logic/world_state.cpp @@ -102,6 +102,7 @@ void copyAllComponents(entityx::Entity from, entityx::Entity to) copyComponentIfPresent(from, to); copyComponentIfPresent(from, to); copyComponentIfPresent(from, to); + copyComponentIfPresent(from, to); copyComponentIfPresent(from, to); copyComponentIfPresent(from, to); copyComponentIfPresent(from, to); diff --git a/src/ui/options_menu.cpp b/src/ui/options_menu.cpp index 7e2b79f96..e8bdcb080 100644 --- a/src/ui/options_menu.cpp +++ b/src/ui/options_menu.cpp @@ -381,8 +381,6 @@ void OptionsMenu::updateAndRender(engine::TimeDelta dt) ImGui::NewLine(); ImGui::Checkbox("Show FPS", &mpOptions->mShowFpsCounter); - ImGui::Checkbox( - "Enable screen flashing", &mpOptions->mEnableScreenFlashes); if (mpOptions->mUpscalingFilter == data::UpscalingFilter::PixelPerfect) { @@ -431,6 +429,78 @@ void OptionsMenu::updateAndRender(engine::TimeDelta dt) ImGui::EndTabItem(); } + if (ImGui::BeginTabItem("Visuals/Accessibility")) + { + ImGui::NewLine(); + + ImGui::Checkbox( + "Enable screen flashing", &mpOptions->mEnableScreenFlashes); + + ImGui::NewLine(); + + ImGui::SliderFloat( + "Foreground tile brightness", + &mpOptions->mForeTileBrightness, + 0.0f, + 1.0f); + ImGui::SliderFloat( + "Background tile brightness", + &mpOptions->mBackTileBrightness, + 0.0f, + 1.0f); + ImGui::SliderFloat( + "Parallax tile brightness", + &mpOptions->mDropTileBrightness, + 0.0f, + 1.0f); + + ImGui::NewLine(); + + ImGui::SliderFloat( + "Foreground sprite brightness", + &mpOptions->mForeSpriteBrightness, + 0.0f, + 1.0f); + ImGui::SliderFloat( + "Regular sprite brightness", + &mpOptions->mRegSpriteBrightness, + 0.0f, + 1.0f); + ImGui::SliderFloat( + "Background sprite brightness", + &mpOptions->mBackSpriteBrightness, + 0.0f, + 1.0f); + if (mpOptions->mBackTileBrightness != mpOptions->mBackSpriteBrightness) + { + ImGui::Spacing(); + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f)); + ImGui::TextWrapped( + "NOTE: Recommend Background sprite and Background tile brightness are equal"); + ImGui::PopStyleColor(); + } + else + { + ImGui::NewLine(); + } + ImGui::Checkbox( + "Prisoner monster is background sprite", + &mpOptions->mPrisonerIsBackground); + if ( + (!mpOptions->mPrisonerIsBackground && + mpOptions->mRegSpriteBrightness != mpOptions->mBackTileBrightness) || + (mpOptions->mPrisonerIsBackground && + mpOptions->mBackSpriteBrightness != mpOptions->mBackTileBrightness)) + { + ImGui::Spacing(); + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f)); + ImGui::TextWrapped("NOTE: Prisoner monster bar color will not match"); + ImGui::PopStyleColor(); + } + + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Sound")) { ImGui::NewLine(); From 2d6536a6f6e539b6c0768c039e09bac8f20db7e4 Mon Sep 17 00:00:00 2001 From: lethal-guitar Date: Fri, 14 Oct 2022 22:24:06 +0200 Subject: [PATCH 2/3] Also apply brightness mods to dynamic geometry --- src/engine/map_renderer.cpp | 40 +++--------------------- src/engine/map_renderer.hpp | 11 +++---- src/game_logic/game_world.cpp | 58 ++++++++++++++++++++++++++--------- 3 files changed, 51 insertions(+), 58 deletions(-) diff --git a/src/engine/map_renderer.cpp b/src/engine/map_renderer.cpp index e3fa6a21f..652982f56 100644 --- a/src/engine/map_renderer.cpp +++ b/src/engine/map_renderer.cpp @@ -287,39 +287,17 @@ void MapRenderer::switchBackdrops() void MapRenderer::renderBackground( const base::Vec2& sectionStart, - const base::Size& sectionSize, - const float backColorMod) const + const base::Size& sectionSize) const { - if (backColorMod < 1.0f) - { - // const auto saved = renderer::saveState(mpRenderer); - mpRenderer->setColorModulation(base::Color{ - base::roundTo(255 * backColorMod), - base::roundTo(255 * backColorMod), - base::roundTo(255 * backColorMod), - 255}); - } renderMapTiles(sectionStart, sectionSize, DrawMode::Background); - mpRenderer->setColorModulation(base::Color{255, 255, 255, 255}); } void MapRenderer::renderForeground( const base::Vec2& sectionStart, - const base::Size& sectionSize, - const float foreColorMod) const + const base::Size& sectionSize) const { - if (foreColorMod < 1.0f) - { - // const auto saved = renderer::saveState(mpRenderer); - mpRenderer->setColorModulation(base::Color{ - base::roundTo(255 * foreColorMod), - base::roundTo(255 * foreColorMod), - base::roundTo(255 * foreColorMod), - 255}); - } renderMapTiles(sectionStart, sectionSize, DrawMode::Foreground); - mpRenderer->setColorModulation(base::Color{255, 255, 255, 255}); } @@ -419,24 +397,14 @@ renderer::TexCoords MapRenderer::calculateBackdropTexCoords( void MapRenderer::renderBackdrop( const base::Vec2f& cameraPosition, - const base::Size& viewportSize, - const float dropColorMod) const + const base::Size& viewportSize) const { - if (dropColorMod < 1.0f) - { - // const auto saved = renderer::saveState(mpRenderer); - mpRenderer->setColorModulation(base::Color{ - base::roundTo(255 * dropColorMod), - base::roundTo(255 * dropColorMod), - base::roundTo(255 * dropColorMod), - 255}); - } + const auto saved = renderer::saveState(mpRenderer); mpRenderer->setTextureRepeatEnabled(true); mpRenderer->drawTexture( mBackdropTexture.data(), calculateBackdropTexCoords(cameraPosition, viewportSize), {{}, data::tilesToPixels(viewportSize)}); - mpRenderer->setColorModulation(base::Color{255, 255, 255, 255}); } diff --git a/src/engine/map_renderer.hpp b/src/engine/map_renderer.hpp index 215bcd08c..22deb207e 100644 --- a/src/engine/map_renderer.hpp +++ b/src/engine/map_renderer.hpp @@ -108,16 +108,13 @@ class MapRenderer void renderBackdrop( const base::Vec2f& cameraPosition, - const base::Size& viewportSize, - const float dropColorMod) const; + const base::Size& viewportSize) const; void renderBackground( const base::Vec2& sectionStart, - const base::Size& sectionSize, - const float backColorMod) const; + const base::Size& sectionSize) const; void renderForeground( const base::Vec2& sectionStart, - const base::Size& sectionSize, - const float foreColorMod) const; + const base::Size& sectionSize) const; void updateAnimatedMapTiles(); void updateBackdropAutoScrolling(engine::TimeDelta dt); @@ -144,7 +141,7 @@ class MapRenderer void renderMapTiles( const base::Vec2& sectionStart, const base::Size& sectionSize, - const DrawMode drawMode) const; + DrawMode drawMode) const; data::map::TileIndex animatedTileIndex(data::map::TileIndex) const; private: diff --git a/src/game_logic/game_world.cpp b/src/game_logic/game_world.cpp index 6809647a6..b50764b13 100644 --- a/src/game_logic/game_world.cpp +++ b/src/game_logic/game_world.cpp @@ -252,6 +252,27 @@ base::Size clampedSectionSize( std::min(sectionSize.height, map.height() - sectionStart.y)}; } + +base::ScopeGuard + applyBrightnessOption(renderer::Renderer* pRenderer, float brightness) +{ + if (brightness < 1.0f) + { + auto guard = renderer::saveState(pRenderer); + pRenderer->setColorModulation(base::Color{ + base::roundTo(255.0f * brightness), + base::roundTo(255.0f * brightness), + base::roundTo(255.0f * brightness), + 255}); + return guard; + } + else + { + return base::ScopeGuard{[]() { + }}; + } +} + } // namespace @@ -990,10 +1011,10 @@ void GameWorld::drawMapAndSprites( } else { + const auto saved = + applyBrightnessOption(mpRenderer, mpOptions->mDropTileBrightness); state.mMapRenderer.renderBackdrop( - params.mInterpolatedCameraPosition, - params.mViewportSize, - mpOptions->mDropTileBrightness); + params.mInterpolatedCameraPosition, params.mViewportSize); } }; @@ -1010,12 +1031,15 @@ void GameWorld::drawMapAndSprites( }; auto renderBackgroundLayers = [&]() { - state.mMapRenderer.renderBackground( - params.mRenderStartPosition, - params.mViewportSize, - mpOptions->mBackTileBrightness); - state.mDynamicGeometrySystem.renderDynamicBackgroundSections( - params.mRenderStartPosition, params.mViewportSize, interpolationFactor); + { + const auto saved = + applyBrightnessOption(mpRenderer, mpOptions->mBackTileBrightness); + state.mMapRenderer.renderBackground( + params.mRenderStartPosition, params.mViewportSize); + state.mDynamicGeometrySystem.renderDynamicBackgroundSections( + params.mRenderStartPosition, params.mViewportSize, interpolationFactor); + } + state.mSpriteRenderingSystem.renderBackgroundSprites( mSpecialEffects, mpOptions->mBackSpriteBrightness); state.mSpriteRenderingSystem.renderRegularSprites( @@ -1023,12 +1047,16 @@ void GameWorld::drawMapAndSprites( }; auto renderForegroundLayers = [&]() { - state.mMapRenderer.renderForeground( - params.mRenderStartPosition, - params.mViewportSize, - mpOptions->mForeTileBrightness); - state.mDynamicGeometrySystem.renderDynamicForegroundSections( - params.mRenderStartPosition, params.mViewportSize, interpolationFactor); + { + const auto saved = + applyBrightnessOption(mpRenderer, mpOptions->mForeTileBrightness); + + state.mMapRenderer.renderForeground( + params.mRenderStartPosition, params.mViewportSize); + state.mDynamicGeometrySystem.renderDynamicForegroundSections( + params.mRenderStartPosition, params.mViewportSize, interpolationFactor); + } + state.mSpriteRenderingSystem.renderForegroundSprites( mSpecialEffects, mpOptions->mForeSpriteBrightness); renderTileDebris(); From a9c794e1c6f83114be3d9fe5b7450d6769284a8a Mon Sep 17 00:00:00 2001 From: lethal-guitar Date: Sat, 15 Oct 2022 15:01:58 +0200 Subject: [PATCH 3/3] WIP Keep the prisoner's grabbing hand in the foreground --- src/engine/sprite_rendering_system.cpp | 4 +++- src/engine/visual_components.hpp | 8 +++++++- src/game_logic/entity_configuration.ipp | 9 ++++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/engine/sprite_rendering_system.cpp b/src/engine/sprite_rendering_system.cpp index 1538c83af..ee42a1cd3 100644 --- a/src/engine/sprite_rendering_system.cpp +++ b/src/engine/sprite_rendering_system.cpp @@ -162,7 +162,9 @@ void collectVisibleSprites( sprite.mUseCloakEffect, drawTopmost, drawOrder, - background); + background && + entity.component()->mRenderSlotMask.test( + slotIndex)); ++slotIndex; } diff --git a/src/engine/visual_components.hpp b/src/engine/visual_components.hpp index d854fe006..9d7ecbc4e 100644 --- a/src/engine/visual_components.hpp +++ b/src/engine/visual_components.hpp @@ -181,7 +181,6 @@ struct Sprite std::bitset mFlashingWhiteStates; bool mUseCloakEffect = false; bool mShow = true; - bool mBackground = false; }; @@ -206,6 +205,13 @@ struct ExtendedFrameList struct SpriteBackground { + SpriteBackground() + { + // Apply to all render slots by default + mRenderSlotMask.set(); + } + + std::bitset mRenderSlotMask; }; diff --git a/src/game_logic/entity_configuration.ipp b/src/game_logic/entity_configuration.ipp index f40850825..a98740322 100644 --- a/src/game_logic/entity_configuration.ipp +++ b/src/game_logic/entity_configuration.ipp @@ -1670,7 +1670,14 @@ void EntityFactory::configureEntity( entity.component()->mDestroyWhenKilled = false; entity.assign(); if (mpOptions->mPrisonerIsBackground) - entity.assign(); + { + auto background = SpriteBackground{}; + + // Keep the grabbing hand in the foreground + background.mRenderSlotMask.reset(1); + + entity.assign(background); + } break; case ActorID::Passive_prisoner: // Monster in prison cell, passive