Skip to content

[SP] Fix footstep and view bob speed depending on the frame rate - #1356

Open
Rugaliz wants to merge 1 commit into
JACoders:masterfrom
Rugaliz:sp-fix-bobcycle-truncation
Open

Rugaliz wants to merge 1 commit into
JACoders:masterfrom
Rugaliz:sp-fix-bobcycle-truncation

Conversation

@Rugaliz

@Rugaliz Rugaliz commented Oct 3, 2026

Copy link
Copy Markdown

Problem

PM_Footsteps advances the integer bobCycle with

pm->ps->bobCycle = (int)( old + bobmove * pml.msec ) & 255;

old is an int, so the fraction of bobmove * msec is dropped on every pmove step (0.3 * 6 msec = 1.8 becomes 1). The singleplayer player runs one pmove per rendered frame, so the bob cycle speed, and with it the footstep event cadence and the view/weapon bob, depends on the frame time:

frame time run (0.4) walk (0.3)
8 ms (125 fps, the default cap) -6% -17%
6 ms (144-166 fps) -17% -44%
5 ms (200 fps) exact -33%
3 ms -17% stops

Swimming (0.15) stops advancing below 7 ms per frame, so EV_SWIM is lost. Higher frame rate caps (high refresh rate displays) hit this directly.

Fix

Advance by floor( bobmove * time ) at the end of the step minus the same expression at its start. The rounding errors of consecutive steps cancel, so for a constant bobmove the cycle advances at exactly the intended rate at any frame rate, and the result does not drift. No state is added: a remainder field in playerState_t would change the save game and network formats.

Applied to both codeJK2/game/bg_pmove.cpp and code/game/bg_pmove.cpp (the two call sites each: swimming and the general case).

Behaviour change

At the default 125 fps running footsteps/bob get about 6% faster and walking about 20% faster, i.e. they now match the nominal bobmove rates; at low frame rates the change is small (e.g. 30 fps: under 2%).

Testing

  • Offline simulation of old vs new maths at 3-33 ms frame times (including uneven 6/7 ms frames): the new advance equals bobmove * 1000 per second.
  • In game (Jedi Outcast SP, kejim_base, temporary counter that was removed again): running advances 400.0 bob units per moving second at com_maxfps 60, 144 and 200.
  • JK2 and JA SP build on Linux; Windows (MinGW/clang cross) builds. JA was only build-tested, not run.

🤖 Generated with Claude Code

bobCycle is an integer and was advanced by (int)( old + bobmove * msec ), which
drops the fraction on every pmove step: 0.3 * 6 msec = 1.8 became 1. The cycle
therefore ran slow by an amount that depends on the frame time (running -6% at
125 fps, -17% at 144 fps; walking -17% at 125 fps, -44% at 144 fps; swimming
and walking stop entirely below ~7 and ~4 msec per frame), so footstep
cadence and view bob changed with the frame rate.

Advance by floor( bobmove * time ) at the end of the step minus the same at its
start instead. The rounding errors of consecutive steps cancel, so the cycle
runs at the exact rate at any frame rate without adding state to playerState_t
(which would change save games and the network format). Fixed in JK2 and JA SP.

Measured in game (running, bobmove 0.4): 400.0 per second at 60, 144 and 200 fps.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@Rugaliz
Rugaliz requested a review from a team as a code owner October 3, 2026 19:29
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.

1 participant