From b7a703c790487b4bd93bd01df87aca450b631c58 Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Fri, 8 Dec 2023 01:43:51 +0300 Subject: [PATCH 1/4] Make speed of fade-in & fade-out animations for AI-controlled heroes dependent on the AI speed setting --- src/fheroes2/ai/ai_hero_action.cpp | 30 +++++++----- src/fheroes2/game/game_delays.cpp | 8 +++- src/fheroes2/game/game_delays.h | 7 ++- src/fheroes2/game/game_startgame.cpp | 4 +- src/fheroes2/heroes/heroes.h | 19 +++++++- src/fheroes2/heroes/heroes_move.cpp | 72 ++++++++++++++-------------- 6 files changed, 83 insertions(+), 57 deletions(-) diff --git a/src/fheroes2/ai/ai_hero_action.cpp b/src/fheroes2/ai/ai_hero_action.cpp index c7a74f8a4f4..7a33e2e81a8 100644 --- a/src/fheroes2/ai/ai_hero_action.cpp +++ b/src/fheroes2/ai/ai_hero_action.cpp @@ -254,7 +254,7 @@ namespace if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { Interface::AdventureMap::Get().getGameArea().SetCenter( hero.GetCenter() ); - hero.FadeOut(); + hero.FadeOut( Game::AIHeroAnimSpeedMultiplier() ); } hero.Scout( targetIndex ); @@ -264,7 +264,7 @@ namespace if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { Interface::AdventureMap::Get().getGameArea().SetCenter( hero.GetCenter() ); - hero.FadeIn(); + hero.FadeIn( Game::AIHeroAnimSpeedMultiplier() ); } AI::Get().HeroesActionComplete( hero, targetIndex, hero.getObjectTypeUnderHero() ); @@ -283,8 +283,12 @@ namespace if ( playSound ) { AudioManager::PlaySound( M82::KILLFADE ); + + hero.FadeOut(); + } + else { + hero.FadeOut( Game::AIHeroAnimSpeedMultiplier() ); } - hero.FadeOut(); } hero.Dismiss( reason ); @@ -847,7 +851,7 @@ namespace if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { // AI-controlled hero cannot activate Stone Liths from the same tile, but should move to this tile from some // other tile first, so there is no need to re-center the game area on the hero before his disappearance - hero.FadeOut(); + hero.FadeOut( Game::AIHeroAnimSpeedMultiplier() ); } hero.Scout( indexTo ); @@ -856,7 +860,7 @@ namespace if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { Interface::AdventureMap::Get().getGameArea().SetCenter( hero.GetCenter() ); - hero.FadeIn(); + hero.FadeIn( Game::AIHeroAnimSpeedMultiplier() ); } hero.ActionNewPosition( false ); @@ -912,7 +916,7 @@ namespace if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { // AI-controlled hero cannot activate Whirlpool from the same tile, but should move to this tile from some // other tile first, so there is no need to re-center the game area on the hero before his disappearance - hero.FadeOut(); + hero.FadeOut( Game::AIHeroAnimSpeedMultiplier() ); } hero.Scout( indexTo ); @@ -923,7 +927,7 @@ namespace if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { Interface::AdventureMap::Get().getGameArea().SetCenter( hero.GetCenter() ); - hero.FadeIn(); + hero.FadeIn( Game::AIHeroAnimSpeedMultiplier() ); } hero.ActionNewPosition( false ); @@ -1573,7 +1577,7 @@ namespace if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { Interface::AdventureMap::Get().getGameArea().SetCenter( hero.GetCenter() ); - hero.FadeOut( offset ); + hero.FadeOut( Game::AIHeroAnimSpeedMultiplier(), offset ); } hero.Scout( dst_index ); @@ -1616,7 +1620,7 @@ namespace if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { Interface::AdventureMap::Get().getGameArea().SetCenter( prevPos ); - hero.FadeIn( offset ); + hero.FadeIn( Game::AIHeroAnimSpeedMultiplier(), offset ); } hero.ActionNewPosition( true ); @@ -2057,7 +2061,7 @@ namespace AI bool resetHeroSprite = false; if ( heroAnimationFrameCount > 0 ) { - const int32_t heroMovementSkipValue = Game::AIHeroAnimSkip(); + const int32_t heroMovementSkipValue = Game::AIHeroAnimSpeedMultiplier(); gameArea.ShiftCenter( { heroAnimationOffset.x * heroMovementSkipValue, heroAnimationOffset.y * heroMovementSkipValue } ); gameArea.SetRedraw(); @@ -2087,7 +2091,7 @@ namespace AI else { const fheroes2::Point movement( hero.MovementDirection() ); if ( movement != fheroes2::Point() ) { // don't waste resources for no movement - const int32_t heroMovementSkipValue = Game::AIHeroAnimSkip(); + const int32_t heroMovementSkipValue = Game::AIHeroAnimSpeedMultiplier(); heroAnimationOffset = movement; gameArea.ShiftCenter( movement ); @@ -2136,7 +2140,7 @@ namespace AI if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { Interface::AdventureMap::Get().getGameArea().SetCenter( hero.GetCenter() ); - hero.FadeOut(); + hero.FadeOut( Game::AIHeroAnimSpeedMultiplier() ); } hero.Scout( targetIndex ); @@ -2147,7 +2151,7 @@ namespace AI if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { Interface::AdventureMap::Get().getGameArea().SetCenter( hero.GetCenter() ); - hero.FadeIn(); + hero.FadeIn( Game::AIHeroAnimSpeedMultiplier() ); } hero.ActionNewPosition( false ); diff --git a/src/fheroes2/game/game_delays.cpp b/src/fheroes2/game/game_delays.cpp index cafa72a5e46..1cc0b605f3a 100644 --- a/src/fheroes2/game/game_delays.cpp +++ b/src/fheroes2/game/game_delays.cpp @@ -204,13 +204,17 @@ void Game::UpdateGameSpeed() delays[BATTLE_FLAGS_DELAY].setDelay( static_cast( 250 * adjustedIdleAnimationSpeed ) ); } -int Game::HumanHeroAnimSkip() +int Game::HumanHeroAnimSpeedMultiplier() { + assert( humanHeroMultiplier > 0 ); + return humanHeroMultiplier; } -int Game::AIHeroAnimSkip() +int Game::AIHeroAnimSpeedMultiplier() { + assert( aiHeroMultiplier > 0 ); + return aiHeroMultiplier; } diff --git a/src/fheroes2/game/game_delays.h b/src/fheroes2/game/game_delays.h index 6fd49dfee7a..937d73ee6c8 100644 --- a/src/fheroes2/game/game_delays.h +++ b/src/fheroes2/game/game_delays.h @@ -86,8 +86,11 @@ namespace Game uint32_t ApplyBattleSpeed( uint32_t delay ); - int HumanHeroAnimSkip(); - int AIHeroAnimSkip(); + // Returns the animation speed multiplier for a human-controlled hero. + int HumanHeroAnimSpeedMultiplier(); + + // Returns the animation speed multiplier for an AI-controlled hero. + int AIHeroAnimSpeedMultiplier(); // Returns true if every of delay type has passed. bool hasEveryDelayPassed( const std::vector & delayTypes ); diff --git a/src/fheroes2/game/game_startgame.cpp b/src/fheroes2/game/game_startgame.cpp index c0daccfd49a..9c2c8f5c23a 100644 --- a/src/fheroes2/game/game_startgame.cpp +++ b/src/fheroes2/game/game_startgame.cpp @@ -1233,7 +1233,7 @@ fheroes2::GameMode Interface::AdventureMap::HumanTurn( const bool isload ) if ( hero ) { bool resetHeroSprite = false; if ( heroAnimationFrameCount > 0 ) { - const int32_t heroMovementSkipValue = Game::HumanHeroAnimSkip(); + const int32_t heroMovementSkipValue = Game::HumanHeroAnimSpeedMultiplier(); _gameArea.ShiftCenter( { heroAnimationOffset.x * heroMovementSkipValue, heroAnimationOffset.y * heroMovementSkipValue } ); _gameArea.SetRedraw(); @@ -1279,7 +1279,7 @@ fheroes2::GameMode Interface::AdventureMap::HumanTurn( const bool isload ) // Do not generate a frame as we are going to do it later. Interface::AdventureMap::RedrawLocker redrawLocker( Interface::AdventureMap::Get() ); - const int32_t heroMovementSkipValue = Game::HumanHeroAnimSkip(); + const int32_t heroMovementSkipValue = Game::HumanHeroAnimSpeedMultiplier(); heroAnimationOffset = movement; _gameArea.ShiftCenter( movement ); diff --git a/src/fheroes2/heroes/heroes.h b/src/fheroes2/heroes/heroes.h index 48f9741bfb4..8670407412b 100644 --- a/src/fheroes2/heroes/heroes.h +++ b/src/fheroes2/heroes/heroes.h @@ -524,8 +524,23 @@ class Heroes final : public HeroBase, public ColorBase fheroes2::Point getCurrentPixelOffset() const; - void FadeOut( const fheroes2::Point & offset = fheroes2::Point() ) const; - void FadeIn( const fheroes2::Point & offset = fheroes2::Point() ) const; + // Performs the fade-out animation for the hero with the given speed multiplier and an optional offset + void FadeOut( const int animSpeedMultiplier, const fheroes2::Point & offset = fheroes2::Point() ) const; + + // Performs the fade-in animation for the hero with the given speed multiplier and an optional offset + void FadeIn( const int animSpeedMultiplier, const fheroes2::Point & offset = fheroes2::Point() ) const; + + // Performs the fade-out animation for the hero with an optional offset at the slowest speed + void FadeOut( const fheroes2::Point & offset = fheroes2::Point() ) const + { + FadeOut( 1, offset ); + } + + // Performs the fade-in animation for the hero with an optional offset at the slowest speed + void FadeIn( const fheroes2::Point & offset = fheroes2::Point() ) const + { + FadeIn( 1, offset ); + } void Scout( const int tileIndex ) const; int GetScoutingDistance() const; diff --git a/src/fheroes2/heroes/heroes_move.cpp b/src/fheroes2/heroes/heroes_move.cpp index 533ae470526..02b30823944 100644 --- a/src/fheroes2/heroes/heroes_move.cpp +++ b/src/fheroes2/heroes/heroes_move.cpp @@ -483,71 +483,71 @@ fheroes2::Point Heroes::getCurrentPixelOffset() const return realOffset; } -void Heroes::FadeOut( const fheroes2::Point & offset ) const +void Heroes::FadeOut( const int animSpeedMultiplier, const fheroes2::Point & offset /* = fheroes2::Point() */ ) const { - if ( !isInVisibleMapArea() ) + assert( animSpeedMultiplier > 0 ); + + if ( !isInVisibleMapArea() ) { return; + } Interface::AdventureMap & iface = Interface::AdventureMap::Get(); Interface::GameArea & gamearea = iface.getGameArea(); - int multiplier = std::max( offset.x < 0 ? -offset.x : offset.x, offset.y < 0 ? -offset.y : offset.y ); - if ( multiplier < 1 ) - multiplier = 1; - - const bool offsetScreen = offset.x != 0 || offset.y != 0; - fheroes2::Display & display = fheroes2::Display::instance(); LocalEvent & le = LocalEvent::Get(); - _alphaValue = 255 - 8 * multiplier; - const std::vector delayTypes = { Game::HEROES_FADE_DELAY }; - while ( le.HandleEvents( Game::isDelayNeeded( delayTypes ) ) && _alphaValue > 0 ) { - if ( Game::validateAnimationDelay( Game::HEROES_FADE_DELAY ) ) { - if ( offsetScreen ) { - gamearea.ShiftCenter( offset ); - } + _alphaValue = 255 - 8 * animSpeedMultiplier; - iface.redraw( Interface::REDRAW_GAMEAREA ); + while ( le.HandleEvents( Game::isDelayNeeded( { Game::HEROES_FADE_DELAY } ) ) && _alphaValue > 0 ) { + if ( !Game::validateAnimationDelay( Game::HEROES_FADE_DELAY ) ) { + continue; + } - display.render(); - _alphaValue -= 8 * multiplier; + if ( offset.x != 0 || offset.y != 0 ) { + gamearea.ShiftCenter( offset ); } + + iface.redraw( Interface::REDRAW_GAMEAREA ); + + display.render(); + + _alphaValue -= 8 * animSpeedMultiplier; } _alphaValue = 255; } -void Heroes::FadeIn( const fheroes2::Point & offset ) const +void Heroes::FadeIn( const int animSpeedMultiplier, const fheroes2::Point & offset /* = fheroes2::Point() */ ) const { - if ( !isInVisibleMapArea() ) + assert( animSpeedMultiplier > 0 ); + + if ( !isInVisibleMapArea() ) { return; + } Interface::AdventureMap & iface = Interface::AdventureMap::Get(); Interface::GameArea & gamearea = iface.getGameArea(); - int multiplier = std::max( offset.x < 0 ? -offset.x : offset.x, offset.y < 0 ? -offset.y : offset.y ); - if ( multiplier < 1 ) - multiplier = 1; - - const bool offsetScreen = offset.x != 0 || offset.y != 0; - fheroes2::Display & display = fheroes2::Display::instance(); LocalEvent & le = LocalEvent::Get(); - _alphaValue = 8 * multiplier; - const std::vector delayTypes = { Game::HEROES_FADE_DELAY }; - while ( le.HandleEvents( Game::isDelayNeeded( delayTypes ) ) && _alphaValue < 250 ) { - if ( Game::validateAnimationDelay( Game::HEROES_FADE_DELAY ) ) { - if ( offsetScreen ) { - gamearea.ShiftCenter( offset ); - } + _alphaValue = 8 * animSpeedMultiplier; - iface.redraw( Interface::REDRAW_GAMEAREA ); + while ( le.HandleEvents( Game::isDelayNeeded( { Game::HEROES_FADE_DELAY } ) ) && _alphaValue < 255 ) { + if ( !Game::validateAnimationDelay( Game::HEROES_FADE_DELAY ) ) { + continue; + } - display.render(); - _alphaValue += 8 * multiplier; + if ( offset.x != 0 || offset.y != 0 ) { + gamearea.ShiftCenter( offset ); } + + iface.redraw( Interface::REDRAW_GAMEAREA ); + + display.render(); + + _alphaValue += 8 * animSpeedMultiplier; } _alphaValue = 255; From f88e72d86d6aaa9fca99f5c61ad06be63f41c17b Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Fri, 8 Dec 2023 02:12:53 +0300 Subject: [PATCH 2/4] Paraphrase the comment --- src/fheroes2/heroes/heroes.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fheroes2/heroes/heroes.h b/src/fheroes2/heroes/heroes.h index 8670407412b..412267f0d04 100644 --- a/src/fheroes2/heroes/heroes.h +++ b/src/fheroes2/heroes/heroes.h @@ -530,13 +530,13 @@ class Heroes final : public HeroBase, public ColorBase // Performs the fade-in animation for the hero with the given speed multiplier and an optional offset void FadeIn( const int animSpeedMultiplier, const fheroes2::Point & offset = fheroes2::Point() ) const; - // Performs the fade-out animation for the hero with an optional offset at the slowest speed + // Performs the fade-out animation for the hero with an optional offset at the lowest possible speed void FadeOut( const fheroes2::Point & offset = fheroes2::Point() ) const { FadeOut( 1, offset ); } - // Performs the fade-in animation for the hero with an optional offset at the slowest speed + // Performs the fade-in animation for the hero with an optional offset at the lowest possible speed void FadeIn( const fheroes2::Point & offset = fheroes2::Point() ) const { FadeIn( 1, offset ); From b602c6116fe317c4c1721159311da336e81b3075 Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Fri, 8 Dec 2023 11:51:35 +0300 Subject: [PATCH 3/4] Make logic more clear --- src/fheroes2/heroes/heroes_move.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/fheroes2/heroes/heroes_move.cpp b/src/fheroes2/heroes/heroes_move.cpp index 02b30823944..1753c421c5b 100644 --- a/src/fheroes2/heroes/heroes_move.cpp +++ b/src/fheroes2/heroes/heroes_move.cpp @@ -497,7 +497,7 @@ void Heroes::FadeOut( const int animSpeedMultiplier, const fheroes2::Point & off fheroes2::Display & display = fheroes2::Display::instance(); LocalEvent & le = LocalEvent::Get(); - _alphaValue = 255 - 8 * animSpeedMultiplier; + _alphaValue = 255; while ( le.HandleEvents( Game::isDelayNeeded( { Game::HEROES_FADE_DELAY } ) ) && _alphaValue > 0 ) { if ( !Game::validateAnimationDelay( Game::HEROES_FADE_DELAY ) ) { @@ -508,11 +508,11 @@ void Heroes::FadeOut( const int animSpeedMultiplier, const fheroes2::Point & off gamearea.ShiftCenter( offset ); } + _alphaValue = std::max( 0, _alphaValue - 8 * animSpeedMultiplier ); + iface.redraw( Interface::REDRAW_GAMEAREA ); display.render(); - - _alphaValue -= 8 * animSpeedMultiplier; } _alphaValue = 255; @@ -532,7 +532,7 @@ void Heroes::FadeIn( const int animSpeedMultiplier, const fheroes2::Point & offs fheroes2::Display & display = fheroes2::Display::instance(); LocalEvent & le = LocalEvent::Get(); - _alphaValue = 8 * animSpeedMultiplier; + _alphaValue = 0; while ( le.HandleEvents( Game::isDelayNeeded( { Game::HEROES_FADE_DELAY } ) ) && _alphaValue < 255 ) { if ( !Game::validateAnimationDelay( Game::HEROES_FADE_DELAY ) ) { @@ -543,11 +543,11 @@ void Heroes::FadeIn( const int animSpeedMultiplier, const fheroes2::Point & offs gamearea.ShiftCenter( offset ); } + _alphaValue = std::min( _alphaValue + 8 * animSpeedMultiplier, 255 ); + iface.redraw( Interface::REDRAW_GAMEAREA ); display.render(); - - _alphaValue += 8 * animSpeedMultiplier; } _alphaValue = 255; From ad05628b48ec77343cb6f2c93926df7e091d3ed2 Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Fri, 8 Dec 2023 12:12:59 +0300 Subject: [PATCH 4/4] Paraphrase the comments a bit --- src/fheroes2/heroes/heroes.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fheroes2/heroes/heroes.h b/src/fheroes2/heroes/heroes.h index 412267f0d04..628d8fcbeaf 100644 --- a/src/fheroes2/heroes/heroes.h +++ b/src/fheroes2/heroes/heroes.h @@ -524,19 +524,19 @@ class Heroes final : public HeroBase, public ColorBase fheroes2::Point getCurrentPixelOffset() const; - // Performs the fade-out animation for the hero with the given speed multiplier and an optional offset + // Performs a hero fade-out animation with the given speed multiplier and an optional offset void FadeOut( const int animSpeedMultiplier, const fheroes2::Point & offset = fheroes2::Point() ) const; - // Performs the fade-in animation for the hero with the given speed multiplier and an optional offset + // Performs a hero fade-in animation with the given speed multiplier and an optional offset void FadeIn( const int animSpeedMultiplier, const fheroes2::Point & offset = fheroes2::Point() ) const; - // Performs the fade-out animation for the hero with an optional offset at the lowest possible speed + // Performs a hero fade-out animation with an optional offset at the lowest possible speed void FadeOut( const fheroes2::Point & offset = fheroes2::Point() ) const { FadeOut( 1, offset ); } - // Performs the fade-in animation for the hero with an optional offset at the lowest possible speed + // Performs a hero fade-in animation with an optional offset at the lowest possible speed void FadeIn( const fheroes2::Point & offset = fheroes2::Point() ) const { FadeIn( 1, offset );