Fixed FPS issue.

This commit is contained in:
2026-09-07 10:43:49 -04:00
parent 189c0af447
commit cba40ba2db
2 changed files with 46 additions and 13 deletions

View File

@@ -32,6 +32,11 @@ public class Game1 : Game
int _fps, _fpsFrames; int _fps, _fpsFrames;
double _fpsTimer; double _fpsTimer;
// precise 120Hz pacing (MonoGame's fixed-timestep Sleep overshoots and drops ticks)
const double TickSeconds = 1 / 120.0;
readonly System.Diagnostics.Stopwatch _frameClock = System.Diagnostics.Stopwatch.StartNew();
double _nextFrameTime;
public Game1() public Game1()
{ {
_graphics = new GraphicsDeviceManager(this) _graphics = new GraphicsDeviceManager(this)
@@ -42,8 +47,7 @@ public class Game1 : Game
}; };
Content.RootDirectory = "Content"; Content.RootDirectory = "Content";
IsMouseVisible = true; IsMouseVisible = true;
IsFixedTimeStep = true; IsFixedTimeStep = false; // paced manually in EndDraw for an accurate 120Hz
TargetElapsedTime = TimeSpan.FromSeconds(1 / 120.0);
Window.Title = "Freedom Fighter"; Window.Title = "Freedom Fighter";
Window.AllowUserResizing = true; Window.AllowUserResizing = true;
Window.ClientSizeChanged += (_, _) => Window.ClientSizeChanged += (_, _) =>
@@ -113,6 +117,21 @@ public class Game1 : Game
} }
} }
protected override void EndDraw()
{
base.EndDraw();
// hybrid sleep/spin wait until the next 1/120s boundary
_nextFrameTime += TickSeconds;
double now = _frameClock.Elapsed.TotalSeconds;
if (now > _nextFrameTime + 0.25)
_nextFrameTime = now; // resync after a stall (window drag, load, etc.)
while (_nextFrameTime - _frameClock.Elapsed.TotalSeconds > 0.002)
System.Threading.Thread.Sleep(1);
while (_frameClock.Elapsed.TotalSeconds < _nextFrameTime)
System.Threading.Thread.SpinWait(50);
}
protected override void Update(GameTime gameTime) protected override void Update(GameTime gameTime)
{ {
// all logic runs in Draw, matching the original's timer callback // all logic runs in Draw, matching the original's timer callback

View File

@@ -1,5 +1,14 @@
using System; using System;
using System.Runtime.InteropServices;
// 1ms timer resolution so the 120Hz fixed timestep's Thread.Sleep doesn't overshoot
// (default ~15.6ms granularity caps the loop at 80-90 FPS; OmegaTimer did the same)
[DllImport("winmm.dll")] static extern uint timeBeginPeriod(uint ms);
[DllImport("winmm.dll")] static extern uint timeEndPeriod(uint ms);
timeBeginPeriod(1);
try
{
using var game = new FreedomFighter.Game1(); using var game = new FreedomFighter.Game1();
// debug aid: --shot <file> [frames] renders, saves the backbuffer to a PNG, and exits // debug aid: --shot <file> [frames] renders, saves the backbuffer to a PNG, and exits
var cmdArgs = Environment.GetCommandLineArgs(); var cmdArgs = Environment.GetCommandLineArgs();
@@ -15,3 +24,8 @@ for (int i = 1; i < cmdArgs.Length - 1; i++)
game.StartLevel = level; game.StartLevel = level;
} }
game.Run(); game.Run();
}
finally
{
timeEndPeriod(1);
}