Fixed FPS issue.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -1,17 +1,31 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
using var game = new FreedomFighter.Game1();
|
// 1ms timer resolution so the 120Hz fixed timestep's Thread.Sleep doesn't overshoot
|
||||||
// debug aid: --shot <file> [frames] renders, saves the backbuffer to a PNG, and exits
|
// (default ~15.6ms granularity caps the loop at 80-90 FPS; OmegaTimer did the same)
|
||||||
var cmdArgs = Environment.GetCommandLineArgs();
|
[DllImport("winmm.dll")] static extern uint timeBeginPeriod(uint ms);
|
||||||
for (int i = 1; i < cmdArgs.Length - 1; i++)
|
[DllImport("winmm.dll")] static extern uint timeEndPeriod(uint ms);
|
||||||
|
timeBeginPeriod(1);
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (cmdArgs[i] == "--shot")
|
using var game = new FreedomFighter.Game1();
|
||||||
|
// debug aid: --shot <file> [frames] renders, saves the backbuffer to a PNG, and exits
|
||||||
|
var cmdArgs = Environment.GetCommandLineArgs();
|
||||||
|
for (int i = 1; i < cmdArgs.Length - 1; i++)
|
||||||
{
|
{
|
||||||
game.ShotFile = cmdArgs[i + 1];
|
if (cmdArgs[i] == "--shot")
|
||||||
if (i + 2 < cmdArgs.Length && int.TryParse(cmdArgs[i + 2], out int frames))
|
{
|
||||||
game.ShotFrames = frames;
|
game.ShotFile = cmdArgs[i + 1];
|
||||||
|
if (i + 2 < cmdArgs.Length && int.TryParse(cmdArgs[i + 2], out int frames))
|
||||||
|
game.ShotFrames = frames;
|
||||||
|
}
|
||||||
|
if (cmdArgs[i] == "--level" && int.TryParse(cmdArgs[i + 1], out int level))
|
||||||
|
game.StartLevel = level;
|
||||||
}
|
}
|
||||||
if (cmdArgs[i] == "--level" && int.TryParse(cmdArgs[i + 1], out int level))
|
game.Run();
|
||||||
game.StartLevel = level;
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
timeEndPeriod(1);
|
||||||
}
|
}
|
||||||
game.Run();
|
|
||||||
|
|||||||
Reference in New Issue
Block a user