shinyquagsire23 / OpenJKDF2

A cross-platform reimplementation of JKDF2 in C
Other
513 stars 43 forks source link

Physics only work correctly at 30 Hz #222

Closed QmwJlHuSg9pa closed 1 year ago

QmwJlHuSg9pa commented 1 year ago

Physics are currently broken, out of the box. Currently, the only way to get correct physics is to check "Disable Physics Stepping" (OT: this should really be reversed to be "Enable ...", much less confusing), then limit the framerate to 30 FPS. This enforces correct behaviour at ~30 Hz.

This is verifiable by riding a vertical exhaust port on "The Valley Tower Ascent". Only at 30 FPS is the air flow sufficient to carry one to the next landing above. 50 or 60 FPS limit results in lackluster lift, whilst 5 FPS guarantees you'll smash your head into the ceiling.

Also, physics currently misbehave below 30 FPS, regardless of whether "Disable Physics Stepping" is enabled.

Edit: Another note about 5 FPS -- input handling is noticeably bad; button presses are too often missed -- presumably this was motivation for 150 Hz handling in the first place?

Vortikai commented 1 year ago

I can confirm this, tested The Valley Ascent with multiple air vents being too weak compared to the vanilla version of the game.

shinyquagsire23 commented 1 year ago

I think you might have misinterpreted the Disable Physics Stepping box? The default is unchecked, which will always advance the game state the same regardless of the current framerate. I've changed it to Restore Inconsistent Physics for the next release to clarify that though, the checkbox basically only exists on the off chance that speedrunners really want to keep the 50Hz physics.

The air shaft though actually ended up not being a physics issue at all; The issue was COG timing in 18_pipethrust.cog.

while (1)
     {
      SetPulse(0.25);
      dummy = PlaySoundPos(burst, SurfaceCenter(soundsurf), 1.0, 5, 40, 0);
         for (power = fullpower; power > 0; power = power - 0.025)
         {
          Sleep(0.01);
          ThingLight(dynalite0,power,0.0);
          ThingLight(dynalite1,power,0.0);
          ThingLight(dynalite2,power,0.0);
          for (index=0; index <=7; index = index +1)
             {
              SectorThrust(mainthrust0[index], vect, (power * 6));            //sector thrusts
             }

         }
      SetPulse(0.0);
      Sleep(hardness);
      }
    stop;

Because the original game had a 50Hz frame limiter, every script with Sleep(0.01); (or any value under 0.02) would actually always sleep for 0.02s or longer in the original game. In OpenJKDF2, it slept for the ~intended 0.01s.

There's an argument to be had as to whether I should set that value to the "canonical" physics framerate (25 FPS) to match what the developers saw, or whether I should set it to 50 FPS to match the theoretical maximum of the original EXE (and what a lot of frame limiters targeted to reach max FPS afaik).

shinyquagsire23 commented 1 year ago

Also to clarify, the 150Hz tickrate is primarily to solve the issue of high-FPS gameplay in multiplayer/co-op, but it also has the downstream effect of making sure that physics are identical across all framerates. At least in theory.

shinyquagsire23 commented 1 year ago

Fixed v0.8.13

QmwJlHuSg9pa commented 1 year ago

I think you might have misinterpreted the Disable Physics Stepping box? The default is unchecked, which will always advance the game state the same regardless of the current framerate.

This was my understanding; I was moreso concerned that its default value was not resulting in correct physics, though as you explained, the issue was more directly tied to COG timing inconsistencies.

I'm curious -- as of v0.8.13, what exactly is the difference between default Openjkdf2 behaviour, and enabling "Restore 50Hz midair player physics"?