Skip to content

Commit 8a26472

Browse files
authored
tweak(scrolling): Prevent far camera jumps when scrolling while the game stalls (#1661)
1 parent 972240b commit 8a26472

File tree

8 files changed

+20
-10
lines changed

8 files changed

+20
-10
lines changed

Core/GameEngine/Include/Common/FramePacer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class FramePacer
4949

5050
Real getUpdateTime() const; ///< Get the last update delta time in seconds.
5151
Real getUpdateFps() const; ///< Get the last update fps.
52+
Real getBaseOverUpdateFpsRatio(Real minUpdateFps = 5.0f); ///< Get the last engine base over update fps ratio. Used to scale user inputs to a frame rate independent speed.
5253

5354
void setTimeFrozen(Bool frozen); ///< Set time frozen. Allows scripted camera movement.
5455
void setGameHalted(Bool halted); ///< Set game halted. Does not allow scripted camera movement.

Core/GameEngine/Source/Common/FramePacer.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,13 @@ Real FramePacer::getUpdateFps() const
118118
return 1.0f / m_updateTime;
119119
}
120120

121+
Real FramePacer::getBaseOverUpdateFpsRatio(Real minUpdateFps)
122+
{
123+
// Update fps is floored to default 5 fps, 200 ms.
124+
// Useful to prevent insane ratios on frame spikes/stalls.
125+
return (Real)BaseFps / std::max(getUpdateFps(), minUpdateFps);
126+
}
127+
121128
void FramePacer::setTimeFrozen(Bool frozen)
122129
{
123130
m_isTimeFrozen = frozen;

Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
////////////////////////////////////////////////////////////////////////////////
2424

2525
// InGameUI.cpp ///////////////////////////////////////////////////////////////////////////////////
26-
// Implementation of in-game user interface singleton inteface
26+
// Implementation of in-game user interface singleton
2727
// Author: Michael S. Booth, March 2001
2828
///////////////////////////////////////////////////////////////////////////////////////////////////
2929

@@ -1939,7 +1939,7 @@ void InGameUI::update( void )
19391939
if (m_cameraRotatingLeft || m_cameraRotatingRight || m_cameraZoomingIn || m_cameraZoomingOut)
19401940
{
19411941
// TheSuperHackers @tweak The camera rotation and zoom are now decoupled from the render update.
1942-
const Real fpsRatio = (Real)BaseFps / TheFramePacer->getUpdateFps();
1942+
const Real fpsRatio = TheFramePacer->getBaseOverUpdateFpsRatio();
19431943
const Real rotateAngle = TheGlobalData->m_keyboardCameraRotateSpeed * fpsRatio;
19441944
const Real zoomHeight = (Real)View::ZoomHeightPerSecond * fpsRatio;
19451945

Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
#include "Common/FramePacer.h"
3232
#include "Common/GameType.h"
33+
#include "Common/GameEngine.h"
3334
#include "Common/MessageStream.h"
3435
#include "Common/Player.h"
3536
#include "Common/PlayerList.h"
@@ -440,7 +441,7 @@ GameMessageDisposition LookAtTranslator::translateGameMessage(const GameMessage
440441
{
441442

442443
// TheSuperHackers @bugfix Mauller 07/06/2025 The camera scrolling is now decoupled from the render update.
443-
const Real fpsRatio = (Real)BaseFps / TheFramePacer->getUpdateFps();
444+
const Real fpsRatio = TheFramePacer->getBaseOverUpdateFpsRatio();
444445

445446
switch (m_scrollType)
446447
{

Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DView.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,7 +1207,7 @@ void W3DView::update(void)
12071207
// if scrolling, only adjust if we're too close or too far
12081208
if (m_scrollAmount.length() < m_scrollAmountCutoff || (m_currentHeightAboveGround < m_minHeightAboveGround) || (TheGlobalData->m_enforceMaxCameraHeight && m_currentHeightAboveGround > m_maxHeightAboveGround))
12091209
{
1210-
const Real fpsRatio = (Real)BaseFps / TheFramePacer->getUpdateFps();
1210+
const Real fpsRatio = TheFramePacer->getBaseOverUpdateFpsRatio();
12111211
const Real zoomAdj = (desiredZoom - m_zoom) * TheGlobalData->m_cameraAdjustSpeed * fpsRatio;
12121212
if (fabs(zoomAdj) >= 0.0001f) // only do positive
12131213
{
@@ -1219,7 +1219,7 @@ void W3DView::update(void)
12191219
else if (!didScriptedMovement)
12201220
{
12211221
// we're not scrolling; settle toward desired height above ground
1222-
const Real fpsRatio = (Real)BaseFps / TheFramePacer->getUpdateFps();
1222+
const Real fpsRatio = TheFramePacer->getBaseOverUpdateFpsRatio();
12231223
const Real zoomAdj = (m_zoom - desiredZoom) * TheGlobalData->m_cameraAdjustSpeed * fpsRatio;
12241224
if (fabs(zoomAdj) >= 0.0001f)
12251225
{

GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
////////////////////////////////////////////////////////////////////////////////
2424

2525
// InGameUI.cpp ///////////////////////////////////////////////////////////////////////////////////
26-
// Implementation of in-game user interface singleton inteface
26+
// Implementation of in-game user interface singleton
2727
// Author: Michael S. Booth, March 2001
2828
///////////////////////////////////////////////////////////////////////////////////////////////////
2929

@@ -1995,7 +1995,7 @@ void InGameUI::update( void )
19951995
if (m_cameraRotatingLeft || m_cameraRotatingRight || m_cameraZoomingIn || m_cameraZoomingOut)
19961996
{
19971997
// TheSuperHackers @tweak The camera rotation and zoom are now decoupled from the render update.
1998-
const Real fpsRatio = (Real)BaseFps / TheFramePacer->getUpdateFps();
1998+
const Real fpsRatio = TheFramePacer->getBaseOverUpdateFpsRatio();
19991999
const Real rotateAngle = TheGlobalData->m_keyboardCameraRotateSpeed * fpsRatio;
20002000
const Real zoomHeight = (Real)View::ZoomHeightPerSecond * fpsRatio;
20012001

GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
#include "Common/FramePacer.h"
3232
#include "Common/GameType.h"
33+
#include "Common/GameEngine.h"
3334
#include "Common/MessageStream.h"
3435
#include "Common/Player.h"
3536
#include "Common/PlayerList.h"
@@ -439,7 +440,7 @@ GameMessageDisposition LookAtTranslator::translateGameMessage(const GameMessage
439440
{
440441

441442
// TheSuperHackers @bugfix Mauller 07/06/2025 The camera scrolling is now decoupled from the render update.
442-
const Real fpsRatio = (Real)BaseFps / TheFramePacer->getUpdateFps();
443+
const Real fpsRatio = TheFramePacer->getBaseOverUpdateFpsRatio();
443444

444445
switch (m_scrollType)
445446
{

GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DView.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,7 +1356,7 @@ void W3DView::update(void)
13561356
// if scrolling, only adjust if we're too close or too far
13571357
if (m_scrollAmount.length() < m_scrollAmountCutoff || (m_currentHeightAboveGround < m_minHeightAboveGround) || (TheGlobalData->m_enforceMaxCameraHeight && m_currentHeightAboveGround > m_maxHeightAboveGround))
13581358
{
1359-
const Real fpsRatio = (Real)BaseFps / TheFramePacer->getUpdateFps();
1359+
const Real fpsRatio = TheFramePacer->getBaseOverUpdateFpsRatio();
13601360
const Real zoomAdj = (desiredZoom - m_zoom) * TheGlobalData->m_cameraAdjustSpeed * fpsRatio;
13611361
if (fabs(zoomAdj) >= 0.0001f) // only do positive
13621362
{
@@ -1368,7 +1368,7 @@ void W3DView::update(void)
13681368
else if (!didScriptedMovement)
13691369
{
13701370
// we're not scrolling; settle toward desired height above ground
1371-
const Real fpsRatio = (Real)BaseFps / TheFramePacer->getUpdateFps();
1371+
const Real fpsRatio = TheFramePacer->getBaseOverUpdateFpsRatio();
13721372
const Real zoomAdj = (m_zoom - desiredZoom) * TheGlobalData->m_cameraAdjustSpeed * fpsRatio;
13731373
if (fabs(zoomAdj) >= 0.0001f)
13741374
{

0 commit comments

Comments
 (0)