Skip to content

Conversation

@bobtista
Copy link

@bobtista bobtista commented Jan 4, 2026

Summary

  • Credits screen scrolling now uses wall-clock time instead of frame counting
  • Credits scroll at consistent speed regardless of frame rate

Changes

  • Replaced m_framesSinceStarted frame counter with m_lastScrollTime timestamp
  • Uses timeGetTime() to measure elapsed time between scroll updates
  • Converts original frame-based interval to milliseconds (1 frame = 33ms at 30fps)

Test plan

  • Verify credits scroll at the same speed at 30fps and higher frame rates
  • Verify credits still scroll smoothly without stuttering

30FPS
https://github.com/user-attachments/assets/0215fd82-49f7-4c7c-9903-c8b0f53eb239

60FPS
https://github.com/user-attachments/assets/a45a847b-1f9d-4642-8ab3-23e30de25c04

@bobtista bobtista force-pushed the bobtista/fix-credits-scroll-timing branch 2 times, most recently from aa81f5a to 7fa2519 Compare January 4, 2026 06:21
// TheSuperHackers @tweak Credits scroll timing is now decoupled from the render update.
const UnsignedInt scrollIntervalMs = static_cast<UnsignedInt>(m_scrollRatePerFrames * MSEC_PER_LOGICFRAME_REAL);
const UnsignedInt now = timeGetTime();
if (now - m_lastScrollTime < scrollIntervalMs)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this approach because it is inaccurate. Scrolling should be specified as scroll distance per second and then scale each frame by the render frame rate. Probably better to have a start time, then take new time, calculate position offset, check if position has reached new integer, then continue update, otherwise wait next update and fractional move.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New code looks promising. Does it work?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works for me :) Took me a minute to figure out how to use the On Screen Keyboard to get at the numpad keys 😆 and that they don't work while the snipping tool is recording for me. Once I got the FPS up and then started recording it seems as smooth on my machine at either framerate, and it maxed out at 70 something, it's old.

@bobtista bobtista force-pushed the bobtista/fix-credits-scroll-timing branch from 5a98add to 7d49889 Compare January 30, 2026 03:14
@greptile-apps
Copy link

greptile-apps bot commented Jan 30, 2026

Greptile Overview

Greptile Summary

Replaced frame-based scrolling with wall-clock time-based scrolling to ensure consistent credits scroll speed regardless of frame rate.

Key changes:

  • Replaced m_framesSinceStarted frame counter with m_scrollStartTime timestamp and m_lastScrollPixels cumulative tracker
  • Calculates expected scroll position using timeGetTime() and elapsed milliseconds
  • Implements catch-up behavior that prevents slowdown during frame drops
  • Converts original frame-based interval to milliseconds using MSEC_PER_LOGICFRAME_REAL (33.33ms at 30fps)
  • Identical changes replicated across both Generals/ and GeneralsMD/ directories

Analysis:
The implementation correctly calculates scroll speed as pixels per millisecond, then determines the expected scroll position based on elapsed time. The difference between expected and last scroll position determines how many pixels to move this frame, enabling smooth catch-up after frame drops without cumulative drift. The approach is mathematically sound and consistent with the codebase's existing time measurement patterns.

Confidence Score: 5/5

  • This PR is safe to merge with no issues found
  • The timing logic is mathematically correct, properly handles frame drops with catch-up behavior, follows existing codebase patterns for time measurement, maintains code style consistency, and has been tested at both 30fps and 60fps as shown in the test plan
  • No files require special attention

Important Files Changed

Filename Overview
Generals/Code/GameEngine/Source/GameClient/Credits.cpp Implemented time-based scrolling with catch-up logic for frame drops
GeneralsMD/Code/GameEngine/Source/GameClient/Credits.cpp Implemented time-based scrolling with catch-up logic for frame drops

Sequence Diagram

sequenceDiagram
    participant GameLoop
    participant CreditsManager
    participant timeGetTime

    Note over CreditsManager: init() or reset() called
    CreditsManager->>timeGetTime: timeGetTime()
    timeGetTime-->>CreditsManager: startTime
    Note over CreditsManager: m_scrollStartTime = startTime<br/>m_lastScrollPixels = 0

    loop Every frame
        GameLoop->>CreditsManager: update()
        
        alt m_isFinished
            CreditsManager-->>GameLoop: return early
        else not finished
            CreditsManager->>timeGetTime: timeGetTime()
            timeGetTime-->>CreditsManager: now
            
            Note over CreditsManager: elapsedMs = now - m_scrollStartTime<br/>scrollSpeedPixelsPerMs = m_scrollRate / (m_scrollRatePerFrames * 33.33ms)<br/>expectedScrollPixels = elapsedMs * scrollSpeedPixelsPerMs<br/>pixelsToMove = expectedScrollPixels - m_lastScrollPixels
            
            alt pixelsToMove < 1
                CreditsManager-->>GameLoop: return (no scroll needed)
            else pixelsToMove >= 1
                Note over CreditsManager: m_lastScrollPixels = expectedScrollPixels
                
                loop For each displayed credit line
                    Note over CreditsManager: Update position:<br/>pos.y += pixelsToMove * directionMultiplier
                end
                
                CreditsManager-->>GameLoop: credits scrolled
            end
        end
    end
Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants